2011-10-19

שיקולים בתכנון מקביליות: Beyond Threads

מקביליות (concurrency) מתורגמת ע"י לא מעט אנשים ל Thread ו synchronized (בג'אווה) - דבר שהוא נכון, אבל מסתיר כמה אלטרנטיבות חשובות.

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


Thread נתפס כ"אמצעי להאצת התוכנה", אבל זה לא בדיוק נכון. אם יש לי משימה מקבילית שכוללת הרבה I/O (כגון client להורדת קבצים מהאינטרנט) הגדרת thread לכל קובץ או segment שמורד היא הדרך הקלה לפיתוח, אבל לא הדרך היעילה.

דרך יעילה יותר היא הגדרת thread יחיד שעובד עם ערוצים רבים של IO אסינכרוני (כגון channels בספרית java.nio. מקביל לפקודת select ב C של unix/linux, למי שמכיר). בגישה זו יש thread יחיד שמאזין לרשימת ערוצי ה IO הרלוונטים (sockets מאתר ההורדות + streams לכתיבה לקבצים) וכל פעם שערוץ IO זמין לקבל פקודה (התקבל packet ברשת או נסתיימה כתיבה של באפר לדיסק)ה thread שלנו יתעורר ע"י event. עליו לעשות איטרציה ולבדוק איזה ערוצ(י)  מוכנים, לבצע את הפעולה ולחזור לישון עד פעולת ה I/O הבאה שהסתיימה.


אז מה חסכנו בעבודה עם thread יחיד (בסדר עולה):
  • יצירה של thread היא פעולה יקרה (thread pool עוזר להתמודד)
  • תזמון ה threads השונים הוא overhead.
  • לcontext switch בין threads יש מחיר.
כתיבה ב Thread אחד היא בהחלט יותר יעילה! בכל זאת ברוב הפרוייקטים הייתי מעדיף לעבוד עם מספר threads. דוגמת אפליקציית ההורדות היא דוגמא פשוטה במיוחד שבה כל ה threads הם אחידים, אבל לרוב המצב יותר מורכב. כמות הרווח מ thread יחיד תתרום, נאמר, 5% לביצועי המערכת? לא שווה ברוב המקרים לייצר קוד מסובך בשביל שיפור שכזה.
סיכום: thread יחיד היא אופטימיזציה טובה למקרים כמו המתואר לעיל.

היבט חשוב נוסף הוא מערכת multi-core שאותה ניתן לנצל רק עם מספר threads שיתאים למספר ה cores.
אם הייתי מריץ את המערכת הנ"ל על מערכת עם ארבעה cores (וייתכן היה שיש לי מספיק ערוצי IO להעסיק את ה thread עד תום) - הייתי רוצה 4 threads שינצלו את ה CPU עד הסוף. דוגמא קלאסית היא WinZip שעובד עם thread בודד מול תוכנות דומות (winrar, 7zip) שעובדות עם מספר threads:


אפרופו multi-core: הנוסחא המקובלת לבחור כמה threads לייצר ליעילות מרבית היא:

# threads = # of cores / (1 - blocking coefficient)
כאשר המקדם (Blocking Coefficient) הוא ערך מ 0 עד 1 כמה אחוז מהזמן ה thread ישן בין פעולות IO. אם יש לי מערכת עם 4 cores שישנים 30% מהזמן, אני ארצה לעבוד עם 6 threads.

Runtime.getRuntime().availableProcessors();
ייתן לי בג'אווה את מספר הcores הלוגים (יתחשב ב hyperthreading).

אסטרטגיות מקביליות

אחד הדברים שכן כואבים במספר threads הוא עלות הסינכרון. אם לא נסנכרן - יכולים להיות שיבוש מידע, deadlocks ו livelocks. אם אנחנו מסנכרנים, אז המחיר הוא בביצועים: כל lock שמגיעים אליו n threads גורם לכך ש n-1 יאלצו "לישון" למרות שהם רוצים לעבוד. דמיינו בעבודה את קבצי ה excel שמישהו פותח ואף אחד לא יכול לעבוד עליהם (כי הם נעולים), אבל במקום לעבור למשימה אחרת - כל מי שניסה לפתוח את הקובץ חייב ללכת לישון! (ועד עובדי חברת החשמל - רעיון לעיונכם). יצירת המון threads במקום לרוב לא תשפר את המצב: תשלמו הרבה על context switch בלי לפתור את הבעיה המהותית.

יתרה מכך, סינכרון חוסם את מידת ה scalability האפשרי בריבוי cores.
בהינתן מערכת ש 5% מזמן הביצוע שלה הוא קטע מסונכרן, אפילו אם יהיה לי את ה banana bridge i9-9990EX של אינטל שיצא ב 2024 עם 6400 cores, לא אוכל להשיג יותר מפי 5 ביצועים מאשר על מעבד ה i5 ארבעה cores הסטנדרטי שלי (בהנחה שלא היה חיזוק כוחו של כל core ושזו משימה יחידה שאני מריץ). נשמע דיי מאכזב למי שמתכוון לחכות לbanana bridge מעכשיו.

עקרון זה ידוע כ Amdahl's Law וניתן לקרוא עוד עליו כאן. הפיתרון הוא לצמצם את כמות הסינכרון למינימום.


אז איך מפחיתים את כמות הסינכרון למינימום? ישנן מספר אסטרטגיות להתמודדות עם סנכרון:
  • mutable synchronization
  • isolated mutability
  • pure immutability
  • actors
mutable synchronization
זו הגישה שרובנו בוחרים בד"כ באופן אוטומטי בלי לשים לב. העקרון הוא לשים synchronized על כל מתודה שיש בה שינוי state שיכול להשתנות בין threads. זו הגישה הקלה והפחות יעילה. דרך שיפור מהירה היא לכתוב את ה synchronized בבלוקים הכי קטנים שאפשר ולא בחתימת המתודה (למי שלא מכיר - תנסו - אפשר לכתוב אותם אפילו על שורה בודדת).


isolated mutability
גישה זו היא צעד אחד הלאה, לצמצם את כמות הסינכרון למינימום - שזה המשתנים עצמם. במקום לעבוד עם Long אני אעבוד עם AtomicLong של java.util.concurrent שמספק לי פעולות אטומיות כגון getAndIncrement או incrementAndGet
שימוש בהן יאפשר לי לצמצם את הסינכרון לנתונים עצמם ולא מעבר.

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

actors
זו גישה שפופולארית היום ב scala (השפה שנוצרה ל multi-core ו scalability). הגישה מדברת על active objects או actors שהם אובייקטים "חיים" - כלומר ה threads. לכל actor יש תור נכנס ("דואר נכנס") והם מתקשרים אחד עם השני רק בהודעות אסינכרוניות (שמונעות מצב של deadlock). בזכות התקשורת - אין צורך בסנכרון בכלל. גישה זו ניראית מוצלחת וישימה, לא ניסיתי בעצמי - אך שמעתי כמה סיפורי הצלחה ממקור ראשון. נראה שהיא גם עובדת יפה כשהמערכת גדלה והופכת למסובכת.
אמנם בג'אווה אין תמיכה בשפה ל actors אך יש מספר ספריות (כגון akka או GPars) שלמרות שנכתבו בשפות שונות על ה JVM - עובדות יפה מתוך Java. הגישה מתאימה, אגב, גם לסנכרון בתוך אותו JVM וגם ב remoting בין JVMs שונים (כגון nodes שונים ב cluster).


-----

קישורים
מעבדי XEON מול Power8 של יבמ: http://anandtech.com/show/9193/the-xeon-e78800-v3-review



2011-10-18

ארבעה דברים טובים שנוספו עם Java 7

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

פחות צורך במשמעת עצמית ב Exception Handling
Java נבנתה בצורה שתקל על המפתח להמנע משגיאות, הפחזבל (Garbage Collector) חסך מיליוני שנות פרך של debug וחיפוש אחר זליגות זכרון. בכל זאת, חברה שלא אנקוב בשמה, שילמה 17 מיליון דולר השתתפות בנזקים של הלקוח בעקבות הבאג הבא (חפשו אותו):

  Connection conn = null;
  Statement stmt = null;
  try {
    conn = connectionPool.getConnection();
    stmt = conn.createStatement();
    // Do the lookup logic
    // return a list of results
    } finally {
      if (stmt != null) {
        stmt.close();
      }
      if (conn != null) {
        conn.close();
    }
  }

אני מניח שהבאג לא צועק, הקוד נראה במבט ראשון מסודר ונכון. אבל מה - אם ()stmt.close יזרוק exception (בגלל מנגנון ה keep alive  של Oracle?), ה connection לא יתנקה וכשפעולה זו תחזור שוב ושוב, Oracle יסרב לקבל עוד קריאות. במערכת Mission Critical המשמעות היא לבצע restart לבסיס הנתונים כל מספר דקות, חוסר יכולת לעבוד, יום בטלה לעובדים והפסד אדיר ללקוח.

הפתרון הוא לעטוף ב try-catch נוספים (ה catch יישאר כנראה ריק) את קריאות ה ()close של stmt ו conn. זה היה ה best practice שדרשנו ממפתחים לעשות, שוב ושוב, וברגשות מעורבים.

איך מוודאים שבקשה זו תיושם בפועל? ביצוע תחוף של Code Reviews, הגדרת המודעות בקרב המפתחים ובארגון שעובד נכון - בניית Connection Pool שיודע לזרוק Connections בשעת לחץ.
בג'אווה 7 ניתן לכתוב את הקוד הבא:

  try (Connection conn = connectionPool.getConnection();
       Statement stmt = conn.createStatement()) {
    // Do the lookup logic
    // return a list of results
    } catch {
      // respond to exception
    }

  }

שדואג ש conn ו stmt ייסגרו, אם לא שווים ל null ולמרות exceptions שיכולים להזרק. הוא מקביל לקוד הארוך והמכוער שתארתי למעלה. נחמד!


פחות חזרה חזרה חזרה ב catch statement
תופסים שלושה סוגי Exception ורוצים לעשות אותו הדבר?
מעכשיו כתבו:


} catch (IOException | SQLException | SQLStatementException ex) {
  log.warn(ex);
  throw ex;
}
המשתנה ex יתייחס לסוג ה Exception (מתוך השלושה) שנזרק. יופי.


Performance Profiling: שחרור VistualVM
אם תחפשו בתוך ספריית Bin ב JDK שהורדתם, תגלו שיושב לו שם Profiler בשם VisualVM. מלבד כך שהוא חינמי, מתחבר לכל ה IDEs החשובים (עם plugin) ויש לו ממשק משתמש נחמד, הוא מספק נקודת איזון מאוד מוצלחת של פשוטות מול עוצמה. הוא ידידותי - אבל גם אינו צעצוע. הוא יכול להספיק לרוב משימות ה profiling הנפוצות, גם בתוך tomcat, ואינו דורש הגדרות מיוחדות לJVM או לשרת שאתם עובדים איתו.

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

נ.ב. - אופס, תפסתם אותי. VisualVM מסופק החל ממרץ כבר ב JDK 1.6 ואינו חידוש של Java 7. בכלל הוא יכול לעבוד (תחת מגבלות) עם אפילקציות שקומפלו ב JDK1.4. הוספתי אותו לכאן מכיוון שהוא תוספת מכובדת ל JDK שקל לפספס בגלל שיצא ב update ולא ב major release.


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


בהצלחה!

2011-10-17

מה Amazon עושים נכון?

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

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

אני אקצר לכם, אבל הוא מדבר על SOA ואיך ארכיטקטורה שמחייבת אנשים לעבוד בממשקים מוגדרים היטב, ללא קיצורי דרך (זכרון משותף, למשל) גורמת לאנשים לצמצם תקשורת לאותם ממשקים. ואז - דברים מתפרקים: למשל מתרחשים (SDoS (Self Denial of Service כאשר שירות מהיר קורא לשירות איטי הרבה פעמים. לא היו מפתחים שמדברים אחד עם השני ויכלו למנוע זאת. 

וכך... כך מתפתח ה DNA* הארגוני: כל Service נבנה בצורה robust ו isolated לחלוטין. "על המפתח להגן על הקוד בפני... עצמו", אמר כבר פרדריך ברוקס בשנות השבעים.

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

שווה לקרוא בשפת מקור (context: נכתב ע"י אדם שעובד כשש וחצי שנים בגוגל):


Google+ is a knee-jerk reaction, a study in short-term thinking, predicated on the incorrect notion that Facebook is successful because they built a great product. But that's not why they are successful. Facebook is successful because they built an entire constellation of products by allowing other people to do the work. So Facebook is different for everyone. Some people spend all their time on Mafia Wars. Some spend all their time on Farmville. There are hundreds or maybe thousands of different high-quality time sinks available, so there's something there for everyone.
Our Google+ team took a look at the aftermarket and said: "Gosh, it looks like we need some games. Let's go contract someone to, um, write some games for us." Do you begin to see how incredibly wrong that thinking is now? The problem is that we are trying to predict what people want and deliver it for them.
You can't do that. Not really. Not reliably. There have been precious few people in the world, over the entire history of computing, who have been able to do it reliably. Steve Jobs was one of them. We don't have a Steve Jobs here. I'm sorry, but we don't.

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

בקיצור, יפה.


אפשר למצוא את המקור כאן:

הרגישו חופשי להוסיף תובנות עקרונויות נוספות שפספסתי / לא ציינתי.

כמובן שדברים יכלו להתפתח אחרת.

2011-10-14

Performance: דחיינות = מקצוענות?

הפוסט עודכן ב 16/10


שאלה: כיצד כותבים קוד שבנוי לביצועים גבוהים?
תשובה: בדיוק אותו הדבר.


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


הקדמה
פעם, עבדתי עם מתכנתת שקיבלה הערות על מסמך Design שכתבה ונראתה פגועה: "כתבו לי שה-Design שלי ילדותי". מה?? שאלתי – תראי לי. קראתי את ההערה והיא הייתה: "premature optimization".

Premature Optimization
"Premature Optimization" למי שלא הבין אינה קשורה לילדותיות, אלא לאופטימיזציה שלא הגיעה זמנה. הזקנים שביננו שלמדו פיתוח בשפת C יכולים עוד לזכור את הסנסיי (במקרה זה מרצה מזדקן למדעי המחשב שעסק במקור במתמטיקה) סופר לנו כל ביט וכל פעולת if. "מה?, כתבת x/4? ברור ש x*0.25 זה מהיר יותר. בכלל הייתי מצפה ל x>>2" - הם הכו בנו תורה (סלחו לי אם השיפט הוא לכיוון ההפוך, מרגיז אותי בכלל לבדוק).
בשנות השבעים, שהמחשב ביצע מאות פעולות בשנייה – הייתה לאופטימיזציה כזו חשיבות. טראומת הקוד-הלא-אופטימלי היה כ"כ קשה שעד היום יש זכר לצלקות (במיוחד באקדמיה).

כיום, מחשב ביתי ממוצע מכיל 2 או 4 ליבות, בקצב של לפחות 2 מיליארד פעולות בשנייה (Ghz), עם instruction-set (כגון MMX או SSE - אליהם ניתן לגשת בעזרת ספריות מיוחדות בשפת C) שמבצעים פעולות ארוכות ומסובכות בצורה יעילה יותר. רק אזכיר שהיום לכל מחשב חדש יש גם (GPU - Graphical Processing Unit) אותו כרטיס גרפי שמובנה בלוח האם, בתוך ה CPU או על לוח נפרד. יחידות עיבוד אלה בנויות לביצוע פעולות מתמטיות פשוטות במקביליות גבוהה ויכולים להציג כח חישוב מפחיד.

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

למה לעשות אופיטמיזציה?
אז מה ניתן להסיק? שחשיבה על יעילות היא לא חשובה? כן - ולא.
כוח העיבוד הפך זול, הזכרונות יכולים לשמש כתחליף לנייר טואלט, אבל זמן המתכנת הוא יקר. כל אלה מובילים עוד ועוד אנשים למסקנה שיש לדחות אופטימיזציות performance כמה שרק אפשר, וחלקן הגדול אין בכלל לעשות. חשוב לציין 2 סייגים חשובים מאוד:
  • אלגוריתמים (או מבני נתונים שעליהם מבוססים האלגוריתמים) עלולים להיות חסיני-כח-מחשוב. חיפוש ב O(N) מול O(logN), כאשר רשימת האלמנטים עולה על כמה אלפי איברים, יעשה את ההבדל בין תגובה מהירה להפסקת קפה (של המשתמש, כמובן). כאן אין על מה להתפשר.
  • לחזור לפונקציה אחרי שנה ולשפר כל אלמנט למקסימום - זה קל (במיוחד אם יש unit tests). לשפר ארכיטקטורה – זה קשה מאוד. על הארכיטרטורה להיות יעילה מבחינת ביצועים מההתחלה.
אתם עשויים להשאר ספקנים, אז אציג דוגמא אחת של שיפור ביצועים שחוויתי על בשרי: דפדפנים.
תחום הדפדפנים החל ברצינות באמצע שנות התשעים – כלומר, ידע רב הצטבר בתחום בחמש עשר השנים האחרונות. 
אני זוכר מקרה שבו אפליקציית web שכתבנו הייתה איטית להחריד. לדף מלא לקח 56 שניות (!) לעלות על reference client hardware, שהיתה מכונה חלשה מהרגיל כדי לייצג את המשתמש עם המחשב שמיושן. המעבר מ explorer 6 ל explorer 7 (שאז היה חדש) שיפר את טעינת הדף לפחות מ 12 שניות. מקור הבעיה היה קובץ javascript גדול במיוחד. ניתוח מקיף הראה שאספלורר 6 ביזבז יותר מ 40 שניות על פיענוח (parsing) של הקובץ בעוד מנוע פיענוח חדש באספלורר 7 הוריד את הזמן לשניות בודדות (הנה דוגמא לסדרי גודל).
"כיצד יכול להיות שיפור כ"כ גדול בגירסה מס' 7 של מוצר?" תהיתי זמן רב. האם הדפדפנים הגיעו לקצה גבול היכולת? עם כל אופטימזציה אפשרית? (צחוק גדול ברקע)

הנה התבוננו במספרים מתוך מבחני ביצועים של האתר הראוי Tomshardware. המבחן בחן דפדפנים שונים על חומרה זהה שבבסיסה מעבד i7-750.


מרכיב משמעותי בימנו הוא הרצה של קוד JavaScript. בשנים האחרונות היו שיפורים משמעותיים בכל הדפדפנים, האם אפשר להשיג יותר?
הנה פיירפוקס 3.6 וכרום 10 ו אקספלורר 9 (מרס 2011) מול פיירפוקס 7, כרום 14 ואקספלורר 9 עם מספר עדכונים (ספטמבר 2011). מוצרים לא לגמרי חדשים, שנוצרו ע"י טובי המהנדסים:
הרצת JavaScript במבחן Kraken 1.1
מהההה???

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


הנה עוד מבט, כמה אפשר עוד לשפר ממוצר קיים ובוגר את זמן העלייה (startup time)?


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


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

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


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

אז למה לדחות?
למה עלינו לדחות את שיפור הביצועים? כדי להתמקד בדברים יותר קריטיים מוקדם יותר:
האם ה Software Design מוכיח את עצמו? אם השקעתי יום בשיפור הקוד והדזיין לא טוב – זהו יום מבוזבז. האם המוצר בכלל מעניין לקוחות ומצליח להמכר? אם שיפרתי ביצועי קוד עשרות פעמים עד השחרור כדי לגלות שייצרתי מוצר לא מעניין (אך מהיר) – אלו עשרות ימים שהלכו לפח. גישת האג'ייל מפרטת את הנושא הזה בצורה יסודית.
עוד נקודה היא קריאות הקוד: קוד אופטימלי הוא לרוב פחות קריא. נקודה זו רק מחזקת את הנקודה הקודמת - לא ארצה להשקיע בקריאת קוד קשה לקריאה במשך זמן פיתוח רק בכדי לגלות שהמוצר לא מעניין.
נקודה חשובה אחרונה היא עקרון פארטו שמתאר יפה מאוד את תחום הביצועים התוכנה: 80 אחוז מהשיפורים יושגו ב 20 אחוז מאזורי הקוד. אולי אפילו יותר. להשקיע ולהקשות את הקוד לקריאה ב 100% מהאזורים של הקוד - זו פשוט השקעה לא משתלמת. וב Performance כמו ב Performance יש תמיד הפתעות. שיפור במקום אחד יכול לפתוח מספר צווארי בקבוק ולהשיג שיפור משמעותי מאוד בעוד ששיפור אחר שנראה נהדר על הנייר לא ישפיע כ"כ בפועל כי הקוד ייתקע במקום אחר. חשוב מאוד לבצע pilots של שיפורים ולעשות profiling שוב ושוב בתצורות שונות בכדי להבין את התנהגות ביצועי המערכת.


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


** כדי להשתמש ביחידות אלה יש לכתוב קוד ל instruction-set מיוחד, כגון CUDA. עקרון זה של כתיבת קוד כללי ל GPU נקרא GPGPU.


*** במקור המילה Hacker הייתה תיאור כבוד יקר-ערך. האקרים היו אותם מומחי מחשבים, יחידים במינם, שהבינו לעומק את ה Linux Kernel, דקויות של פרוטוקולי תקשורת וידעו לכתוב קוד יעיל שמתקיים על כמעט-אפס זיכרון או פעולות מעבד. מאז מחולקים באינטרנט כלים אוטומטים לפירוק אתרי-ענק לגורמים, שלא דורשים יותר מהקלדת כתובת ה IP של הקורבן. ההאקרים קראו למשתמשים אלו Script Kiddies בקול מלא בוז – אך השם לא כ"כ תפס. על כל האקר אמיתי שמפצח פירצה וכותב ספרייה לנצל אותה, יש עשרות אלפי Script Kiddies שזכו בתהילה. טננבאום, ה"אנלייזר", הוא דוגמא טובה. עצוב.

2011-10-13

תקשורת: מיהו התוכי האמיתי של האינטרנט המהיר?

הצחיק אתכם התוכי של בזק שנוסע במרכז ת"א במסלול משלו?

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


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

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


כנראה שתמונת האינרנט לא תהיה שלמה ללא הכרות עם חברת Akamai.
אקמיי (Akamai) חברה מסחרית היושבת במדינת מסצ'וסטס (זו שקשה לומר את שמה) אחראית לנתון מדהים של 15 עד 30 אחוז* מתעבורת האינטרנט העולמית!
היא עושה זאת בעזרת 90 אלף שרתים המפוזרים ב 1800 אתרים (נכון למידע העדכני שמצאתי באינטרנט - והמספר רק גדל)
מי שמשלם על השירות הוא חברות האינטרנט שרוצות לספק תוכן מהיר (Apple, CNN, MTV ועוד). הרשת של Akamai אינה רשת פיסית (כמו כל דבר כמעט באינטרנט...) אלא רשת ווירטואלית ומשתמשת בעיקר בטכניקות הבאות:

Caching 
Akamai מבצעת Caching (דינאמי, שעם הזמן יכול להיות העתק של השרת המקורי) של תוכן משרת הלקוח לשרתים רבים ברשת שלה שפזורים בכל רחבי העולם. המשתמש שפונה לאתר הלקוח מופנה (ללא ידיעתו) לשרת הקרוב אליו גאוגרפית של Akamai.
אם התוכי של Akamai לא היה מביא את הסרט שאתם מורידים (אופס, כתבתי את זה?) לישראל או הסביבה - שום תוכי של בזק לא היה משיג 100Mbps בהורדת התוכן.
"אבל חלק גדול מאוד מדפי האינטרנט הוא דפים דינאמיים" יטען מפתח האינטרנט. נכון, אבל יש תמונות וקבצי מדיה (וידאו הוא כמעט חצי בכל תעבורת האינטרנט בבתים) שניתן לעשות caching בקלות ויש גם דרכים לבודד אלמנטים מהתוכן הדינאמי שלא משתנים ולשמור אותם ב cache.

Remote Proxy
למי שזוכר קצת תאוריה, יצירת קשר ב tcp (או http) דורשת 3 קריאות IP (הידוע כ three way handshake) ואם רוצים תוכן מאובטח (ssl) - עוד 4 קריאות handshake נוספות. במצב בו כל קריאת http/s מייצרת connection חדש - יעברו 3 או 7 הודעות ברשת בין השרת והלקוח עד שעמוד האינטרנט יתחיל לרדת (= latency). אקמיי יודעת להחזיק connection קבוע בין השרת של הלקוח לשרת המקומי שלה, לתת למשתמש לבצע handshake מול השרת המקומי שלה ומשם להשתמש ב connection קבוע. טכניקה זו פחות נדרשת עם העליה בתמיכה בפרוטוקול http 1.1 שהסדיר את שמירת ה connection הקיים בעזרת keep alive או pipelining. עדיין - פתרון מעורר מחשבה.

Improved Routing
Akamai טוענת שיש לה אלגוריתם גאוני (הרי הוקמה ע"י בוגרי MIT, שאחד מהם, ישראלי, דני לוין נהרג בפיגועי 9/11  תוך מאבק בחוטפי אחד המטוסים***) ל routing משופר ברחבי האינטרנט, שמגיב גם הרבה יותר מהר לתקלות בתשתית התקשורת העולמית. עם פריסה ב 1800 אתרים ושליטה מרכזית בהם ייתכן שהיא צודקת (למרות שמבחנים הראו רק שיפור קל, בממוצע, על ה routing של האינטרנט עצמו).

Data Compression
יש חברות (CDN (Content Delivery Network אחרות (Akamai היא הגדולה, אך בהחלט לא היחידה) שמבצעות דחיסה יעילה במיוחד של תוכן דינאמי בין שרת הלקוח לשרת המקומי - לשיפור התעבורה. בוודאי יש עוד טכניקות רבות בשימוש...
ספציפית דחיסה נראית לי שיטה שלא תחזיק זמן רב בהתבסס על חוק נילסן: החוק שאומר שאמנם מעבדים מכפילים את כוחם כל 18 חודשים (חוק מור), אך הרשת מכפילה את קצב ההעברה פי 100 כל עשור (שזה יותר) - ולכן מתישהו (אנחנו עדיין מחכים) תשתנה הפרדיגמה ויהיה עדיף להעביר יותר תוכן ברשת בכדי לחסוך cycles של המעבד.

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

העתיד
כיום כבר יש לא מעט חברות CDN, אני מודע לאחת משלנו (קונטנדו הישראלית) והתחרות גוברת. Akamai שהבינה שהיא מאויימת על ידי רשתות P2P לגיטימות שצצו בשנים האחרונות (שהן זולות יותר ובעלות scale פוטנציאלי גדול יותר), התחילה לפעול גם בזירה הזו. Akamai מספקת Download Manager שאמור לשפר מהירות הורדה מאתרים מסוימים, אבל בעצם משתף את ההורדה P2P עם גולשים קרובים גיאוגרפית ששותפים לאותה ההורדה.
מאחר וחברות אבטחה הוסיפו למוצרהם יכולות CDN (דוגמא ישראלית: אינקפסולה**), הלכה Akamai והוסיפה יכולות אבטחה (בסיסיות) לשירותי ה CDN שלה. בזכות מערך השרתים האדיר השלה היא הצליחה לעצור ביולי 2009 התקפת DDoS אימתנית בקצב של 124Gbps על גוף ממשלתי בארה"ב - קצב שהיה מפיל חברות רבות שנותנות שירותים דומים. בקיצור - נשמע שתהיה פה עוד נגיסה הדדית בין תחום האבטחה לתחום ה CDN.

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

עדכון: ניתן למצוא סיכום עברי על דו"ח מצב האינטרנט של Akamai כאן.


* תלוי ב יום / שעה.

** כצפוי, אינקפסולה מספקת אבטחה חזקה מזו של Akamai, כמו ש Akamai מספקת CDN טוב בהרבה מזה של אינקפסולה.

*** תודה ל Kalen מאתר HWZone על הלינק לוידאו.

2011-10-12

בורסת הטכנולוגיה: איך מחליטים על השקעה בתחום לא מוכר?

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


כיצד אנו בוחרים ספריה/טכנולוגיה/מתודולוגיה?

אנשים טכנולוגיים נוטים להתבונן על הטכנולוגיה בפרטים:
  • איך ה Design או הארכיטקטורה של הספריה?
  • באיזו שפת תכנות היא כתובה? (חשוב!) "מה, בBoo? כנראה שאלו חבר'ה מביני עניין! אני כבר מחבב אותם"
  • איך נראים ה API?
  • כמה קצר ומרשים ה tutorial שאיתו אוכל להתחיל ולהתשמש בה (טעות אנושית נפוצה היא להניח שאם אפשר להרים Hello World בפחות מדקה, אנו עתידים לשבוע נחת מהספרייה...)
  • לבדוק את ה Roadmap ופ'יצרים עתידיים. 

מתכנתים קצת יותר מנוסים יביטו על עוד כמה הבטים:
  • תיעוד ארכיטקטורה - כמה ברור מה קורה בפנים ואיך הספריה עובדת?
  • adoption וה community - האם נראה שהספריה תתמך עוד זמן רב או שהיא בנסיגה? כמה פעילות יש בפורומים?
  • בחינת רשימת הבאגים במערכת ניהול הבאגים (אם היא ציבורית) ולקבל מושג על רמת האיכות ואיזה סוג בעיות יש.
  • בחינת ה release notes האחרונים, כמה הם תכופים (כמה מהר נקבל עדכונים חשובים) וחיפוש אחר סימנים מעניינים. לדוגמא: ספריית client side שמדווחת על תמיכה ב windows 7 מעלה סימן שאלה על התלות ולמה רק עכשיו? דיווח על תיקון באג ב authentication ב SAML2 על Firefox יכול להיות סימן לבגרות. הכל כמובן תלוי ב context.

מנהלים, אולי כי יש להם פחות זמן להשקיע ואולי בגלל שהם לא רוצים להכנס לפרטים, ישתמשו בכלים ניהוליים:
  • לשלוח מישהו שעליו סומכים עליו לעשות את הבדיקה (עדיף שזה יהיה אדם מנוסה)
  • שימוש בקשרים להשגת references חיים (כלומר מישהו שאפשר לתשאל אותו) - חשוב להתייחס לכל פידבק בהקשר הנכון.
  • Benchmarking - "אתה אומר ש Haskell שפה נהדרת, אך אף אחת מהחברות בתחום שלנו לא עובדת בה. זה גם נכון לחברות בתחומים דומים".
    "היא שפה נהדרת" יענה המתכנת הנבון והצעיר "אתה יודע כמה בינוניות יש בתעשיה - זה שאחרים לא משתמשים בה לא אומר שומדבר".
    "לא נראה לי" - סביר שתהיה החלטת המנהל, וכנראה בצדק [א]. הוא לא יודע כלום על Haskell, אבל מגמת התעשייה מכילה ידע שאלה האדם הבודד יכול להגיע רק לאחר חודשים ארוכים. אי הליכה בתלם משמעותה גם פחות Eco-System לעבוד איתו, כמובן (אפרט יותר בפוסט המשך).
  • חיפוש ובחינת נקודות מפתח מנחות - מה מאפיין את שפת Haskell? משולבת בעיקר באוניברסיטאות? (נאמר, אני לא יודע באמת). מה ניתן ללמוד מכך - מה מאפיין אוניברסיטאות?
בחיינו היום-יומיים, יש נושאים שאנו מבינים בהם יותר (או יכולים להבין בהם), למשל -  קניית טלויזיה חדשה. אנו נוטים לפעול בנושאים אלו יותר כמו מפתחים. בנושאים שבהם אין לנו באמת סיכוי להבין בהם לעומק, למשל, השקעה בורסאית בחברות - אנו נוטים לפעול יותר כמו כמנהלים.

בעיית חוסר היכולת להכנס לפרטים אינה חדשה. איזה פתרון יצר עולם ההשקעות לחוסר ההבנה של לקוחותיו? - אנליסטים! אותם מומחים שאומרים לנו "לקנות לקנות" או "למכור למכור" ואפילו קצת השתכללו עם השנים ועתה הם קובעים מחיר יעד למניה "לאחר הכניסה לשוק הזימבבואי, על מנת לשקף את שווי השוק האמיתי, מניית נייס צריכה להגיע למחיר של 23 דולר ו 14 סנט בדיוק!" [ב].


אנליסטים של עולם התוכנה
כמו שלשוק המניות יש אנליסטים שמסכמים כמות אדירה של נתונים להמלצה פשוטה, כך לשוק התוכנה יש את האנליסטים שלה. החברות המוכרות הן Gartner ו Forrester וקצת מאחור IDC ו Altimeter Group. תוצאות מחקרי השוק שלהן עולות אלפים רבים של דולרים למחקר ומכסים תחומים רבים, בעיקר ב IT. הרבה ביקורת קיימת על מחקרים אלו, אך רוב החברות בגודל בינוני-ומעלה עובדות לפחות עם אחד מהגופים הללו. אם תבדקו במחלקת ה PM רוב הסיכויים שתגלו שיש להם (או יש להם גישה) לחומר כתוב ויכולת לקבוע פגישת יעוץ עם אנליסטים מאחת מהחברות הנ"ל.
 
מצד שני יש את דו"ח הטכנולוגיה של חברת ThoughtWorks שמחולק בחינם ומכסה מספר מצומצם של טכנולוגיות, אך מתוך הכרות אינטימית של מובילים טכנולוגיים שהשתמשו בטכנולוגיות אלו בפועל. דו"ח זה נקרא Technology Radar והוא מיועד יותר למנהל הפיתוח / ארכיטקט / מנהל בכיר ופחות ל Marketing. תוכלו למצוא בדו"ח זה סיכום על מצבן על טכנולוגיות, כלים ומתודולוגיות כגון OAuth, HAML, DevOps או ESB. הדו"ח מדבר על מגמות ולא נכנס לפרטים. סקירת הדו"ח יכולה להיות מקור טוב לקבלת החלטות (אם הטכנולוגיה עליה אתם חושבים מכוסה) או לעקוב אחר טכנולוגיות וטכניקות חדשות שצוברות תאוצה.

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

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



2011-10-08

האם Java גוססת?

כבר בסביבות שנת 2008 התחיל לצבור תאוצה הקרב על הירושה: איזו שפה תחליף את שפת Java? אם היה קרב לרשת את סטלין בעודו בחיים, מחנות החינוך מחדש בסיביר היו מקבלים מספר חברים חדשים לשורותיהם, אבל שפת Java עם הקהילה הפתוחה שלה, היא רחוקה מאוד מדיקטטורה*. אחת התלונות הקשות על Java היא הקצב האיטי בו גוף התקינה של Java מקבל החלטות. JDK 1.7 יצא לאחר חמש שנים ולא כלל שיפורים יוצאי דופן. C#, שפה מאוד דומה, מציגה שיפורים משמעותיים (לדוגמה LINQ, closures) באופן תדיר.


האם צריך להחליף את Java? מה רע בה?
"if it’s not broken – don’t touch!" יאמרו רבים.
"if it’s ain't broke – break it" יענו המהפכנים. "חובה עלינו לחפש שיפורים כל הזמן", בתרגום חופשי. "ואם נוח לנו במצב הקיים, אדרבא"

התלונות העיקריות לגבי Java הן הבאות:

שפה  verbose (מרבה במילים) ומסורבלת.
יש אינספור דוגמאות של: 10 שורות בג'אווה, 4 שורות ב X (שפה אחרת) . דברים מרגיזים כוללים:
  • Checked exceptions
  • Java Beans (הסינטקסט המסורבל של getXXX/setXXX שהופך משפטים לקשים לקריאה)
  •  הצורך לכתוב anonymous class בכדי להעביר פונקציה פשוטה כפרמטר (שפות אחרות פשוט נותנת להקליד את הקוד הרצוי במקום הנכון)
גוף התקינה הוא שמרן ואיטי.
"מדוע היה צריך לחכות לג'אווה 7 בכדי שמשפט switch יוכל לקבל String?" היא תלונה נפוצה וקלה להבנה (אך קצת קטנונית). הבעיה האמיתית היא ריבוי ה cores שהפך למציאות תיכנותית, וחוסר היכולת של Java להתאים את עצמה למציאות החדשה. Fork-Join שהגיע באיחור ולא יושב יפה בתוך השפה ו Actors (בדקו בתחתית הפוסט בבלוג זה להסבר על Actors) שמתכנתי Java אוספים משדות זרים.

האם שפה שהיא verbose (מרבה במילים) משפיעה באופן משמעותי על פריון המתכנתים? השאוות הראו שלספריות העומדות לרשות המפתח, ה IDE, ניסיון והכישרון של המפתח יש השפעה גדולה מהשפה עצמה. רק אסמבלי (ואולי קצת קובול) נשארה משמעותית מאחור (מקור: ספר Code Complete) אני מכיר היטב את הטענה שכתיבה ברובי או פייטון היא הרבה יותר מהירה אך אין לזה חיזוק אמפירי. הסיכוי לטעויות בשפות אלה בגלל שאין בדיקת קומפיילר מפצה לרעה על ה syntax הקליל. אני מניח שזו עניין של הרגשה ואולי מתכנתים מעולים שלא צריכים קומפיילר (שמעתי TDD?) באמת כותבים מהר יותר בשפות סקריפט. 

בואו נתבונן בשני האלמנטים האובייקטיבים (לא תלוי במתכנת) שכן משפרים את הפריון, וכיצד השפות החדשות יכולות להתמודד מול Java:
1.   כלים – auto-complete, קומפיילר טוב, Refactoring וכו'. כל שפה חדשה שמוצגת לשוק מהר מאוד מייצרת כלים בסיסיים (לפחות syntax highlighting ו auto-complete), קשה לשכנע שהשפה שלך תקצר זמני פיתוח אם אתה אמור לעבוד ב Notepad. כל מערכות ה IDE המרכזית (Eclipse, VS, IntelliJ ו NetBeans) בנויות להרחבה ותמיכה בשפות נוספות.
2.  ספריות - האם עלייך לכתוב ספריית Scheduling בעצמך, או שאתה מוריד את Quartz ומתחיל לעבוד? ב C++ לא היו הרבה ספריות משותפות, אולי בגלל שהיו קומפיילרים שונים למערכות הפעלה שונות. ברגע שJava הציגה את "Write Once, Run Everywhere"** – כמות הספריות הזמינות להורדה (ובחינם) נערמה והפכה לכוחה הגדול של Java – ה Community. אז איך מציגים שפה עם 0 ספריות מול Java עם אלפי ספרות בדוקות ובוגרות? רובי הצליחה להתרומם בעזרת Rails – ספרייה חדשנית ומוצלחת במיוחד לפיתוח אפליקציות Web (וגם בעזרת שפה מוצלחת בפני עצמה, כמובן) – אבל זה לא הספיק. ואז – נתגלתה השיטה: ב JDK 1.6, ה JVM - Java Virtual Machine הורחב לתמוך ב JavaScript שיתקמפל ל Byte Code – וירוץ בצד השרת. לצורך העניין נעשו שינויים שאפשרו ל JVM לתמוך בתכונות של שפה דינמית (כלומר פונקציה היא evaluated רק ברגע שצריך להריץ אותה, שמאפשר לתוכנה לבצע שינויים עד אותו הרגע). הסכר נפרץ ושפות רבות קפצו על ה JVM: בוגר, יעיל, מוצלח,highly optimized, עם התקנה לעשרות מערכות הפעלה ואולי הכי חשוב – היכולת  להשתמש באופן טבעי בכל מאגר ספריות הJava הקיימות. אפילו שפות שהיה להן Virtual Machine – פיתחו וריאציה עבור ה JVM.

היכן המהפכה?
אוקיי, אז עברו שלוש שנים, וJava עדיין כאן. השפות שעשו זינוק בשנה האחרונה הן דווקא LUA ו F#  – שאינן קשורות ל JVM. השפות המדוברות תופסות הרבה נפח בכנסים ובבלוגים, אך עדיין הנוכחות שלהן סה"כ קטנה.
ברוכים הבאים לעולם העסקי (ניתן לומר: האמיתי). מקום שבו טכנולוגיה טובה לא מבטיחה הצלחה, מקום שבו שיתופי פעולה והרגלים הם בעלי כוח מכריע.
הדעיכה של Java כנראה התחילה, אבל Java לא עתידה להעלם סתם כך. הייתי מעריך שיעברו עוד שנים רבות עד שJava תחשב כשפה לא רלוונטית. כמות הקוד הקיים, הספרות והכי חשוב – האנשים שמושקעים באופו אישי בJava הוא עצום והוא לא יעלם סתם כך. (בעולם הJVM) תמיכת ה IDE בJava היא עדיין הטובה ללא עוררין, וכך גם כמות החומר הלימודי. יתרונות השפות המדוברות – הן עדיין הדרגתיות וצריך סיבה טובה כדי לעשות מעבר.למשל: אם יש לי בעיות Concurrency קשות באמת, אני יכול לכתוב מודול ב Scala, לייצר .jar ולצרף אותו לפרוייקט הJava הקיים.

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

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

Scala  - כנראה המתמודדת הבולטת ביותר. משלבת אלמנטים פונקציונליים ו Object Oriented. מאפשרת גם תכנות דינמי (כמוJavaScript  או רובי) אבל גם Static Typing – כלומר הקומפיילר יתפוס לכם את רוב הבעיות. הייחוד שלה היא ההצלחה לשלב פרדיגמות שונות בצורה מוצלחת והתכנות מהיסוד לשפה לתכנות מקבילי. היא תהיה יחסית נוחה למתכנת Java, C++ או C# אבל תציע הרבה כוח ואפשרויות שלא היו זמינות בשפות אלה.

Groovy – שפה מגניבה, שכוללת אלמנטים של python Syntax ותאימות רבה לJava. קוד Java ללא שינוי צפוי להתקמפל בגרובי ב 95% מהמקרים. נעשתה עבודה לא כ"כ מסודרת בפרטים – וכבר יצאה גרובי++ שמטפלת בכמה מהבעיות. הביאה לעולם את Grails שזה העתק של Rails של רובי, ואת Griffon – שזו גרסת ה Desktop לאותה ארכיטקטורה. נראתה מועמדת מובילה לפני שנתיים-שלוש (בעיקר בעקבות backward compatibility), אך לאחר שהמפתח שלה הצהיר "אם הייתי מכיר את סקאלה – לא הייתי טורח לפתח את גרובי" גורלה כנראה נחרץ.

JRuby – רובי היא רביזיה Pure-Object-Oriented של שפת Python מתחילת שנות ה-90 שהוזכרה קודם. יש לה את ספריית Rails שזכתה להצלחה רבה. JRuby היא פשוט מאוד גרסת ה של רובי JVM, שילוב שגרם לרובי לרוץ מהר הרבה יותר. יש לה מומנטום חזק כ"כ בעולם ה web – כך שנראה שהיא כאן בכדי להשאר. השאלה בעיקר היא האם תתפשט מחוץ ל Web UI לכיוונים אחרים.

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



Jython - פייטון (ע"ש להקת מונטי-פייטון, כדרך אגב) היא הותיקה בשפות, אפילו ותיקה מ Java. מאז הצלחת Java ירדה מהכותרות אך חזרה אליהן לאחרונה, אולי גם בגלל Jython ה porting ל JVM. היא פחות סקסית וחדישה, אך יש בעולם הרבה מאוד קוד פייטון ומתכנתי פייטון (יותר מרובי, למשל) בעוד שרובי תפסה את הנישה הוובית, פייטון נשארה general purpose. באופן אישי, אני מכיר בעיקר סקריפטים וכלים שכתובים בה ומעט מוצרים ולכן יש לי רושם שנתוני השימוש היבשים קצת מזייפים. כמו לשאול כמה מתכנתי Bash יש בעולם...


המצב הקיים:

הצמיחה:
Python לא כלולה בסקר


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


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

** Java לא הייתה המערכת הראשונה שרצה על מערכות שונות: פייטון הגיע לשם כמה שנים מוקדם ממנה עם Virtual Machine משלה. מה שהכריע את הכף הוא כנראה ש Java קסמה למפתחי ה C++ (שהיו אז הרוב) בכך שאימצה תחביר דומה וגם תמיכה גורפת מגופי ענק כמו IBM, אורקל, SUN ועוד.

2011-10-07

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

לאחרונה יוצא לי קצת להתעסק בהרמת הבלוג.

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

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

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

לא ציפיתי לכיף חיים. הוספתי גוגל אנליטיקס ממש לפני זה ונאלצתי לחפש tutorial בגוגל, לערוך את ה HTML View של הבלוג ולשתול javascript שנתנו לי. ואז עוד עשר דקות בפורומים של גוגל להבין ש "invalid connection" בסוף ההתקנה הוא נורמאלי וייקח לו עד חצי שעה להתרפרש.
גוגל אנליטיקס ובלוגר הם שני מוצרים של גוגל - חברת ענק עם גוף פיתוח שידוע באיכותו הגבוהה. ואאוטבריין? סטארט-אפ ישראלי?

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

פתאום הייתי בבלוגר - מאשר להוסיף? מאשר.
נגמר.

מה???
בדקתי כמה פעם לא מאמין - הכל עובד.

אני לא יודע אם החוויה שלי היא המייצגת, אבל היא בהחלט הייתה טובה. הדהדו לי קולות של מנהלי מוצר שעבדתי איתם בעברי: "המשתמש הוא administrator - הוא יסתדר גם עם להקליד regex במקום להקליק על checkbox". "זה משתמש טכנולוגי, אז שימחק הכל וייצר את הרשימה מחדש, הוא ימצא עזרה בגוגל".


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

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


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

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


מה עושים?
מנהל בכיר שהכרתי הציע ברגע של יאוש לשלוח מאמר בנושא ל all-customers@worldwide.com, המייל חזר.

הייתי שמח מאוד לראות חרם צרכנים של אנשי IT: "לא Wizard - לא קונה". מהפכת צרכנים כמו שקרתה בעולם המערבי בשנות החמישים.*

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

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

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

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


ויש את המציאות הקיימת שנדרש להמשיך להתמודד איתה.

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

בקיצור, גמר חתימה טובה וצום קל.

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


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

2011-10-06

איך לגרום לאנשים להקשיב לכם יותר?

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

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

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

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

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

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

טיפ מס' 2
את הטריק הבא למדתי בסדנא של סער פאר המצוין:

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

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

אין לי מדד אובייקטיבי, אך ההרגשה שלי היא שהטיפ עובד.


נסו ושתפו כיצד זה עובד לכם.

ליאור

* אפרופו השאוות בין טובים ומצוינים ומה ניתן ללמוד מהן: ישנה קלאסיקה ניהולית קולסאלית בשם "מטוב למצוין" Good to Great שמשווה בין מנהלים טובים ומנהלים מצוינים ומצליחה לפספס בגדול מאוד: בפועל המחקר השווה בין מנהלים שמרנים לבין מהמרים גדולים - וכיוון שרק מהמרים שהימורם צלח נכנסו למדגם - המסקנה הייתה שמנהלים טובים הם מהמרים שהולכים על הקצה.
את הניתוח המלא ועוד כמה דוגמאות טובות לאיך אנשים נבונים יכולים לטעות בגדול ניתן למצוא בספר המעולה (של מחבר אחר) בשם "אפקט ההילה" (The Halo Effect). הספר ממולץ בחום!


2011-10-03

איכות תוכנה - ארגז כלים (3)

המשך ל פוסט 2: איכות תוכנה - ארגז כלים

מחפשים כיצד לשפר את איכות התוכנה ומחפשים אחר ה Best Practices בתעשייה?

בטבלה למטה ריכזתי את הטכניקות העיקריות שעברו את מבחן ההוכחה בתעשייה. ציינתי גם התייחסות כמה אתם יכולים לצפות לשיפור באיכות הפנימית (IQ - Internal Quality) או החיצונית (EQ - External Quality). אנשים לדוגמה מופתעים ש Unit Tests לא תופס הרבה באגים - אבל זו עובדה מוכרת. לעומת זאת טכניקות כמו Code Inspection ו TDD פחות מוכרות ברחבי התעשייה - אבל מניסיוני הן אפקטיביות ביותר. שימו לב שהטכניקות הקלות יותר להטמעה הן אלו שנפוצות בקרב האירגונים - זה דבר טבעי.

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

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

טכניקה
השפעה על איכות חיצונית EQ
השפעה על איכות פנימית IQ
כמות השקעה
קושי הטמעה
הערות
תהליכים – לרוב קורים לפני או בזמן הפיתוח. לא מסכנים את הקוד. יעילים בצורה מפתיעה.
CI
לא רלוונטי
בינונית
נמוכה
נמוך
הרצת בדיקה ואינטגרציה בצורה אוטומטית מיד אחרי כל שינוי קוד ולא בסוף גרסת הפיתוח. נקודת פתיחה טובה ובסיס לבדיקות רגרסיה.
Bug Tracking
גבוהה
נמוכה
נמוכה (לארגון)
נמוך
מעקב יסודי אחר כמות הבאגים וקצב הפתיחה / סגירה.עם המדידה באים הלחצים והרעיונות לשיפור. הכרחי!
 Requirements Inspection & verification
גבוהה
עקיפה בלבד
בינונית
בינוני
לעתים קרובות לא נעשה או נעשה בצורה חפיפה. הכוונה להשקעה יסודית בבחינת ואימות הדרישות.
 Formal Design Inspection
נמוכה
גבוהה
בינונית
גבוה
לעתים קרובות לא נעשה או נעשה בצורה חפיפה. בחינת אלטרנטיבות אמיתיות וסיבות על כל שינוי מהותי במערכת שנבע אפילו מתיקן באג – לא אותם מסמכים שמתארים את המובן מאליו מתובל ב interfaces וקוד!
גבוהה
גבוהה
בינונית
בינוני עד גבוה
קריאה אינטנסיבית של קוד ללא מחשב + דיון. זהו לא ה  freestyle Code Review שעושים לעתים בארגונים.
Peer Review
נמוכה
בינונית
נמוכה
נמוך עד בינוני
ישיבה עם מתכנת או ראש צוות עד רבע שעה לפני check-in 
בדיקות רגרסיה – מגבירים את הביטחון והיכולת לבצע refactoring בבטחה. כיסוי גבוה נדרש להשגת האפקט.
Unit-Tests
נמוכה
בינונית
גבוהה
גבוה
לכל class בקוד – בדיקה. נכתב ע"י המפתח. קשה מאוד להטמעה בקוד שנכתב ללא unit tests
Integration / Component Tests
בינונית
נמוכה
בינונית
בינוני
בדיקה ל flow בקוד שכולל מספר classes. נכתב ע"י המפתח.
Acceptance Tests
בינונית
זניחה
בינונית
בינוני עד גבוה
בדיקת black box למערכת עצמה, הזרקה של input ובדיקת התוצאות. נבדק לעתים קרובות ע"י "צוות אינטגרציה"
GUI Tests
בינונית
זניחה
גבוהה
בינוני
בדיקת ה UI ע"י כלים שמדמים browser (כמו Selenium). בדיקות קשות לתחזוקה אך הדרך האוטומטית לבדיקת GUI.
TDD
זניחה
גבוהה
בינונית
בינוני
טכניקה משופרת לכתיבת unit-test, משפר את המודולריות בקוד, יעילות כתיבת הבדיקות וכתיבת בדיקות יציבות יותר. כיף חיים!
אחרים
גבוהה
זניחה
גבוהה
נמוך
צוות QA שעובד בצורה נבונה ומתמקד בבדיקת הפונקציות החשובות והמורכבות של המערכת
Testing Tools
נמוכה
זניחה
בינונית
נמוך
השקעה בכלי עזר שיעזרו למפתחים ו QA לבדוק מהר יותר וטוב יותר. מאפשר למפתחים לבדוק יותר ולהתעייף פחות.
נמוכה
זניחה
בינונית
גבוה
העמדת המערכת בעומס גבוה לראות מה נשבר ראשון. לרוב מגלה מספר מצומצם של בעיות, אך בעיות שהיו קורים אצל לקוחות.
Alpha / Beta Test
בינונית
זניחה
נמוכה
גבוה (מחוץ לפיתוח)
להגיע ללקוח מהר עם מוצר לא גמור ולבדוק את המוצר אצלו ובעזרתו. מסייע לאימות Requirements שיכול להיות קריטי להצלחת המוצר!
Static Code Analysis
בינונית
נמוכה
נמוכה
נמוך
כלים אוטומטים שמנתחים את הקוד למצוא בעיות. PMD, Find bugs ו CheckStyle הם המפורסמים בג'אווה, כאשר יש כלים כמו Sonar או פלאג-אינים כמו QA Plug שמרכזים את כולם ביחד.

להוסיף (חשוב!): Eat your own dogfood

עוד כמה הערות:

Formal code / design / requirement inspection - כמו שניסיתי לציין בטבלה יש הרבה ארגונים שעושים חלק מזה, אבל בצורה לא יסודית ולא יעילה. ראיתי המון מסמכי designs בחיים שחבל שנכתבו. הרבה ישיבות design או requirements review שהיו ריקות מתוכן כי לאלו שאמורים לעשות את הביקורת לא היה ידע מספק "לעשות את העבודה". לסיכום: קל ליפול בטכניקות הללו לביצוע בינוני בלי לשים לב.

בדיקות רגרסיה
הסוגים השונים של הבדיקות הן לא כ"כ אלטרנטיבות אחת לשנייה, אלא יותר משלימות. רגרסיה טובה כוללת הרבה unit-tests, מספר לא מבוטל של integration ו acceptance tests ומעט GUI Tests (פרמידת הבדיקות). פוסט טוב שמסביר קצת יותר ניתן למצוא כאן.

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

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

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

בהצלחה!