היזהרו מאנשים חד-תכליתיים
טהור עד כאב
הSingle Responsibility Principle הוא אחד מהרעיונות האלה שנשמע כל כך הגיוני שהוא יכול לחמוק מהשיפוט שלך.
עשה דבר אחד. עשה אותו היטב. שמור על מודולים ממוקדים. תן לקוד סיבה להשתנות. עצה טובה.
ואז מישהו הופך את העצה לסרט מדידה ומתחיל להכריז שכל פונקציה מעל חמש שורות היא ריח קוד.
הבעיה היא לא SRP. הבעיה היא להתייחס ל”קטן” כתחליף ל”קוהרנטי”.
בנקודה זו פגשת את אנשי המטרה היחידה: מפתחים שלא טועים לגבי מודולריות, בדיוק, אבל בלבלו בין גבולות שימושיים לבין פרגמנטציה מקסימלית.

I. הרעיון השימושי שמתחת
הוספת תיבת סימון בודדת לטופס אמורה באופן אידיאלי להשפיע רק על קובץ אחד. לא 8 קבצים ב-5 תיקיות… אני מסתכל עליכם, React/Redux.
כאשר SRP מיושם עם שיקול דעת, הוא עוזר. יחידות קוד הממוקדות במשימה רעיונית אחת קלות יותר להבנה. בדיקות יכולות למקד התנהגות בגבול הגיוני. מודולים ברורים מקלים על שינוי חלק אחד של המערכת מבלי לגרור את שאר האפליקציה לחדר.
אפילו הדוגמאות הקלאסיות של יוניקס הן יותר פרקטיות ממה שהסיסמה מרמזת. ls מפרט קבצים, כן, אבל הוא גם מתאם קריאות כמו opendir, readdir, closedir, ו-stat. היחידה השימושית היא לא הפעולה הקטנה ביותר האפשרית. היחידה השימושית היא הדבר הקוהרנטי הקטן ביותר שפותר את המשימה.
הפילוסופיה המקורית של יוניקס עסקה בקומפוזיציה ובפשטות, לא בצמצום הכל לפונקציה או קובץ בודד.
ההבחנה הזו חשובה. “אחריות אחת” אינה זהה ל”שורת התנהגות אחת”.
II. אבסטרקציית יתר: כשפשטות הופכת לכאוס
הארכיטקט שלנו מתעקש שכל פונקציה ארוכה מ-5 שורות היא ‘ריח קוד’. בסיס הקוד שלנו כעת מריח קלות של ייאוש חסר מושג.
קל לזהות את מצב הכשל אחרי שהוא כבר הרס לך את השבוע.
בסיס הקוד מכיל יותר קבצים, אבל פחות צורה. לכל עוזר יש עוזר. כל מושג פוצל לתיקיות על שם תפקידים טכניים במקום משמעות מוצרית. הוספת תיבת סימון דורשת נגיעה בקומפוננטה, הוק, סלקטור, אקציה, רדיוסר, קבוע, מתקן בדיקה, וייצוא חבית שקיים בעיקר כדי לשמור על נתיבי הייבוא מלהיראות אשמים.

מה קנתה כל הטוהר הזה?
- רסיסי מערכת קבצים: תיקיות מקור פורחות לנופים סיוטיים של אינספור קבצים זעירים, לרוב המכילים פונקציה בודדה ועצובה באופן טרגי. הניווט הופך לתרגיל במערות.
- סבכי תלויות: רשת של יבוא וייצוא כה צפופה עד שמעקב אחר ביצוע דורש לוח לבן גדול וסבלנות רבה יותר ממה שהתכונה ראויה לו. קבצים שמיובאים פעם אחת יושבים ומעמידים פנים שהם ניתנים לשימוש חוזר.
- בגידה בבדיקות: בדיקות הופכות לשבירות, שומרים היפר-ספציפיים המגינים על פרטי מימוש זעירים. שינית חתימת פונקציה? צפה בעשרות בדיקות מתפוררות כמו כלי חרס עתיקים. חבילת הבדיקות הופכת מרשת ביטחון לשדה מוקשים.
- מהירות שנעלמה: שינויים פשוטים גולשים לסאגות שינוי מרובות קבצים. הכנסת מפתחים חדשים כרוכה בשבועות של מסירת מפות ומצפנים רק כדי למצוא היכן הקומפוננטה
UserProfileבאמת חיה השבוע. ההתקדמות קדימה מואטת לקצב גיאולוגי תחת המשקל העצום של ה”ארגון” הזה.
בהיתי בתהום של בסיסי קוד שבהם תכונה פשוטה בת 100 שורות נותחה על פני 15+ קבצים, כל אחד מלאך קטן “טהור” המכיל אולי פונקציה אחת או שתיים. רדיוס הפיצוץ הקוגניטיבי של ניסיון להחזיק את הבלאגן הזה בראש ביטל לחלוטין כל ניצחון תיאורטי מההפרדה. זה לא היה פשוט יותר; זה היה פשוט מפוזר.
III. המחיר של השלמות: השפעה על מפתחים
אנחנו מבזבזים יותר זמן בוויכוחים על מבנה קבצים ומוסכמות שמות מאשר במשלוח תכונות. זה אג’ילי?

הפיצול הפתולוגי הזה אינו רק בעיה אסתטית. הוא משנה את האופן שבו מפתחים מפנים את תשומת הלב שלהם:
ניקוז הפרודוקטיביות: תשכחו מחוב טכני; זה חוב ארגוני שנצבר דרך קינון תיקיות כפייתי-אובססיבי. כל שינוי קטן הופך לחפירה ארכיאולוגית דרך שכבות של הפשטה. הזמן נעלם לתוך החור השחור של cd .. ו-grep.
מס הבדיקות: במקום לספק ביטחון, חבילת הבדיקות הופכת למקור חיכוך. שעות נמסות בתיקון בדיקות שנשברו על ידי רפקטורינג טריוויאלי, בדיקות שהיו צמודות מדי לפרטים המיקרוסקופיים שהן היו אמורות לאמת.
העומס הקוגניטיבי: יש גבול קשיח לכמה פיסות מידע מנותקות מוח אנושי יכול לאזן. לאלץ מפתחים להרכיב את זרימת התוכנית מתוך תריסר קבצים מפוזרים מעכב באופן פעיל את ההבנה ומקשה על ביצוע שינויים בביטחון.
IV. אימוץ הפרגמטיות: אלטרנטיבה מעשית
הצעתי לשים שתי פונקציות קשורות באותו קובץ. החדר הגיב כאילו הצעתי למחוק את ה-staging. — קורא מחלים מפוריות
בריחת החירום אינה נטישת עקרון האחריות היחידה. התשובה היא ליישם אותו ברמת המשמעות הנכונה.
הנה איך זה נראה בפועל:
- התמקדו בקוהרנטיות, לא באטומים: קבצו יחד דברים שמשתנים יחד ושייכים יחד מבחינה רעיונית. מודול עשוי לטפל במספר היבטים קשורים של אימות משתמש. זה בסדר. זה כנראה טוב יותר משישה קבצים נפרדים, כל אחד מחזיק פונקציה אחת הקשורה למצב התחברות.
- שמרו על קרבה: אל תפצלו קוד קשור אלא אם יש תועלת מוחשית וצורחת – כמו שימוש חוזר אמיתי בפועל, לא באיזה עתיד היפותטי שלעולם לא מגיע. קרבה חשובה להבנה.
- תנו למציאות להכתיב: ארגנו לפי התכונות והזרימות בפועל של האפליקציה שלכם, לא לפי אידיאל מופשט כלשהו של טוהר פונקציונלי³. האם המבנה הזה מקל או מקשה על מישהו להבין ולשנות את
תכונה X? - זכרו את החומרה האנושית: זכרו את המפתח המסכן. איזה ארגון ממזער את אקט הלהטוטנות המנטלית הנדרש לעבודה על הקוד? בצעו אופטימיזציה להבנה אנושית.
- בדקו מה שחשוב: כתבו בדיקות שמאמתות התנהגות בגבול הגיוני, לא בדיקות שמולחמות באופן אינטימי לחיווט הפנימי של כל פונקציה זעירה. כוונו לביטחון, לא רק לתיאטרון של אחוזי כיסוי.
המטרה אינה שלמות תאורטית הראויה לתזה דוקטורט; היא יצירת קוד שעמיתיך (והעצמי העתידי שלך) יוכלו לנווט בו, להבין ולשנות מבלי לרצות להצית את הבניין.
לפעמים זה אומר שקובץ באורך 200 שורות במקום 50. לפעמים פונקציה מטפלת בשליפת נתונים וגם משנה אותם מעט. לפעמים למחלקה יש שתי אחריות שכל כך צמודות זו לזו שהן צריכות לחיות יחד. אם זה הופך את המערכת לקלה יותר לעבודה בסך הכול, זו כנראה ההחלטה הנכונה.
הישארו ממוקדים ללא הרף בשאלות המעשיות:
- האם מישהו חדש יכול למצוא את דרכו?
- האם נוכל לשנות את
Xמבלי לשבורYלא קשור? - האם הבדיקה הזאת באמת אומרת לי אם התכונה עובדת?
- האם אנחנו מספקים ערך, או רק מסדרים מחדש תיקיות?
V. מסקנה: טיפוח קוד קוהרנטי ובר-תחזוקה
עקרון האחריות היחידה הוא כלי שימושי. הוא לא צו לטחון את בסיס הקוד שלכם לאבק אטומי. כמו כל כלי, ערכו תלוי בשיקול הדעת של המשתמש בו.
אז כשאתם נתקלים באנשי המטרה היחידה, מוכנים לצאת למלחמה על כל פונקציה שמעזה לעלות על שלוש שורות, קחו נשימה. זכרו את תיבת הסימון בת 12 הקבצים.
התפקיד שלנו הוא לא לבנות פונקציות שלג מושלמות תאורטית. התפקיד שלנו הוא לבנות תוכנה שעובדת, פותרת בעיות, ואינה מענישה את האדם הבא שיצטרך לגעת בה.
הישארו פרגמטיים. התמקדו בתוצאות. אל תתנו למרדף אחר טוהר מושלם להפוך לאויב של קוד בר-תחזוקה. השפיות שלכם, והמהירות של הצוות שלכם, תלויות בכך.
¹ האירוניה היא שהשגת מטרה אחת אמיתית ברמות הנמוכות ביותר דורשת מורכבות עצומה החבויה ממש מתחת לפני השטח.
² אנחנו מדברים כאן על טוהר רעיוני: הרעיון שפונקציה צריכה לעשות רק “דבר אחד” מבחינה לוגית. אל תבלבלו זאת עם המושג של תכנות פונקציונלי של “פונקציה טהורה” ללא תופעות לוואי, שהוא רעיון שונה, אם כי לעיתים קשור.