Object Oriented Design: כמה שאלות חשובות

ליאור בר און מעלה שאלות בנוגע למספר מחלוקות ב-OOD, ואתם מוזמנים להביע את דעתכם ולהגיד מי צודק ובאילו עקרונות כדאי לדבוק בעת פיתוח תוכנה

לפני כשבוע נתקלתי בוויכוח הבא:

OOD questions

במערכת כלשהי, באזור לו נקרא “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 סותרים זה את זה?

shutterstock_39089305

כמה שאלות

  • האם יכול אדם, המכיר את 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

עקרונות אחרים של תכנון מערכת:

באופן גס ניתן לומר שחלוקת הקוד למודולים, הגדרת הפשטות וניהול תלויות היא רוב העבודה ב”הגדרת ארכיטקטורת תוכנה”.

נראה לי שאבחר כמה מהעקרונות הנ”ל – ואתחיל לנתח אותם יותר לעומק.
הערות ומחשבות יתקבלו בשמחה.

הפוסט פורסם לראשונה בבלוג ארכיטקטורת תוכנה.

קרדיט תמונה: Computer Programming, Shutter Stock

ליאור בר-און

ליאור בר-און הוא Chief Architect בחברת סטארטאפ ישראלית גדולה.

הגב

14 תגובות על "Object Oriented Design: כמה שאלות חשובות"

avatar
Photo and Image Files
 
 
 
Audio and Video Files
 
 
 
Other File Types
 
 
 

* היי, אנחנו אוהבים תגובות!
תיקונים, תגובות קוטלות וכמובן תגובות מפרגנות - בכיף.
חופש הביטוי הוא ערך עליון, אבל לא נוכל להשלים עם תגובות שכוללות הסתה, הוצאת דיבה, תגובות שכוללות מידע המפר את תנאי השימוש של Geektime, תגובות שחורגות מהטעם הטוב ותגובות שהן בניגוד לדין. תגובות כאלו יימחקו מייד.

סידור לפי:   חדש | ישן | הכי מדורגים
דורון מועלם
Guest

כתבה מעולה. רוצים עוד!

בוג'ובי
Guest

זה רק אני או שהפתרון טריויאלי?

תוציא את ה-enum מחוץ ל-2 המחלקות – כך שאף מחלקה לא תלויה במחלקה שאינה נדרשת, אך עדיין יכולה להשתמש ב-enum.
זה ידרוש שינוי יחסית מינורי במחלקות, אך יתן את ההפרדה הנדרשת.

ירון לוי
Guest

אתה צודק לגמרי, וזה אכן טריוויאלי. או שיש עוד פרטים בתיאור המקרה שלא קיבלנו.

רפי
Guest

לא הבנתי את כל מהות הוויכוח. הפתרון כזה טריוויאלי.

אלון
Guest

מה שאתה מפספס:
1) זה שלא רצה להוסיף רפרנס בתשתיות – עדיין יצטרך להתעסק עם רפרנסים כדי להוציא את ה-enum;
2) זה שרצה את ה-enum תחת אחריותו, בלי להוסיף סיבוכים – עדיין יצטרך לוותר, ולהתעסק עם ממשקים החוצה, תהליכים אם רוצים לשנות משהו, ובטח יש גם תקציבים מחלקתיים שנכנסים פה לתמונה….

בקיצור – הבעיה האמיתית היא יותר פוליטיקה מארכיטקטורה…

חן ראובן
Guest

למה אלון?
אם יש לך גישה לתשתית אתה פשוט שם פונקציה בתוך util שמחזירה enum.
ואז בקוד חדש ובתשתית במקום הנחוץ אתה משתמש בפונקציה הזאת.
אם תרצה לשנות/להוסיף ל- enum משהו, אזי תוסיף שם ושני המקומות יתעדכנו אוטומטית.

*הכל בהתחשב שיש לך גישה כתיבה לספריות התשתית.
* אם אסור לגעת בתשתית זה בעייתי.

Alon P
Guest

במחלקה B אסור שיהיה פונקציה שמקבלת enum כפרמטר.
אלה מספר פונקציות כמספר האפשרויות של ה enum.
()setToA
()setToB
()setToC
במקום
( setTo(enum_m x

זה פותר את הבעיות הנ”ל ובעיה יותר חמורה אפשרית – שפרויקט אחד ירצה להוסיף מצב לenum שהפרויקט השני לא צריך.

נ.ב – לפי הגישה של uncle bob – פרק functions (אם אני זוכר נכון) ב clean coders

גיק
Guest

חסר מידע. אבל לצורך העניין תמיד אפשר להציב את הENUM בקובץ/פרויקט בודד, שאליו שני הצוותים יתממשקו.
ברמה הקונספטואלית, הפתרון צריך להיות כזה שמשרת את צרכי העסק, ובד”כ זה אומר פתרון מהיר ליישום.
אבל מי בכלל עובד עדיין עם שפות Strictly typed? תעבדו עם פייטון, פהפ, ולא תצטרכו להתעסק בשטויות…

שם (לא חובה)
Guest

מגניב, אשמח לראות איך נראת ב”פהפ” מערכת מסחר בינונית, תוכנה למכשור רפואי, או בעצם כל דבר שאסור כי יפול בזמן ריצה על שגיעות של סוגי נתונים.

למרות שבטח זה גם שטויות…

בוקי
Guest

מערכת מסחר
Magento
מערכת לא קטנה
Facebook
Wordpress

לגבי מכשור רפואי, הנקודה שציינת היא פחות העניין כמו זמן ריצה וזיכרון
לPhp יכולת להתמודד עם סוגי משתנים וקאסטינג

איל
Guest

השמרן מה הוא אומר? Refactor
והרדיקל? סמוך עלי…

לא כזאת דילמה מעניינת. אבל רשימת עקרונות טובה – תרחיב ואנשים יקראו…

יודה
Guest

מאמר מצויין שבא לברר התלבטויות של ממש, ושיוצר ציפייה להמשך.

אמנם, כפי שאמרו לפניי, הדוגמה דווקא נראית על פניה לא כזו בעייתית – אבל זה “על הנייר” – במצבים אמיתיים נכנסים לכאן המון שיקולים – “פוליטיקה” כפי שאמרו קודם.

תודה!

עמרי
Guest
בכנות… הדוגמה קצת חוטאת לרעיון שאתה מנסה להעביר. לא הגיוני שאתה מציג דילמה ארכיטקטונית במנותק מעולם התוכן. שכן עולם התוכן הוא זה שעוזר לקבוע מי הוא זה שאחראי על אותו enum, מי עושה רפרנס למי, והאם צריך לשכפל קוד או לא. למשל יש הרבה מאוד מקרים שבהם כן נכון לשכפל קוד, למשל במקרה שבוא קוד הוא במקרה זהה אך שייך לתחומי אחריות שונים (Domain) . כדוגמה מעולם תוכן – יש לנו כתובת בתוכנת ניווט ותוכנת מיון דואר… נראה כמו בזבוז? לא? אולי שתוכנת הניווט תיקח את הכתובות מתוכנת הדואר? או להפך? אך כשמסתכלים לעומק רואים שבעצם הם אולי נראים זהים… Read more »
עמרי
Guest

אופס.. הגבתי בטעות לתגובה במקום למאמר עצמו. (usability problem?)
מתנצל….
ראו את התגובה כתגובה למאמר.

wpDiscuz

תגיות לכתבה: