יום חמישי, 22 בספטמבר 2011

למה אני לומד

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

לצורך ביצוע משימה נקודתית (php)
לצורך ביצוע מספר משימות או מטלה ארוכת טווח
כי כל הילדים המגניבים מדברים על זה (ruby on rails)
כדי למצוא עבודה (java, .NET, php)
כי נשאר תקציב הכשרות לשנת 2011
כדי לעשות מזה כסף (אייפון)
כדי לפגוש אנשים חדשים עם תחומי עניין דומים לשלי
כדי לתת מענה טוב יותר ללקוחות/עמיתים
כדי להבין באגים מוזרים החוזרים על עצמם (character encoding)
כדי לשפר את ההבנה שלי במרחב הבעיות שבו אני עוסק
כי אי אפשר אחרת

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

יום שלישי, 20 בספטמבר 2011

מצגות טובות

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

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

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

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

ומה על מאיה ? צייתנות לא מייצרת עתיד. חשיבה יצירתית כן. תעזבו את המצגות ותתחילו לעבוד.

יום שני, 22 באוגוסט 2011

למידה יעילה

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

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

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

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

יום שלישי, 14 ביוני 2011

קצר או קריא ?




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

 אם ניקח את הקוד הבא לדוגמא:

 1 $f2 = shift or die "Missing dictionary file";
 2 
 3 open FH, "<$f2" or die $!;
 4 while(<FH>) {
 5   chomp;
 6   $h{$1} = $2 if /^(\w+) *= *(.*)$/;
 7 }
 8 close FH;
 9 
10 while(<>) {
11   s/\b\w+\b/exists $h{$&} ? $h{$&} : $&/ge;
12   print;
13 }
14 


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

 1 use strict;
 2 use warnings;
 3 
 4 my $USAGE = <<END;
 5 Usage: perl translate_long.pl <dictionary_file>
 6 END
 7 
 8 my $WORD = qr { \b\w+\b }xms;
 9 
10 my $dictionary_filename = shift or die $USAGE;
11 my %dictionary          = init_dictionary($dictionary_filename);
12 
13 while (<>) {
14   s/($WORD)/translated(\%dictionary, $1)/ge;
15   print;
16 }
17 
18 sub init_dictionary {
19   my ($filename) = @_;
20   my %dictionary;
21 
22   open my $dict_file, '<', $filename;
23 
24   while (my $line = <$dict_file>) {
25     chomp $line;
26 
27     my ($term, $value) = split / *= */, $line;
28     $dictionary{$term} = $value;
29   }
30 
31   close $dict_file;
32 
33   return %dictionary;
34 }
35 
36 sub translated {
37   my ($dictionary, $term) = @_;
38 
39   return ( exists $dictionary->{$term} ?
40                   $dictionary->{$term} : $term );
41 }
42 


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

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


 1 use strict;
 2 use warnings;
 3 use Config::Std;
 4 
 5 my $USAGE = <<END;
 6 Usage: translate.pl <dictionary_file>
 7 END
 8 
 9 my $dict_filename          = shift or die $USAGE;
10 read_config $dict_filename => my $dictionary;
11 
12 # Use the default section of the file
13 my $section = $dictionary->{''};
14 
15 while (<>) {
16   s{ (\b\w+\b) }
17    { exists $section->{$1} ?
18      $section->{$1} : $1
19    }xge;
20    print;
21 }
22 


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

יום רביעי, 11 במאי 2011

תמונות שחור-לבן

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




 1 use strict;
 2 use warnings;
 3 use Image::Magick;
 4 use File::Basename;
 5 
 6 my $path = '.' || shift;
 7 foreach my $png (glob("$path/*.png")) {
 8   my $basename = fileparse($png, '.png');
 9   my $bw_name  = "$basename-bw.png";
10   my $image    = Image::Magick->new;
11 
12   $image->Read($png);
13   $image->Quantize(colorspace =>'gray');
14   $image->Write($bw_name);
15 }
16 

יום שלישי, 10 במאי 2011

כשהפטיש לא מתאים למסמר

 כשכל מה שיש זה פטיש, כל בעייה נראית כמו מסמר.

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

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


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

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

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

יום שני, 9 במאי 2011

ציונים

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

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

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


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

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