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

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

זה לא חשוב

10/01/2022

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

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

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

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

רק בגלל שבנית פרויקט

09/01/2022

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

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

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

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

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

עריכה

08/01/2022

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

אבל זו אשליה.

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

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

חידת React ו ref

07/01/2022

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

import { useRef } from "react";

export default function App() {
  const inputRef = useRef(null);
  const hasText = inputRef?.current?.value !== "";

  return (
    <div className="App">
      <h1>Write some text to enable the button</h1>
      <input type="text" ref={inputRef} />
      <button 
          disabled={!hasText}
      >Go</button>
      <p>hasText = {hasText}</p>
    </div>
  );
}

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

אפליקציית Swift UI הראשונה שלי

06/01/2022

ב 2008 קניתי את הסמארטפון הראשון שלי כי חשבתי שזו פלטפורמה מלהיבה להרצת קוד - מחשב שזמין בכל מקום, כולל שבב GPS, מצלמה וחיבור קבוע לרשת. זה היה N95 של נוקיה ולקח לי כמעט חצי שנה עד שהבנתי איך שפת המאקרו-אים שהם בנו מעל C++ עובדת והצלחתי לבנות אפליקציה.

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

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


import SwiftUI

struct ContentView: View {
    @State private var count = 0

    var body: some View {
        VStack {
            Text("Turtle Rock... \(count)")
                .font(.title)
                .foregroundColor(.orange)
            .padding()
            Stepper(value: $count, in: 1...10) {
               Text("Hello")
            }
            Button("Click Me", action: {
                self.count += 1
                print("count = \(count)")
            })
        }

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

בגדול אם תפעילו את הקוד ב XCode הקרוב אליכם תגלו ש:

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

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

וכמה מילים על הקוד עצמו:

  1. ב Swift מה שמופיע על המסך הוא View, ואפשר להגדיר View-ים משלנו. כל View הוא דבר שנקרא struct שזה משהו שהזכיר לי קלאס משפות אחרות. בקוד המודבק יצרתי View בשם ContentView.

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

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

  4. אלמנט VStack לוקח את ה View-ים שתתנו לו ומציג אותם על המסך אחד מתחת לשני.

  5. אלמנט Text הוא View שמציג טקסט.

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

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

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

פריימוורק מעל פריימוורק (או: למה קוד מסתבך)

04/01/2022

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

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

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

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

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

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

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

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

הסחות דעת

03/01/2022

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

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

  1. עלות שקועה - העובדה שכבר למדתי 10 שנים Java גורמת לי להעדיף משרת מתכנת Java מאשר עבודה אחרת, למרות שהעבודה האחרת אולי יותר משתלמת כלכלית לטווח הרחוק. כל פרויקט חדש שאני לוקח בטכנולוגיה הישנה רק הופך את המעבר לטכנולוגיה החדשה ליותר קשה.

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

  3. פחד - האם תהיה לי עבודה בטכנולוגיה החדשה? האם אי פעם אצליח להיות טוב ב"למידת מכונה" כמו שאני טוב ב Java? האם Swift זה לא עוד טרנד חולף שעוד שנתיים יעלם? עדיף כבר להמשיך במה שאני עושה היום.

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

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

עוד מבט על זמן

02/01/2022

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

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

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

טיפ Web Scraping שלמדתי מטלגרם

01/01/2022

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

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

private String[] userAgents = new String[] {
  "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36", // 13.5%
  "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36", // 6.6%
  "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0", // 6.4%
  "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0", // 6.2%
  "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36", // 5.2%
  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36" // 4.8%
};

connection.setRequestProperty("User-Agent", userAgents[(int) Math.round(Math.random() * (userAgents.length - 1))]);

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

עד כמה זה הכרחי או עוזר? אני לא יודע. אבל תמיד נחמד להציץ בקוד של אחרים כדי ללמוד איך העולם עובד.


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