עוד שאלות Class Diagram

guznik

New member
עוד שאלות Class Diagram

היי לכם. יש לי כמה שאלות שבטח אין להן תשובות חד-משמעיות, אבל אני אשמח לשמוע את דעתכם. אני כותב Class Diagram למודל הנתונים. בגדול אפשר להגיד שאני כותב זוגות של מחלקות וממשקים, כאשר הדבר היחיד שיש במחלקה ואין בממשק זה שדה id (כמובן שהוא private עם public accessors) לצורך persistance. הבעיה הראשונה שלי היא שזה מסורבל לכתוב את כל ה-accessors methods בדיאגרמה של הממשק, ואני תוהה אם מקובל לכתוב פשוט שדות בממשק, למרות שטכנולוגית זה אסור. עוד בנושא זה, אם אמרנו שההבדל בין הממשקים והמחלקות של מודל הנתונים זה ה-id, האם כדאי לשרטט עבור על זוג כזה את קשר המימוש ובדיאגרמה כל המחלקות יראו אותו דבר (שדה id)? אם כדאי שכל המחלקות ירשו ממחלקת אב שמכילה רק את שדה id? האם כדאי להשתמש בסטראוטיפ כמו Entity? האם לפצל לשתי Class Diagrams - אחת לממשקים ואחת למחלקות? יש למישהו דוגמא מומלצת? עוד משהו שמציק לי הוא Code Generation - כיוון שאני לא יכול לשים שדות בממשקים, האפשרויות שלי הן: 1. לשרטט קודם את המחלקות עם השדות כ-private, לחולל עבור כל השדות accessors ואז לחולל ממשק מתוך המחלקה, מה שנראה לי תהליך קצת הפוך. 2. לכתוב את הממשק עם כל ה-accessors, לחולל ממנו מחלקה ואז להוסיף לה את כל השדות כ-private וידנית לכתוב את התוכן של כל ה-accessors, שזה פשוט עבודה שחורה. אני נוטה יותר לפיתרון הראשון, אבל מציק לי שהתהליך הפוך. יש לכם מה להגיד בנושא? תודה לכל מי שהייתה לו סבלנות לקרוא את כל זה... חג חירות שמח!
 

עידו פ

New member
לא יודע אם לקרוא לזה שאלות או

הבהרות, או אולי שאלות הבהרה, אבל בכל אופן : - למה אתה מחלק את ישויות המידע שלך לממשק ומחלקה ? למה לא פשוט להגדיר רק מחלקה ? מה הרווח שלך מכך שאתה מפריד את זה ? - class diagram בהקשר ה-uml-י נועד להמחשת ישויות המידע של המערכת. אף אחד לא קבע חוקים מה מותר ומה עשור לעשות ב-CD, כל מה שחשוב הוא שאתה מסוגל להשתמש בו בשביל להסביר את מודל הישויות ובשביל להעביר לתוכניתן את המידע הנדרש על-מנת שיוכל לפתח את המערכת - לרשת ממחלקה רק עבור generalization זה דבר רע במהותו. אם אתה מגיע למצב שיש לך מכנה משותף למחלקות, עדיף כבר להגדיר interface ושכולם יממשו אותו (מי דרך אגב אמר שכל הישויות הן בעלות מזהה מאותו טיפוס ?!) - לא הבנתי מה הכוונה ב-"טכנולוגית זה אסור", אני מפנה אותך להבהרה הראשונה (ב-UML אין דבר כזה אסור). - אני יכול להבין שבשלב אפיון המערכת, יותר מעניין לדעת את מבנה המחלקה בתור ישות (מאפיינים + פעולות) ואילו בשלב העיצוב כבר יותר מעניין לדעת איך המחלקה תראה בהקשר לאיך היא תיושם (עם/בלי שדה ID, עם/בלי מתודות persistance) - לרוב זה פשוט אומר שעושים שני CD, אחד בשלב האפיון (שלא מבוצע לא code generation) והרחבה של CD האפיוני בשלב העיצוב (CD שלו כן עושים code generation). אני חושב שאי-ההבנה בין הגישות נובעת מהסיבה הראשית שאתה מחלק את ה-CD שלך לממשקים ומחלקות, אז אם תוכל להבהיר את הסיבה לכך, אולי אני אוכל "להתחבר" לצורת המחשבה שלך.
 

guznik

New member
הסברים

לחלוקה למחלקות וממשקים יש כמה סיבות: 1. אני רוצה שהשכבה העסקית לא תכיר את שדה ה-ID, ולכן הוא לא יוגדר בממשק. השכבה העסקית וכל מה שמעליה בכלל לא יעבדו עם מחלקות של מודל הנתונים, אלא רק עם ממשקים. רק שכבת הגישה לנתונים תכיר את המחלקות ותוכל ליצור אובייקטים עבור השכבות שמעליה. 2. יכול להיות מצב שאני לא ארצה לתת לשכבה העסקית ומעלה גישה ל-setter של של שדה באובייקט מסויים. במקרה כזה אני אוכל לשים setter במחלקה כדי ששכבת הגישה לנתונים תוכל לעדכן אותו אבל השכבות שמעליה לא יוכלו לעדכן אותו כי הן לא יראו את ה-setter בממשק. 3. אני ארצה להשתמש במודל נתונים "חכם", כלומר עם מתודות "אמיתיות" (לא accessors). במקרה כזה שימוש בממשקים מאוד יעזור בפיתוח כי התוכניתן שעובד על השכבה העסקית למשל יוכל לכתוב מחלקת Stubs שתהיה מחוייבת לממש את כל המתודות. בגדול אפשר להגיד שאני פשוט שואף למקסימום הגבלות על התוכניתן שלא יוכל לחרוג מהמגבלות של מודל הנתונים ומה שאפשר לעשות איתו, בין אם בטעות ובין אם בעקבות יצירתיות יתר (ואני יודע כי גם אני אוהב להיות יצירתי בקוד שלי וזה לפעמים גורם לי להתרחק ממה שהגדירו לי). אני אכן מקבל CD מהמאפיין של מודל נתונים "טיפש" ואני וכותב CD חדש שמכיל מודל נתונים "חכם" ואובייקטים תשתיתיים (DAOs, Factories, Service Classes...). משהו שצריך להבין בצורת העבודה של הצוות שלי, זה שהשאיפה היא שאני בתור מעצב אגדיר עד הסוף את כל החבילות והמחלקות והתוכניתנים יתעסקו רק בקוד הפנימי. בגלל זה אני רוצה דיאגרמה שניתן יהיה לחולל ממנה את המחלקות והממשקים - ככה גם אם יהיה צורך לעדכן את העיצוב, האובייקטים יתעדכנו בהתאם, ומנסיון העבר מאוד קל לפספס עדכון של שדה בקוד בעקבות עדכון העיצוב.
 

עידו פ

New member
כמה הערות

1. ישנן טכניקות שונות להגדרת שדות כבלתי נגישים למחלקות חיצוניות, שאינן דורשות עבודה כה נרחבת בהגדרת Inerface. בין השיטות ניתן למצוא את friend של ++C ו-internal של דוטנט (כמובן שאם מי שצריך להכיר את ה-ID זו המחלקה עצמה בלבד, תמיד אפשר לשמור את השדה כ-Private !) 2. הגדרה סטנדרטית של private/public לא תעזור לך לחסום setters למחלקה א' ולא למחלקה ב', וגם interface לא יעזור מאחר ו-Interface מגדיר מאפיינים ומתודות שהן public. פתרונות למצבים אלו, כפי שציינתי מקודם, תלויות בסביבת הפיתוח, בין אם ע"י שימוש ב-friend/interal או ע"י טכניקות אחרות של סביבות הפיתוח, כגון attributes בדוט נט שמאפשרים הסתרה של מתודות ב-intellisense 3. אם אתה רוצה "לאכוף" על התוכניתן שלך מתודות שהוא ימלא, ואתה משתמש ב-CD, אז הכי פשוט זה לבצע עבורו code generation שייצר לו את המתודות (כמו שדוט נט עושה כשהוא מייצר מתודות עם throw exception "not implemented") - אני אישית עשיתי את זה לא פעם עם כלי חילול קוד (במקרה שלי עם EA ועם XDE). מנסיון אישי, רצון לקבוע הגבלות על תוכניתן באמצעות interface מוביל בסוף לאיזשהו interface של מספר מתודות זעום (כגון insert/update/delete) ולעוד הרבה מתודות אחרות בכל אחת מהמחלקות שלא לפי ה-interface (כגון deleteByX/DuplicateY/UpdateBulkZ ...). אם תמשיך בשיטה זו, טיפ קטן להמשך - עוד כמה חודשים, נסה לבדוק בקוד שלך כמה פעמים אתה מיישם פולימורפיזם על הישויות (מסתכל על ישות כעל ה-Interface שהיא מממשת). בהצלחה, עידו.
 

guznik

New member
הבהרות

1. הטכנולוגיה היא Java אם זה רלוונטי, וזה לא שאני לא רוצה שכל המחלקות האחרות לא יכירו שדה מסויים (כשאני אומר שדה אני מתכוון שהוא private ויש לו public accessors), אלא ששדה מסויים יהיה נגיש למחלקות משכבת הגישה לנתונים ולא למחלקות משכבות עליונות. 2. ממשקים יכולים לעזור במקרה כזה: מחלקת C מממשת את ממשק I ויש במחלקת C שדה id (לצורך עבודה מול בסיס הנתונים) שאינו מוגדר בממשק I. מחלקת גישה לנתונים מכילה מתודה שהערך המוחזר שלה הוא מטיפוס I. מחלקה מהשכבה העסקית קוראת לאותה מתודה ומקבלת אובייקט מטיפוס I. כמובן שהמחלקה של אותו אובייקט מוחזר היא C, אבל המחלקה מהשכבה העסקית לא יודעת את זה, ולכן היא לא יכולה לגשת לשדה id (ולגרום נזק). זו בדיוק ההסתרה שאני רוצה. 3. זה תמיד אפשרי, אבל זה פיתרון של סביבת פיתוח ולא של טכנולוגיית הפיתוח. הממשק הרי מהווה "חוזה" בין מחלקות/מודולים/שכבות במערכת. אם מחליטים שהתוכניתן פשוט לא נוגע בממשקים, הוא לא יכול להתעלם מהאכיפה, בעוד שאם אני מספק לו מחלקות הוא יוכל לשנות אותן ובעצם לשנות את "החוזה". הבעיה תהיה כשתוכניתנים עובדים על מודולים שתלויים זה בזה - אם העיצוב לא יגדיר מראש בדיוק איך המחלקות מדברות ביניהן, זה יגרום לחוסר סדר בעבודה והתוכניתנים יצטרכו לתאם ביניהם את העבודה כל הזמן או שבשלב האינטגרציה הם יגלו שהמוגולים שלהם לא מדברים זה עם זה. תוכניתן לא יוכל לכתוב מתודות public נוספות מעבר למה שמוגדר בממשק (הוא יכול, אבל אף אחד לא יוכל לגשת אליהן) כי מי שיקרא למתודות של האובייקט לא יכיר את מימוש המחלקה, אלא רק את הממשק שלה. אם התוכניתן יראה צורך במתודות נוספות הוא יוכל לבקש להוסיף אותן לממשק וזה גם יעודכן בעיצוב, כך שכל מי שעובד עם הממשק יהיה מיודע. אני מסייג את זה קצת - התוכניתן יוכל להוסיף מתודות public לשימוש ע"י המחלקות שכן מכירות את המחלקה (במקרה שלנו רק מחלקות גישה לנתונים) ואין לי בעיה עם זה כי זה נחשב לעניין פנימי בשכבה. עדיין אובייקטים משכבות אחרות לא יראו את זה וזה בדיוק מה שאני רוצה. תודה על כל התשובות.
 

עידו פ

New member
לאחר מחשבה מעמיקה

של 2-3 דקות, אני יכול להתחבר לחששות שלך ולדרך הארכיט' שלך ולהסכים עם הגישה. אני לא אומר שאני מעכשיו אעבוד כמוך, אבל מבחינת צורת העבודה שבחרת, אני לא רואה הרבה מינוסים, כל עוד אתה תדאג בתור מעצב לדברים הבאים: 1. ה-CD הוא למעשה יותר עבור ה-interface ופחות עבור המחלקות (אף על פי שצריך לשמור אותו עדכני עבור שניהם) 2. הגיון בריא בהפרדה בין מה שנמצא בממשק ובין מה שנמצא במחלקה 3. מאחר ואתה לא סומך על התוכניתנים שלך כל כך - הרבה code review !
 

MalcolmX

New member
Attributes in Interfaces

In UML2 you may have attributes in an interface. In Java you can try using an abstract class instead of an interface and add the attributes necessary for the business logic and add the implementation attributes to the derived classes.Shimon
 
למעלה