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

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

צעדים ראשונים עם Firebase

07/07/2018

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

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

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

https://zoom.us/meeting/register/3dea94be140a83cbcde7dc3c8da9331e

ועכשיו לקוד.

המשך קריאה

ללמוד את הדבר הלא נכון

06/07/2018

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

וזה משפיע על הכל.

אנחנו הולכים לקורס Design Patterns במקום להשקיע את הזמן בללמוד Design. אנחנו מחפשים קורס Angular (או React, או Vue) במקום להשקיע את הזמן וללמוד JavaScript. ומי בכלל יעז לחשוב שהוא מסתבך עם React או Redux כי הוא לא יודע מספיק JavaScript?

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

סביבת בדיקות

05/07/2018

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

שתי מחשבות בעקבות הסיפור-

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

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

הרגלים רעים

04/07/2018

החל מגירסא 3.3 מתכנתי פייתון לא צריכים יותר ליצור קבצי __init__.py כדי להגדיר חבילות של מודולים. מעל חמש שנים שמתכנתי פרל לא צריכים לכתוב use strict בהתחלה של התוכניות שלהם והתוכנית הבאה ב C++ עובדת גם בלי שנציין את טיפוסי המשתנים:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

using namespace std;

int main(int argc, char **argv)
{
  auto x = atoi(argv[1]);
  auto y = atoi(argv[2]);
  auto z = x + y;
  cout << x << " + " << y << " = " << z << endl;
}

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

הזמנה לוובינר: פיתוח Web Application מאפס כולל צד שרת

03/07/2018

הי חברים,

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

ביום חמישי (עוד יומיים) בשעה עשר בבוקר אעביר וובינר חינמי בו אציג פיתוח Web Application מלא מאפס באמצעות HTML/CSS/JavaScript בצד הלקוח שמתממשק עם שרת Firebase.

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

  1. מהו המבנה המומלץ לפרויקט Web.

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

  3. מהו Firebase ואיך הוא יכול לעזור לנו לבנות יישומים מהר יותר.

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

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

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

הוובינר יתקיים בשני חלקים וביום חמישי הקרוב יהיה החלק הראשון בו נכתוב את צד הלקוח ואת החיבור הבסיסי לשרת Firebase.

פרטים והרשמה בקישור: https://www.tocode.co.il/workshops/38

נתראה, ינון

אלף סיבות לא

02/07/2018

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

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

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

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

כוונות טובות

30/06/2018

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

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

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

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

הפיצ'ר הכי חשוב שפייתון שכחו לגנוב ל perl

29/06/2018

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

הספריה Moose של פרל מציעה תחביר מאוד נוח לכתיבת Data Objects:

use v5.18;
package User {
  use Moose;
  has 'name', is => 'rw', isa => 'Str', required => 1;
  has 'password', is => 'rw', isa => 'Str', required => 1;
}

my $u = User->new(name => 'ynonp', password => '1234');
say $u->name;

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

from dataclasses import dataclass

@dataclass
class User:
    name: str
    password: str

u = User(name='ynon', password='1234')

print(u.name)

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

use v5.18;
use HTTP::Tiny;
package User {
  use Moose;
  has 'name', is => 'rw', isa => 'Str', required => 1;
  has 'password', is => 'rw', isa => 'Str', lazy_build => 1;

  sub _build_password {
    my $response = HTTP::Tiny->new->get('https://makemeapassword.org/api/v1/passphrase/plain?pc=1');
    $response->{content};
  }
}

my $u = User->new(name => 'ynonp', password => '1234');
say $u->name;
say $u->password;

my $t = User->new(name => 'ynonp');
say $t->name;
say $t->password;
say $t->password;

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

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

מימוש redo ב Python

28/06/2018

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

לדוגמא הקובץ הבא:

I can see\
a tree behind\
the wall

And it's lovely

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

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

while (defined($line = <FH>) ) {
    chomp $line;
    if ($line =~ s/\\$//) {
        $line .= <FH>;
        redo unless eof(FH);
    }
    # process full record in $line here
}

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

זה עובד כי redo יודע לדלג ל"תחילת" הלולאה בלי לבצע את הקוד שבתוך ה while. הוא קצת דומה ל continue רק שמתחיל שורה אחת קדימה.

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

def redo_loop(iterable):
    fake_next = None
    def redo(n):
        nonlocal fake_next
        fake_next = n

    def read_next():
        nonlocal fake_next
        return next(iterable)

    while True:
        try:
            if fake_next is not None:
                val = fake_next
                fake_next = None
            else:
                val = next(iterable)

            yield val, redo, read_next
        except StopIteration:
            break


for line, redo, read_next in redo_loop(iter(fileinput.input('demo.txt'))):
    line = line.strip()
    if line.endswith('\\'):
        line = line[:-1] + ' '
        line += read_next()
        redo(line)
        continue
    print(line)

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

הפונקציה redo היא נקודת הכניסה שלנו חזרה ללוגיקה של הלולאה. אומנם אי אפשר לדלג על ההשמה שה for מבצע, אבל אפשר לקבוע איזה ערך יישלח לשם. זה בדיוק מה ש redo עושה: אם קוראים לה אז במקום לקחת שורה חדשה מהקובץ השורה שתוחזר היא בדיוק מה שעבר ל redo. כך אנחנו "עובדים" על הלולאה להחזיר את הערך שכבר נמצא במשתנה line.

הפונקציה read_next שחוזרת גם היא מ redo_loop עוקפת את הבעיה שלא תמיד יש לנו בגוף הלולאה את ה Generator Object עליו אנחנו רצים. בשביל לקרוא את השורה הבאה מהקובץ צריך לדעת משהו על fileinput ועל ה File Object שעכשיו שמור בו. אומנם ב fileinput אפשר להגיע לאוביקט זה (באמצעות שדה _state של fileinput) אבל זה לא נכון במקרה הכללי וגם כאן לא בטוח שרצוי להסתמך עליו.

האם הייתי משתמש ב redo הזה בעולם האמיתי? כלל לא בטוח. אבל אני חושב (מקווה?) שהדוגמא הזאת תעזור לכם לחשוב מזווית נוספת על Generator Functions בפייתון ואולי תיתן לכם רעיונות לדברים מדליקים נוספים שאפשר לממש עם פיצ'ר זה.

לכתוב קוד כאילו שיש זמן

27/06/2018

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

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

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

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

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

https://www.tocode.co.il/workshops/33