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

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

לא צריך קורס

04/06/2020

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

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

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

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

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

אבל קורס יכול (וצריך) להיות הזדמנות:

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

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

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

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

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

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

רישום לקורס פייתון במסלול בוטקמפ בפיג'מה

רישום לקורס ריאקט במסלול בוטקמפ בפיג'מה

תחליף פשוט ל create-react-app

03/06/2020

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

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

בניגוד ל create-react-app הוא לא מבטיח לכם פרויקט עם כל התוספים וכל הספריות מחוברות במקום אלא בדיוק להיפך. אתם תקבלו קומפוננטה קטנה (ב JavaScript או ב TypeScript) ותמשיכו לבד. בדיקות? הצחקתם אותו. סרביס וורקר? למי יש כח לזה. טמפלייטס מורכבים עם Redux או MobX? עזבו, תכתבו לבד.

ועכשיו רק נשאר להבין: אם כל מה שצריך זה לשים כמה קבצים בתיקיה, בשביל מה היינו צריכים את הכלי הזה מלכתחילה?

ארבעה טיפים להעברת ביקורת יעילה יותר ב Code Review הבא שלכם

02/06/2020

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

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

המשך קריאה

מה יש לך נגד for...in

01/06/2020

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

בדוגמא מעשית נניח שיש לנו אוביקט שמחזיק כתובות מייל של משתמשים:

const email = {
    bob: 'bob@gmail.com',
    jane: 'jane@gmail.com',
    dave: 'dave@hotmail.com',
};

אז נוכל להשתמש בלולאת for...in כדי להדפיס את כל האנשים שיש להם כתובת מייל בג'ימייל:

for (let name in email) {
    const address = email[name];
    if (address.endsWith('@gmail.com')) {
        console.log(name);
    }
}

אבל - לולאת for...in כוללת גם מוקש קטן. המפתחות שחוזרים הם לא רק המפתחות מהאוביקט שאתם סורקים, אלא גם המפתחות מכל ה Prototypes של אותו אוביקט. לכן הקוד הבא ידפיס 3:

let count = 0;
const one = { a: 10, b: 20 };
const two = Object.create(one);
two.c = 30;

for (let k in two) {
    // count the keys
    count ++;
}

console.log(count);

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

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

let count = 0;
const one = { a: 10, b: 20 };
const two = Object.create(one);
two.c = 30;

for (let k of Object.keys(two)) {
    // count the keys
    count ++;
}

console.log(count);

סיגנלים

31/05/2020

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

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

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

  1. שימוש במנגנונים ישנים וגרועים של JavaScript - נכון, כנראה יהיו מקומות שיפסלו אתכם כי כתבתם var במקום const בתרגיל הבית, אבל הרבה יותר סביר להיפסל על מנגנונים גרועים באמת. שימוש ב eval במקום ב JSON.parse למשל יהיה דגל אדום לרוב מתכנתי ה Front שאני מכיר. אותו דבר לגבי with או onclick בתור מאפיין של תגית HTML.

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

  3. ביצועי JavaScript זה לא משהו שהרבה אנשים מתרגשים ממנו, אלא אם כן ממש תעשו שטויות. לרוץ בלולאה על כל האלמנטים בעמוד במקום להשתמש ב querySelector ממוקד יותר למשל ירים הרבה גבות ואותו דבר לגבי הגדרה של יותר מדי Event Handler במקום להשתמש ב Delegation.

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

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

פרטים על המסלולים בקישורים-

קורס Python במסלול בוטקמפ בפיג'מה.

קורס React במסלול בוטקמפ בפיג'מה.

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

30/05/2020

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

״חוג כדורסל? כן רעיון טוב. אצטרף אחרי שאצליח לקלוע לסל״

ואפשר לראות את ההגיון, כי מי ירצה להצטרף לחוג ושכל האנשים מסביב יראו שאתה מפשל? מה כולם יחשבו?

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

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

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

למה לא כדאי להמשיך לעבוד על בראנצ' ישן (ומה לעשות במקום)

29/05/2020

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

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

% git log --oneline --graph
*   5dc5b62 (HEAD -> master) merged
|\
| * 9630f65 (funnytext) add answer
| * 862a455 add some funny text
* | c99a456 made some changes
|/
* 7042a02 initial commit

הענף funnytext כולל שני קומיטים שנוצרו מתוך 7042a02, וענף master כולל גם הוא שני קומיטים שיצאו מתוך 7042a02, הראשון קומיט רגיל והשני הוא Merge Commit. הקומיט השני הוא זה שמעניין אותנו.

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

*   f64231d (HEAD -> master) fixed conflicts
|\
| * ad878a8 (funnytext) FIXED joke
* |   5dc5b62 merged
|\ \
| |/
| * 9630f65 add answer
| * 862a455 add some funny text
* | c99a456 made some changes
|/
* 7042a02 initial commit

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

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

% git log --oneline --graph
*   5dc5b62 (HEAD -> master) merged
|\
| * 9630f65 (funnytext) add answer
| * 862a455 add some funny text
* | c99a456 made some changes
|/
* 7042a02 initial commit

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

% git switch funnytext
% git reset --hard master

וקיבלנו לוג הרבה יותר פשוט:

*   5dc5b62 (HEAD -> master, funnytext) merged
|\
| * 9630f65 add answer
| * 862a455 add some funny text
* | c99a456 made some changes
|/
* 7042a02 initial commit

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

יש טעויות ויש טעויות

28/05/2020

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

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

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

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

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

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

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

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

מסלול בוטקמפ בפיג'מה קורס ריאקט.

ומסלול בוטקמפ בפיג׳מה קורס פייתון.

שני המרכיבים של התמדה

27/05/2020

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

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

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

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

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

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

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

  3. פרילאנסרית שמתעקשת לא להקים אתר ולהמשיך לקבל עבודות דרך X-Place רואה את הבעיה (השכר הנמוך והלקוחות הבלתי נסבלים) אבל אולי לא מאמינה ביכולת שלה לבנות משהו שאנשים יחפשו ויגיעו אליו לבד.

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

היום למדתי: הפניות ונתיבים ב Apache

26/05/2020

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

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

אבל מה שיותר מעניין זה הפיסקה הבאה מתוך ההגדרות שהפתיעה לטובה:

<VirtualHost *:443>
    ServerName tocode.co.il
    Redirect permanent / http://www.tocode.co.il/
</VirtualHost>

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

אגב רק בשביל השוואה ב nginx אנחנו כן צריכים להיות יותר מפורשים ולספר שאנחנו רוצים את ההפניה מכל הנתיבים - כך בשביל לקבל את אותה התנהגות ב nginx היינו כותבים:

server {
    server_name tocode.co.il;
    return 301 $scheme://www.tocode.co.il$request_uri;
}

ורק בינינו - הגישה של nginx נראית לי הרבה יותר ברורה (ולא בפעם הראשונה).