oop best practices

orengolan

New member
oop best practices

I just wonder what is considered a better OO approach: x=myCalc.Add(5,8) or this: myCalc.FirstNumber=5 myCalc.SecondNumber=8 x=myCalc.Add() my intuition is toward the second option, but i don't know why. can anyone explain the differences? does any one know good books or articles about OOP or OOD?​
 

עידו פ

New member
אני לא כל כך סגור על למה לדעתך יש

הבדל בגישות. בשני המקרים מדובר על מחשבון שמקבל שני פרמטרים ומחבר ביניהם. כל ההבדל בין העליון לתחתון הוא הצורה בה מעבירים את הפרמטר למתודה - מעבר לכך אין שום הבדל בין שתי המחלקות. מה שכן, הצורה השנייה קצת קשה לתחזוקה. נניח היית רוצה לעשות מתודת ADD שמקבלת יותר משני פרמטרים (A+B+C) - היית מוסיף מאפיין thirdNumber ?! ואח"כ גם fourth ? גם מה היה קורה אם היית רוצה מחשבון שמאפשר לטפל במספרים שלמים בלבד ? או אולי במספרים מרוכבים ? לא היה יותר קל להגדיר את המתודה add כבעלת overloades מאשר להגדיר עוד ועוד מאפיינים ?
 

arnonrgo

New member
כמו שציינת

דוקא כמו שצינת בהמשך התשובה (במקרה הזה) יש יתרון לצורה הראשונה בגלל הגמישות הרבה יותר לשינויים למשל (בNET.) עם שימוש בparms[] בפרמטר אניתן היה לתמוך בחיבור של כל מספר משתנים וכמו בדוגמא שלך ניתן באמצעות overloads לתמוח במספר types (למרות שזה תלוי בשפת המימוש למשל שפות שאינן strongly-typed אין את הבעיה הזו) ארנון
 

hg1979

New member
יש הבדל מהותי

הגישה הראשונה נקראה Chunky והשניה נקראת Chatty אני מקווה שאין צורך להסביר את השמות, אבל לענינו, בניגוד לשתי התגובות שראיתי אני חושב שהשניה היא יותר קלה לתחזוקה, נכון בדוגמא המאד מופשטת של חיבור שני מספר זה כביכול לא בא לידי ביטוי אבל בדוגמאות מורכבות יותר לדוגמא כמו חיפוש אנשים במערכת מסוימת מטודה שתקבל את כל הפרמטרים האפשריים לחיפוש היא לא הגיונית לדוגמא חיפוש לפי שם פרטי שם משפחה ת.ז גיל מקום מגורים למטודה יהיו 5 פרמטרים, אם מחר נוסיף פרמטר חדש נצטרך או להוסיף פרמטר למטודה או לעשות Overload למתודה עם 6 פרמטרים וכד' וכמובן מה קורה שאנחנו לא יכולים לשנות את המטודות ? (Web Service לדוגמא) בגישה השניה פשוט נוסיף עוד שורה במקרה הצורך ולא נצטרך לשנות שום מטודה פשוט תהיה מטודה אחת בלי פרמטרים שתבצע את הדבר הרלווטני הסיבה העיקרית לשימוש בשיטה Chunk-ית הוא במקומות ש-Round Trip של כל קריאה הוא "יקר" כמו קריאה ל Web Service לדוגמא
 

arnonrgo

New member
../images/Emo26.gif

אני לפחות התיחסתי לדוגמא שנשאלה ושם (לדעתי) יש עדיפות לצורה הראשונה במקרים אחרים צריך לשפוט לגופם לגבי chatty וChunky זה לא ברור מהsyntax אם אכן יתקיים דו-שיח chatty בגרסא השניה מפני שזה תלוי במימוש 1. myCalc צריך להיות אוביקט מרוחק 2. בתור שכזה הוא אמור לממש כל השמה לProperty כקריאה לאוביקט המרוחק (למשל גם אם myCalc הוא proxy לאוביקט מרוחק עדיין שליחת הפרמטרים יכולה להתרחש רק בקריאה לADD) ארנון
 

orengolan

New member
chatty/chunky and remote objects

So if i understand your idea speaking of chatty or chunky is only relevant when myCalc is a remote object (web service, for example). And if myCalc is a class in the same proccess of the client, i don't really care about it.​
 

arnonrgo

New member
אכן

לפחות לדעתי אין הבדל אמיתי אם אתה לא יוצא לרשת ארנון
 

arnonrgo

New member
ועוד דבר

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

hg1979

New member
כן

אחד הפתרונות הוא ליצור CLASS שנקרא לדוגמא SearchParameters ולמלא אותו בצורה Chatty-ית לדוגמא (תסלחו לי שאני לא כותב Properties בשביל הדוגמא) public class SearchParamters { public string firstName = string.empty; public string lastName = string.empty; public int Age = 0; public string Location = string.empty; } לפני הקריאה למתודה SearchParameters s = new SearchParameters(); s.Firstname = "myname"; s.LastName = "yourname"; s.Age = 55; DoSearch(s); כתובת קונסטרקטור Chunky ל Class הזה תחזיר אותנו לאותה דילמה תחזוקתית
 

ייוניי

New member
אין מקום לדבר על OO

בסיטואציה שעוסקת ברמה שהיא כל כך עמוק ב Low Level. הקשיים התחזוקתיים שעלולים להיגרם כתוצאה מיישום כזה או אחר של הפונקציונאליות שאתה מתאר הם כל כך זעומים שאין טעם לבזבז אנרגיה בניתוח OO של הבעיה. אם אתה רוצה את דעתי באופן כללי, השימוש בפונקציות סטאטיות (ציבוריות) במערכת מבוססת OOP צריך להיות מועט מאוד עד כדי לא קיים - ומקומו אך ורק ב Low Level. כלומר, פונקציות שהחתימות שלהן אינן שייכות לבעיה הספציפית שהמערכת באה לפתור אלא לעניינים פרוצדוראליים של תכנות. מצד שני, השימוש באובייקט שחושף את השדות הפנימיים שלו כמו האופציה השניה שהראית - הוא שגיאה בסיסית וחמורה בעקרון ה encapsulation ויש לכך השפעה מרחיקת לכת על תחזוקתיות המערכת. אני מציע פתרון שלישי:
x = new myCalc(5, 8).getAdditionResult();​
שוב, זה אולי נראה מגוחך במקרה הספציפי הזה אבל אני מניח שאתה רוצה להבין כאן את העקרונות הכלליים. מה שחשוב כאן היא ההפרדה בין יצירת האובייקט לבין הפעילות שלו, בהחלט יתכן שהאובייקט מסוג myCalc יווצר במקום אחד בקוד אך ישתמשו בו במקום אחר.
 

hg1979

New member
כן , אבל

בקשר לפתרון שהצעת, אולי לא שמת לב אבל הוא בעצם יישום של השיטה הראשונה שאומרת להעביר את הפרמטרים לפעולה בקריאה אל הפונקציה. ולא בסט פקודות מקדימות ובלתי תלויות. הטענות בקשר לסטאטי או לא סטאטי לא קשורות בכלל לענין בכלל ובפרט, יכול להיות שאני טועה אבל אני הבנתי הן לפי השאלה והן לפי הדוגמא (אות קטנה בתחילת שם מחלקה דיי לא נהוג) כי myCalc הוא מופע של מחלקה ולא מחלקה - זאת אומרת המטודות אינן סטאטיות. בקשר לטענה ששימוש בשדות פנימיים חשופים של מחלקה לצורך העברת פרמטרים הוא "שגיאה בסיסית וחמורה" - לא הבנתי אם אתה מתייחס ספציפית לדוגמא שלי - שכתבתי בפרוש שלא כתבתי Properties לחשיפה של השדות הפנימיים מפאת חוסר עניין או שגם עם Properties זה לא בסדר ? ובחזרה לענין, אם המטרה של המחלקה הוא להעביר פרמטרים בצורה קלה יותר לשינוי ולהרחבה ולריכוזיות אז בהחלט ניתן וצריך לחשוף את המשתנים הפנימיים (בעזרת Property - ולו רק בגלל סרלזציה עתידית אפשרית)
 

ייוניי

New member
העניין הוא כזה

קודם כל, אני לא מיישם את השיטה של העברת פרמטרים בקריאה לפונקציה כי הקריאה למתודה שמחזירה את התוצאה יכולה להתבצע בכל מקום אחר בקוד. העברת הפרמטרים צריכה להתבצע במקום אחד והוא בשלב יצירת האובייקט. קשה לי לראות את הפונקציה Add של המחלקה myCalc מהדוגמא כמתודה שנקראית על מופע, אלא אם הכוונה היא ליישום מספר אלגוריתמים של חיבור בין שני מספרים (?). לכן פשוט הנחתי שמדובר בפונקציה סטאטית כי אין משמעות למופע. שימוש ב Properties על מנת לעדכן ולאחזר ערכים של שדות פרטיים שווה ערך להפיכת השדות הפרטיים לציבוריים (אם הייתי צריך לבחור בין השניים הייתי הופך את השדה הפרטי לציבורי וחוסך מספר שורות קוד). גם מבחינת OOP דרגת החומרה שווה על פי עקרון ה encapsulation שבא למנוע מצב שבו גישה למידע פנימי של האובייקט פוגעת ביכולת שלנו לשנות אותו בקלות. בקשר לקביעה האחרונה שלך, אני חושב שליצור מחלקה לצרכים של העברת פרמטרים בלבד זה בזבוז זמן ושורות קוד מיותרות - וכל שורת קוד נוספת יכולה רק להקשות על שינוי ולא להועיל. אם מתעורר צורך לעשות שינוי בפרמטרים של פונקציה תמיד אפשר לכתוב פונקציה חדשה עם פרמטרים שונים ולהנדס אותה כך שתעשה שימוש מושכל בפונקציה הקיימת. גם עבור סריאליזציה לא הייתי מתחיל לחשוף Properties בכל מקום אלא משתמש בשיטות שלא דורשות אותן (כמו Reflection למשל).
 

FireBird

New member
תרשו גם לי להכנס

לדעתי: 1. שימוש בProperties טוב מהפיכת השדות הפרטיים לציבוריים כי יש לך שליטה בערך שיוצא ואף יותר חשוב, בנכנס. 2. הפונקציה Add יכולה להיות יעילה במופע של המחלקה במידה ולמשל חלק ממטרתה הוא להחזיק את התוצאה ולהשתמש בה יותר מאוחר. 3. -נניח שלא ?- אז למה לא להפוך את המחלקה לSingleton ?
 

ייוניי

New member
-->

1. מה שהצעתי הוא להתחיל בשדות ציבוריים (פחות שורות קוד) ובמקרה הצורך קל מאוד לשנות שדה ציבורי ל Property עם או בלי שדה פרטי מתאים, בלי לגעת בקוד שמשתמש באותו שדה (על ידי שינוי שמות וכו'...). האמת היא שלא כל שפה מאפשרת את הטריק הזה ולכן אולי לפעמים אין ברירה אלא לחשוף Property מהתחלה. מה שחשוב לזכור זה את הסיבה שבגללה אנחנו לא חושפים ייצוג פנימי של אובייקט החוצה והיא היכולת שלנו לשנות (ובד"כ גם להחליף) את האובייקט בלי לשנות את הקוד שמשתמש בו. 2. אמנם גם פונקציה סטטית יכולה לעשות זאת אבל זה נכון שאפשר ליישם את Add בצורות קצת שונות ולכן אולי יש צורך במופע, זה פשוט לא היה נראה כמו השימוש שהתכוונו אליו בדוגמא זה הכל... 3. אני לא רואה הבדל גדול בין Singleton לפונקציות סטאטיות מבחינה עיצובית. Singleton זה פשוט מימוש מסויים של גישה סטאטית.
 
למעלה