ch
Feedback
ToCode

ToCode

前往频道在 Telegram

טיפים קצרים למתכנתים מאת ינון פרק

显示更多
1 420
订阅者
无数据24 小时
+27
-230
帖子存档
ToCode
1 420
# היום למדתי: מצב גלישה פרטית ב bash פקודות shell שאנחנו רושמים במסוף נשמרות לזיכרון ובסיום העבודה יישמרו לקובץ בשם ~/.bash_history. זה נוח כי אפשר לדפדף בהיסטוריה כדי למצוא פקודות ולהריץ אותן שוב, אבל יכול להיות מסוכן אם פקודה מסוימת כוללת מפתחות גישה או סיסמאות (למשל בהפעלה של curl). מתכנני מנגנון ההיסטוריה ב bash וגם ב zsh כבר חשבו על הבעיה ויצרו פיתרון מובנה - כשמתחילים פקודה בסימן רווח היא לא תישמר בהיסטוריה, בהנחה שהגדרתם נכון את משתנה הסביבה HISTCONTROL. ב bash נציג את התוכן של משתנה הסביבה עם:
$ echo $HISTCONTROL
ignoreboth
ערך של ignorespace או ignoreboth מציין ששליטה על ההיסטוריה פעילה. אם המשתנה ריק תצטרכו לעדכן אותו ורצוי גם בקובץ .bashrc עם:
$ export HISTCONTROL=ignoreboth
ב zsh השליטה בפיצ'ר היא באמצעות Shell Option בשם hist_ignore_space. הפקודה setopt מדפיסה את כל האופציות המופעלות ואנחנו צריכים את histignorespace ברשימה:
$ setopt|grep histignorespace
histignorespace
אם זה לא שם תצטרכו לעדכן אותו עם (ורצוי גם בקובץ rc) עם:
$ setopt hist_ignore_space
עכשיו שהכל במקום אפשר לנסות את מצב הפקודה הפרטית החדש שלנו. כתבו פקודה רגילה ושימו לב שהיא מופיעה בהיסטוריה:
$ echo one
one
$ history| tail -1
10010  echo one
ואז פקודה שמתחילה ברווח ובדקו שהיא לא ברשימה:
$  echo two
two
$ history | tail -1
10010 echo one

ToCode
1 420
# פי או סי כשהבחור בפרסומת ביוטיוב מסביר איך להתעשר מהר אני רוצה לענות לו - בן אדם, איפה ההוכחה? איפה ה POC? בוא תראה לי מוצר שעושה את מה שאתה אומר ואני אהיה מוכן להשקיע. אבל שנינו יודעים שזה לא נכון. הרי יש לו POC-ים בלי סוף, האנשים האלה אלופים בלהביא דוגמאות לאנשים שפעלו לפי "השיטה" והצליחו. האמת ששום כמות של POC-ים לא תשכנע אותי בגלל שהאמונה שלי על כסף, עבודה, רווחים, התעשרות וכל המסביב שונה ממה שצריך בשביל להאמין לשיטה שלו. האמונה באה לפני ה POC והיא מבוססת על ניסיון כמו גם על בחירה אישית. וכך אנחנו חוזרים ל POC-ים מהעולם שלנו ולשאלות שאנחנו מנסים לברר ביום יום: 1. האם לעבור לענן או להישאר עם שרת פרטי? (או להיפך) 2. האם לפתח מיקרו סרביסים או מונולית? 3. האם לגייס מפתחים מקומיים או להיעזר בפרילאנסרים מהעולם? 4. האם לפתח אפליקציה אחת עם React Native או להשקיע בפיתוח כל פלטפורמה בנפרד? 5. האם לעבור לעבוד בתחום חדש ומתפתח או להמשיך להשקיע בתחום שלי למרות שהוא כבר פחות טרנדי? 6. האם להתאמץ למצוא עבודה בענקית טכנולוגיה או לקחת משרה פחות מתגמלת בסטארט-אפ? 7. האם אפשרי להתפרנס בארץ מפרילאנס או שאני חייב למצוא עבודה כשכיר? הוכחת היתכנות לא תעזור פה כי האמונה באה קודם. אם את חושבת שיש לך את הכישורים להתקבל לגוגל את תעשי את העבודה הקשה של ללמוד ולהתכונן לאינסוף ראיונות, אבל אם את לא מאמינה בזה אז שום כמות של אנשים שהצליחו להתקבל לשם לא תשכנע אותך שגם את תצליחי. אם אתה חושב שפיתוח Cross Platform הוא באזוורד והאפליקציה שלך מסובכת מדי, אז שום כמות של POC-ים לא תעזור כי תמיד תרגיש שהם לא באמת משקפים את המורכבות של היישום שאתה רוצה לבנות. לא חייבים לבזבז זמן על POC. זה אפשרי. עכשיו בואו נתחיל לעבוד.

ToCode
1 420
# גלאי עשן מה הדבר הראשון שנשבר אצלכם במערכת? איזה מנגנונים קיימים כדי לזהות שהוא נשבר? ומי אחראי לתקן? בקוד Front End הדבר הראשון שנשבר הוא בדרך כלל CSS. אנחנו מוסיפים עוד קוד CSS לפי איפיונים חדשים שמקבלים, ולא תמיד מקפידים (או יכולים) לבדוק את האתר על כל המכשירים בעולם. מהר מאוד האתר יראה פחות יפה על איזשהו מכשיר או איזשהו דפדפן, ולאורך זמן יצטרפו עוד מכשירים שאינם נתמכים. עד שנשים לב לבעיה יש לנו כבר עשרות מכשירים לא נתמכים בגלל מאות שורות CSS בעייתיות, והתיקון יהיה מאתגר. בקוד Back End מהירות התגובה של API Endpoints נוטה להאט עם הזמן. ככל שיש יותר מידע וככל שאנחנו משנים את הקוד, מתקנים באגים בלי לשים לב למחיר בדמות זמני תגובה. בהתחלה השינוי הוא מזערי אבל לאט לאט דברים מצטברים, וכשמישהו כבר שם לב לבעיה אנחנו עם עשרות API Endpoints איטיים כשהאיטיים ביותר יכולים לקחת שניות ארוכות. "גלאי עשן" הוא מנגנון שעוזר לנו לזהות שריפה כשהיא רק מתחילה ויחסית קל להתמודד איתה. ב CSS זה יכול להיות כלי אוטומטי שמנסה את האתר על אינסוף מכשירים במעבדה בענן, מצלם תמונות ומשווה לגירסאות קודמות. ב API זה יכול להיות איסוף זמני טיפול במשתמשים אמיתיים, שמירת הנתונים וניתוח מסודר שלהם עם השוואה לנתוני עבר. כל מערכת נשברת אחרת וצריכה גלאים אחרים. דברים בעולם האמיתי סובלים מבלאי כתוצאה משימוש סביר: שטיח בן עשר שנים מתבלה כי עשר שנים אנשים דורכים עליו. קוד לא מתבלה כשמשתמשים בו אלא כשמשנים אותו, או כשמשנים את העולם בתוכו הוא עובד. בשניהם, זיהוי ותיקון מוקדם של שברים יבטיח עבודה תקינה לאורך זמן.

ToCode
1 420
# אקרופליפסה לא מזמן התגלתה בעיה באפליקציית צילומי המסך של אנדרואיד שמאפשרת לכל מי שקיבל תמונה חתוכה לשחזר את התמונה המקורית. הבעיה היתה שחיתוך תמונה לא באמת מחק את החלקים שנחתכו החוצה אלא רק דרס את ההתחלה של הקובץ, כך שתוכנת צפיה רגילה לא מראה את החלק החתוך, אבל עדיין ניתן לשחזרו. כמה ימים אחרי הגילוי ואנשים מתחילים לחפש את אותה בעיה בתוכנות אחרות וכמובן מוצאים. ולא, אין שיתוף של קוד או תשתיות בין שתי התוכנות. פשוט צורת מחשבה דומה של המפתחים. לפני שהתחלנו להשתמש בפריימוורקים לפיתוח ווב, או כשהפריימוורקים לא היו טובים מספיק, שגיאות אבטחה באינטרנט היו דבר שבשיגרה. כמעט בכל אתר היתה בעיית SQL Injection באיזשהו דף. ולפני שמערכות הפעלה הוסיפו מנגנוני הגנה נגד ניצול של Buffer Overflows, שגיאות תכנות אלה יצרו כאוס ואיפשרו לאינסוף וירוסים להשתלט לנו על המחשבים. ואחד הדברים שהפתיעו אותי בהדרכה היה כמה דומות השאלות בכל כיתה. אחרי 7-8 פעמים שהדרכתי את אותו קורס לאנשים שונים, כבר ידעתי מראש איזה שאלות אנשים הולכים לשאול ומתי. אם מישהו עשה טעות בקוד, כנראה שהוא לא היחיד. ולכן שתי מסקנות- 1. הדרך הכי קלה להכיר טוב יותר מערכת היא לחפש איזה טעויות נפוצות אנשים עושים עם המערכת הזו, וללמוד מה הטעות, למה אנשים עושים אותה ומה הפיתרונות האפשריים. 2. פיתוח תשתיות טובות יותר הוא הדרך היחידה לצמצם בעיות אבטחה, ובמקרה הכללי כשיש טעות שחוזרת על עצמה עלינו לחפש את הבעיה בתשתית. במקרה של אקרופליפסה לפחות הבעיה היתה שפתיחת קובץ לכתיבה על אנדרואיד 10 לא מוחקת את התוכן שלו (בניגוד לגירסאות קודמות) ויש לציין במפורש מצב Truncation בשביל לרוקן את הקובץ. כשאתם משתמשים פנימית במערכת תוכנה ואתם מבינים את הטעויות הנפוצות והתיקונים שלהן, שווה לחשוב איך לבנות מנגנונים אוטומטיים או עטיפה לקוד כדי לצמצם את אותן טעויות.

ToCode
1 420
# ברווז הגומי התחיל לענות דיבוג ברווז הגומי הוא מושג אמיתי במדעי המחשב, ומתיחס לרעיון שקל לנו יותר לראות בעיה כשאנחנו מסבירים אותה למישהו אחר. שם השיטה הגיע מסיפור מהספר The Pragmatic Programmer שם הציעו את הרעיון להסביר את הבעיה לברווז גומי שנמצא אצלך על השולחן לפני שאתה הולך להתייעץ עם מישהו אחר. ועכשיו ברווז הגומי גם עונה חזרה. כל מה שצריך זה לפתוח את chat gpt או בינג, ולהתחיל לספר את הצרות שלכם, והידע האינסופי של האינטרנט יבוא לשירותכם. זה מפתה, אבל גם מסוכן. הבינה המלאכותית לא באמת מבינה אתכם או את הבעיה שלכם, אבל הרעש שהיא מייצרת מנווט את המחשבה לכיוונים שלה. המוח צריך שני דברים בשביל לעבוד: קלט וזמן עיבוד. אל תוותרו על השני.

ToCode
1 420
# רק נראים עסוקים ג'ון קארמק כתב ציוץ שתפס כותרות היום ברדיט. הוא כתב (תרגום שלי)- ״תוכנה היא רק כלי כדי לבנות משהו שיעזור לאנשים. מתכנתים רבים אף פעם לא מבינים את זה. שימו לב לערך שאתם מייצרים ללקוחות יותר מאשר למאפיינים הספציפיים של הכלי״. קארמק מתיחס כאן להשפעה של כלים כמו ChatGPT על עולם התוכנה והאם כדאי בכלל ללמוד עכשיו תכנות. אבל אני חושב שיש פה עוד רובד שצריך לשים לב אליו, ושמשפיע גם על מתכנתים יותר וותיקים. ההתאהבות בכלים וב Best Practices היא הרבה פעמים לרעתנו ועולה לנו באיכות המוצר. דוגמאות מפרויקטים אמיתיים: 1. התעקשות לכתוב בדיקות יחידה עם 100% כיסוי קוד, והתוצאה היא בדיקות שלא בודקות כלום ושנכתבות רק בשביל "לעבור" איזה כלי אוטומטי. 2. בחירה ב Micro Services למרות שהמוצר והצוות קטנים, שעולה בזמני פיתוח ארוכים יותר, רק בגלל "ככה עושים היום". 3. השקעה מוגזמת בכלים של אבטחת מידע כשהמוצר עדיין לא בשל או לא באוויר. 4. הוספת עוד יכולות לפיצ'רים (Feature Creep) במקום שיחרור גירסאות ללקוחות. 5. שיכתובים אינסופיים של מנגנוני תשתית, אפילו שהמנגנונים האלה הם לא הבעיה האמיתית של המוצר. אין ספק שיש כיף בבניית מערכות גנריות ושימוש בטכנולוגיות הכי חדשות, אבל בטווח הרחוק גישה כזאת שוחקת, כי אנחנו כל הזמן מרגישים במירוץ אחרי הטכנולוגיה. יותר משתלם ומספק להשקיע במנגנונים שיעזרו למשתמשים האמיתיים של התוכנה שלכם. לאורך זמן השקעה כזאת גם הופכת אתכם לממוקדים ורגועים יותר.

ToCode
1 420
# המלצה על פרויקט - Helm Dashboard עבודה על פרויקטי קוד פתוח היא דרך טובה ללמוד ולצבור ניסיון. חלק מזה מגיע מכתיבת הקוד עצמו, אבל חלק יותר משמעותי מגיע מהאינטרקציה עם מפתחים אחרים ועבודה בכלים שמשתמשים בהם בתעשייה. הבעיה עם עבודה על פרויקטי קוד פתוח בתור דרך לצבור ניסיון היא שזה לא תמיד נגיש. אנשים שיש להם היסטוריה של עבודה בקוד פתוח מרגישים בנוח להיכנס לפרויקט, לשכפל, לבחור משימות ולשלוח Pull Requests, אבל עבור מי שעדיין לא התנסה או התנסתה בחוויה זה עלול להיות מתסכל - לא ברור איך לגרום לסביבת הפיתוח לעבוד אצלך על המחשב, לא ברור איך בדיוק לשלוח את ה Pull Request או על מה כדאי לעבוד, הרבה פעמים התגובות שמקבלים על ה PR מנוסחות בשפה שאתם עדיין לא מכירים. בקיצור בכניסה לעולם הזה יש מחסום שצריך (וכדאי) לעבור. וכאן נכנס לתמונה ניר פריזיאן, שהוא חבר יקר של האתר, מתכנת פרונטאנד מנוסה ומנהל חברת Enpitech. ניר מקים קבוצת לימוד פרטית אותה הוא ידריך וילווה בעבודה על פרויקט קוד פתוח בשם Helm Dashboard. הקבוצה תכלול שני מפגשים שבועיים וצ'אט פרטי ותתן לכם הזדמנות להתנסות בפיתוח פרויקט Front End בקוד פתוח (ריאקט וטייפסקריפט). מהיכרות עם ניר אני בטוח שיהיה מוצלח. אתם יכולים למצוא את כל הפרטים על הפרויקט בקישור כאן: https://www.facebook.com/groups/frontendistim/permalink/913268943434540/

ToCode
1 420
# להפסיד משני העולמות (זמני טעינת אתר) בהרבה מערכות משתלם להשתמש ב HTML סטטי, עיצוב שכתוב בתוך תגית style, ו JavaScript שנטען מקבצי סקריפט חיצוניים עם script src כדי לצמצם כמה שרק אפשר את זמן הטעינה של העמוד. דף נחיתה שנטען תוך פחות משניה שווה את המאמץ, וגם אם ייקח עוד כמה שניות עד שה JavaScript יגיע והעמוד יהפוך לאינטרקטיבי ויטען מידע דינמי מהשרת זה בסדר גמור. עבודת Product ועיצוב טובה יכולה לגשר על הפער. בהרבה מערכות אחרות המידע הדינמי של העמוד הוא חלק בלתי נפרד ממנו, אבל בשביל לאפשר Scale גדול נבחר עדיין להשתמש בקבצי HTML/CSS/JS סטטיים, שימשכו את המידע הדינמי מהשרת בעליה דרך API. ההנחה היא שבמקרי קיצון משיכת מידע מ API תעמיס פחות על השרתים מאשר ייצור של Template מלא של ה HTML, ובנוסף קל יותר לפתח את המערכת עם הפרדה ברורה בין צוות ה Front End לצוות ה Back End. בהרבה מערכות נוספות המידע הדינמי של העמוד הוא חלק בלתי נפרד ממנו אבל בגלל שהצוות קטן ומורכב ממתכנתי Full Stack, או שלא מתוכנן עומס של אלפי בקשות בשניה על ה API, שווה לנו לוותר על ה HTML הסטטי וליצור את ה HTML דינמית מתוך קוד צד שרת (לדוגמה קוד Rails או Django). דף HTML כזה שחוזר לדפדפן מכיל בטעינה הראשונית גם את כל המידע הדינמי של העמוד ואז הדפדפן יכול להציג את התוכן מיד איך שמקבל את התשובה לבקשה הראשונה. נכון, הפסדנו את היכולת להפיץ את ה HTML דרך CDN, אבל חסכנו צורך בבקשת רשת נוספת בשביל המידע הדינמי של העמוד. ובהרבה מערכות אחרות כתוצאה משיקולים היסטוריים אנחנו שוכחים את הבעד והנגד ונגררים לארכיטקטורה שמפסידה משני העולמות - למשל נשתמש בקוד Rails כדי לייצר דף HTML דינמי, ואז נשתמש בקוד JavaScript כדי למשוך עוד מידע דרך API מאותו שרת ריילס. בין אם הגעתם למבנה כזה בגלל שיקולים היסטוריים או חוסר תשומת לב, כדאי לשים לב לחוסר ההגיון שלו ולחזור לכלל הבסיסי: אם אני יודע מה הדפדפן ירצה, עדיף לשלוח לו את זה כמה שיותר מוקדם.

ToCode
1 420
$waiting_at[7] += 1 if (ticks % 4).zero?

  break if $waiting_at.all?(&:zero?)
  ticks += 1

  pp $waiting_at
end
פעם בארבע שניות עוד בן אדם יוצא מדירה בקומה 7 ומחכה למעלית. כן, הרבה אנשים גרים בקומה 7, ככה זה בבניינים לפעמים. בשביל להבין מה קורה הוספתי גם הדפסה של כמה אנשים מחכים בכל קומה. התוכנית עכשיו לא תסתיים אבל כך נראה הפלט אחרי כמה שניות שהיא רצה:
[0, 2, 0, 0, 0, 0, 0, 174] at second 11446
[0, 2, 0, 0, 0, 0, 0, 174]
[0, 2, 0, 0, 0, 0, 0, 174] at second 11447
[0, 2, 0, 0, 0, 0, 0, 174]
[0, 2, 0, 0, 0, 0, 0, 174] at second 11448
אפשר לראות 174 אנשים מחכים בקומה 7, ועוד שני אנשים מחכים בקומה ראשונה. בעוד שהאנשים בקומה 7 חדשים, השכנים מקומה ראשונה ממתינים שם למעלית מתחילת הסיפור וכנראה ימשיכו לחכות לנצח או עד שיבינו שעדיף להם לקחת את המדרגות. ## איך זה יעבוד בלי הרעבה הבעיה הראשונה באלגוריתם היא שהוא לא הוגן כלפי אותם מסכנים בקומה ראשונה. אפילו שיש להם רק קומה אחת לרדת, אולי הם מבוגרים וקשה להם לרדת או שיש להם ציוד כבד. אין סיבה להעדיף תמיד את השכנים בקומה 7 רק בגלל שיש להם דרך יותר ארוכה. אבל הבעיה השניה היא שהאלגוריתם פשוט לא יעיל. כל פעם שהמעלית יורדת היא צריכה לעצור גם בקומה ראשונה, רק כדי לגלות שאין מספיק מקום במעלית לשני האומללים שמחכים שם ואז להמשיך ללובי. בשביל לתקן את האלגוריתם אנחנו רק צריכים להוסיף מנגנון עדיפויות - למשל להחליט שכל סיבוב המעלית קודם תעצור בקומות בהן היא השאירה אנשים. ככל שהמעלית תהיה יותר עמוסה נרצה אולי לשמור לכל קומה גם "גיל" שיגיד כמה פעמים השארנו שם אנשים שלא הצליחו לעלות. תיקון הקוד בצורה שנותנת עדיפות לשכנים שנשארו לחכות בקומה יראה כך:

def tick_no_starvation
  if $lift_at.zero?
    puts "#{$people_in_lift} people exited to the lobby"
    $people_in_lift = 0
    if $destination > 0
      $lift_at += 1
    elsif $waiting_at.rindex(&:positive?) > 0
      $destination = $left_to_wait.rindex(&:positive?) || $waiting_at.rindex(&:positive?)
    end
  else # lift not at zero
    if $lift_at == $destination
      $destination = $waiting_at[..$lift_at-1].rindex(&:positive?) || 0
      # pick up the people from $destination
      picked_up = [$waiting_at[$lift_at], LIFT_SIZE - $people_in_lift].min
      left_to_wait = $waiting_at[$lift_at] - picked_up

      $left_to_wait[$lift_at] = left_to_wait

      puts "picked up #{picked_up} people from floor #{$lift_at}; #{left_to_wait} people left to wait there"

      $people_in_lift += picked_up
      $waiting_at[$lift_at] = left_to_wait
    else # lift not at zero and not at destination
      $lift_at += ($destination - $lift_at) / ($destination - $lift_at).abs
    end
  end
end
והרצה אחרי כמה שניות נראית הרבה יותר טוב:
[0, 0, 0, 0, 0, 0, 0, 6] at second 45782
[0, 0, 0, 0, 0, 0, 0, 6]
[0, 0, 0, 0, 0, 0, 0, 6] at second 45783
[0, 0, 0, 0, 0, 0, 0, 6]
[0, 0, 0, 0, 0, 0, 0, 6] at second 45784
[0, 0, 0, 0, 0, 0, 0, 7]
[0, 0, 0, 0, 0, 0, 0, 7] at second 45785
[0, 0, 0, 0, 0, 0, 0, 7]
[0, 0, 0, 0, 0, 0, 0, 7] at second 45786
כן עדיין מחכים אנשים בקומה 7 (תמיד יחכו כי תמיד באים לשם עוד אנשים), אבל שאר הקומות ריקות. בקומה 7 עצמה אין יותר מדי אנשים כי המעלית יכולה לנסוע יותר מהר ולא צריכה לעצור בקומות התחתונות. ## נ.ב. קוד יכול לעזור לחקור בעיות ולגלות דברים מעניינים על העולם האמיתי. לא משנה מה השפה שאתם אוהבים, הניסיון למדל את הבעיה ולשנות את הפרמטרים שלה מלמד אותנו הרבה גם על העולם וגם על תכנות. כמו שראיתם מדוגמת הרובי כאן, זה לא צריך להיות קוד יפה, שלם או אפילו מדויק. העיקר הוא המשחק. אם אתם רוצים להמשיך לחקור אלגוריתמים של מעליות יש הרבה לאן להתקדם - אפשר להוסיף "גיל" ולתת עדיפות לאנשים שמחכים כמה פעמים, והכי מעניין יהיה להוסיף עוד מעלית ולחשוב איך למנוע הרעבה שם.

ToCode
1 420
# תאכל תאכל למעלית אצלנו בבניין יש רק כוונות טובות: אם כמה אנשים מכמה קומות מנסים להזמין אותה, היא תלך קודם לקומה העליונה ביותר כדי לאסוף משם את האנשים, ואז תרד לשאר הקומות בהן אנשים מחכים לפי הסדר עד שמגיעה לקומת קרקע ואז תתחיל מחדש את הסבב. האלגוריתם הפשוט הזה עובד טוב אם אתה בקומה 10, אבל מי שמחכה למעלית בקומות הנמוכות יכול לבלות הרבה זמן בהמתנה - כל פעם שהמעלית מגיעה היא מלאה באנשים מהקומות הגבוהות וצריך לחכות לסיבוב הבא. במדעי המחשב תופעה כזו נקראת ״הרעבה״, בויקיפדיה הם מתארים את זה במשפט: > הרעבה (באנגלית: Starvation) היא בעיה הנוצרת בסביבה המאפשרת ריבוי משימות (Multitasking), כאשר מתהליך מסוים נמנעת גישה לאחד ממשאבי המערכת כך שהתהליך לעולם לא יצליח לסיים את משימתו. במקרה שלנו התהליך שצריך לסיים את משימתו הוא הדייר מהקומה השלישית, וריבוי המשימות הם כל האנשים משאר הקומות שמנסים גם לרדת. בזמן אחת ההמתנות הארוכות חשבתי שיהיה מעניין למדל את המעלית בקוד, וכך נראה ה Ruby שיצא. ## מעלית עם הרעבה איך עובדת מעלית עם הרעבה? אפשר לדמיין מערך של קומות ובכל תא במערך יהיה כתוב מספר האנשים שמחכים באותה הקומה. נניח שלמעלית לוקח שניה לעבור מקומה לקומה ועוד שניה להכניס אנשים, ולכן אפשר לקרוא לאלגוריתם המעלית פעם בשניה ולתת לאלגוריתם להחליט לאן המעלית צריכה לנסוע. אנחנו נספור כמה שניות לוקח למעלית להוריד את כל האנשים ללובי (בשביל הפשטות המעלית בתוכנה לא מעלה אנשים אף פעם). אפשר להתחיל עם לולאה כזאת:
$waiting_at = [0, 2, 0, 0, 1, 0, 3, 0]
ticks = 0
loop do
  tick
  break if $waiting_at.all?(&:zero?)

  ticks += 1
end

puts "took #{ticks} seconds"
כשהפונקציה tick היא הפונקציה המרכזית של המעלית. ברובי משתנה שמתחיל בסימן דולר הוא משתנה גלובאלי, ושוב בשביל הפשטות כל המידע על העולם נשמר במשתנים גלובאליים. את הפונקציה tick מימשתי כך:
LIFT_SIZE = 4
$waiting_at = [0] * 10
$people_in_lift = 0
$lift_at = 0
$destination = 0
$left_to_wait = [0] * 10

def tick
  if $lift_at.zero?
    puts "#{$people_in_lift} people exited to the lobby"
    $people_in_lift = 0
    if $destination > 0
      $lift_at += 1
    elsif (destination = $waiting_at.rindex(&:positive?)) > 0
      $destination = destination
    end
  else # lift not at zero
    if $lift_at == $destination
      $destination = $waiting_at[..$lift_at-1].rindex(&:positive?) || 0
      # pick up the people from $destination
      picked_up = [$waiting_at[$lift_at], LIFT_SIZE - $people_in_lift].min
      left_to_wait = $waiting_at[$lift_at] - picked_up

      puts "picked up #{picked_up} people from floor #{$lift_at}; #{left_to_wait} people left to wait there"

      $people_in_lift += picked_up
      $waiting_at[$lift_at] = left_to_wait
    else # lift not at zero and not at destination
      $lift_at += ($destination - $lift_at) / ($destination - $lift_at).abs
    end
  end
end
קצת מסורבל אבל בגדול עובד כמו בתיאור המילולי בתחילת הפוסט. המעלית מתחילה בלובי, מחפשת את הקומה הגבוהה ביותר בה אנשים מחכים, נוסעת לשם לאסוף את האנשים ואז מתחילה לרדת ועוצרת בכל קומה בה אנשים מחכים. אם אין מספיק מקום במעלית חלק מהאנשים עשויים להישאר בקומה שלהם ולחכות (וגם פה העולם האמיתי יותר מסובך, כי לפעמים אנשים לא רוצים להתפצל). כך נראה הפלט:
0 people exited to the lobby
0 people exited to the lobby
picked up 3 people from floor 6; 0 people left to wait there
picked up 1 people from floor 4; 0 people left to wait there
picked up 0 people from floor 1; 2 people left to wait there
4 people exited to the lobby
0 people exited to the lobby
picked up 2 people from floor 1; 0 people left to wait there
took 18 seconds
למעלית לוקח שניה להבין מי לחץ על מה, אחרי זה היא מתחילה לנסוע למעלה, אוספת שלושה אנשים מקומה 6, עוצרת בקומה 4 לאסוף עוד שכן ואז מגיעה לקומה 1 שם היא מוצאת שני שכנים מחכים. בגלל שיש בסך הכל מקום לארבעה, השניים יצטרכו להמשיך לחכות לסיבוב הבא. אחרי שכולם יוצאים מהמעלית היא עולה שוב לקומה ראשונה, לוקחת את הזוג שחיכה שם ויורדת חזרה ללובי, סך הכל המסלול לקח 18 שניות. עכשיו בואו נסבך קצת את הסיפור - ונניח שאנשים חדשים כל הזמן מזמינים את המעלית בקומות העליונות. אפשר לעדכן את הלולאה כך:
loop do
  tick

ToCode
1 420
# מיתוסים על קוד ישן בכל מערכת יש את החלקים "הישנים", הקוד שאף אחד לא נוגע בו, שאף אחד לא כתב אותו ושאין עליו בדיקות כי "כתבו אותו לפני שכתבנו פה בדיקות". אנחנו אוהבים לחשוב כל מיני דברים על אותו קוד ישן, מיתוסים כמו- 1. הקוד הישן מכוער ולא גמיש. 2. אסור לגעת בקוד הישן כי כל המערכת תישבר. אם צריך לשנות משהו עדיף לעטוף את הקוד הישן בקוד חדש וטוב יותר. 3. בקוד הישן אין באגים כי כולם כבר תוקנו. 4. כל בעיות האבטחה של המערכת הן בגלל הקוד הישן. 5. הקוד הישן הוא הגורם העיקרי לאיטיות. 6. בשביל לתקן באג בקוד הישן צריך למחוק את כולו ולכתוב הכל מחדש. 7. הקוד הישן הוא הנשק הסודי שלנו, הוא כולל טיפול באינסוף מקרי קצה ובזכותו אף אחד אחר לא יוכל להקים מערכת מתחרה. שווה לזכור שקוד ישן הוא בסך הכל קוד ישן. כל מאפיין אחר שלו הוא נקודתי, יכול להיות שהוא טוב ויכול להיות שהוא גרוע; יכול להיות שיש בו יותר באגים ואולי יש בו פחות. בעבודה על קוד ישן כדאי להצטייד באותה סקרנות וביקורתיות שאנחנו שומרים לקוד חדש או לפרויקט חדש. גם מקוד ישן יש הרבה טריקים ללמוד ולפעמים אפילו יותר מעניינים.