ToCode
Открыть в Telegram
1 421
Подписчики
Нет данных24 часа
+37 дней
-430 день
Архив постов
1 421
# מי מפחד מ Chat GPT בראיונות עבודה
פעם חשבנו שמספיק להזמין מועמד לראיון כדי שיענה על כמה שאלות תכנות על הלוח, כדי להעריך רמה מקצועית. אחרי זה גילינו שיש הרבה אנשים טובים שנלחצים מהלוח, ובכלל חווית הראיון מוטית לכיוון אנשים עם אופי מסוים. פספסנו הרבה אנשים טובים וגייסנו הרבה אנשים לא נכונים.
אחרי זה חשבנו שמספיק לתת למועמדת עבודת בית כדי לראות איך היא מתמודדת עם משימה קצת יותר מורכבת. ועכשיו אנחנו מתחילים ללמוד שגם עבודת בית לא משקפת יכולת התמודדות של מועמדת עם אתגרים. שמועמדים מסוימים מצליחים "לתחמן" את המערכת, ושעם כלים כמו Chat GPT התחמון הזה נהיה קל. לא רחוק היום שכלים אוטומטיים יפתרו משימות בית בתכנות טוב יותר מהמועמדים הטובים ביותר שלנו.
וכן אפשר לחשוב על בעיות יותר יצירתיות או קשות, או כלי מעקב שיאפשרו לנו לזהות אם מישהו נעזר בכלי אוטומטי כדי לפתור אתגר של ראיון עבודה. אבל זה לא הדבר החשוב. יותר חשוב לשים לב שהבעיות האלה פשוט לא משקפות את הדברים שנצטרך לעשות בעבודה האמיתית ולא בודקות את כישורי הפיתוח שאנחנו מחפשים.
בעתיד (הלא רחוק) נצטרך לעבוד יותר קשה, ולא בטוח שזה דבר רע. בתור מגייסים נצטרך להיות מסוגלים להסתכל על עבודות גדולות של מועמדים ולשפוט אותם לפי הישגיהם בפרויקטים קודמים. בתור מועמדים נצטרך לבנות תיקי עבודות מרשימים יותר, כולל פרויקטי קוד פתוח בהם נשתתף לאורך זמן, בעזרתם מגייסים יוכלו להעריך את היכולת שלנו גם בלי משימות בית או ראיונות.
"הראו את עבודתכם" זו כבר הדרך שאנשים מגייסים אנשים בהרבה מאוד תחומים. בקרוב אצלנו.
1 421
# היום למדתי: RANDOM ב zsh עלול להיות מבלבל
ב bash המשתנה המיוחד
RANDOM מוחלף במספר אקראי. לכן אפשר לכתוב קוד כזה:
$ echo $0
bash
$ echo $RANDOM
5953
$ echo $RANDOM
12763
$ echo $RANDOM
2894
וזה עובד ממש בסדר. גם בתוך Subshells המשתנה RANDOM ממשיך לעבוד ובגלל זה אפשר לכתוב גם את זה ב bash ולקבל שלוש שורות שונות בקובץ:
$ echo $0
bash
$ echo $RANDOM | tee -a numbers
3064
$ echo $RANDOM | tee -a numbers
4881
$ echo $RANDOM | tee -a numbers
6698
ב zsh ההתנהגות קצת יותר מבלבלת. בשורת הפקודה RANDOM עדיין יתקדם ויציג כל פעם מספר אחר:
$ echo $0
-zsh
$ echo $RANDOM
4402
$ echo $RANDOM
2260
$ echo $RANDOM
12200
אבל הדפסת מספר אקראי בתוך Subshell לא משנה את המצב הפנימי של יצרן המספרים האקראיים ולכן הקוד הבא ידפיס תמיד את אותם שלושה מספרים לקובץ:
$ echo $RANDOM | tee -a numbers
27376
$ echo $RANDOM | tee -a numbers
27376
$ echo $RANDOM | tee -a numbers
27376
וכן עם tee זה לא בעיה כי רואים את המספרים. בפקודות אחרות שכותבות מספרים אקראיים למקומות אחרים זה עלול להיות פחות ברור, אז היו ערניים.1 421
# ההשקעה הכי גרועה שעשיתי
השקעה היא ייחוד זמן ומאמץ למטרה כלשהי. להשקעה יש תמורה (ROI) ואנחנו יכולים למדוד איכות השקעה לפי התמורה שהיא נותנת. קניית דירה היא דוגמה טובה להשקעה כי אנחנו משלמים סכום גדול של כסף ומקבלים בתמורה נכס שאפשר לגור בו או להשכיר אותו. השקעה בעסק יכולה להיות קניה של מכונות חדשות למפעל או הרמת קמפיין פירסומי. ההשקעה היא חד פעמית ומאפשרת לשפר את הפרודוקטיביות של העסק.
שינוי סגנון חיים הוא מה שקורה כשאנחנו מבינים שמשהו לא עובד בחיים שלנו ורוצים לחלק אחרת את הזמן או המשאבים שלנו לטווח הרחוק. שינויים בסגנון חיים יהיו לדוגמה מעבר לתזונה בריאה, בחירה במגורים בעיר או בכפר, בחירת מסגרת הוצאות או שינוי בהיקף המשרה בעבודה.
ההבדל המרכזי בין השקעה לשינוי סגנון חיים הוא במועד הסיום: מי שקונה מכונה חדשה לעסק מצפה להשקיע כסף בציוד החדש ואחרי זה ההשקעה מסתיימת ואפשר ליהנות מהמכונה. אם יום אחד יגמרו לבנות את הרכבת הקלה הם יפסיקו לבנות מסילות ונוכל להתחיל ליהנות מהדרך. שינוי סגנון חיים לעומת זאת לא כולל מועד סיום, מי שעובר לתזונה בריאה לא מתכנן יום אחד "לגמור" את התשלום ולהתחיל לאכול ג'אנק. זאת פשוט לא המטרה.
ובחזרה להשקעות גרועות - כל קורס טכנולוגי שניקח, כל טכנולוגיה שנבחר ללמוד, היא השקעה גרועה. רוב הטכנולוגיות הפופולריות היום לא יהיו איתנו עוד 5 שנים, והרבה מהן דורשות זמן לימוד של כמה חודשים בשביל להגיע לרמה טובה. אני לא אשכח איך ישבתי חצי שנה ללמוד איך לכתוב אפליקציות לטלפונים של נוקיה, רק בשביל להתעורר שנתיים מאוחר יותר לעולם בלי נוקיה ובלי זכר לכלי הפיתוח שלהם. אם המטרה של ההשקעה היתה להשיג מיומנות חדשה שתשרת אותי לשנים קדימה זו היתה ההשקעה הגרועה ביותר שאפשר לדמיין.
שווה יותר לחשוב על לימודי תכנות בתור בחירת סגנון חיים - חלק מסגנון החיים של אנשים שעובדים בתחום הוא ללמוד כל הזמן טכנולוגיות חדשות ואז לראות אותן מתות. המעגל לעולם לא ייגמר, אף פעם לא יהיה לכם מספיק ידע בשביל שתוכלו להפסיק ללמוד, כמו שאף פעם לא תאכלו מספיק אוכל בריא בשביל שאפשר יהיה לחזור לאכול ג'אנק. המטרה של הלימוד היא לא "לגמור עם זה" ולהתחיל לעבוד, אלא להבין איך ליהנות ממנו ולשלב אותו ביום יום של החיים.
1 421
# טיפ דרמטיק - עבודה עם actors אסינכרוניים
דרמטיק היא ספריה להרצת משימות ברקע בפייתון. היא מאוד דומה ל celery אבל קצת יותר מתוחזקת ויודעת לעבוד טוב יותר עם משימות שצריך לתזמן לשעה מסוימת בעתיד. פועל של דרמטיק מריץ Threads, וכל Thread יודע להריץ פונקציות שנקראות Actors. דוגמת הקוד הבאה מהאתר שלהם מראה איך למשוך דף אינטרנט ולספור כמה מילים יש בו:
## קוד הדוגמה
import dramatiq
import requests
@dramatiq.actor
def count_words(url):
response = requests.get(url)
count = len(response.text.split(" "))
print(f"There are {count} words at {url!r}.")
# or send the actor a message so that it may perform the count
# later, in a separate process.
count_words.send("http://example.com")
בשביל ש count_words באמת ירוץ לא מספיק להפעיל את הסקריפט. יש להפעיל גם תהליך נפרד שמריץ את ה Worker של dramatiq, ואת זה עושים באמצעות הפעלה בחלון נפרד של הפקודה:
dramatiq main.py
בהנחה שלקובץ התוכנית קוראים main. עכשיו כל פעם שאריץ את main בחלון השני אני מקבל את ההודעה:
There are 298 words at 'http://example.com'.
## תרגום לקוד אסינכרוני
עד לפה הכל טוב אבל מה קורה אם רוצים להריץ קוד אסינכרוני? מה אם count_words היתה משתמשת למשל ב aiohttp במקום ב requests? אני מעדכן את הקוד:
@dramatiq.actor
async def count_words(url: str):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
response = await resp.text()
count = len(response.split(" "))
print(f"There are {count} words at {url!r}.")
asyncio.run(count_words("http://example.com"))
והתוכנית עובדת, אבל הפעלה אסינכרונית כבר לא ממש:
count_words.send("http://example.com")
הודעת השגיאה שמופיעה על מסך ה Worker היא:
/Users/ynonp/work/intel-dec-2020/dramatiq-demo/venv/lib/python3.10/site-packages/dramatiq/worker.py:460: RuntimeWarning: coroutine 'count_words' was never awaited
self.process_message(message)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
בואו נתקן את זה
## הוספת תמיכה בפונקציות אסינכרוניות ל dramatiq
בגלל שדרמטיק פותח Thread-ים לא מומלץ לפתוח Event Loop חדש מתוך פונקציית ה Actor. לפעמים זה יעבוד אבל לפעמים זה ייכשל עם שגיאות מוזרות. עדיף להעביר את ה Event Loop מה Thread הראשי ל Threadשלנו, ולהריץ ב Event Loop הראשי. אבל איך נעשה את זה אם אין לנו גישה לתהליכון הראשי?
מסתבר שגירסאות עדכניות של דרמטיק הוסיפו תמיכה במנגנון זה ואפילו בצורה פשוטה. דבר ראשון יש להסיר את דרמטיק ולהתקין את גירסת ה master שלו:
$ yes | pip uninstall dramatiq
$ pip install git+https://github.com/Bogdanp/dramatiq@master
לאחר מכן יש להתקין מידלוור של דרמטיק שמריץ משימות אסינכרוניות. אני מעדכן שוב את הקוד:
import dramatiq
from dramatiq.middleware.asyncio import AsyncIO
from dramatiq.brokers.redis import RedisBroker
import requests
import aiohttp
import asyncio
import os
broker_url = os.environ.get("BROKER_URL", "redis://localhost:6379/0")
broker = RedisBroker(url=broker_url)
broker.add_middleware(AsyncIO())
dramatiq.set_broker(broker)
@dramatiq.actor
async def count_words(url: str):
async with aiohttp.ClientSession() as session:
async with session.get(url) as resp:
response = await resp.text()
count = len(response.split(" "))
print(f"There are {count} words at {url!r}.")
# asyncio.run(count_words("http://example.com"))
# Synchronously count the words on example.com in the current process
# count_words("http://example.com")
# or send the actor a message so that it may perform the count
# later, in a separate process.
count_words.send("http://example.com")
וזה הכל - מפעיל מחדש את הפועל של dramatiq בחלון אחד וכשאני מפעיל את הסקריפט עם ה Actor האסינכרוני הכל עובד ודרמטיק יודע להריץ אותו ב Event Loop הראשי של התהליך ולחכות שיסיים.1 421
# הפרפקציוניסט והחאפר
גם הפרפקציוניסט וגם החאפר לא מצליחים לכתוב קוד מספיק טוב, אבל מסיבות אחרות.
הפרפקציוניסט צריך שהכל ישב במקום לפני שהוא יכול להתחיל לקודד. הוא חייב שה IDE יהיה מקונפג כמו שצריך, שתשתית הבדיקות האוטומטיות תעבוד, שהקוד ישב מסודר יפה ומתועד, שהאבסטרקציות יהיו בדיוק נכונות. פרפקציוניסטים מתקדמים לאט ובעבודה מחקרית כמו כתיבת קוד עד שהם יסיימו כבר מישהו בפרודקט ישנה את דעתו והרבה עבודה תיזרק.
החאפר הוא חלומו של כל איש פרודאקט כי אתה יכול לדבר איתו בבוקר על פיצ'ר ושעתיים אחרי זה המנגנון כבר עובד בפרודקשן, אבל בגלל חוסר סדר יהיו הרבה באגים, הוא לא יצליח לעבוד בצוות או על מערכות מורכבות ורגרסיות יקרו כל הזמן. בנוסף חצי שנה לתוך הפרויקט הקוד יראה כמו ערימת בוץ ענקית שהמוצא היחיד ממנה יהיה לשכתב את הכל.
ברור שאנחנו לא רוצים להתקדם לאף אחד מהקצוות של הסקאלה ביניהם. אנחנו כן רוצים למצוא מקום טוב באמצע ויותר מעניין - אנחנו רוצים להתנסות בעבודה יותר פרפקציוניסטית או יותר חאפרית באופן שוטף בחלקים בפרויקט שמאפשרים את זה. הדרך הנכונה להסתכל על שני החבר'ה האלה היא לא בתור שתי אפשרויות ריאליות, אלא בתור מיומנויות שכדאי ליישם בזמן הנכון ובמידה הנכונה: פיתוחים מסוימים דורשים מחקר מהיר וכתיבת קוד שייזרק, ופיתוחים אחרים דורשים קוד יציב ותשתיות שילוו אותנו לשנים. הגמישות המחשבתית לעבור בין סוגי העבודה עוזרת, לא משנה על איזה פרויקט אתם עובדים עכשיו.
1 421
# פעם אחת מספיקה
פעם אחת מספיקה בשביל לשנות את הגישה ולפתוח את הדלת לרעיון חדש.
אחרי שכתבת אפלקיציה למובייל פעם אחת, השניה תרגיש פחות מפחידה (גם אם הקוד עצמו יהיה שונה לגמרי)
אחרי שהעברת הרצאה בכנס, הפעם הבאה מול קהל תהיה פחות מפחידה (גם אם הנושא יהיה אחר לגמרי)
אחרי שלמדת נושא חדש בעצמך דרך קורס אונליין, יהיה לך הרבה יותר קל להמשיך לקחת קורסים ולהתקדם לבד.
אנחנו אוהבים לחשוש מיציאה מאזור הנוחות, אבל בעצם אזור הנוחות משתנה כל הזמן. אזור הנוחות של היום הוא לא אזור הנוחות של אתמול ולא של שנה שעברה. פעם אחת מספיקה, וזו סיבה מספיק טובה לחפש אותה.
1 421
# עשר שנים מאוחר יותר
כל אחד ירגיש אבוד אם יפוטר ממקום עבודה אחרי עשר שנים של עבודה באותו מקום. כל אחד ירגיש מבולבל וחושש ולכן התגובה הטבעית במצב כזה היא להאשים את האירוע הנקודתי: אם רק לחברה היה עוד כסף, אם רק המנכ"ל לא היה לוקח הכל לעצמו, אם רק היו מורידים משכורות במקום לפטר, אולי החיים שלי היו נשארים טובים כשהיו.
תגובה כזאת מקבלת חיזוק אחרי שמתחילים לחפש עבודה חדשה ורואים שהשוק לא חיכה לך, שבעצם המיומנויות שלך לא מספיק רלוונטיות לרוב מקומות העבודה ושבגילך כבר אף אחד לא רוצה לגייס אותך למשרת סטודנט והמגייסים מחפשים רמה מקצועית שתואמת לגיל ולניסיון.
ובדיוק במצבים האלה חשוב לשים לב שהבעיה היא לא החברה שפשטה רגל או המחלקה שנסגרה. שווה להסתכל על אנשים אחרים באותו מצב שדווקא כן מצאו מהר עבודה חדשה, או אפילו על חברים שהבינו שהחברה נכנסת לקשיים כבר לפני שנה ושנתיים ועזבו בתנאים שלהם.
המטרה שלנו כמתכנתים היא לשמור על רמת כשירות גבוהה בכל מצב. לזכור שלא משנה כמה הרווחתי או באיזה תפקיד הייתי, מחר בבוקר אני יכול לחזור לנקודת ההתחלה. מה שנשאר איתנו בין עבודות זה המיומנות והמקצועיות שלנו. לאורך זמן אלה הדברים שאנחנו חייבים לשמר ולשפר.
וכשרואים את זה גם קל יותר להתמודד עם התחושות ולמצוא את הדרך קדימה: כן, צריך להשלים עשור של התקדמות טכנולוגית שבו היית תקוע בקוביה עם משכורת גבוהה בחברה שכבר מזמן לא פיתחה מוצרים רלוונטיים. זה ייקח זמן ועבודה. ואחרי שתסגור את הפער ותמצא את העבודה הבאה, נסה להשאיר את הרגע הזה של עשר שנים קדימה בתודעה. השקעת עבודה בלימוד ביום יום תהפוך את החיפוש הבא להרבה יותר פשוט.
1 421
# האם Panda CSS הוא הדבר הגדול הבא בעיצוב לריאקט?
פנדה הוא בהחלט כל מה שאפשר לדמיין כשחושבים על פריימוורק ל CSS in JS. היתרון הגדול שלו הוא התמיכה המלאה בקומפוננטות צד-שרת, כלומר בבניית כל הגדרות העיצוב בצד בתור קלאסים ושימוש אוטומטי בקלאסים אלה בתוך הקוד, בסגנון Tailwind CSS. אבל בניגוד לטיילווינד, פה יש לנו גם חיבור ל TypeScript כדי לקבל השלמה ואימות טיפוסים על כללי העיצוב ואינטגרציה טובה עם ריאקט כדי לייצר עיצובים מתוך קוד.
וכמו שאומרים קוד שווה יותר מאלף מילים, אז הנה דוגמה קטנה ל Panda בקומפוננטת ריאקט:
function App() {
return (
<div className={css({ background: 'red.400'})}>
<div className={css({ fontSize: "2xl", fontWeight: 'bold' })}>Hello 🐼!</div>
</div>
)
}
אני משתמש בפונקציה css ומעביר את ערך החזרה שלה בתור className. באופן אוטומטי פנדה מייצר קלאס שיש לו את הגדרות העיצוב שכתבתי והפונקציה מחזירה את שם הקלאס. במידה והקומפוננטה תרונדר מצד שרת, אז ה HTML שיישלח ללקוח יכיל ממש את שמות הקלאסים שג'ונרטו וכך גולשים יכולים לראות את העמוד עם העיצוב גם בלי JavaScript.
ודוגמה שניה קצת יותר מתוחכמת-
function App() {
const [clicked, setClicked] = useState(false);
return (
<div>
<button
className={css({
color: {
base: 'blue',
_hover: 'green',
},
cursor: 'pointer',
background: '#dadada',
padding: '10px',
borderRadius: '5px',
})}
onClick={() => setClicked(true)}
>
Click Here
</button>
<p className={css({
color: clicked ? 'green' : 'red'
})}>{clicked ? 'Passed' : 'Failed'}</p>
</div>
)
}
המפתח _hover מגדיר ערך עיצוב שיפעל כשהאלמנט נמצא ב hover, ואין בעיה בתוך האוביקטים של העיצוב לבדוק ערכים של משתני JavaScript.
כדי לשחק עם Panda תצטרכו קודם להוסיף אותו לפרויקט ריאקט שלכם. אלה ההוראות לפרויקט שבנוי ב Vite:
https://panda-css.com/docs/getting-started/vite1 421
# הזן של פייתון - מפורש טוב יותר ממובלע
בניוזלטר שלו ראובן כתב על הזן של פייתון ואיך פייתון היא שפה "מפורשת" ובלי הרבה יוצאים מהכלל, בניגוד ל Ruby או JavaScript. אחת הדוגמאות שם היתה שבפייתון אנחנו תמיד יודעים מי יהיה ה self, בניגוד ל JavaScript שיכולה להפתיע עם this בזמן ריצה. בואו נפרק את הטענה הזאת ונבדוק מתי גם פייתון יכולה להפתיע.
## קשירה דינמית של this
נתחיל בהתחלה, ב JavaScript אני יכול לכתוב קלאס עם מתודות באופן הבא:
class Foo {
constructor(name) {
this.name = name;
}
hello() {
console.log(`Hello ${this.name}`);
}
}
ואז להשתמש בו עם:
const f = new Foo("ynon");
f.hello();
והכל יעבוד והטקסט הנכון יודפס. הבעיה שהחיבור בין הפונקציה hello לקלאס Foo הוא חיבור חלש. הוא נקבע בזמן ההפעלה של הפונקציה וקל להפעיל את אותה פונקציה בצורה אחרת כדי לשבור את המימוש שלה. דוגמה קלה היא הקריאה:
const x = f.hello;
x();
שמפעילה את הפונקציה עם undefined בתור this ולכן זורקת Exception, או הקריאה:
const bar = { name: 'tony' };
f.hello.call(bar);
שפשוט מפעילה את הפונקציה עם אוביקט this אחר. באופן רגיל דפדפנים משתמשים המון בטריק הזה במיוחד בקוד שמטפל באירועים, שם המשתנה this יהיה בדרך כלל האוביקט שגרם לאירוע, בלי קשר לקלאס שבתוכו הוגדרה הפונקציה.
## קשירה קשיחה של this עם bind
הפונקציה bind ב JavaScript, או הגדרה של פונקציית חץ, מגדירות חיבור מסוג אחר ל this. נשים לב לקוד הבא:
class Foo {
constructor(name) {
this.name = name;
}
hello = () => {
console.log(`Hello ${this.name}`);
}
}
const f = new Foo("ynon");
const x = f.hello;
x();
const bar = { name: 'tony' };
f.hello.call(bar);
הפעם הכל תקין ושתי הקריאות מדפיסות את הטקסט Hello ynon. בעצם בכתיבת קוד JavaScript אנחנו צריכים לבחור באיזה סוג binding נרצה להשתמש, כשהשפה תומכת בשתי האפשרויות אבל ברירת המחדל שלה קצת מפתיעה.
## קשירת פונקציות למחלקות בפייתון
אבל לא באנו לדבר על JavaScript אלא על פייתון - האם פייתון היא באמת יותר Explicit או יותר Implicit בהיבט של קשירת פונקציות למחלקות?
נתחיל בכתיב ברירת המחדל:
class Foo:
def __init__(self, name):
self.name = name
def hello(self):
print(f"Hello {self.name}")
f = Foo("ynon")
f.hello()
הקוד כמעט מועתק מ JavaScript ועובד אותו דבר. כשננסה להפעיל את הפונקציה דרך משתנה אחר נראה שהפונקציה "מחוברת" למחלקה Foo והקוד עדיין יעבוד:
x = f.hello
x()
## קשירה חלשה בפייתון
אבל פייתון תומכת גם בכתיב השני של קשירה חלשה, לפחות סוג-של. השדה המיוחד __func__ של מתודה מחזיר את הפונקציה שמממשת אותה, בלי קשר למחלקה ממנה הגיעה. הפונקציה __get__ של אותה פונקציה קושרת את הפונקציה למתודה חדשה, אולי של אוביקט אחר. ולכן הקוד הבא מדפיס Hello tony:
class Foo:
def __init__(self, name):
self.name = name
def hello(self):
print(f"Hello {self.name}")
class Bar:
def __init__(self):
self.name = "tony"
f = Foo("ynon")
b = Bar()
x = f.hello.__func__.__get__(b, Bar)
x()
אז נכון הספריות המובנות בפייתון עושות שימוש פחות נרחב במבנה זה לעומת דפדפן, אבל כמו ב JavaScript גם בפייתון אנחנו יכולים לבחור איזה סוג חיבור נרצה בין הפונקציה למחלקה ולבחור בזמן הקריאה לפונקציה מי יהיה ה self שהיא תראה. פייתון בסך הכל מסתירה את הפיצ'ר הזה קצת יותר טוב.1 421
# להעלות את הסטנדרטים
אין ספק שאם קוד לא עובד כמו שצריך אנחנו לא צריכים להכניס אותו למערכת. אבל הרבה פעמים הסטנדרטים שלנו יותר גבוהים. בואו נדבר על ריאקט בשביל הדוגמה ונסתכל על הקוד הבא:
import "./styles.css";
function Counter() {
function handleClick() {
const btn = document.querySelector(".counter button");
const count = Number(btn.textContent);
btn.textContent = count + 1;
}
return (
<div className="counter">
<button onClick={handleClick}>0</button>
</div>
);
}
export default function App() {
return (
<div className="App">
<Counter />
</div>
);
}
הקוד עובד - הוא מראה כפתור עם המספר 0 וכשלוחצים על הכפתור המספר עולה לפי מספר הלחיצות. לא אפליקציה מעניינת במיוחד אבל עובדת. ולמרות שהיא עובדת יש לא מעט סיבות בגללן לא נרצה לכתוב כך:
1. הקוד לא יציב - אם App ישתנה, למשל אם יוסיפו עוד Counter, אז אחד מהם יפסיק לעבוד בגלל השימוש ב document.querySelector. יותר מזה, אם יוסיפו משתנה State או Props ל Counter אז ברינדור הבא הערך שכתוב בכפתור יימחק.
2. הקוד מעודד סטנדרטים לא טובים - ככל שהקוד יועתק ליותר מקומות למערכת (כמו שקורה לקוד), איכות הקוד הכללי במערכת תרד. מי שכתב אותו בבירור לא מבין מספיק את ריאקט.
3. בקוד קשה לבצע בקוד שינויים קטנים והגיוניים, למשל בשביל להציג את הערך של הכפתור במקומות נוספים בקומפוננטה נצטרך לעדכן גם את הפונקציה handleClick וגם את הפונקציה הראשית Counter.
רק שלושת הסיבות האלה מספיקות בשביל לשכתב את הקוד בהקדם האפשרי. כל יום שקוד כזה נשאר במערכת, הוא פוגע בנו ובחברים שלנו לצוות. וברור, לא הייתם כותבים את הקוד שהדבקתי, השאלה כמה פעמים אתם מכניסים למערכת קוד שאתם לא מבינים עד הסוף? כמה פעמים אתם משאירים קוד רק בגלל שהוא עובד? והאם לא הגיע הזמן להעלות את הסטנדרטים?
Уже доступно! Исследование Telegram 2025 — ключевые инсайты года 
