דפוס עיצוב מאגרים בסוויפט

דרך נקייה לשאילתות בדגמים שלך

איזו בעיה היא פותרת?

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

משרטט את הסצינה.

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

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

קטע הקוד הזה כן

  1. בקשת GET לשרת
  2. ממפה את JSON שהוחזר למערך של אובייקטים של מאמר
  3. הסגר נקרא כאשר כל העבודות נעשות.

מדוע אנו זקוקים למאגר?

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

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

לא נגרם שום נזק, אף אחד לא מת. ימין?

באותו רגע אזעקה אדומה גדולה צריכה להתחיל להבהב במוחכם.

מאגר שלום.

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

בואו ליצור אובייקט מאגר שמספק ממשק API ציבורי לקבל את המאמרים.

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

טפל בכל אינטראקציות המאמר

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

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

בפועל השימוש במאגר נראה כך.

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

הפעלת כוח: פרוטוקולים

בקוד הקודם תמיד השתמשתי בדוגמה של 'קבלת נתונים מממשק API'. אבל מה אם אתה צריך להוסיף תמיכה כדי לטעון נתונים מקובץ JSON מקומי במקום ממקור מקוון.

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

זה יכול להיראות כך.

פרוטוקול פשוט אומר 'אם אתה תואם אותי אתה צריך להיות חתימות על השיטות האלה, אבל לא אכפת לי מהביצוע בפועל!'

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

הפעלה: בדיקת יחידה

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

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

דוגמה

נניח שיש לך מודל תצוגה, ומודל התצוגה מקבל את הנתונים שלו דרך מאגר.

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

למרבה המזל זה באמת פשוט לפתור את זה.

שלום, הזרקת תלות.

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

אבל אולי אתה חושב, מה עם הסוגים? מאגר WebArticleRepository אינו MockArticleRepository, אז מהדר לא יתלונן? ובכן, לא אם אתה משתמש בפרוטוקול כסוג. בדרך זו אנו מודיעים למהדר, מאפשרים הכל כל עוד הוא תואם את פרוטוקול ArticleRepository (שגם האינטרנט וגם MockArticleRepository עושים).

הקוד הסופי ייראה כך.

ובמבחן היחידה שלך אתה יכול להחליף את זה כך.

כעת יש לך שליטה מלאה על הנתונים שהמאגר שלך מחזיר.

הפעלת כוח סופר: גנריים

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

  1. קבל את כל הדברים
  2. קבל כמה מהדברים
  3. הכנס כמה דברים
  4. למחוק דבר
  5. עדכן דבר

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

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

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

1. מאגר מאמרים

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

2. מאגר משתמשים

זהו זה.

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