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

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

אי אפשר להגיד שלא ראית את זה בא

10/10/2018

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

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

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

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

יותר לאט

08/10/2018

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

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

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

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

שני סיפורים קצרים על פיתוח Web

07/10/2018

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

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

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

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

אנשים שלא קונים ממני קורסים

06/10/2018

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

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

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

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

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

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

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

עכשיו שזה ברור נחזור רגע לשאלה "למה אין פרויקט גדול בקורס?" או יותר נכון ל-3 השאלות שבאמת מטרידות את מי שרוצה כזה פרויקט:

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

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

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

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

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

איך להתכונן להרצאה טכנית

05/10/2018

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

המשך קריאה

הטלגרם בוט הראשון שלי

04/10/2018

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

המשך קריאה

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

03/10/2018

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

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

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

sentence = process.argv[2];
result = [];

words = sentence.split(/\W+/);

for (let i=words.length - 1; i >= 0; i--) {
  result.push(words[i]);
}

console.log(result.join(" "));

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

System.argv
|> List.first
|> String.split
|> Enum.reverse
|> Enum.join(" ")
|> IO.inspect

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

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

List.first(System.argv)

אפשר לכתוב את הדבר הזה שעושה בדיוק את אותו דבר:

System.argv |> List.first

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

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

  1. לוקחים את המשתנה הראשון שקיבלנו בשורת הפקודה.
  2. את התוצאה שוברים למילים.
  3. את התוצאה הופכים.
  4. את התוצאה מחברים חזרה.
  5. את התוצאה מדפיסים.

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

console.log(
  process.argv[2]
  .split(/\W+/)
  .reverse()
  .join(" ")
)

געגועים ל ++

02/10/2018

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

use v5.18;
use List::Util qw/min max/;

my @numbers = <>;
my $rounds = 0;

while (min(@numbers) < 1000) {
  my $idx = int(rand(@numbers));
  $numbers[$idx]++;
  $rounds += 1;
}

say "@numbers";
say "took $rounds rounds";

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

numbers = ARGF.readlines.map(&:to_i)
rounds = 0

while numbers.min < 1000
  idx = rand(numbers.size)
  numbers[idx]++
  rounds += 1
end

puts "#{numbers}"
puts "took #{rounds} rounds"

נסו להריץ ותגלו שהקוד ב Ruby אף פעם לא מסתיים. זה די ברור כשנזכרים שאין ++ בשפת רובי. אז מה כן קרה שם? הנה הגירסא שיותר קל לקרוא:

numbers = ARGF.readlines.map(&:to_i)
rounds = 0

while numbers.min < 1000
  idx = rand(numbers.size)
  numbers[idx] + (+rounds += 1)
end

puts "#{numbers}"
puts "took #{rounds} rounds"

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

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

היכרות עם הספריה Immer

01/10/2018

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

המשך קריאה