ToCode
الذهاب إلى القناة على Telegram
1 419
المشتركون
-124 ساعات
لا توجد بيانات7 أيام
-230 أيام
أرشيف المشاركات
1 419
# מכשולים לעבודת צוות
רשימה חלקית של דברים שגורמים לצוות שלכם לא לעבוד מספיק טוב יחד:
1. יעד לא ברור או לא ברור מספיק
2. כללי התנהגות לא ברורים או לא ברורים מספיק
3. תחרות לא בריאה, מדידת הישגים אישיים במקום קבוצתיים (לדוגמה צוות שמודד לכל מתכנת כמה באגים הוא סגר ביום, וכך מעודד אנשים "לסגור" באגים מהר על חשבון באגים אחרים שנוצרים)
4. חוסר ביטחון, כשכל אחד חושש על המקום שלו
5. כשמנהלים או מובילים טכניים לא מוכנים לקחת אחריות על החלטות (לדוגמה מובילה טכנית שתתאמץ לקבל הסכמה של כל הצוות לפני שתחליט על שיטת עבודה חדשה).
תיקון המכשולים האלה יעזור הרבה יותר מאשר עוד אפליקציית תקשורת ארגונית, לא משנה כמה טרנדית.
1 419
# טיפ גיט: איך לאחד מספר מאגרים למונוריפו
אחד הדברים האהובים עליי בגיט הוא שאפשר תמיד לשנות את דעתך. בדוגמה היום בואו נראה מה עושים כשיש לנו מספר פרויקטים ששמורים במספר מאגרים, ואנחנו רוצים לחבר אותם למונוריפו אחד כך שכל פרויקט ישב בתיקיה משלו במונוריפו.
## מה לא כדאי לעשות
נפתח תיקיה חדשה ונשכפל לתוכה שני פרויקטים בשביל הדוגמה:
$ git clone https://github.com/sindresorhus/awesome.git
$ git clone https://github.com/ossu/computer-science.git
עכשיו ניצור תיקיית monorepo חדשה:
$ mdkir monorepo
ובתוכה ניצור את המונוריפו שלנו בתור מאגר גיט:
$ cd monorepo
$ git init .
עכשיו אנחנו יכולים פשוט להעתיק את הקבצים מכל אחד משני המאגרים וליצור קומיט ראשון במונוריפו. זה יעבוד:
$ cp -R ../awesome .
$ rm -rf ./awesome/.git
$ cp -R ../computer-science .
$ rm -rf ./computer-science/.git
$ git add .
$ git commit -m 'initial monorepo commit'
אבל הבעיה היא שאנחנו מאבדים את כל ההיסטוריה של שני המאגרים.
## איך לאחד ולשמור את ההיסטוריה
פיתרון טוב יותר ישתמש בכלי שנקרא filter-repo ובמנגנון ה merge של גיט.
נמחק את תיקיית monorepo שיצרנו וניצור חדשה במקומה:
$ rm -rf monorepo
$ mkdir monorepo
עכשיו צעד ראשון הוא להכין את שני המאגרים שאנחנו רוצים לשלב. כרגע הקבצים בכל אחד מהם נמצאים בתיקיה הראשית שלו, וההיסטוריה שמורה לפי הנתיב הראשי. אנחנו רוצים לעשות כאילו מאז ומעולם כל מאגר שמר את כל הקבצים שלו בתוך תת-תיקיה ששמה כשם המאגר. אחרי התקנת filter-repo אני נכנס למאגר הראשון ומפעיל בתוכו את הכלי:
$ cd ../awesome
$ git filter-repo --to-subdirectory-filter awesome
זה יוצר תיקיה חדשה בשם awesome, שם את כל הקבצים של הפרויקט בתוך אותה תיקיה ומשנה את ההיסטוריה כדי שהכל יראה כאילו מאז ומעולם המאגר היה מורכב מתיקיה בשם awesome ובתוכה כל הקבצים.
את אותו דבר אני עושה על המאגר השני:
$ cd ../computer-science
$ git filter-repo --to-subdirectory-filter computer-science
ועכשיו אני ממשיך ל monorepo כדי לאחד את שניהם. הטריק הוא שבגלל שכל פרויקט מנוהל בתיקיה משלו, אני יכול להוסיף כל אחד מהם בתור remote ל monorepo, ואז להפעיל merge:
$ cd ../monorepo
$ git init .
$ git remote add awesome ../awesome
$ git remote add computer-science ../computer-science
$ git fetch --all
$ git merge --allow-unrelated-histories awesome/main
$ git merge --allow-unrelated-histories computer-science/master
וזה כל הסיפור. עכשיו ב monorepo יש את שתי תתי התיקיות awesome ו computer-science, את כל הקומיטים של שני הפרויקטים, ואני יכול להפעיל log על כל אחת מתתי התיקיות כדי לראות רק את הקומיטים מאותו פרויקט.1 419
# הרגע שכולם עוזבים
המשימה התכנותית הראשונה בקורסרה
חדר כושר, חודשיים אחרי הרישום
בלוג, אחרי השמונה פוסטים הראשונים
תואר ראשון, אחרי המבחנים של שנה א
פיתוח מוצר תוכנה, אחרי שהוא באוויר ואף אחד לא נרשם
הרגע שכולם עוזבים הוא חלק מהמסלול. הוא חייב להגיע כי רוב האנשים לא מסיימים את המסלול שבו בחרת ללכת, והוא בדיוק מה שהופך את המסלול לכזה שרצית ללכת בו. הרגע שכולם עוזבים הוא הרגע לצלול פנימה ולהבין מה עשו אלה שכן נשארו ואיך לעשות כמוהם. וכן הרגע שכולם עוזבים הוא הסימן הראשון שאתה בכיוון הנכון.
1 419
# מי מתאמץ יותר?
אם אני ויוסיין בולט נצא לתחרות ריצה, די ברור מי יהיה המנצח, ומי יהיה זה שיתאמץ יותר (רמז: זה לא אותו אחד).
העבודה הקשה היא לא ביום התחרות, או בלילה הלבן שלפני הדמו. וכן ברור שמאמץ נותן הרגשה טובה ולילות לבנים לפני דמו מגבשים את הצוות. אבל אם מה שמעניין אותנו זה בניה מהירה של מערכות עדיף להשקיע בתשתיות.
אצל אצנים אלה שרירים חזקים יותר; אנחנו נתאמץ לבנות קוד יותר פשוט, רכיבי תשתית יציבים, בדיקות אמינות, וכל שאר הדברים שהופכים את הפיתוח למקצועי. מערכות אמיתיות לא נבנות בלילה לבן או אפילו בסופשבוע.
1 419
# טיפ ריילס: שתי דרכים ליצור פחות מיגרציות
אחד הדברים הראשונים שאנחנו לומדים בעבודה עם ריילס הוא ליצור מיגרציות. מיגרציה היא בעצם קוד שמשנה משהו בבסיס הנתונים, למשל יוצר טבלה או משנה עמודות בטבלה. הנה דוגמה לקוד של מיגרציה:
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.string :name
t.text :description
t.timestamps
end
end
end
שורת הפקודה של ריילס מאפשרת להריץ מיגרציות עם הפקודה:
$ ./bin/rails db:migrate
להרצת מיגרציה יש מספר השלכות:
1. קודם כל מיגרציה משנה משהו בבסיס הנתונים. בשביל זה כתבנו אותה.
2. בנוסף, ריילס שומר בבסיס הנתונים את המזהה של המיגרציה האחרונה שהוא הריץ, כדי שהוא יידע להריץ רק מיגרציות חדשות כל הפעלה של db:migrate.
3. בנוסף, ריילס שומר קובץ בשם db/schema.rb שבו הוא מחזיק את ״התוצאות״ של כל המיגרציות, כלומר סוג של תמונה של בסיס הנתונים.
לכן אם הרצנו מיגרציה שיש בה טעות לא יעזור לנו לחזור לקובץ, לעדכן אותו ואז להפעיל שוב db:migrate. ריילס לא יריץ את הקובץ הזה שוב כי בבסיס הנתונים מסומן לו שהקובץ כבר הורץ.
תוצאה עצובה של ההתנהגות הזאת יכולה להיות תיקיית מיגרציות עמוסה, אפילו בפרויקטים חדשים או שעוד לא עלו לפרודקשן. זה קורה כי מתכנתים לא יודעים איך לבטל מיגרציה שהריצו ולכן יוצרים מיגרציות חדשות עם התיקונים. בדוגמה שהדבקתי קודם, אם אני מגלה בזמן פיתוח שחסרה לי עמודה בטבלת המוצרים אחרי שכבר הרצתי db:migrate אני עלול להיבהל וליצור מיגרציה חדשה שתוסיף את העמודה.
שני רעיונות יותר טובים שיעזרו לכם לשמור את תיקיית המיגרציות קטנה לפחות כשהפרויקט בתחילת הדרך-
1. הכי קל אם זו מיגרציה יחסית עדכנית להפעיל:
$ ./bin/rails db:rollback
הפקודה הזאת מבטלת את הרצת המיגרציה האחרונה, ואז אפשר לשנות את הקוד שלה ולהפעיל db:migrate מחדש.
2. אם צריך לשנות משהו רוחבי בהרבה טבלאות או הרבה קבצי מיגרציה, אפשר ללכת בכיוון אחר ופשוט לזרוק את כל בסיס הנתונים. כל עוד לא עלינו לפרודקשן וממילא אנחנו בפיתוח נוכל להפעיל:
$ ./bin/rails db:drop
לשנות את כל קבצי המיגרציה שיתאימו למה שאנחנו צריכים ואז להפעיל מחדש:
$ ./bin/rails db:migrate
$ ./bin/rails db:seed
שימו לב שהפעלת db:migrate מעדכנת את הקובץ db/schema.rb, וקובץ זה משפיע על הפקודה db:reset. לכן אין טעם לשנות קובץ מיגרציה ולהפעיל אחרי זה ./bin/rails db:reset. פעולה כזאת פשוט תיצור את בסיס הנתונים מחדש באותו מבנה שהוא היה קודם. אחרי שמשנים קובץ מיגרציה חייבים להפעיל מחדש db:migrate כדי לשנות גם את db/schema.rb.
בעבודה עם db:rollback ו db:drop אנחנו יכולים לבנות כמעט את כל הגירסה הראשונה של הפרויקט עם תיקיית מיגרציות יחסית קטנה. אחרי העלייה לפרודקשן החיים הופכים יותר מסובכים וכמובן שלא כדאי לשנות קבצי migration שכבר הרצתם על בסיס הנתונים האמיתי.1 419
# איך לזהות פעלים בטקסט עם nltk ו Python
בשפת פייתון ספריית nltk כוללת אינסוף יכולות לעבודה עם טקסטים ולכן כשרציתי לקחת טקסט ולמצוא בו את הפעלים זו היתה נקודת ההתחלה. הנה מה שיצא-
## התקנת הכלים
בשביל להתחיל לעבוד עם nltk אנחנו צריכים רק להתקין את הספריה:
pip install nltk
הבעיה עם nltk היא שהמודול לא כולל הרבה קבצי data שהוא צריך בשביל לעבוד, לכן אחרי שנכתוב את התוכנית וננסה להפעיל נקבל כל מיני הודעות כמו:
LookupError: [11/35]
**********************************************************************
Resource averaged_perceptron_tagger not found.
Please use the NLTK Downloader to obtain the resource:
>>> import nltk
>>> nltk.download('averaged_perceptron_tagger')
For more information see: https://www.nltk.org/data.html
Attempted to load taggers/averaged_perceptron_tagger/averaged_perceptron_tagger.pickle
כשזה קורה אנחנו כותבים משורת הפקודה python נכנסים ל repl וכותבים את שתי הפקודות שהוא הציע, בהודעה שהדבקתי זה:
import nltk
nltk.download('averaged_perceptron_tagger')
זה יקרה כמה פעמים עם קבצים שונים אבל בסוף התוכנית תרוץ.
## ועכשיו לקוד
אוקיי אז אנחנו יודעים מה צריך לעשות בשביל להתחיל לעבוד עכשיו בואו נראה איך nltk עוזרת לנו למצוא פעלים בטקסט. אני משתמש ב 3 רכיבים של nltk:
1. הרכיב word_tokenize שלוקח טקסט ומפרק אותו למילים.
2. הרכיב pos_tag שלוקח רשימה של מילים ומסמן לנו מה התפקיד של כל מילה.
3. הרכיב WordNetLemmatizer שלוקח מילה ומחזיר את צורת הבסיס שלה. אנחנו נשתמש בו כדי לקבל את צורת הבסיס של הפועל (בלי הטיה).
מבחינת סימונים הפונקציה pos_tag לוקחת רשימה של מילים ומחזירה רשימה של Tuples. הפריט הראשון ב tuple הוא המילה, והפריט השני הוא התפקיד שלה במשפט. התפקידים שמתחילים ב V מציינים פעלים.
קוד? קבלו:
from nltk.tokenize import word_tokenize
from nltk import pos_tag
from nltk.stem.wordnet import WordNetLemmatizer
import re
lemmatizer = WordNetLemmatizer()
text =word_tokenize("To Sherlock Holmes she is always the woman. I have seldom heard him mention her under any other name. In his eyes she eclipses and predominates the whole of her sex. It was not that he felt any emotion akin to love for Irene Adler. All emotions, and that one particularly, were abhorrent to his cold, precise but admirably balanced mind. He was, I take it, the most perfect reasoning and observing machine that the world has seen, but as a lover he would have placed himself in a false position. He never spoke of the softer passions, save with a gibe and a sneer. They were admirable things for the observer—excellent for drawing the veil from men’s motives and actions. But for the trained reasoner to admit such intrusions into his own delicate and finely adjusted temperament was to introduce a distracting factor which might throw a doubt upon all his mental results. Grit in a sensitive instrument, or a crack in one of his own high-power lenses, would not be more disturbing than a strong emotion in a nature such as his. And yet there was but one woman to him, and that woman was the late Irene Adler, of dubious and questionable memory.")
tokens_tag = pos_tag(text)
only_verbs = set([lemmatizer.lemmatize(w[0], 'v') for w in tokens_tag if w[1].startswith('V') and re.search(r'^\w+$', w[0])])
print("Verbs:", only_verbs)
והתוצאה:
After Token: {'adjust', 'predominate', 'have', 'take', 'see', 'observe', 'eclipse', 'save', 'place', 'seldom', 'speak', 'mention', 'balance', 'felt', 'love', 'be', 'admit', 'draw', 'introduce', 'throw'}
סך הכל עבודה לא רעה, חוץ מ seldom שלא ברור איך הסתנן לשם.1 419
# הנדסת יתר
הנדסת יתר, או בשמה הלועזי Over Engineering, תמיד תקרה כשאנחנו כותבים מערכת בטכנולוגיה שאנחנו לא מכירים מספיק. זה פשוט כי לוקח כמה ניסיונות עד שמבינים מה הדרך הכי מדויקת להגיע לפיתרון, ובטכנולוגיה שנאחנו לא מספיק מכירים אנחנו נמצאים בניסיון הראשון.
וככה אנחנו מקבלים אתרים שכתובים בריאקט, כש HTML פשוט עם קצת JavaScript היה מספיק טוב; מערכות ענן שהיו עובדות הרבה יותר טוב על VPS פשוט או קוד עם כל כך הרבה Design Patterns שאפשר היה לכתוב ממנו ספר.
הבעיה עם Over Engineering היא שהעלות ממשיכה ללוות אותנו בכל שלב בדרך. זה לא שפעם אחת בהתחלה השקעתי יותר מדי ובניתי פיתרון מתוחכם ועכשיו הרווחתי וכל פיתוח עתידי יהיה יותר קל, אלא ממש להיפך - השקעתי בהתחלה בבניית פיתרון יותר מדי מתוחכם, ועכשיו:
1. הרבה יותר קשה לי לשנות את הקוד, בלי לשבור את התבנית המתוחכמת שבניתי בהתחלה.
2. אני צריך להשקיע הרבה יותר זמן בשידרוג תלויות או עדכונים אחרים, רק כדי לעמוד בקצב של כל הספריות שהכנסתי.
3. מתכנתים חדשים שייכנסו לפרויקט יצטרכו לעבור מסע ייסורים עד שיצליחו לתרום קוד, כי קשה מאוד להבין את הפיתרון המהונדס להפליא שבניתי.
4. בניית פיתרון מתוחכם שלא לצורך, בטכנולוגיה שאני לא מספיק מכיר, מייצרת יותר באגים מוזרים, שימשיכו ללוות אותי לנצח.
שתי דוגמאות כאן מטוקוד - כמו שאולי אתם יודעים האתר הזה בנוי בריאקט עם React Router כדי לתת חווית Single Page Application. זה היה נראה כמו רעיון טוב לפני 5 שנים כשלא ידעתי הרבה על בניית אתרים, אבל היום אני כבר יודע לראות שזו היתה הנדסת יתר. בימים אלה אני עובד על גירסה חדשה של האתר, פשוטה בהרבה ובלי פריימוורקים, שנותנת חוויה טובה יותר ותחזוקה הרבה יותר קלה.
דוגמה שניה היא הבוט טלגרם שכתבתי פעם באליקסיר, ולא מזמן החלפתי בכמה עשרות שורות פייתון. קוד הפייתון מצליח לעשות בדיוק את אותו דבר שהאליקסיר עשה, ובזכות הקוד הפשוט יותר אני יכול להפעיל אותו ב Github Action ולא צריך לדאוג לשרת, מערכת הפעלה וגירסה של אליקסיר. אותה חוויה עם הרבה פחות תחזוקה.
אי אפשר לברוח מהנדסת יתר בתחילת הפרויקט. אפשר ורצוי להנדס את הדרך לפיתרון פשוט יותר ככל שלומדים יותר על הבעיה והטכנולוגיה.
1 419
# רק פוסטים טובים
אני חולם לפעמים לכתוב רק פוסטים טובים. שכל פוסט יהיה פצצה ויקבל אלפי שיתופים, שכל מי שקורא או קוראת אותו פתאום ירגיש מואר ומלא מוטיבציה. ומה בעצם הבעיה? הרי לכתוב פוסט טוב ולכתוב פוסט רע לוקח בדיוק אותו זמן. אם ממילא אני יושב לכתוב כל יום, לא עדיף לכתוב רק את הטובים? בשביל מה לבזבז זמן על פוסט שאף אחד לא יקרא?
כשאנחנו חושבים על הצלחות אני בטוח שלכל אחד יש מטרות שונות- אולי את רוצה לפתח כלי עבודה ותהליכי עבודה טובים יותר לצוות, כדי להפסיק לכבות שריפות כל היום; אולי אתה רוצה למצוא עבודה חדשה במשכורת גבוהה יותר ובתנאים יותר טובים; אולי את חולמת שפרויקט הצד שבנית יתחיל להכניס כסף ותוכלי לעזוב את העבודה ולהשקיע רק בו.
כל אחד מהחלומות האלה דורש השקעה ומוטיבציה וזמן ויותר מהכל הרבה זמן מיותר. הרבה זמן שבו תכתבי כלים שאף אחד בצוות לא ירצה להשתמש, ותחטפי על הראש כי עדיף להשקיע את הזמן בלתקן באגים. הרבה זמן שבו תלמד ותתכונן לראיונות ובסוף לא תתקבל ותצטרך ללמוד נושאים חדשים לקראת הראיון הבא. הרבה זמן שיושקע בפרויקט הצד שתצטרכי לזרוק עד שתגיעי בסוף לרעיון שכן יצליח.
קל לראות למה אנחנו מתפתים להפסיק ללכת לראיונות כי "אני לא מתקבל לשום מקום"; להפסיק לכתוב כלים כי "אף אחד פה לא באמת רוצה לשפר"; להפסיק לבנות פרויקטי צד כי "אני לא מספיק טובה בשביל לבנות משהו רציני" או להפסיק לכתוב כי "אני לא כותב מספיק טוב". כבני אדם אנחנו רוצים להשתייך, רוצים לקבל משוב חיובי, רוצים להצליח. התחושה הכי טבעית בעולם היא להפסיק כי זה פשוט לא הולך.
ולמרות שביום רגיל אני תמיד בעד להקשיב לרגשות, בסיפור הזה הרגש לא עוזר. במקום זה, שווה לנסות להוסיף את המילה "עדיין":
- אני עדיין לא כותב מספיק טוב, וזה בסדר להמשיך לעשות דברים שאני עדיין לא מספיק טוב בהם.
- אני עדיין לא עובר ראיונות, וזה בסדר להמשיך להתכונן וללכת גם אם בסוף לא אחליף עבודה. ללימוד עצמו גם יש ערך.
- אני עדיין לא מספיק טובה בשביל לבנות ולשווק פרויקט צד רציני. וזה בסדר להמשיך לכתוב פרויקטי צד גם אם הם לעולם לא ירוויחו כסף. העבודה עליהם מעשירה אותי ומשמחת אותי.
- אני עדיין לא הצלחתי להטמיע את תהליכי העבודה שרציתי בצוות, וזה בסדר להמשיך לנסות גם אם הבוס לא אוהב את זה. אני מעדיף להיות הבן אדם ששואף למצוינות מאשר עוד בורג במערכת.
"רק פוסטים טובים" זה חלום יפה, אבל לא יעד מעניין במיוחד. כשהכל מצליח זה בסך הכל אומר שאתה לא מנסה דברים מספיק מעניינים.
1 419
# ההבדל בין ה"מה" ל"איך"
כמתכנתים אנחנו תמיד ממהרים לבנות את הדבר הגדול הבא וכמעט תמיד מחפשים את ה"איך" - איך להוסיף OAuth ליישום שלי? איך להעתיק קבצים מבראנץ אחד לשני? איך להתחבר לבסיס נתונים ולהריץ שאילתה.
מה שמפתה ב"איך" זה שאפשר לקבל תשובה קצרה ובסופה להרגיש שהתקדמנו: הוספנו מנגנון זיהוי משתמשים ליישום, סידרנו את הבראנצ'ים, קיבלנו תשובה מבסיס הנתונים. ל"מה" אין את הקסם הזה.
ועדיין קשה להתעלם מהחשיבות של "מה" - מה זה בעצם OAuth והאם אני בכלל צריך אותו? איזה Grant Types קיימים? ואיזה מהם אני צריך? מה זה בראנץ ומה זה בכלל אומר להעתיק קובץ מבראנץ אחד לשני? איזה בסיס נתונים יעבוד הכי טוב עם המערכת שלי ועם עולם התוכן שאני צריך לשמור?
ל"מה" אין תשובה קלה, אבל היכרות טובה עם ה"מה" יכולה לחסוך הרבה עבודה מיותרת וצרות בעתיד, ובנוסף היא המפתח שעוזר לנו להפוך למתכנתים טובים יותר.
1 419
# כלים
לכלים יש השפעה דרמטית על הפרודוקטיביות שלנו. הם יכולים להפוך אותנו לפי 10 יותר מהירים או פי 10 יותר איטיים.
מי שרגילה להתחיל פרויקטים חדשים יכולה להתחיל פרויקט חדש בנקודת פתיחה שכבר הכל במקום, ולהתחיל לכתוב את הקוד "האמיתי" של היישום כבר ביום הראשון. במקומות רציניים שמתחילים הרבה פרויקטים חדשים יש טמפלייטים מסודרים לאיך פרויקט חדש צריך להיראות בדיוק בשביל שאפשר יהיה לעשות את זה.
מי שלא רגילה להתחיל פרויקטים חדשים עשויה לבזבז שעות ואפילו ימים רק על התלבטויות טכנולוגיות - באיזה DB להשתמש? איך לעשות אותנטיקציה למשתמשים? באיזה ספריית CSS לעצב? איזה תיקיות ליצור, ואיזה קבצים לשים בכל תיקיה; ועוד מיליון שאלות שמצד אחד מאוד משפיעות על הקוד שלנו Going Forward, אבל מצד שני בנקודת התחלה של הפרויקט אין לנו מספיק אינפורמציה להחליט שם החלטות יותר מדי מתוחכמות. טמפלייט היה עובד הרבה יותר טוב.
כשאנחנו ניגשים למשימה בלי שיש לנו כלים מספיק טובים כדי לפתור אותה יש לנו שתי אפשרויות - אנחנו יכולים לפתור את המשימה בכלים שיש לנו, ולהניח שאף פעם לא ניתקל במשימה דומה ולכן אין טעם להשקיע בכלים טובים יותר; או לראות את המשימה בתור הזדמנות, ולהשקיע בחיפוש ולימוד כלי העבודה שיתאימו לאותה משימה. ברוב המקרים, אם עשיתם משהו פעם אחת יש סיכוי טוב שתצטרכו לעשות אותו שוב בעתיד כך שההשקעה משתלמת.
متاح الآن! بحث تيليغرام 2025 — أهم رؤى العام 
