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

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

כן, לשכפל

16/02/2023

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

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

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

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

לכן בכל המקרים הבאים אני מעדיף לשכפל קוד ולא להתאמץ ולכתוב פונקציה אחת שעושה הכל:

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

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

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

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

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

איך להפוך למתכנתי פייתון טובים יותר

13/02/2023

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

אבל זה לא ממש עובד.

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

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

  1. להבין איך פייתון מבינה ומריצה את התוכנית שלי.

  2. להבין איך להשתמש ב Type Hints בצורה שתייצר ערך ותהפוך את הקוד לקל יותר לקריאה.

  3. להבין איך לעשות דברים במקביל, באמצעות Threads, Processes או async.

  4. להבין מה זה תכנות מונחה עצמים ואיך למדל באמצעותו בעיות.

  5. להבין איך לכתוב בדיקות בצורה יעילה ומהירה.

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

  7. להכיר את המבנים היותר בסיסיים של פייתון כמו Decorator ו Metaclass ואיזה תפקיד הם משחקים בספריות קוד מרכזיות.

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

כשיש ספק, השקיעו בדברים שנשארים.

[ריאקט] זהירות! מידע גלובאלי בין בדיקות

12/02/2023

נתבונן בקומפוננטה הבאה מתוך דף הפתיחה של swr:

import useSWR from 'swr'

function Profile () {
  const { data, error, isLoading } = useSWR('/api/user/123', fetcher)

  if (error) return <div>failed to load</div>
  if (isLoading) return <div>loading...</div>

  // render data
  return <div>hello {data.name}!</div>
}

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


import { render, screen } from '@testing-library/react';
import Profile from './Profile;

test('test one', async () => {
  jest.spyOn(global, 'fetch').mockImplementation(url => Promise.resolve({
    json: () => Promise.resolve({ name: 'bug'})
  }));

  render(<Profile />);
  expect(await screen.findByText(/hello bug/));
});

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

המשך קריאה

[ריילס] היום למדתי: לא מעבירים מזהים למודל ביצירה או עדכון

11/02/2023

את הטיפ הבא מצאתי במאמר הזה של חברת Betterment ומיד התחברתי אז אני משתף גם פה.

נתחיל עם קוד ריילס הבא עבור controller:

class Documents::AttachmentsController < ApplicationController
    def create
        AttachmentLink.new(create_params.merge(document: document)).save!
    end

    private

    def create_params
        params.permit(:attachment_id, :caption)
    end

    def document
        current_user.documents.find(params[:document_id])
    end
end

הקוד מאפשר להצמיד Attachments למסמך דרך הפונקציה create. הפונקציה מקבלת מהדפדפן מזהה של "קובץ מצורף" ומזהה של "מסמך" ויוצרת AttachmentLink שזה אוביקט חיבור בין השניים.

קחו רגע לקרוא את הקוד ונסו לחשוב מה שבור בו.

המשך קריאה

חדש באתר: מיני קורס בדיקות בריאקט

10/02/2023

זה לא פשוט לכתוב בדיקות, במיוחד בדיקות לקוד צד לקוח.

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

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

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

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

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

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

  1. היכרות עם react-testing-library, איך נראית תוכנית בדיקה ואיך לא לבזבז זמן בכתיבת תוכניות הבדיקה.

  2. בדיקת טיפול באירועים עם user-event.

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

  4. בדיקת תקשורת באמצעות mock לפונקציית fetch ו Best Practices סביב בדיקות כאלה.

  5. בדיקת קומפוננטות-בתוך-קומפוננטות באמצעות Jest Spies.

  6. בדיקת יישומים המשתמשים ב Redux.

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

אם יש לכם מנוי לאתר יכולים כבר להיכנס ולצפות בקישור: https://www.tocode.co.il/boosters/7

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

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

08/02/2023

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

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

ואם זה גם המקרה שלכם הנה כמה רעיונות פרקטיים שאפשר לנסות:

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

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

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

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

למה למחוק קוד?

07/02/2023

אודי הרשקוביץ כתב בסיפור על הבראנץ הנדיב-

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

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

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