ניתן לומר שהגדרת ארכיטקטורה מורכבת מ 4 פעולות בסיסיות:
תחום ה Object Oriented Design הוא תולדה של רעיונות שהתפרסמו במספר ספרים / מאמרים משפיעים - אך בניגוד למה שניתן לחשוב, אין הגדרה "חד-משמעית וברורה" מהם "עקרונות ה Object Oriented Design".
העשור האחרון
האם העקרונות הארכיטקטונים של חלוקה מערכת למודולים או יצירת Abstractions נכונים גם לכתיבת קוד? - אני מאמין שכן.
כלומר: ארכיטקטים יכולים ללמוד על ארכיטקטורת-מערכת מתוך עקרונות ומגמות של כתיבת קוד, כשם שמתכנתים יכולים ללמוד לכתוב קוד טוב יותר ע"י למדיה של עקרונות "ארכיטקטונים". להזכיר: ההפרדה ל"ארכיטקט" ול "מתכנת" היא גם חצי-מלאכותית, אני משתמש בה כי היא נוחה לצורך הדיון.
הנה שתי דוגמאות:
עקרון קוד: המעט בכתיבת הערות - ע"י כתיבת קוד שמסביר את עצמו טוב יותר ("Literary Code").
אני לא מכיר כלל ברור ש"תיעוד ארכיטקטורה הוא סממן לארכיטקטורה לא ברורה" אבל דיי ברור לי שזה נכון. אם צריך לתעד ארוכות את הארכיטקטורה - כנראה שהיא לא ברורה ואפשר לנסות לשפר את המטפורות / הגדרת המודולים בכדי שתהיה ברורה יותר. כך יהיה צורך בפחות תיעוד.
עקרון ארכיטקטוני: Interface Segregation Principle
עקרון זה אומר שמודול לא אמור להיות תלוי ב interfaces רבים שאינם בשימוש. אם נוצר מצב כזה - יש לפצל את ה Interfaces כך שהמודול יהיה תלוי, עד כמה שאפשר, רק ב Interfaces שהוא משתמש בהם בפועל. העיקרון נכון מאוד גם למתודות בתוך interface יחיד (רמת ה Design) או לפרמטרים בחתימה של פונקציה בתוך הקוד (רמת הקוד).
עוד היבט קוד שאני מאמץ מעקרון ה ISP הוא לנסות ולהימנע משימוש בספריות (כגון "Open Source") שיש לי מעט שימוש בהן. אני אשתדל לא להכליל במערכת ספרייה של אלף שורות קוד - אם אני משתמש רק ב 50 מהן. אני מעדיף למצוא ספרייה אחרת או אפילו לכתוב אותן שורות קוד לבד. מדוע? א. סיכוי לבעיות מ 950 שורות קוד לא רלוונטיות, ב. מסר לא ברור האם נכון "להשתדל" להשתמש במתודות אחרות בספריה או לא. ג. אם צריך לשנות / לדבג - ייתכן וצריך להבין הרבה קוד בדרך שלא רלוונטי למקרה שלנו.
אפשר להראות כמה דוגמאות של עקרונות ש"עוברים פחות נקי":
בסופו של דבר - יש הרבה מאוד חפיפה בין עקרונות "ארכיטקטורה" לעקרונות "קוד", כך שאין כ"כ חדש ללמוד. הרעיונות חוזרים על עצמם בשינוי אדרת. חלק מהעקרונות (למשל KISS = Keep It Simple Stupid) הם פשוט אוניברסליים.
עדכון: אף עיקרון בעצם לא דורש ש"נגרום לתוכנה לעבוד". כן, כן! גם זה חלק בעל חשיבות :) גם בקוד, גם בתכנון וגם בארכיטקטורה. עד כמה שזה נשמע משעשע - לעתים אנחנו שוכחים את זה (בעיקר "ארכיטקטים").
עדכון2: ארצה להרחיב מעט על העיקרון שנקרא SLAP, לקוראים שלא מכירים אותו. הוא אומר את הדבר הבא: "על כל פונקציה להיות ברמה יחידה של הפשטה". למשל, אם יש לי פונקציה:
הרי שזו חריגה ברורה מהעיקרון. הפונקציה drawItems עוסקת בפרטים: כיצד לצייר פריט אחר פריט. מה פתאום היא מבצעת שמירה לבסיס הנתונים?! (פעולה ברמת הפשטה גבוהה יותר - OMG!)
השינוי, אם כן, שנדרש בקוד הוא להעביר את השורה dbTable.save לפונקציה שביצעה את הקריאה ל drawItem - בהנחה שזו רמת ההפשטה המתאימה.
קושי מסוים בשימוש ב SLAP הוא שאין "מד רמת-הפשטה", כזה שנכוון אותו לשורה בקוד והוא יגיד לנו "רמה 6!" או "רמה 7!". זה הכל בראש שלנו כמפתחים ובני-אדם אינטליגנטים. לפעמים יהיו "סתירות" כך שיוחלט שפעולה X תהיה פעם אחת ברמה n ופעם אחרת ברמה n+1. אני אומר: זה אנושי. זהו עקרון חשוב - פשוט קחו אותו בפרופורציה ("We figured they were more actual guidelines").
במקום להסתגר כשנה וחצי ולהוציא בסוף פוסט באורך של ספר (גישת ה Waterfall), אני מנסה לתקוף את הנושא בצורה אג'ילית: בעזרת nibbles ("ביסים קטנים"). כמו ערמה של דוקים לפרק אחד אחד - עד אשר אוכל להגיע לגרעין הקשה של העניין.
שיהיה לנו בהצלחה!
פ.ס. : הערות, מחשבות, ביקורות - יתקבלו בהחלט בשמחה!
- חלוקת המערכת למודולים / תתי מערכות
- ניהול תלויות (בין המודולים)
- יצירת הפשטות (Abstractions) והגדרת API
- תיעוד הארכיטקטורה.
כמעט כל העקרונות והטכניקות של הגדרת ארכיטקטורה (למשל Quality Attributes או חלוקה ל Views) הן הנחיות כיצד לבצע פעולות בסיסיות אלו בצורה נכונה יותר.
Quality Attributes היא טכניקה שכתבתי עליה בפוסט הזה והזה.
Quality Attributes היא טכניקה שכתבתי עליה בפוסט הזה והזה.
תכנון מונחה אובייקטים - OOD
תחום ה Object Oriented Design הוא תולדה של רעיונות שהתפרסמו במספר ספרים / מאמרים משפיעים - אך בניגוד למה שניתן לחשוב, אין הגדרה "חד-משמעית וברורה" מהם "עקרונות ה Object Oriented Design".
2 המודלים המקובלים ביותר להגדרת OOD כיום הם:
- עקרונות ה S.O.L.I.D שהוצגו ע"י "דוד בוב" (Robert C. Martin) בספר Agile Software Development, Principles, Patterns, and Practices (בקיצור PPP).
- מודל ה GRASP שתואר ע"י קרייג לרמן בספר Applying UML and Patterns
העשור האחרון
זרם ה Agile השפיע גם הוא רבות על OOD וקידם כמה רעיונות:
- "כשאתה מקודד - אתה בעצם עושה Design" (מקור: TDD) --> ומכאן רעיונות כמו "Design by Tests/Coding"
- ההכרה שביצוע Design או הגדרת ארכיטקטורה הם Waste - שיש לנסות ולייעל אותם ("Just Enough Software Architecture")
- ההבנה שחיזוי העתיד הוא דבר בלתי-מציאותי, גם על ידי אנשים נבונים למדי, במיוחד במוצרים חדשים אך גם במוצרים קיימים. ירידת קרנם של "העיקרון הפתוח-סגור" (מתוך SOLID) ו "(Predictable Variations (PVs" (מתוך GRASP) והצבת סימני שאלה בפני כמה מהעקרונות האחרים...
התאוריה המאוחדת
בכל מקרה ישנה השאלה: בהינתן עקרונות ל"ארכיטקטורה", "תכנון" ו"כתיבת קוד" - היכן בדיוק עוברים הגבולות הללו? מתי יש להשתמש בעקרון ארכיטקטוני ומתי בטכניקת Design?
אני רוצה לטעון שהקו הוא דיי מלאכותי - וכדאי להתייחס אליו ככזה.
כמו שיש דמיון בין יחסי גומלין בין אנשים בודדים, קבוצות אנשים ומדינות (קונפליקטים, "כבוד", מעשה טוב שנזכר במשך שנים) וניתן להכליל ביחסים ברמות שונות עקרונות דומים, ניתן למצוא ולהכליל עקרונות דומים ברמות שונות של תוכנה.
ניתן להשתמש בכללי הקוד, התכנון והארכיטקטורה מבלי להתייחס לגבולות - חוץ מאשר בכמה מקרים יוצאי דופן.
ניסיתי למפות את "ארבע הפעולות הבסיסיות של הגדרת ארכיטקטורה" לפעולות תכנון וכתיבת קוד:
אפשר לראות שמות שונים ("גבוהים" ו"נמוכים") לרעיונות דומים - אבל ההקבלה הרעיונית יפה למדי.
אני רוצה לטעון שהקו הוא דיי מלאכותי - וכדאי להתייחס אליו ככזה.
כמו שיש דמיון בין יחסי גומלין בין אנשים בודדים, קבוצות אנשים ומדינות (קונפליקטים, "כבוד", מעשה טוב שנזכר במשך שנים) וניתן להכליל ביחסים ברמות שונות עקרונות דומים, ניתן למצוא ולהכליל עקרונות דומים ברמות שונות של תוכנה.
ניתן להשתמש בכללי הקוד, התכנון והארכיטקטורה מבלי להתייחס לגבולות - חוץ מאשר בכמה מקרים יוצאי דופן.
ניסיתי למפות את "ארבע הפעולות הבסיסיות של הגדרת ארכיטקטורה" לפעולות תכנון וכתיבת קוד:
אפשר לראות שמות שונים ("גבוהים" ו"נמוכים") לרעיונות דומים - אבל ההקבלה הרעיונית יפה למדי.
האם העקרונות הארכיטקטונים של חלוקה מערכת למודולים או יצירת Abstractions נכונים גם לכתיבת קוד? - אני מאמין שכן.
כלומר: ארכיטקטים יכולים ללמוד על ארכיטקטורת-מערכת מתוך עקרונות ומגמות של כתיבת קוד, כשם שמתכנתים יכולים ללמוד לכתוב קוד טוב יותר ע"י למדיה של עקרונות "ארכיטקטונים". להזכיר: ההפרדה ל"ארכיטקט" ול "מתכנת" היא גם חצי-מלאכותית, אני משתמש בה כי היא נוחה לצורך הדיון.
הנה שתי דוגמאות:
עקרון קוד: המעט בכתיבת הערות - ע"י כתיבת קוד שמסביר את עצמו טוב יותר ("Literary Code").
אני לא מכיר כלל ברור ש"תיעוד ארכיטקטורה הוא סממן לארכיטקטורה לא ברורה" אבל דיי ברור לי שזה נכון. אם צריך לתעד ארוכות את הארכיטקטורה - כנראה שהיא לא ברורה ואפשר לנסות לשפר את המטפורות / הגדרת המודולים בכדי שתהיה ברורה יותר. כך יהיה צורך בפחות תיעוד.
עקרון ארכיטקטוני: Interface Segregation Principle
עקרון זה אומר שמודול לא אמור להיות תלוי ב interfaces רבים שאינם בשימוש. אם נוצר מצב כזה - יש לפצל את ה Interfaces כך שהמודול יהיה תלוי, עד כמה שאפשר, רק ב Interfaces שהוא משתמש בהם בפועל. העיקרון נכון מאוד גם למתודות בתוך interface יחיד (רמת ה Design) או לפרמטרים בחתימה של פונקציה בתוך הקוד (רמת הקוד).
עוד היבט קוד שאני מאמץ מעקרון ה ISP הוא לנסות ולהימנע משימוש בספריות (כגון "Open Source") שיש לי מעט שימוש בהן. אני אשתדל לא להכליל במערכת ספרייה של אלף שורות קוד - אם אני משתמש רק ב 50 מהן. אני מעדיף למצוא ספרייה אחרת או אפילו לכתוב אותן שורות קוד לבד. מדוע? א. סיכוי לבעיות מ 950 שורות קוד לא רלוונטיות, ב. מסר לא ברור האם נכון "להשתדל" להשתמש במתודות אחרות בספריה או לא. ג. אם צריך לשנות / לדבג - ייתכן וצריך להבין הרבה קוד בדרך שלא רלוונטי למקרה שלנו.
אפשר להראות כמה דוגמאות של עקרונות ש"עוברים פחות נקי":
- מקבילה ל"ניהול תלויות" ברמת הקוד - לא מצאתי בדיוק. הסתפקתי בעקרון של הימנעות ממשתנים גלובליים.
- לרעיון של חלוקת מודולים ע"פ "Unit Of Work" (כך שקבוצות פיתוח שונות יוכלו לעבוד במקביל עם מינימום תלות) - אני לא חושב שיש הקבלה אמיתית ברמת קוד.
- העיקרון האלמותי של (DRY (Do Not Repeat Yourself הוא "No Brainer" בקוד, אבל הופך לנושא מורכב ולא חד-משמעי ברמת הארכיטקטורה.
בסופו של דבר - יש הרבה מאוד חפיפה בין עקרונות "ארכיטקטורה" לעקרונות "קוד", כך שאין כ"כ חדש ללמוד. הרעיונות חוזרים על עצמם בשינוי אדרת. חלק מהעקרונות (למשל KISS = Keep It Simple Stupid) הם פשוט אוניברסליים.
עדכון: אף עיקרון בעצם לא דורש ש"נגרום לתוכנה לעבוד". כן, כן! גם זה חלק בעל חשיבות :) גם בקוד, גם בתכנון וגם בארכיטקטורה. עד כמה שזה נשמע משעשע - לעתים אנחנו שוכחים את זה (בעיקר "ארכיטקטים").
עדכון2: ארצה להרחיב מעט על העיקרון שנקרא SLAP, לקוראים שלא מכירים אותו. הוא אומר את הדבר הבא: "על כל פונקציה להיות ברמה יחידה של הפשטה". למשל, אם יש לי פונקציה:
הרי שזו חריגה ברורה מהעיקרון. הפונקציה drawItems עוסקת בפרטים: כיצד לצייר פריט אחר פריט. מה פתאום היא מבצעת שמירה לבסיס הנתונים?! (פעולה ברמת הפשטה גבוהה יותר - OMG!)
השינוי, אם כן, שנדרש בקוד הוא להעביר את השורה dbTable.save לפונקציה שביצעה את הקריאה ל drawItem - בהנחה שזו רמת ההפשטה המתאימה.
קושי מסוים בשימוש ב SLAP הוא שאין "מד רמת-הפשטה", כזה שנכוון אותו לשורה בקוד והוא יגיד לנו "רמה 6!" או "רמה 7!". זה הכל בראש שלנו כמפתחים ובני-אדם אינטליגנטים. לפעמים יהיו "סתירות" כך שיוחלט שפעולה X תהיה פעם אחת ברמה n ופעם אחרת ברמה n+1. אני אומר: זה אנושי. זהו עקרון חשוב - פשוט קחו אותו בפרופורציה ("We figured they were more actual guidelines").
סיכום
כפי שאולי אתם שמים לב, התחלתי לאחרונה לתקוף את נושא הארכיטקטורה וה OOD. זה נושא גדול ומורכב, עם זוויות רבות לכל עניין.במקום להסתגר כשנה וחצי ולהוציא בסוף פוסט באורך של ספר (גישת ה Waterfall), אני מנסה לתקוף את הנושא בצורה אג'ילית: בעזרת nibbles ("ביסים קטנים"). כמו ערמה של דוקים לפרק אחד אחד - עד אשר אוכל להגיע לגרעין הקשה של העניין.
שיהיה לנו בהצלחה!
פ.ס. : הערות, מחשבות, ביקורות - יתקבלו בהחלט בשמחה!