איך לא להשתמש בממשקים ב- C #

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

מהם ממשקים?

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

הימנע מביצוע שינויים בממשקים 

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

תכנת לממשק, לא ליישום

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

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

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

ממשק ציבורי IR מאגר

    {

        // קצת קוד

    }

    מחלקה ציבורית ProductRepository: IRepository

    {

        // קצת קוד

    }

    מחלקה ציבורית CustomerRepository: IRepository

    {

        // קצת קוד

    }

ניתן להשתמש בקוד הבא ליצירת מופע של המאגר ProductRepository.

מאגר IR מאגר = ProductRepository חדש ();

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

מאגר IRepository = CustomerRepository חדש ();

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

הימנע משימוש יתר בממשקים

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

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

בואו נסתכל כעת על דוגמה לאופן השימוש בממשקים. שקול את הממשק הבא בשם IProduct.

ממשק ציבורי IProduct

    {

        int מזהה {get; מַעֲרֶכֶת; }

        מחרוזת ProductName {get; מַעֲרֶכֶת; }

        מחיר כפול {לקבל; מַעֲרֶכֶת; }

        כמות כמות {get; מַעֲרֶכֶת; }

    }

מחלקת המוצר מרחיבה את ממשק ה- IProduct כמוצג להלן.

מעמד ציבורי מוצר: IProduct

    {

        ID מזהה ציבורי {get; מַעֲרֶכֶת; }

        מחרוזת ציבורית ProductName {get; מַעֲרֶכֶת; }

        מחיר כפול ציבורי {get; מַעֲרֶכֶת; }

        כמות ציבורית ציבורית {get; מַעֲרֶכֶת; }

    }

ברור שאיננו זקוקים לממשק ה- IProduct מכיוון שהממשק והיישום שלו זהים. הקוד המיותר אינו מיותר.

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

 ממשק ציבורי IProductManager

    {

        בטל שמירה (מוצר מוצר IP);

        עדכון ריק (מוצר מוצר IP);

    }

ממשק ה- IProductManager מכיל את הצהרות השיטות הציבוריות של מחלקת ProductManager. הנה איך נראית מחלקת ProductManager.

 מחלקה ציבורית ProductManager: IProductManager

    {

        בטל ציבורי שמור (מוצר מוצר IP)

        {

           // כתוב כאן את היישום שלך

        }

        עדכון חלל ציבורי (מוצר מוצר IP)

        {

            // כתוב כאן את היישום שלך

        }

    }

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

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