הבלוג של ינון פרק

טיפים קצרים וחדשות למתכנתים

גיט אליאס עם פרמטרים

03/06/2019

הדרך הרגילה לכתוב git alias היא פשוט לכתוב בקובץ הקונפיגורציה את הפקודה המקוצרת, אחריה סימן שווה ואז הפקודה המלאה. למשל השורות הבאות בגיט קונפיג יגדירו את הקיצור st שיפעיל אוטומטית את status:

[alias]
  st = status

אפשר גם להוסיף פרמטרי ברירת מחדל לפקודות לכן האליאס הבא יפעיל את reset hard בלי בעיה:

[alias]
    trashall = git reset --hard

ושועלי האליאסים ביניכם אולי גם זוכרים שאפשר להשתמש בסימן קריאה כדי להריץ פקודת Shell מה שייתן לנו אפשרות להפעיל מספר פקודות גיט בתוך אליאס אחד:

[alias]
  stst = !git status && git status

ייתן את האליאס הקצת מוזר שיפעיל סטטוס פעמיים. באופן רגיל פרמטרים שתכתבו בשורת הפקודה אחרי הפעלת האליאס יתווספו לפקודה האחרונה ברצף לכן כשאני אכתוב:

$ git stst -s

פקודת ה status האחרונה תקבל את המתג אבל הראשונה עדיין תדפיס את הסטטוס הרגיל.

בעזרת פונקציות bash אנחנו יכולים לשנות את ההתנהגות הזאת ולהעביר פרמטרים גם לפקודה הראשונה ברצף. למשל האליאס הבא:

[alias]
  acm = "!f() { git add \"$@\"; git commit; }; f"

הוא קיצור ל add ו-commit. אנחנו מעבירים לו בשורת הפקודה רשימה של קבצים והאליאס גם עושה לכולם add וגם מפעיל בסוף קומיט. זה נראה ככה:

$ git acm demo.txt hello.py

וזה יגרום להפעלה של:

$ git add demo.txt hello.py && git commit

ואם אהבתם תוכלו למצוא עוד כמה דוגמאות לאליאסים מוזרים שמשתמשים בטריק הזה בקישור כאן:

https://www.atlassian.com/blog/git/advanced-git-aliases

שתי שיטות ללמוד

02/06/2019

יש את השיטה של הבית ספר ואת השיטה של החדר כושר.

בשיטה של הבית ספר יש תוכנית לימודים ויעדים מסודרים ואנחנו יודעים כמה זמן הולכים להשקיע בכל נושא ואפילו לאיזה רמה הולכים להגיע בנושא הזה אחרי הזמן שקבענו. אה ויש גם מבחנים שעוזרים לוודא שהגענו לרמה שרצינו ותעודה בסוף שאומרת שהבן אדם הזה יודע את הדברים האלה והאלה.

בשיטה של החדר כושר בן אדם בא להתאמן שלוש פעמים בשבוע לשעה כל פעם. עם הזמן הריצה כנראה תהיה בקצב מהיר יותר ותרגילי הכח יהיו קשים יותר אבל אין תעודה בסוף ואף אחד לא יבטיח לך שאחרי שלושה חודשים יהיו לך 7 קוביות בבטן או באיזה קצב תוכל לרוץ. תבוא, תתאמן, תתקדם. אני גם לא מכיר הרבה חדרי כושר שמחלקים תעודה בסוף.

הניסיון מראה שכשלומדים למבחן אנחנו שוכחים הכל יומיים אחרי המבחן, אבל כשיוצרים הרגל ומתמידים בו כל שבוע אין אפשרות לשכוח ולכן הלימוד הרבה יותר אפקטיבי. עכשיו נשאר רק להבין למה אנחנו מתעקשים ללמוד וללמד בשיטה שלא עובדת.

שלד לפרויקט Rails שמריץ בדיקות סלניום עם כל קומיט על Bitbucket

01/06/2019

לפני כמה ימים הראיתי פה שלד לפרויקט Node.JS שבכל קומיט מריץ את בדיקות היחידה עם מנגנון Bitbucket Pipelines. כמה חברים הציעו לקחת את זה עוד צעד קדימה ולשלב גם את Selenium כדי להריץ בדיקות End To End לפרויקט. מאחר ומערכות גדולות יותר אני מעדיף לכתוב ב Rails החלפתי גם את טכנולוגיית צד השרת וכך קיבלנו את השלד בפוסט של היום.

הפרויקט כולל:

  1. פרויקט Rails שמציג אתר עם דף אחד ובו הודעת שלום. ההודעה והדף נשמרים בקובץ app/views/home/index.html.erb.

  2. בדיקת End-To-End לפרויקט שמפעילה Selenium, מתחברת לעמוד ומוודאת שהדף עלה והציג את ההודעה. הבדיקה נמצאת בקובץ test/system/home_test.rb.

  3. בסיס נתונים PostgreSQL עבור הבדיקות שמאופס בכל פעם שעושים Push.

  4. קובץ bitbucket-pipelines.yml שמתקין את כל הכלים שצריך ומריץ את הבדיקות.

מוזמנים למצוא את הפרויקט לייב בריפו הזה:

https://bitbucket.org/ynonp/rails-selenium-pipeline/src

החלק שהכי יעניין אותנו היום הוא הקובץ bitbucket-pipelines.yml אז בואו נתחיל ממנו:

image: ruby:2.4.4

pipelines:
  default:
    - step:
        script: # Modify the commands below to build your repository.
        - export DATABASE_URL=postgresql://test_user:test_user_password@localhost/pipelines
        - curl -sL https://deb.nodesource.com/setup_8.x | bash -
        - apt-get update && apt-get install -y unzip libnss3-dev nodejs libgconf-2-4 wget && wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -  && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' && apt-get update && apt-get install -y google-chrome-stable fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-kacst ttf-freefont --no-install-recommends
        - bundle install
        - rake db:setup
        - rake db:test:prepare
        - rails test:system
        services:
        - postgres

definitions:
  services:
    postgres:
      image: postgres
      environment:
        POSTGRES_DB: pipelines
        POSTGRES_USER: test_user
        POSTGRES_PASSWORD: test_user_password

החלק השני מגדיר את בסיס הנתונים בתור אימג' נפרד ובאמצעות משתני סביבה מגדיר את פרטי החיבור אליו. אנחנו מעבירים לריילס את פרטי החיבור באמצעות משתנה הסביבה DATABASE_URL.

החלק הראשון הוא שמגדיר את האימג' שמריץ את הבדיקות. הקונטיינר שלו יתקין את הפרויקט עם כל התלויות, וגם את דפדפן כרום. בסוף הוא יאפס את בסיס הנתונים ויפעיל את כל בדיקות המערכת עם rails test:system. זה יגרום להפעלת סלניום והרצת הבדיקה.

הקובץ שכולל את הגדרות הסלניום נקרא test/application_system_test_case והוא כולל את התוכן הבא:

require "test_helper"

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400], options: {
    args: %w[--headless --no-sandbox --disable-gpu --disable-dev-shm-usage]
  }
end

יכול להיות שאפשר להסתפק בפחות פרמטרים לכרום. את הרשימה שלי העתקתי מכמה מקומות אחרי שכרום סירב לרוץ ובסוף כשזה עבד לא עצרתי לצמצם אותה.

המקום האחרון שדרש התערבות בשביל שכל העסק הזה ירוץ הוא הקובץ test/test_helper.rb. לשם הוספתי את שתי השורות הבאות כדי שתוצאות הבדיקות יישמרו בקובץ XML בפורמט jUnit כך שביטבאקט יצליח לקרוא אותן:

require "minitest/reporters"

Minitest::Reporters.use! Minitest::Reporters::JUnitReporter.new("test-reports")

הג'ם שמפעיל את זה נקרא minitest-reporters והוא נמצא ב Gemfile.

זמן לימוד

31/05/2019

הגישה הרווחת בחברות פיתוח היא שרשימת המשימות של כל מתכנת צריכה להיות קצת יותר ארוכה ממה שאפשר להספיק. ככה אם טעינו בחישוב והבן אדם סיים את העבודה קצת יותר מהר עדיין יהיה לו מה לעשות.

אפילו במקומות שכאילו נותנים לעובדים 20% זמן לעבוד על פרויקט צד הזמן הזה מוקדש לעבודה על פרויקט צד שקשור לעבודה האמיתית, ורוב העובדים לא ישתמשו בו. כך אמרה לדוגמא מריסה מאייר כששאלו אותה מתי גם יאהו תאמץ מדיניות זו:

"It's funny, people have been asking me since I got here, 'When is Yahoo going to have 20% time?'" she said on stage during an all-employee meeting at Yahoo. "I've got to tell you the dirty little secret of Google's 20% time. It's really 120% time."

יש בזה היגיון כי אנחנו חיים בשוק תחרותי ואם המתכנתים שלנו יעבדו שעה ביום פחות מהמתכנתים של המתחרה אז המערכת שלנו תתקדם יותר לאט. יותר מזה, הרבה פעמים מנהלים פוחדים שתיווצר תרבות עבודה הרסנית בתוך הארגון, בה השיעמום ינצח את המוטיבציה ואנשים לא ירצו לבוא לעבודה כי ירגישו שאין להם מה לעשות שם.

מתכנתים טובים מבינים את זה ומצליחים לנווט בתוך עומס המשימות. יצא לי לדבר עם חברה שסיפרה שאצלם בחברה לא נהוג לכתוב בדיקות לקוד. כששואלים אותה כמה זמן פיצ'ר מסוים ייקח והיא עונה "זה ייקח שלושה ימים ועוד יומיים לכתוב את הבדיקות, הדבר הבא שהיא תשמע מהבוס זה שיש לה שלושה ימים לבנות את הפיצ'ר ואת הבדיקות יכתבו בהזדמנות אחרת. בקיצור החברה כבר למדה את הלקח והיום היא פשוט לא מפרידה את הזמנים ונותנת הערכת זמנים שכוללת את הפיצ'ר יחד עם הבדיקות. חברים אחרים מוצאים דרכים לתת הערכות זמנים ארוכות יותר כדי שיהיה להם זמן לחשוב, ללמוד ולמצוא את הפיתרון הטוב ביותר לבעיה.

כששאלו בראיון את קן ת'ומפסון (הממציא של מערכת יוניקס) אם העבודה על יוניקס אותה הוא עשה במהלך העבודה שלו ב AT&T היתה חלק מהמשימות הרשמיות שלו שם הוא ענה:

No, I was sort of incorrigible, to be honest. I suspected that I would eventually get fired, but it didn’t bother me. We were supposed to be doing basic research but there was some basic research we should be doing and some basic research we shouldn’t be doing. And just coming out of the ashes of MULTICS, operating systems was one of those basic research things we shouldn’t be doing

אבל כמובן שאף אחד לא פיטר אותו. המשחק הזה עובד לטובת כל הצדדים: הוא מאפשר למתכנתים הטובים לקבל יותר זמן עבודה, לכתוב בדיקות ולעבוד בקצב שלהם (שרק משתפר עם הזמן), ובאותו זמן מאפשר לשמור את מי שלא מצליח להעסיק את עצמו עסוק כך שלא ישתעמם.

עכשיו הבחירה שלכם - מוכנים להתאמץ, להשתפר וללמוד גם אם לא קיבלתם רשות מהבוס? מוכנים לקחת את הסיכון?

מעיכת קומיטים עם Merge Squash

30/05/2019
git

בעבודה עם גיט אנחנו אוהבים ליצור Feature Branch עבור כל פיצ'ר שאנחנו צריכים, ובסיום העבודה להפעיל merge כדי למזג את כל הקומיטים של ה Feature Branch בחזרה לענף הראשי. בפרויקטים גדולים לפעמים משתלם לכווץ את כל הקומיטים מהפיצ'ר בראנצ' לקומיט יחיד כדי שיהיה יותר קל להסתכל בהיסטוריה.

נניח בשביל הדוגמא ש master הוא הענף הראשי ו dev הוא ענף פיצ'ר קטן, והקומיטים שלהם נראים כך:

$ git log --oneline master
b4ff474 (HEAD -> master) c4
9da14d1 c3
146d73d c2
e82851f c1

$ git log --oneline dev
433746a (dev) c7
8324f82 c6
da5ccb8 c5
146d73d c2
e82851f c1

במצב כזה merge רגיל יחבר את כל הקומיטים כך שנקבל את עץ הפרויקט הבא:

$ git merge dev
$ git log --oneline --graph

*   9b80e8d (HEAD -> master) merge commit
|\  
| * 433746a (dev) c7
| * 8324f82 c6
| * da5ccb8 c5
* | b4ff474 c4
* | 9da14d1 c3
|/  
* 146d73d c2
* e82851f c1

הקומיטים c7, c6 ו-c5 שבוצעו ב Feature Branch עכשיו נמצאים איתנו ויישארו בעץ הפרויקט לנצח. דרך אחת לוותר עליהם היא "לכווץ" אותם לפני ביצוע המיזוג:

  1. נעבור לענף dev

  2. נחזיר את HEAD אחורה ל C2 בלי לשנות את הקבצים בתיקיית העבודה (עם פקודת reset). הקומיט C2 הוא הקומיט המשותף האחרון בין dev ל master ולכן זה בעצם הקומיט שהתחיל את הפיצול. החזרה אליו תאפשר לנו "לאחד" את קומיטים C5, C6 ו C7 לקומיט חדש יחיד.

  3. נעשה קומיט אחד שיכלול את כל הקבצים בתיקיית העבודה, אפשר לקרוא לו C8.

אחרי פעולה זו ב dev יהיה רק קומיט יחיד (הקומיט שעשינו בסעיף 3), וכשנמזג אותו חזרה ל master נראה בהיסטוריה רק את הקומיט היחיד הזה.

לגיט יש קיצור דרך לרצף הזה שעושה משהו אפילו יותר נחמד: הפקודה git merge --squash תיקח את כל הקבצים מענף dev למקום הנוכחי בלי להזיז את HEAD, בלי לעשות קומיט ובלי לעדכן את MERGE_HEAD. הדבר השלישי אומר שהקומיט הבא לא יהיה Merge Commit עם שני הורים אלא קומיט רגיל.

בקוד זה נראה כך:

$ git merge --squash dev
$ git log --oneline --graph

* b4ff474 (HEAD -> master) c4
* 9da14d1 c3
* 146d73d c2
* e82851f c1

עכשיו אפשר לעשות קומיט ולקבל:

$ git add .
$ git commit -m 'C8'
$ git log --oneline --graph

* 08f5e15 (HEAD -> master) C8
* b4ff474 c4
* 9da14d1 c3
* 146d73d c2
* e82851f c1

וקיבלנו מיזוג של Feature Branch לענף הראשי תוך מחיקת ההיסטוריה של ה Feature Branch ושמירה על לוג לינארי בענף הראשי.

המלצה על ספר - אומנות ההונאה

29/05/2019

אחד הספרים המרתקים שקראתי נכתב על ידי ההאקר קווין מיטניק ונקרא באנגלית The Art of Deception. אם עוד לא קראתם הנה תרגום שלי לאחד הדיאלוגים משם, ואחרי זה עוד מילה טובה על הספר וקישור.

בואו נניח שיש לכם עסק עם בנק שמשתמש בשירותים של חברה בשם CreditChex כדי לבדוק נתוני אשראי של אנשים. הייתם שמחים לקבל מ CreditChex מידע על מישהו שרוצה לשכור מכם דירה, אבל הם מוכנים לתת מידע רק לבנק. הפיתרון של מיטניק בשלוש שיחות טלפון נראה בערך כך:

המשך קריאה

איך לעבור שרת ולהשאיר את האתר באוויר

28/05/2019

הבוקר העברתי את טוקוד לשרת חדש, אחרי שעד עכשיו האתר רץ יחד עם עוד כמה מערכות על אותו השרת. זה משהו שרציתי לעשות כבר תקופה ולא הייתי בטוח איך לגשת לזה. סך הכל לא היה כל כך נורא בזכות כמה טריקים קטנים שעזרו לי לעבור תוך כדי שהאתר נשאר באוויר. הנה רשימת הטריקים שלי ועוד אחד ששכחתי.

המשך קריאה

חמש דקות על Bitbucket Pipelines

27/05/2019

שירותי אחסון גיט בענן כבר מזמן כוללים שירותי CI/CD בשביל הפרויקטים שלכם. יצאתי לסיבוב קצר עם המנגנון של Bitbucket כדי לראות איך זה עובד ואתם כמובן מוזמנים להצטרף.

המשך קריאה

כמה זמן זה ייקח?

26/05/2019

כמה זמן ייקח לך ללמוד משהו זאת שאלה הוגנת, במיוחד אם אנחנו נזכרים בבית ספר ובכל מה שאנחנו יודעים על לימודים משם. לוקח שנה ללמוד לקרוא ולכתוב, לוקח 3 שנים לסיים תואר, לוקח ארבעה חודשים ללמוד את הספר אבא גוריו. אז כמה זמן ייקח לי להתקבל לגוגל?

שלוש בעיות עם השאלה הזאת-

  1. אנשים שונים לומדים בקצב שונה. איכשהו בית ספר מצליח לטאטא את זה מתחת לשטיח אבל בחיים האמיתיים יש אנשים שיצטרכו יותר זמן ואחרים שיצטרכו פחות זמן כדי להגיע לאותה רמת מיומנות בנושא מסוים.

  2. לאנשים שונים נקודת מוצא שונה (וגם את זה בית ספר מטאטא יופי מתחת לשטיח).

  3. קו הסיום הוא פיקציה. אי אפשר לדעת כמה טובה תצטרכי להיות כדי לעבור ראיון בגוגל, כי זה תלוי מתי תנסי להתקבל לשם, ומי האחרים שמתמודדים מולך ובעוד אלף גורמים אחרים. ובאופן כללי המחשבה שאנחנו לומדים קורס פייתון ואחרי זה נדע לכתוב פייתון היא נאיבית. לא משנה כמה תתאמנו תמיד יהיה עוד לאן להשתפר. אין ציון 100 כי תמיד יש עוד שאלות לפתור.

המסקנה הפשוטה שלי מהסיפור היא שעדיף להתאמץ לייצר הרגלי למידה מאשר להיכנס למרתון אימונים לקראת ראיון עבודה. אם את יכולה לבנות חיים מקצועיים שמשלבים צפיה בהרצאות, ניסוי טכנולוגיות חדשות, קריאת ספרים מקצועיים והתמודדות עם אתגרים חדשים כל הזמן, אז יש לך סיכויים מצוינים לבנות קריירה טובה לכל החיים.

פרילאנסרים? תתחילו בלהבין מה אתם מוכרים

25/05/2019

אף אחד לא מכין אותך לחיים כפרילאנסר, לחיים בלי בוס. אז כשהתחלתי את החיים כפרילאנסר הדבר הראשון שעשיתי היה לחפש בוס - כלומר לחפש לקוחות. וכמו שכיר לשעבר טוב השתמשתי בכל הכלים שהיו לי בתור שכיר: שלחתי קורות חיים, ניסיתי להיעזר בקשרים, אפילו בניתי אתר שאומר שאני מוכן לכתוב לכם קוד אם רק תסכימו להעסיק אותי. זה לא ממש עבד.

בנוסף הרבה מהעצות שמצאתי ברשת לא היו רלוונטיות לסיטואציה או לשלב שהייתי בו. למשל, אנשים דיברו על פירסום אז זרמתי וניסיתי לשים פירסומות כדי שאנשים שמחפשים מתכנת יגיעו לאתר שלי. ואז התחלתי לקבל המון פניות לא רלוונטיות מכל מיני אנשים שמחפשים מתכנת במחירי ריצפה או לא רוצים לשלם בכלל, ועוד שילמתי לגוגל ופייסבוק על הלידים האלה.

וזה לא שלא היה לי תיק עבודות, הבעיה היתה במה שהיה בתיק.

תיק עבודות טוב צריך להיות ייחודי ולהציג מיומנות ששווה להתאמץ ולמצוא אתכם בשבילה. ככל שהעבודות מספרות יחד סיפור אחיד ככה ללקוחות יותר קל להבין אם הסיפור הזה מדבר אליהם ואם כן לעבוד אתכם, ואם לא להמשיך הלאה. ככל שהסיפור יותר כללי אנשים לא יבינו מה אתם רוצים מהם.

אז לדוגמא אפשר לבנות תיק עבודות של אפליקציות אייפון לחנויות עם 10 אפליקציות לעשר חנויות שונות, או תיק של בדיקות אוטומציה לאתרים עם שבעה אתרים שהרמתם להם תשתית בדיקות. אבל לא כדאי לבנות תיק עבודות שכולל גם אפליקציות, גם בדיקות אוטומטיות וגם סקריפטים בפייתון. זה מבלבל.

״אני אבנה לך תשתית לבדיקות אוטומטיות לאתר״ זה משפט שמוכר הרבה יותר טוב מ-״אני אכתוב לך איזה קוד שתרצה״. אחרי שהבנתם מה אתם מוכרים אפשר להתחיל לעבות את זה בעדויות של לקוחות, בתיק עבודות שמן עם דוגמאות לדבר הספציפי הזה ואפילו לפרסם בפייסבוק. אם ההצעה שלכם טובה יהיה מי שיקנה אותה וישמח לשלם (ואם לא? לא סוף העולם. לוקחים צעד אחורה ובונים הצעה חדשה).