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

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

איך נוצר חוב טכני

06/01/2021

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

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

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

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

  3. כשאנחנו לא בודקים פעם בכמה חודשים שאפשר לחזור מגיבוי.

  4. כשאנחנו לא עושים Refactoring ביום יום, אלא משאירים את זה ליום אחד כשיהיה זמן.

  5. כשאין לנו תשתית בדיקות או שאנחנו מוכנים להשלים עם בדיקות שנכשלות.

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

אם הייתי מתחיל היום פרויקט SaaS חדש

05/01/2021

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

חוץ מהבעיה של Scope גדול מדי לפרויקט עצמו קשה לקרוא את הפוסט בלי לחשוב על כמות העבודה שסבסטיאן השקיע בשימוש בטכנולוגיה מודרנית. בין השאר הוא מספר על שלושה חודשים של השקעה בפיתוח Build System ו CI, ובהמשך גם על השימוש ב Kubernetes ואפילו השקעה של 3,000 אירו ב UX/UI. כל זה לפני שיש לקוח משלם ראשון.

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

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

  1. פריימוורק פיתוח ווב כמה שיותר מלא - לדוגמה Rails או Django.

  2. בלי פריימוורק צד לקוח, מקסימום jQuery.

  3. מבנה Monolith, בלי Micro Services.

  4. קונה Theme מוכן מהרשת, מוכן לעשות קצת התאמות.

  5. מעלה קוד לשרת עם rsync.

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

טיפ נאמפיי: החזרת אינדקסים מפונקציה

04/01/2021

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

import numpy as np

arr = np.arange(1, 11) * np.arange(1, 11).reshape(-1, 1)

אז אפשר לקחת רק את הסלייס של 9 הערכים בצד שמאל למעלה עם הפקודה:

In [6]: arr[0:3,0:3]
Out[6]: 
array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])

אז זה קול והכל אבל מה קורה כשאנחנו רוצים להיות יותר יצירתיים, למשל אם נרצה לבנות פונקציה שתחזיר את הסלייס המתאים לפי כל מיני פרמטרים? הכי אי אפשר לכתוב:

def get_index():
    # THIS DOES NOT WORK
    return 0:3,0:3

print(arr[get_index()])

וזה מביא אותנו לטיפ היומי - הפונקציה המתאימה במקרה כזה נקראת slice ואני משתמש בה באופן הבא:

In [11]: def get_index():
    ...:     return (slice(0, 3), slice(0, 3))

In [12]: arr[get_index()]
Out[12]: 
array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])

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

מה בננה

03/01/2021

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

console.log(('b'+'a'+ +'a'+'a').toLowerCase());

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

...

אז מה קרה כאן?

...

המפתח לתעלומה הוא העובדה שב JavaScript אופרטור הפלוס האונארי (Unary Plus) הוא דרך מתוחכמת לבצע המרה למספר. בגירסה פחות מסתורית של הקוד אפשר לכתוב כך:

console.log(('b' + 'a' + Number('a') + 'a').toLowerCase());

וזה כבר מתחיל להיות הגיוני כי ב JavaScript המרה של המחרוזת a למספר מחזירה את הערך המיוחד NaN שמשמעותו כמו שמו היא פשוט Not A Number (הגיוני, כי a אינו מספר):

> Number('a')
NaN

עכשיו נשאר רק להמיר את NaN למחרוזת ולהפוך לאותיות קטנות, והנה ה n-ים לבננה שלכם.

הגיע הזמן להפסיק להשתמש ב Debugger

02/01/2021

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

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

המשך קריאה

לא חשבתי שאפשר

01/01/2021

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

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

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

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

איך לברוח מלולאה כפולה ב Python

31/12/2020

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

for i in values:
    for j in values:
        for k in values:
            if i != j and j != k and i + j + k == 2020:
                print(f"Found! {i}, {j}, {k}")
                break

זה עובד, אבל... כך נראית התוצאה:

Found! 289, 480, 1251
Found! 289, 1251, 480
Found! 480, 289, 1251
Found! 480, 1251, 289
Found! 1251, 289, 480
Found! 1251, 480, 289

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

מה בכל זאת אפשר לעשות? דרך קלה לברוח מלולאה מקוננת היא להפוך אותה ללולאה רגילה באמצעות yield. הקוד נראה כך:

def triplets(values):
    for i in values:
        for j in values:
            for k in values:
                if i != j and j != k:
                    yield(i, j, k)


for i, j, k in triplets(values):
    if i + j + k == 2020:
        print(f"Found! {i}, {j}, {k}")
        break

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

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

import itertools
for i, j, k in itertools.product(values, values, values):
    if i != j != k and i + j + k == 2020:
        print(f"Found! {i}, {j}, {k}")
        break

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

for i, j, k in itertools.combinations(values, 3):
    if i + j + k == 2020:
        print(f"Found! {i}, {j}, {k}")
        break

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

מילים ומשפטים

30/12/2020

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

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

מצד שני ברגע שלמדנו מבנה מסוים אנחנו יכולים להשתמש בו בשפות חדשות ככל שנלמד את המילים בהן. לכן תוכנית שמדפיסה את לוח הכפל תיראה מאוד דומה ב C, perl, ruby, python, JavaScript או כל שפה פרוצדורלית אחרת שתיקחו. ברגע שיש בשפה תמיכה בלולאות for עם משתנה רץ, יהיה לנו קל לבנות בה את לוח הכפל. וברגע שיש בשפה פונקציות אנחנו יכולים לבנות בה את הרקורסיה, גם אם התחביר של הגדרת פונקציה וקריאה לה יהיו שונים בין שפות.

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

אני יודע את זה

29/12/2020

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

"אני יודע את זה" הוא הרגע בו אפשר להפסיק לחפש ברשת כל מיני רעיונות יצירתיים איך להתמודד עם הבעיה ופשוט להתקדם עם הדבר שאנחנו יודעים עד שנגיע לפיתרון. אם מישהו יבקש ממני מחר למרכז div ב CSS, אני מתחיל עם "אני יודע את זה" ואז ממשיך ליצור את הפלקסבוקס ולמרכז את התוכן. גם אם חסר לי סינטקס, החיפוש ברשת כבר לא יהיה חיפוש כללי של "איך לכתוב תוכן באמצע העמוד באמצעות CSS" אלא משהו יותר ספציפי כמו "Flexbox reference" או אפילו "flexbox align items example".

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

והחלק הקשה? זה יהיה לזהות מתי "אני יודע את זה" יהפוך ל "הייתי בטוח שאני יודע את זה ועכשיו אני מבין שטעיתי בגדול".

קונדה-מה?

28/12/2020

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

המשך קריאה