Object Oriented Design: כמה שאלות חשובות
ליאור בר און מעלה שאלות בנוגע למספר מחלוקות ב-OOD, ואתם מוזמנים להביע את דעתכם ולהגיד מי צודק ובאילו עקרונות כדאי לדבוק בעת פיתוח תוכנה
לפני כשבוע נתקלתי בוויכוח הבא:
במערכת כלשהי, באזור לו נקרא "Sub-Project 3", מחלקה A (בג'אווה) קראה למתודה במחלקה B, אשר דרשה כפרמטר איזה ערך. הערך יכול להיות אחד מ 3 ערכים קבועים – ועל כן המפתחים יצרו enum (נקרא לו ENUM_X). מפתח אחר גילה שבדיוק אותו enum (נקרא לו 'ENUM_X) מוגדר במקום אחר בפרויקט, ודרש שמחלקות A ו B ישתמשו ב enum המקורי – כך שלא יתוחזק "קוד כפול". המפתח אשר כתב את הקוד במקור טען: "חבל לייצר reference לעוד תת פרויקט ב Build בשביל כזה דבר קטן. שיהיו שני enums זהים – לא יקרה שום דבר."
– "אבל אם תשנה אחד ותשכח את השני?! – מה אז?" הוויכוח התלהט והגיע לראש הקבוצה (!).
מה דעתכם? במי אתם הייתם מצדדים?
כיצד לסיים את הוויכוח?
לפני שאספר לכם מה הייתה הצעתי (שנדחתה פה-אחד ע"י 2 הצדדים, כדרך אגב) ארחיב את הדילמה:
מי שקצת בקיא ב"תיאוריה" של הנדסת תוכנה או Object Oriented Design (בקיצור OOD) – יכול לטעון: "שכפול קוד הוא אם כל רוע". יש עיקרון חשוב שאומר שאין לשכפל קוד: כל שינוי קונספטואלי צריך להתרגם בדיוק לנקודה אחת בקוד בה עושים שינוי. עקרון זה נקרא Don't Repeat Yourself Principle (בקיצור DRY) – וזהו עיקרון ידוע. קל להתחבר לטיעון הזה: אותו מכירים אותו, כנראה, מקורס התכנות הראשון שלנו.
האם זהו הטיעון המנצח שיפתור את הדיון? הממ… לא בטוח. הנה טיעון מלומד אחר: "אסור למודול להיות תלוי בחלקי-ממשק שאין לו בהם שימוש". במקרה שלנו יצרנו תלות לא רצויה בכל "Sub-Project 7" – כלומר בהרבה מחלקות וממשקים שאין לנו בהם שימוש. הממ… נשמע חמור!
עיקרון זה נקרא The Interface Segregation Principle. האם ייתכן שעקרונות ה OOD סותרים זה את זה?
כמה שאלות
- האם יכול אדם, המכיר את 2 העקרונות והוא בעל כושר שכנוע, להחליט באופן רגשי במי הוא מצדד וכל פעם לשלוף את "הטיעון התאורטי המתאים" בכדי להנחית "טיעון מנצח"? האם הוא יכול לעשות זאת מבלי להיות מודע לכך ולהאמין שהוא "רק פועל ע"פ התאוריה"?
- בהינתן שחוקי ה OOD סותרים לעתים אחד-את-משנהו, האם ישנם חוקים "חזקים יותר" שיש להעדיף?
- נניח ונוותר על אחד החוקים או שניהם – איזה "נזק" יתרחש? מה ההשלכות של "לא לציית לחוקים"? האם המאמץ הנוסף שבציות לחוקי ה OOD – משתלם?
- האם OOD היא מתודולוגיה מוצלחת? האם, לאחר כל השינויים בשיטות העבודה שחלו בעשור האחרון – היא עדיין יעילה או רלוונטית?
עסקתי הרבה בחיי ב Object Oriented Design: למדתי, למדתי עוד, ניסיתי, יישמתי, שאפתי ליישום "מושלם", הנחיתי אחרים במתודולוגיה וכו'. עדיין, ברגע זה, כשאני עומד ושואל את עצמי את השאלות הנ"ל – אין לי תשובה ברורה.
במשך שנים, פעלתי ע"פ כללי הנדסת-תוכנה שלמדתי. פעלתי? – נלחמתי בחירוף נפש, אפשר לומר. ניסיתי להעמיק כמה שיותר ולעשות את המירב. כיום אני יודע לומר שנצמדתי במידה רבה, לזרם בתוכנה שנקרא "Defensive Programming". זרם ששפת ג'אווה ו JEE היו אולי רגע השיא שלו. הוא מתבטא ברעיונות כגון:
- "על המתכנת צריך להגן על התוכנה בפני המפתחים – כולל הוא עצמו".
- עשה כל מה שתוכל כדי להפחית סיכונים לבאגים.
גישה זו יצרה הרבה משמעת (discipline), אך גם הובילה להמלצות כגון כתיבת מחלקה singleton בג'אווה בתוך enum על מנת להבטיח singleton "שפשוט אי אפשר לקלקל" [א]. מאז, נחשפתי לזרמים אחרים, אולי כמעט הפוכים – שגם הם יכולים לעבוד יפה. הבנתי (פעם נוספת) שאין אמת אחת.
עקרונות ה OOD – למבחן!
עתה אני ניצב מול עקרונות הOOD המוכרים, ואני רוצה להעמידם במבחן הזמן והרלוונטיות.
בניתי רשימה של העקרונות שאני זוכר / מודע אליהם וקיבצתי אותם, באופן גס, ל 3 קבוצות:
חלוקה הקוד למחלקות או מודולים
- (The Single Responsibility Principle (SRP
- (Don't Repeat Yourself Principle (DRY
- Encapsulation
- High-Cohesion / Low-coupling Principle
- The Common Closure / Reuse Principle
הגדרת הפשטות (abstactions) / אינטראקציה בין מחלקות
- The Open-Closed Principle
- The Liskov Substitution Principle
- The Release-Reuse Equivalency Principle
- The Stable Abstraction Principle
ניהול תלויות (מחלקות עד מודולים במערכות)
- The Interface Segregation Principle + גרסת הקוד שלו
- (Single Layer Of Abstraction Principle (SLAP
- The Dependency Inversion Principle
- The Acyclic Dependencies Principle
- The Stable Dependencies Principle
עקרונות אחרים של תכנון מערכת:
- Principle of Least Surprise (לא ממש OOD, בעצם עיקרון בתכנון של יוניקס)
- Fail Fast
- Units of Work
באופן גס ניתן לומר שחלוקת הקוד למודולים, הגדרת הפשטות וניהול תלויות היא רוב העבודה ב"הגדרת ארכיטקטורת תוכנה".
נראה לי שאבחר כמה מהעקרונות הנ"ל – ואתחיל לנתח אותם יותר לעומק.
הערות ומחשבות יתקבלו בשמחה.
הפוסט פורסם לראשונה בבלוג ארכיטקטורת תוכנה.
קרדיט תמונה: Computer Programming, Shutter Stock
הגב
14 תגובות על "Object Oriented Design: כמה שאלות חשובות"
* היי, אנחנו אוהבים תגובות!
תיקונים, תגובות קוטלות וכמובן תגובות מפרגנות - בכיף.
חופש הביטוי הוא ערך עליון, אבל לא נוכל להשלים עם תגובות שכוללות הסתה, הוצאת דיבה, תגובות שכוללות מידע המפר את תנאי השימוש של Geektime, תגובות שחורגות מהטעם הטוב ותגובות שהן בניגוד לדין. תגובות כאלו יימחקו מייד.
כתבה מעולה. רוצים עוד!
זה רק אני או שהפתרון טריויאלי?
תוציא את ה-enum מחוץ ל-2 המחלקות – כך שאף מחלקה לא תלויה במחלקה שאינה נדרשת, אך עדיין יכולה להשתמש ב-enum.
זה ידרוש שינוי יחסית מינורי במחלקות, אך יתן את ההפרדה הנדרשת.
אתה צודק לגמרי, וזה אכן טריוויאלי. או שיש עוד פרטים בתיאור המקרה שלא קיבלנו.
לא הבנתי את כל מהות הוויכוח. הפתרון כזה טריוויאלי.
מה שאתה מפספס:
1) זה שלא רצה להוסיף רפרנס בתשתיות – עדיין יצטרך להתעסק עם רפרנסים כדי להוציא את ה-enum;
2) זה שרצה את ה-enum תחת אחריותו, בלי להוסיף סיבוכים – עדיין יצטרך לוותר, ולהתעסק עם ממשקים החוצה, תהליכים אם רוצים לשנות משהו, ובטח יש גם תקציבים מחלקתיים שנכנסים פה לתמונה….
בקיצור – הבעיה האמיתית היא יותר פוליטיקה מארכיטקטורה…
למה אלון?
אם יש לך גישה לתשתית אתה פשוט שם פונקציה בתוך util שמחזירה enum.
ואז בקוד חדש ובתשתית במקום הנחוץ אתה משתמש בפונקציה הזאת.
אם תרצה לשנות/להוסיף ל- enum משהו, אזי תוסיף שם ושני המקומות יתעדכנו אוטומטית.
*הכל בהתחשב שיש לך גישה כתיבה לספריות התשתית.
* אם אסור לגעת בתשתית זה בעייתי.
במחלקה B אסור שיהיה פונקציה שמקבלת enum כפרמטר.
אלה מספר פונקציות כמספר האפשרויות של ה enum.
()setToA
()setToB
()setToC
במקום
( setTo(enum_m x
זה פותר את הבעיות הנ"ל ובעיה יותר חמורה אפשרית – שפרויקט אחד ירצה להוסיף מצב לenum שהפרויקט השני לא צריך.
נ.ב – לפי הגישה של uncle bob – פרק functions (אם אני זוכר נכון) ב clean coders
חסר מידע. אבל לצורך העניין תמיד אפשר להציב את הENUM בקובץ/פרויקט בודד, שאליו שני הצוותים יתממשקו.
ברמה הקונספטואלית, הפתרון צריך להיות כזה שמשרת את צרכי העסק, ובד"כ זה אומר פתרון מהיר ליישום.
אבל מי בכלל עובד עדיין עם שפות Strictly typed? תעבדו עם פייטון, פהפ, ולא תצטרכו להתעסק בשטויות…
מגניב, אשמח לראות איך נראת ב"פהפ" מערכת מסחר בינונית, תוכנה למכשור רפואי, או בעצם כל דבר שאסור כי יפול בזמן ריצה על שגיעות של סוגי נתונים.
למרות שבטח זה גם שטויות…
מערכת מסחר
Magento
מערכת לא קטנה
Facebook
Wordpress
לגבי מכשור רפואי, הנקודה שציינת היא פחות העניין כמו זמן ריצה וזיכרון
לPhp יכולת להתמודד עם סוגי משתנים וקאסטינג
השמרן מה הוא אומר? Refactor
והרדיקל? סמוך עלי…
לא כזאת דילמה מעניינת. אבל רשימת עקרונות טובה – תרחיב ואנשים יקראו…
מאמר מצויין שבא לברר התלבטויות של ממש, ושיוצר ציפייה להמשך.
אמנם, כפי שאמרו לפניי, הדוגמה דווקא נראית על פניה לא כזו בעייתית – אבל זה "על הנייר" – במצבים אמיתיים נכנסים לכאן המון שיקולים – "פוליטיקה" כפי שאמרו קודם.
תודה!
אופס.. הגבתי בטעות לתגובה במקום למאמר עצמו. (usability problem?)
מתנצל….
ראו את התגובה כתגובה למאמר.