דפוסי עיצוב שלעיתים קרובות אני נמנע מהם: דפוס מאגר

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

שכבת הגישה לנתונים מכילה בדרך כלל קוד ספציפי לאחסון ושיטות להפעלת הנתונים לאחסון הנתונים וממנו. שכבת הגישה לנתונים שמאגר מופשט יכולה להיות ORM (כלומר, Entity Framework או NHibernate), קובץ XML, שירות אינטרנט וכו '. זה יכול אפילו להיות אוסף של הצהרות SQL.

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

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

המאגר הגנרי

מאגר כללי הוא סוג המורכב ממכלול של שיטות כלליות לביצוע פעולות CRUD. עם זאת, זה רק דפוס אנטי נוסף ומשתמשים בו לעתים קרובות עם Entity Framework לשיחות מופשטות לשכבת הגישה לנתונים. לדעתי, שימוש במאגר גנרי הוא הכללה רחוק מדי. זה רעיון רע להפשט שיחות ל- Entity Framework באמצעות מאגר כללי.

תן לי להסביר זאת בדוגמה.

רישום הקוד הבא ממחיש מאגר כללי - הוא מכיל שיטות כלליות לביצוע פעולות ה- CRUD הבסיסיות.

public interface IRepository

   {

       IEnumerable GetAll();

       T GetByID(int id);

       void Add(T item);

       void Update(T item);

       void Delete(T item);

   }

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

public class AuthorRepository : IRepository

   {

       //Implemented methods of the IRepository interface

   }

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

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

public class AuthorRepository : IRepository

   {

       private AuthorContext dbContext;

       //Methods of the IRepository interface

   }

כפי שניתן לראות ברישום הקוד שהוצג קודם לכן, AuthorRepository זקוק למופע AuthorContext כדי לבצע את פעולות ה- CRUD שהוא מיועד להן. אז איפה הניתוק? באופן אידיאלי, בשכבת התחום לא אמורה להיות שום ידיעה על לוגיקת ההתמדה.

שכבה נוספת של הפשטה

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

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

עכשיו שיש לך לא מעט טכנולוגיות התמדה של נתונים בוגרים (NHibernate, Entity Framework וכו '), מדוע בכל זאת אתה זקוק לשכבת ההפשטה הנוספת הזו? לרוב טכנולוגיות ה- ORM הבוגרות הקיימות כיום יש אותן יכולות. בניסיון להשתמש במאגר, אתה פשוט מוסיף שכבת הפשטה נוספת ללא כל סיבה. כדוגמה, ייתכן שתצטרך שיטות כמו הבאות עבור מחבר המאגר שלך.

FindAuthorById()

FindAuthorByCountry()

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