ToCode
Ir al canal en Telegram
1 420
Suscriptores
Sin datos24 horas
+27 días
-230 días
Archivo de publicaciones
1 420
# יום 1 - מספיק Rust בשביל שנוכל לקודד
הי חברים,
גם בלוגרים צריכים לפעמים חופשות והבלוגר הזה אינו שונה. בזמן שהפוסט הזה מתפרסם אני מתפנן על מטוס בדרך לברצלונה (וכן מתפנן זו מילה גדולה כשנוסעים עם ילדים קטנים, אבל אפשר לחלום). ב-9 הימים הקרובים אנסה לשפר את הספרדית שלי ורוב הסיכויים שלא יהיה לי זמן לכתוב באותה תדירות שהתרגלנו. בשביל שלא תשתעממו בזמן שאני מטייל, אני משאיר לכם בפרסום אוטומטי מדריך לשפת Rust ב-9 חלקים: בחלק הראשון (זה שאתם קוראים עכשיו) נסגור כמה פינות בראסט, וב-8 הימים הבאים תקבלו כל יום תוכנית ראסט עם הסבר ותרגילי הרחבה. אם אתם בעניין של ללמוד שפה חדשה תוכלו לקבל את Rust בחשיפה קלה וידידותית. וכמובן אם ראסט לא באה לכם בטוב בדיוק עכשיו, תשמחו לדעת שבעוד 9 ימים נחזור לשיגרת הפירסומים הרגילה.
מוכנים? הדקו חגורות ומיד ממריאים.
## הפעלת קוד ראסט בענן
נקודת ההתחלה שלנו במסלול היא האתר Rust Playground שם נוכל לכתוב ולהפעיל קוד ראסט בענן בלי להתקין כלום על המחשב. אני נכנס לאתר ומוצא שם את התוכנית הבאה:
fn main() {
println!("Hello, world!");
}
לוחץ בצד שמאל למעלה על הכפתור האדום Run והתוכנית רצה בצד ימין. והנה אנחנו כבר רואים שבראסט המילה fn מגדירה פונקציה והמילה println! מדפיסה למסך. התחלה טובה.
נמשיך להגדיר קצת משתנים ולולאות עם התוכנית הקצת יותר מורכבת הבאה:
fn main() {
let mut x = 10;
let mut y = 20;
for i in 1..10 {
x += i;
y *= i;
}
println!("x = {}, y = {}", x, y);
}
והתוצאה אחרי run:
x = 55, y = 7257600
ולמדנו ש let mut מגדיר משתנה חדש (המילה mut היא קיצור של mutable, כי זה משתנה שאפשר לשנות את הערך שלו), ו for היא פקודת הלולאה.
מעניין לגלות שאם אני מנסה להעלות את המספרים, למשל שהלולאה תרוץ עד 100 במקום עד 10, התוכנית נכשלת עם השגיאה:
thread 'main' panicked at 'attempt to multiply with overflow', src/main.rs:7:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
בנוסף אם אני מנסה אחרי הגדרת המשתנה x לשנות את הערך שלו למחרוזת התוכנית אפילו לא רצה, ובמקום מדפיסה את השגיאה:
Compiling playground v0.0.1 (/playground)
error[E0308]: mismatched types
--> src/main.rs:5:9
|
2 | let mut x = 10;
| -- expected due to this value
...
5 | x = "hello";
| ^^^^^^^ expected integer, found `&str`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to previous error
ושתי הבעיות קשורות. למשתנים ב Rust יש טיפוס, ואם אנחנו מנסים לשים במשתנה משהו שלא מתאים לטיפוס שלו ראסט יכעס. לפעמים ראסט מצליח לזהות את הבעיה לפני ריצת התוכנית (בשלב הקומפילציה), ואז הוא יסרב להריץ את התוכנית. לפעמים, כמו בסיפור של הכפל, הניסיון לשים משהו שלא מתאים למשתנה קורה רק בזמן ריצה, ואז ראסט ירסק את התוכנית ויסרב להמשיך. בכל מקרה ראסט מאוד משתדל לא להגיע למצבים "מוזרים" - אם משהו לא מתאים בדיוק למה שהתכוונתם, התוכנית תתרסק.
טיפוס הנתונים שראסט לקח בתור ברירת מחדל למספרים נקרא i32. ה i הוא קיצור של המילה integer וזה מייצג מספר שלם, והמספר הוא הגודל שלו בביטים. יש גם i64 ו i8, וגם u32 למספר שהוא Unsigned ו f32 למספר עם נקודה עשרונית. ואנחנו יכולים לבחור טיפוסים אחרים בעזרת סימן נקודותיים אחרי שם המשתנה למשל:
let mut x: f32 = 10.0;
let mut y: f32 = 20.0;
אבל אז בשביל להוסיף מספר שלם למשתנה נצטרך להגיד ל Rust שאנחנו רוצים להסתכל על המספר בתור Floating Point Number בעזרת המילה השמורה as. התוכנית המלאה תהיה:
fn main() {
let mut x: f32 = 10.0;
let mut y: f32 = 20.0;
for i in 1..10 {
x += i as f32;
y *= i as f32;
}
println!("x = {}, y = {}", x, y);
}
## התקנה וכתיבת תוכנית ראשונה מקומית
מהר מאוד וגם למדריך הזה אנחנו נגלה שאנחנו מעדיפים לעבוד מקומית כדי שיהיה יותר קל לכתוב תוכניות שעובדות על קבצים, מתחברות לרשת או עושות כל מיני דברים מעניינים שתוכניות מחשב עושות.
ראסט מאוד ידידותית להתקנה ואתם יכולים למצוא הוראות למערכת ההפעלה שלכם בקישור:
https://www.rust-lang.org/tools/install1 420
# למה אנחנו לא בוחרים ב X
תחליפו X בכל שפה/פריימוורק/טכנולוגיה. הסיבות לא לבחור בה תמיד יהיו דומות:
1. אין לי שום בעיה ש X פותר (שנים אנשים כתבו jQuery בלי לדעת שיש להם בעיה. שנים אנשים המשיכו להשתמש ב SVN בלי לשים לב ש git היה משפר את המצב שלהם).
2. אני לא מאמין ש X יוכל לפתור לי את הבעיה.
3. הזמן שאשקיע בללמוד את X הופך את הפיתרון ללא רלוונטי (אני צריך עכשיו למצוא את הקבצים שאיבדתי בגלל SVN. אין לי חצי שנה ללמוד איך להשתמש ב git ולהזיז את כל הקוד מכאן לשם).
4. גם ל X יש בעיות. לעבור אליו זה בסך הכל להחליף בעיה אחת באחרת. אני מעדיף להישאר עם הבעיות שאני מכיר.
5. אני לא מכיר אף אחד שמשתמש ב X (או: המערכת שלי שונה מכל המערכות שבונים אנשים שמשתמשים ב X).
כשאתם מנסים להכניס טכנולוגיה חדשה למקום עבודה והחברים מסביב נרתעים, נסו להבין מאיפה מגיע הפחד. מה הדברים שהחברים מסביב פוחדים לאבד או מה מקור חוסר האמון. הדבר החשוב הוא לבנות מנגנונים שמאפשרים לקבוצה שלכם לנסות כל הזמן טכנולוגיות ושיטות עבודה חדשות בלי לשבור את מה שקיים (או לפחות בלי לשבור יותר מדי). וכן כדאי לזכור ולהזכיר שכמעט תמיד צריך לשבור קצת ממה שקיים בשביל להתקדם. גיט מאפשר ליותר מפתחים לעבוד מהר יותר בתיאום על פרויקט בהשוואה ל svn. ריאקט מאפשר פיתוח יישומים בצורה מהירה יותר ועם פחות באגים בהשוואה ל jQuery ולרובנו יהיה יותר קל לתחזק סקריפטים ב Python בהשוואה לסקריפטים ב perl.
1 420
# לקחים מהחלפת כמה עשרות סיסמאות (ועוד מחשבות על הפירצה האחרונה ל lastpass)
הפריצה ל lastpass באוגוסט האחרון מתגלה כאירוע אבטחת מידע מאוד משמעותי עבור חברה שאמורה לשמור על הסיסמאות שלנו. לפי המייל האחרון שהם שלחו, הם גילו שהתוקפים השיגו גישה לכל קבצי הסיסמאות של כולם וגם לפרטים אישיים רבים. לכאורה, קבצי הסיסמאות מוצפנים ופריצת Brute Force שלהם היא בלתי אפשרית; בפועל מרגע שקבצי סיסמאות מוצפנים מגיעים לידיים עוינות קשה לדעת מה יקרה. סיסמאות חלשות בטח ייפרצו בקלות, יש סיכוי לא מבוטל שהתוקפים יודעים משהו שאנחנו לא יודעים שיאפשר להם להגיע לסיסמאות בעלות ערך, והנתונים האישיים שנגנבו בטח ישמשו ליצירת מתקפות פישינג שיעזרו לתוקפים להשיג סיסמאות נוספות.
כמו משתמשי lastpass רבים, אחרי קבלת המייל הלכתי להחליף סיסמאות למספר אתרים חשובים מתוך הנחה שאי אפשר לדעת כמה זמן הסיסמאות המוצפנות יישארו סודיות. הנה כמה לקחים מרכזיים מהסיבוב:
## איך מחליפים סיסמאות באתרים
1. ה Flow שהיה לי הכי נוח היה אתרים שדורשים את הסיסמה הנוכחית, מבקשים פעמיים את הסיסמה החדשה (הכל באותו טופס), ובסיום התהליך שולחים מייל שהסיסמה אופסה.
2. אתרים מסוימים מחביאים את מסך שינוי הסיסמה בתוך אינסוף מסכי הגדרות. מצאתי את עצמי כמה פעמים מחפש בגוגל שם של אתר ואחריו את הביטוי Change Password כדי להגיע לעמוד הנכון. זה עבד כי אתרים גדולים מחזיקים דפי עזרה עם הוראות ולינקים איך לאפס את הסיסמה, למשל הקישור הזה שמסביר איך לשנות סיסמה בפייפאל.
3. רוב האתרים מאפשרים שני מנגנונים לשינוי סיסמה: אם אתם מחוברים תוכלו להיכנס למסך "פרטי חשבון" ולחפש שם את הגדרת הסיסמה, ואם אתם לא מחוברים תוכלו ללחוץ על קישור "שכחתי סיסמה" כדי לקבל מייל עם קישור לאיפוס סיסמה. יש אתרים שמחברים את שני המנגנונים וגם מתוך האתר הם מוותרים על הטופס ופשוט שולחים מייל עם הוראות לאיפוס הסיסמה, ובאתרים מסוימים רק אחד המנגנונים עבד. אלה מכם שבונים מערכות - תהיו אדיבים עם המשתמשים ותוודאו ששני המנגנונים אצלכם עובדים.
4. יש אתרים שניצלו את ההזדמנות שרציתי להחליף סיסמה ודרשו ממני לעדכן פרטים אישיים "על הדרך". למרות שאני מבין את הצורך לעדכן את הפרטים, כדאי לזכור שכשמישהו כבר מגיע להחליף סיסמה הוא מעדיף לסיים עם זה מהר ולהמשיך להחליף סיסמאות בעוד אתרים. אם חסרים לכם פרטים עדיף לשלוח מייל ולבקש להזין אותם בתהליך נפרד.
5. יש אתרים שלא ביקשו את הסיסמה הנוכחית בשביל לשנות סיסמה. זה מסוכן כי אם אני נשאר Logged In לאותו אתר ומישהו אחר מתישב לי על המחשב לכמה דקות, אותו חבר יכול לשנות לי את הסיסמה בלי שאדע.
6. מדיניות חוזק הסיסמאות ברוב האתרים איפשרה לי לבחור כל סיסמה שרציתי. היו אתרים שדרשו ספציפית סיסמה של 8-10 אותיות (בלי לאפשר לי לבחור סיסמה יותר ארוכה) או כזאת שמורכבת גם מאותיות וגם ממספרים (בלי לאפשר לי להוסיף גם סימנים מיוחדים). רצוי לשים לב ביצירת מדיניות חוזק סיסמה תמיד לאפשר לאנשים לבחור סיסמה מאובטחת יותר ממה שאתם דורשים.
7. פריצות כמו זו מזכירות לנו כמה חשוב להשתמש ב 2FA, גם אם בשוטף זה לא הכי נוח, במיוחד לאתרים רגישים. נכון שהכל אפשר לפרוץ, אבל כל שכבה של הגנה נותנת לנו עוד זמן.
1 420
# אם הם רק היו עקביים...
בואו ניקח את Range כדוגמה. יש שפות בהן Range לא כולל את האיבר האחרון, כך בפייתון:
>>> 5 in range(0, 5)
False
ב JavaScript, עם lodash:
_.range(0, 5)
Array(5) [ 0, 1, 2, 3, 4 ]
ב Clojure:
user=> (range 0 5)
(0 1 2 3 4)
ב Rust:
for i in 0..5 {
print!("{}", i)
}
// prints: 01234
אבל אז יש את השפות בהן האיבר האחרון הוא כן חלק מ Range. למשל Elixir:
iex(2)> Enum.member?(0..5, 5)
true
או Bash:
$ echo {0..5}
0 1 2 3 4 5
ואז יש את רובי, שמציעה שתי דרכים ליצור Range:
3.1.1 :001 > (0..5).include?(5)
=> true
3.1.1 :002 > (0...5).include?(5)
=> false
לא משנה כמה שפות אנחנו מכירים, אי אפשר לברוח מלהכיר את המאפיינים הייחודיים של כל שפה. אין איזה מפעל מרכזי או תו תקן לשפות תכנות, וזה באמת יכול להרגיז לפעמים. כן כדאי לזכור איזה אופרטורים מתנהגים אחרת בין שפות, כדי שתוכלו לוודא בשפה הנוכחית שלכם איך זה עובד, ולזכור לא לבנות על זה כשעוברים לשפה אחרת.1 420
# מאחורי כל שאלת "איך"
מאחורי כל שאלת "איך" מתחבאת שאלת "למה", ובדרך כלל ה"למה" היא הרבה יותר מעניינת.
כך לדוגמה השאלה "איך לצאת מ vim" היתה אחת הפופולריות ב Stack Overflow, אבל מה שבאמת מעניין כאן הוא למה בכלל נכנסת ל vim אם אתה לא יודע איך לצאת ממנו. שם אנחנו נגלה את נפלאות משתנה הסביבה EDITOR, ונצלול לתקן הסטנדרטי של יוניקס כדי להבין למה כל התוכנות מפעילות דווקא את vim כשצריכות עורך טקסט.
האיך דחוף, אבל הלמה מלמד אותנו את כל הדברים המעניינים, ואת ה"למה" אנחנו נזכור הרבה אחרי שנתגבר על ה"איך". והרבה פעמים (במיוחד אם ה"איך"מאוד מסובך), אחרי שאנחנו מבינים את ה"למה" אנחנו מגלים שבכלל הסתכלנו על ה"איך" הלא נכון.
1 420
<iframe src="https://codesandbox.io/embed/heuristic-glade-7xprue?fontsize=14&hidenavigation=1&theme=dark"
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
title="heuristic-glade-7xprue"
allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
></iframe>
בגדול זה Store Enhancer שאפשר להוסיף לכל אפליקציית רידאקס קיימת ודואג לכל השכפולים בצורה אוטומטית. בשביל להשתמש בו השינוי היחיד שצריך בקוד הוא בקוד יצירת ה Store:
const store = configureStore({
reducer: rootReducer,
preloadedState: {
todos: [{ id: "ya", message: "yay", completed: false }]
},
enhancers: [multiUserEnhancer(["bob", "mike", "jane"])]
});
במקרה הזה ה preloadedState יועתק לכל המשתמשים, אבל אפשר לחשוב על מנגנונים יצירתיים יותר לבחור מי יקבל איזה סטייט ראשוני. אם לא מעבירים preloadedState כל ענף של משתמש מאותחל לפי ה Reducers שהוגדרו בפונקציית ה reducer הרגילה.
מה שאהבתי בכיוון הזה הוא שבאמת לא צריך לגעת בקוד של הקומפוננטות או ה Actions האסינכרוניים. כל מי שקורא ל getState אוטומטית מקבל את הסטייט של המשתמש הנוכחי, וכל Action אוטומטית מבוצע רק על הענף של המשתמש הנוכחי.
## איך מספר Stores יכולים לפתור לנו את הבעיה
כיוון אחר לגמרי והרבה יותר פשוט לאותה בעיה הוא לוותר על הרעיון של store יחיד. אם יהיה לי store נפרד לכל משתמש, אז "החלפת משתמש" זה בסך הכל להחליף את ה store הפעיל. אפשר לראות דוגמה לרעיון הזה כאן:
https://codesandbox.io/s/admiring-torvalds-e5lu0i?file=/src/index.tsx
או בהטמעה:
<iframe src="https://codesandbox.io/embed/admiring-torvalds-e5lu0i?fontsize=14&hidenavigation=1&theme=dark"
style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;"
title="admiring-torvalds-e5lu0i"
allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
></iframe>
עבודה עם Stores שונים נותנת לנו ניתוק מקסימלי בין החשבונות. במצב כזה באמת אי אפשר לדמיין Action שתשפיע על יותר מחשבון אחד או על שיתוף ענפים מסוימים בעץ בין החשבונות. מצד שני זה פיתרון הרבה יותר פשוט שלא דורש לשבור את רידאקס, וכנראה יכניס הרבה פחות באגים למערכת.1 420
# מעבר בין "חשבונות" באפליקציית Redux
אחד האתגרים בעבודה עם Redux הוא ניהול אוביקט המידע, במיוחד כשהמידע שאנחנו מנהלים לא ממש מסתדר טוב עם העקרונות של רידאקס, ובמיוחד אם אנחנו מדברים על שינוי מערכת קיימת. דוגמה? בואו. ניקח מערכת Todo פשוטה שצריכה להציג רשימת משימות, מאפשרת למשתמשים למחוק משימות ולעדכן שמשימות בוצעו. אפשר ליצור כזאת בשניה וחצי ב code sandbox עם הטמפלייט redux-toolkit-typescript. הנה קישור עם קוד לסקרנים:
https://codesandbox.io/s/eager-thompson-ijimne
## מה אנחנו בונים
ועכשיו נניח שאנחנו רוצים להוסיף תמיכה ב"חשבונות", כלומר נוסיף תיבה שבה אפשר לבחור באיזה "חשבון" אנחנו עובדים. נתחיל בחשבון שנקרא bob, ניצור כמה משימות, ואז נעבור לחשבון שנקרא mike וניצור שם כמה משימות חדשות, ובסוף נוכל לחזור ל bob ונסמן את המשימות כ"בוצעו".
למה זה קשה?
1. אוביקט ה State של היישום חייב להתאים לכל מה שאני רואה על המסך ולכל המידע שהמערכת מכירה, לכן מבנה אוביקט הסטייט צריך להכיל את כל המשתמשים ואת כל המידע שלהם. משהו כזה:
const state = {
bob: {
todos: [...],
},
mike: {
todos: [...],
},
jane: {
todos: [...],
},
};
2. אבל מבנה העבודה ה"רגיל" עם רידאקס לא מעודד שכפול מידע. ברידאקס קל מאוד לייצר Slice שמתאים ל todos עם כל המידע שלו והפעולות שלו, ולהפעיל את combineReducers כדי לחבר כמה סלייסים. לדוגמה:
const rootReducer = combineReducers({
todos: todos.reducer,
});
במקרה של משתמשים אני צריך לשכפל את ה Reducers, לייצר Slice לכל משתמש אבל הפעולות והמידע של כולם זהים. זה יצטרך להיות משהו כמו:
const rootReducer = combineReducers({
bob: combineReducers({ todos: todos.reducer }),
mike: combineReducers({ todos: todos.reducer }),
jane: combineReducers({ todos: todos.reducer }),
});
3. ואפילו אם הצלחנו לשרוד את הסיפור של ה Reducer, הצרה האמיתית תגיע בריאקט. כל קריאה ל useSelector תצטרך להתחיל בשליפת האוביקט של המשתמש המתאים, ובכל קריאה ל dispatch ה action שלנו יישלח לכל ה reducers, כולל לאלה שמתאימים למשתמשים האחרים. בלי טיפול מתאים, כל פעולה תשפיע על כל המשתמשים שמוגדרים באתר, במקום רק על המשתמש הפעיל.
## איך ארגון מחדש של הסטייט יכול לפתור לנו את הבעיה
פה יכול להיות שאתם חושבים - עזוב אותך משטויות, בוא פשוט נוסיף לכל "משימה" את שם המשתמש שמתאים לה. כלומר נלך על אוביקט מידע כזה:
const state = {
todos: [
{ id: 1, user: 'bob', message: 'hello world', completed: false },
],
};
ואז שינוי משתמש הוא בסך הכל "פילטר" על המשימות. בכל רגע נתון מציגים רק את המשימות שמתאימות למשתמש הנוכחי. אני אתכם כאן, ואני חושב שזאת גישה שבאמת יותר מתאימה לחשיבה ה Redux-ית. אם היא עובדת לכם זה מצוין, אבל צריך לזכור שבעבודה על קוד קיים שינוי מבנה ה State בצורה כזאת מחייב שינוי רוחבי בכל האפליקציה - כי עכשיו אחרי כל useSelector צריך לסנן רק את הערכים שרלוונטיים למשתמש הנוכחי. בנוסף, אם יש לי כבר באוביקט שדות שהם מחרוזות, מספרים או אוביקטים אני אצטרך לארגן מחדש את הנתונים בצורה שתחייב שינוי בכל הקוד שמשתמש בהם.
## איך Store Enhancer יכול לפתור לנו את הבעיה
כיוון אחר שאנחנו יכולים לקחת הוא לעדכן את ה Redux Store עצמו. כלומר להישאר עם אוביקט מידע שמכיל את כל הפרטים של כל המשתמשים בתור עץ:
const state = {
bob: {
todos: [...],
},
mike: {
todos: [...],
},
jane: {
todos: [...],
},
};
אבל לעדכן את ה Store כך שיהיה יותר קל לעבוד עם העץ הזה:
1. כל קריאה ל getState תחזיר את הסטייט שמתאים לחשבון ה"נוכחי".
2. כל קריאה ל dispatch תוסיף ל Action שדה meta, שיכיל את שם המשתמש ה"נוכחי".
3. לפני הכניסה ל reducer, נסתכל על שדה ה meta של ה action ונפעיל את ה reducer שנמצא בתוך הענף שמתאים לאותו משתמש (כדי לא לעדכן ענפים של משתמשים אחרים כשהם לא פעילים).
כתבתי מימוש ראשוני ומלא באגים לקונספט בקישור כאן:
https://codesandbox.io/s/heuristic-glade-7xprue?file=/src/store/store.ts
ובהטמעה:1 420
# קוד נכון
הרבה פעמים פיתרון נכון לבעיה לא יהיה יותר "מסובך" לכתיבה מפיתרון לא נכון. הוא לא ידרוש יותר שורות קוד או שימוש באיזו טכנולוגיה חדשה. למעשה הרבה פעמים הפיתרון הנכון דווקא יהיה יותר קצר, יותר פשוט, יותר מדויק, ו... עובד.
שתי דוגמאות מהימים האחרונים ואז שורה תחתונה-
1. פה באתר כפתור "אחורה" בדפדפן לא עבד בחלק מהדפים. הבאג נגרם בגלל השורה:
window.history.replaceState(null, null, url.toString());
בשביל לתקן בסך הכל היה צריך להחליף את השורה ל:
window.history.replaceState(window.history.state, null, url.toString());
כן יש פה כמה תווים יותר, אבל לא משהו שצריך לעשות ממנו עניין. הפער האמיתי היה חוסר ההיכרות עם המשמעות של הפרמטר הראשון לפונקציה replaceState.
2. בפרויקט אחר עזרתי ללקוח לשלב קוד ממערכת ישנה שלו במערכת חדשה. הקוד עבד אבל כל הזמן נתקלנו במקרי קצה ובאגים בגלל שהרבה מהאילוצים של המערכת החדשה היו שונים מאלה של הישנה. בסופו של דבר בניתי מחדש את המנגנון ספציפית למערכת החדשה. הקוד החדש הרבה יותר קצר וחיסל את כל הבאגים של האינטגרציה.
בשני המקרים (וברבים נוספים) לכתוב את הפיתרון הנכון אומר להשקיע יותר זמן בכתיבה - בשביל לסגור פערי ידע או בגלל בניה מחדש של יותר קוד - ולהרוויח לטווח הרחוק. אבל הבעיה היא שאנחנו לא יודעים מראש איזה חלק במערכת ידרוש יותר תחזוקה ויותר שינויים, ובאיזה חלקים כמעט לא נצטרך לגעת. לפתור הכל נכון מההתחלה אומר להשקיע בפיתוח הרבה יותר זמן מהדרוש, ולהסתכן בחריגה מהתקציב או מהזמנים.
הפיתרון לדעתי הוא לקבל את זה שיהיו באגים ושחלק לא מבוטל מהקוד שלנו לא יהיה הכי יעיל או נכון שהוא יכול להיות. אבל באותה נשימה גם לדעת לשים לב לתקן מנגנונים וארכיטקטורה כשאנחנו מזהים את המקומות במערכת שכן צריכים להשתנות. במקביל לעשות הכל כדי ללמוד כמה שיותר על הטכנולוגיות שאנחנו עובדים איתן, מתוך הבנה שככל שאני מכיר טוב יותר את הטכנולוגיה, כך יהיה לי קל יותר לכתוב פיתרונות נכונים כבר בניסיון הראשון.1 420
# ואיך זה ישפיע על הפיתוח בעתיד?
לפני בניית פיצ'ר חדש אנחנו אוהבים לשאול "כמה זמן זה ייקח" ולהתרגז כשהערכות הזמנות שמתכנתים נותנים לא מתממשות, אבל יש כמה שאלות הרבה יותר חשובות-
1. איך הפיצ'ר הזה משפיע על פיתוחים עתידיים? איפה הבחירה הזאת הולכת לעזור? ואיפה היא הולכת להזיק?
2. איזה בדיקות חדשות אצטרך להריץ בכל סבב?
3. מהם מקרי הקצה החדשים שאני צריך עכשיו לקחת בחשבון?
4. איך זה יישבר?
5. איזה פיצ'רים אחרים במערכת יושפעו?
להוסיף Cache למערכת יכול לקחת יום או יומיים עבודה, אבל תוספת הזמן והבאגים שה Cache הזה יביא בטווח הרחוק (בכל הפעמים שמשתמשים יקבלו מידע לא עדכני) הופכים את המשימה להרבה יותר יקרה ממה שנראית ממבט ראשון.
בחירה ב JavaScript במקום ב TypeScript נראית כמו רעיון טוב עכשיו, כי את JavaScript את כבר מכירה, אבל בעוד שנה כשתצטרכי לארגן מחדש קוד שאת לא זוכרת אולי דברים ייראו אחרת.
ואפילו שזה לא בעיה לתקן את הבדיקה האוטומטית ששוב נכשלה, אולי שווה לחשוב מחדש אם היא נחוצה בכלל ולמחוק אותה מהמערכת. כי שנינו יודעים שזאת לא תהיה הפעם האחרונה שהיא נשברת.
שינויים שמשפיעים לטובה על מהירות הפיתוח בעתיד הם שינויים ששווה להתאמץ בשבילם. גם אם היום הם דורשים למידה, ריפקטורינג או קבלת החלטות קשות.
1 420
# חדש באתר: קורס TypeScript
כמו הרבה טכנולוגיות, גם TypeScript לא היתה בשבילי אהבה ממבט ראשון. "מי צריך את זה?" שאלתי בזלזול, הרי אני אף פעם לא טועה בטיפוסים, וממילא באגים "אמיתיים" טייפסקריפט לא יצליח לתפוס. החשדנות שלי כלפי טייפסקריפט רק גברה ככל שהתחלתי לעבוד איתה - מצאתי את עצמי כותב הגדרות טיפוסים מסורבלות, ובטוח שטייפסקריפט הוא עוד מזימה שמטרתה לבזבז לי את הזמן במקום שאוכל להתקדם בקוד.
אחרי יותר משנתיים של עבודה בטייפסקריפט, אני מבין טוב את הטעות.
טייפסקריפט נכתבה כדי לתת למפתחים כלי עבודה טוב יותר לכתוב אפליקציות JavaScript. היא לא הולכת להפוך את JavaScript ל Java או ל C#, והיא לא הולכת להכניס שיטות עבודה "של אנשי בקאנד" לעולם הפרונט-אנד. היא בסך הכל נותנת לכם כלים טובים יותר לכתוב את ה JavaScript שאתם כבר מכירים, כדי שתוכלו לקודד מהר יותר ועם פחות הסחות דעת. אלה כמה מהפיצ'רים שלא חשבתי שאני בכלל צריך, אבל היום לא יכול בלעדיהם:
1. השלמה אוטומטית של import-ים, כך שאני לא צריך לעצור ולהיזכר מאיזה קובץ מגיעה כל פונקציה.
2. ריפקטורינג אוטומטי שאפשר לסמוך עליו, כך שאני לא צריך להיתקע עם שמות לא רלוונטיים לפונקציות או משתנים.
3. השלמה אוטומטית אפקטיבית, גם כשאני משתמש בספריית קוד חדשה שאני עדיין לא מכיר בעל פה את ה API שלה.
ואחרי שלמדתי לעבוד נכון עם טייפסקריפט, גיליתי שה"מס" שאני משלם - כלומר כתיבת הגדרות הטיפוסים - הוא כמעט אפס. בעבודה נכונה, ובשימוש נכון ביכולות של טייפסקריפט, הטיפוסים כמעט כותבים את עצמם.
בקורס ריכזתי מסקנות משנתיים של עבודה עם טייפסקריפט, גם על פרויקטים שהצליחו וגם על פרויקטים שהסתבכו. בניגוד לתיעוד, שפשוט מראה לכם מה אפשר לעשות עם השפה, אני לקחתי כל יכולת לתוך Context של דוגמה או דוגמאות ספציפיות, שמראות איך ובאיזה מצבים היכולת הזאת תעזור לנו ואיזה בעיות כל פיצ'ר בא לפתור.
בין אם אתם צריכים להיכנס לפרויקט טייפסקריפט וחוששים לעשות טעויות, או אם אתם כבר עובדים בטייפסקריפט ומרגישים שהשפה לא נותנת לכם ערך מספיק גבוה, או אפילו אם אתם כבר אוהבים טייפסקריפט ורוצים לראות איך להשתמש בה בצורה יותר יעילה - הקורס הזה בשבילכם. זה הלינק עם סילבוס מלא, כל הפרטים וכמובן אם אתם מנויים יכולים ומוזמנים להתחיל לצפות כבר היום:
https://www.tocode.co.il/bundles/typescript
¡Ya disponible! Investigación de Telegram 2025 — los principales insights del año 
