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

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

כמה פחדים אמיתיים מ WEI

17/08/2023

משמעות ראשי התיבות WEI היא Web Environment Integrity. זהו API שנתמך כבר בכרום אבל עדיין לא סטנדרטי שמטרתו לוודא בצד השרת שהדפדפן שפונה לקבל את התוכן הוא דפדפן "אותנטי".

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

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

אלה הפחדים המרכזיים של מפתחים והקהילה מ API זה:

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

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

  3. פרטיות - איך השרת של גוגל ידע אם אתה בן אדם שגולש דרך דפדפן אמיתי? האם נתוני שימוש או נתונים התנהגותיים כלשהם ישודרו מהדפדפן לשרת האימות? האם תהיה לנו שליטה על הנתונים שנשלחים?

  4. תוספים לדפדפן - האם תוספים לדפדפן יוכלו למשוך מידע מאתרים? או לחסום מידע מאתרים? איך כל העסק ישפיע על עולם פיתוח התוספים?

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

ארבעה חסרונות מורגשים של neo4j (אחרי 4 חודשים של עבודה)

16/08/2023

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

בינתיים קבלו ארבעה חסרונות של neo4j שיכולים ממש להרגיז בזמן פיתוח-

המשך קריאה

איך לכתוב יותר בדיקות יחידה

15/08/2023

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

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

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

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

ניקח דוגמה לבדיקה פשוטה כאן מהאתר:

test 'should subscribe to blog mailing list' do
  visit blog_index_url
  fill_in :email, with: @email
  click_button I18n.t('sign_up_email')

  assert_selector 'p', text: I18n.t('subscriptions.success')
  assert Subscriber.exists?(email: @email)
end

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

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

נשמע טוב. לא היום.

14/08/2023

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

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

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

תשעים ושלוש אחוז נתח שוק

13/08/2023

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

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

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

  3. בסקר של אקליפס מ 2009, חמשים ושמונה אחוז מהמשיבים השתמשו עדיין ב SVN. ב 2011 גיטהאב עקף בפופולריות את SourceForge ושם התחיל אפקט כדור השלג. ב 2015 גיט עדיין עמד על 69% נתח שוק, מספר שהפך ב 2018 ל 87% כשמייקרוסופט רכשה את גיטהאב והכניסה את גיט גם לארגונים גדולים.

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

מבין מה ניסו לעשות שם

12/08/2023

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

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

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

אני מזהה את התבנית הזאת ומאיזה ספר היא הגיעה.

אני רואה את ה Design Pattern שלא ממומש בדיוק לפי הספר אבל גם ברור למה.

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

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

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

משולש האימה

11/08/2023

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

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

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

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

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

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

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

חמישה דברים שהייתי משנה בקלוז'ר

10/08/2023

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

אני כתבתי פוסט מבוא לקלוז'ר בעבר כאן: https://www.tocode.co.il/blog/2019-11-hello-clojure

וגם העברתי יחד עם חבר וובינר על קלוז'ר שמוקלט כאן: https://www.tocode.co.il/past_workshops/95

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

המשך קריאה

יש לי רעיון מבריק!

09/08/2023

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

״מה הבעיה? רק צריך לרשת מ int ולהוסיף ל __add__ פקודת הדפסה. משהו כזה-

class LoggedAddInt(int):
    def __new__(cls, *args, **kwargs):
        args_without_name = {k: v for k, v in kwargs.items() if k != 'name'}
        return super().__new__(cls, *args, **args_without_name)

    def __init__(self, *args, **kwargs):
        self.name = kwargs.get('name', 'New Value')

    def __add__(self, other):
        res = LoggedAddInt(super().__add__(other), name=self.name)
        print(f"{self.name}: {res}")
        return res


counter = LoggedAddInt(0, name="counter")

def do_something():
    global counter
    counter += 1

do_something()
do_something()
do_something()

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

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

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

class NotifyingCounter:
    def __init__(self):
        self.value = 0

    def inc(self):
        self.value += 1
        print(f"counter: {self.value}")

counter = NotifyingCounter()

def do_something():
    counter.inc()

do_something()
do_something()
do_something()

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

אנשים מתים

08/08/2023

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

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

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