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

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

אבל איך ידעת בדיוק מה לעשות?

13/05/2021

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

ובגלל זה כל כך חשוב לשאול "איך יודעים מה צריך לעשות?" ו"איך משתפרים בזה?"

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

  1. הגעתי לבעיה כשהיתה לי היכרות טובה מאוד עם הקוד.

  2. הגעתי לבעיה כשהיתה לי היכרות טובה מאוד עם עולם התוכן.

  3. הגעתי לבעיה אחרי שכבר פתרתי בעיות דומות בעבר.

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

וזה מביא אותנו לשאלה היותר מעניינת - "איך משתפרים בזה?". חיבור שלושת התנאים והיפוך הסדר ילמד אותי ש:

  1. כדאי לפתור כמה שיותר בעיות

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

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

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

איך ליצור Lambda Function ו API Gateway על AWS באמצעות ה CLI

אחד הטרנדים החמים היום בפיתוח הוא Serverless או פיתוח ללא קוד Back End, או יותר נכון פיתוח בלי מערכת Back End מלאה שמטפלת בכל ההיבטים של צד השרת. פיתוח Serverless יהיה יותר דומה לפיתוח Micro Services, אבל בצורה שכל סרביס רץ בתוך סביבת ריצה מנוהלת ומבוקרת משלו.

שירות AWS Lambda הוא דוגמה לפיתוח מסוג זה. הוא מאפשר לנו לכתוב קוד (פונקציה) שירוץ בכל פעם שקורה משהו ויחזיר תוצאה למי שקרא לו. באמצעות חיבור הפונקציה לשירות שנקרא API Gateway אנחנו הופכים את אותה פונקציה לזמינה מכל מקום ברשת למרות שהיא עצמה בסך הכל פונקציה קטנה אחת ולא מערכת Back End מלאה.

במדריך זה אראה איך להקים פונקציה (לא משהו מסובך היא רק תחזיר Hello World בדוגמה שלנו) ולחבר אותה ל API Gateway וכל זה באמצעות שימוש בכלי שורת הפקודה של AWS בלבד.

המשך קריאה

בין Implicit ל Explicit

11/05/2021

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

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

המשך קריאה

חלומות והסחות דעת

10/05/2021

הם מאוד דומים. בשני המקרים אנחנו מדמיינים את עצמנו במקום אחר מזה שאנחנו עכשיו, ובשני המקרים אנחנו אוהבים את התמונה שבדמיון.

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

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

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

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

לא יודע לכתוב בדיקות

09/05/2021

"אני לא יודע איך לעשות X" זו עמדת ברירת המחדל, המצב ההתחלתי. יש המון המון דברים שאני לא יודע וזה לא מעניין לדבר עליהם.

אבל ברגע שהנושא עולה בפעם הראשונה זה משנה הכל.

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

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

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

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

"לי זה לא יקרה"

08/05/2021

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

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

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

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

ועכשיו ברצינות.

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

  1. להחליף סיסמאות כל X זמן וכמובן כל פעם שתוכנה אוטומטית זיהתה סיסמה חלשה.

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

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

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

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

איך לבנות GraphQL API לאפליקציית ריילס

07/05/2021

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

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

המשך קריאה

דוקר קומפוז לפיתוח

06/05/2021

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

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

הנה קובץ docker-compose.yml קטן להמחשה:

version: "3.9"

services:
  mongo:
    image: mongo

  rabbitmq:
    image: rabbitmq

  web:
    build: ./mainapp
    command: ["/usr/bin/wait-for-it.sh", "rabbitmq:5672", "--", "bundle", "exec", "rails", "s", "-p", "3000", "-b", "0.0.0.0"]
    volumes:
      - ./mainapp:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - rabbitmq

  service:
    build: ./service
    command: ["/usr/bin/wait-for-it.sh", "mongo:27017", "--", "/usr/bin/wait-for-it.sh", "rabbitmq:5672", "--", "nodemon", "main.js"]
    volumes:
      - ./service:/myapp
    depends_on:
      - rabbitmq
      - mongo

הקובץ מתאר בסיס נתונים מונגו, תור הודעות rabbitmq, אפליקציית ריילס ראשית ו Micro Service יחיד ב node.js. הקובץ מותאם לסביבת פיתוח ובסביבת פרודקשן יהיה לנו docker-compose.yml אחר.

הקובץ מתייחס לשתי תיקיות שנמצאות איתו באותו מיקום: בתיקיה service נמצא Micro Service שכתוב ב Node.js ובתיקיה mainapp נמצאת אפליקציית ריילס. לכל אחד מהם יש Dockerfile משלו ובגלל זה השימוש ב build. אבל אותו Dockerfile מגדיר את התיקיה /myapp בתור תיקיית הבית באמצעות הפקודה:

WORKDIR /myapp

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

עם קובץ ה docker-compose.yml הזה מספיק להפעיל פעם אחת:

$ docker compose build

ואחרי זה בתחילת הפיתוח:

$ docker compose up

והמערכת עולה עם כל הסרביסים והאפליקציות ובסיסי הנתונים ומה לא.

יש לכם טריקים נוספים לפיתוח קל עם docker-compose או docker? אשמח לשמוע וללמוד, מוזמנים לשתף בתגובות.

ומה למדתם היום?

05/05/2021

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

עם השנים הפנמנו את המסר ובמעבר לעולם העבודה התחלנו לשאול את עצמנו "ומה בנית היום?", ולצפות שהשקעה תייצר התקדמות. לצפות שאם צריך לכתוב מערכת של אלף שורות אז כל מה שצריך הוא לכתוב 100 שורות ביום כדי לסיים ב 10 ימים. איזה קישקוש.

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

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

אם לא תדע מה הבעיה

04/05/2021

שיחקתי היום עם המדריך הזה כדי ליצור Web API ב C#.

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

לא לדאוג - אני מתכנת. יש המון דברים שאפשר לעשות כדי לגרום לקוד לעבוד:

  1. אפשר להדביק את הודעת השגיאה בגוגל ולקוות שיעלה איזה דף מ Stack Overflow.

  2. אפשר למחוק את הכל ולהתחיל לעקוב מההתחלה אחרי ההוראות.

  3. אפשר לנסות Tutorial אחר.

  4. אפשר להיכנס לפרויקט ולהתחיל לשנות קוד באקראי או להוסיף הודעות הדפסה.

אבל האמת שיש רק דבר אחד מעניין לעשות כאן - להבין מה הבעיה. וזה קשה, כי אם אתה לא מכיר את הטכנולוגיה בכלל אז ה"להבין מה הבעיה" הולך לקחת אותך למסע כדי לבדוק איזה קוד מתחבר לאיזה Route, ומה זה בכלל Controller, ואיזה Middlewares נמצאים בשימוש ביישום ASP.NET דיפולטי, ומה זה בכלל appsettings.json, ואיך הוא מחליט על איזה פורט להקשיב, ולמה הם כותבים מילים בתוך סוגריים מרובעות מעל שמות של מחלקות או מתודות. במבט ראשון זאת לא נראית כמו הדרך הקצרה ביותר לגרום ליישום לעבוד. במבט שני קל לראות שכשיודעים לענות על כל השאלות שראינו ויודעים לחפש את הבעיה, גם הרבה יותר קל לפתור אותה עבור יישום זה ועבור היישומים הבאים שנכתוב.