البرنامج التعليمي: تحديث واجهات مع أعضاء الواجهة الافتراضية في C # 8.0

بدءًا من الإصدار C # 8.0 على .NET Core 3.0 ، يمكنك تحديد تطبيق عندما تعلن عضوًا في واجهة. السيناريو الأكثر شيوعًا هو إضافة أعضاء بأمان إلى واجهة تم إصدارها بالفعل واستخدامها من قبل عملاء لا حصر لهم.


في هذا البرنامج التعليمي ، سوف تتعلم كيفية:


  • تمديد واجهات بأمان عن طريق إضافة أساليب مع التطبيقات.
  • إنشاء تطبيقات ذات معلمات لتوفير قدر أكبر من المرونة.
  • تمكين المنفذين لتقديم تطبيق أكثر تحديداً في شكل تجاوز.



المتطلبات الأساسية


ستحتاج إلى إعداد جهازك لتشغيل .NET Core ، بما في ذلك برنامج التحويل البرمجي لمعاينة C # 8.0. يتوفر برنامج التحويل البرمجي لمعاينة C # 8.0 بدءًا من Visual Studio 2019 ، أو أحدث معاينة .NET Core 3.0 SDK . تتوفر أعضاء الواجهة الافتراضية بدءًا من معاينة .NET Core 3.0 4.


نظرة عامة على السيناريو


يبدأ هذا البرنامج التعليمي بالإصدار 1 من مكتبة علاقات العملاء. يمكنك الحصول على التطبيق المبدئي على عينات الريبو الخاصة بنا على جيثب . تهدف الشركة التي أنشأت هذه المكتبة إلى أن يقوم العملاء الذين لديهم تطبيقات حالية باعتماد المكتبة الخاصة بهم. لقد وفروا الحد الأدنى من تعريفات الواجهة لمستخدمي مكتبتهم ليتم تنفيذها. هنا تعريف الواجهة للعميل:


public interface ICustomer { IEnumerable<IOrder> PreviousOrders { get; } DateTime DateJoined { get; } DateTime? LastOrder { get; } string Name { get; } IDictionary<DateTime, string> Reminders { get; } } 

قاموا بتعريف واجهة ثانية تمثل طلبًا:


 public interface IOrder { DateTime Purchased { get; } decimal Cost { get; } } 

من هذه الواجهات ، يمكن للفريق بناء مكتبة لمستخدميها لخلق تجربة أفضل لعملائهم. كان هدفهم إنشاء علاقة أعمق مع العملاء الحاليين وتحسين علاقاتهم مع العملاء الجدد.


الآن ، حان الوقت لترقية المكتبة للإصدار التالي. تتيح إحدى الميزات المطلوبة خصم الولاء للعملاء الذين لديهم الكثير من الطلبات. يتم تطبيق خصم الولاء الجديد هذا عندما يصدر العميل طلبًا. الخصم المحدد هو خاصية لكل عميل على حدة. يمكن لكل تطبيق ICustomer وضع قواعد مختلفة لخصم الولاء.


الطريقة الأكثر طبيعية لإضافة هذه الوظيفة هي تحسين واجهة ICustomer باستخدام طريقة لتطبيق أي خصم على الولاء. تسبب اقتراح التصميم هذا في قلق المطورين ذوي الخبرة: "تعتبر الواجهات غير قابلة للتغيير بمجرد إصدارها! هذا هو التغيير الفاسد! " يضيف C # 8.0 تطبيقات الواجهة الافتراضية لترقية الواجهات. يمكن لمؤلفي المكتبة إضافة أعضاء جدد إلى الواجهة وتوفير تطبيق افتراضي لهؤلاء الأعضاء.


تمكن تطبيقات الواجهة الافتراضية للمطورين من ترقية واجهة مع الاستمرار في تمكين أي منفذين لتجاوز هذا التطبيق. يمكن لمستخدمي المكتبة قبول التطبيق الافتراضي كتغيير غير متقطع. إذا كانت قواعد أعمالهم مختلفة ، فيمكنهم تجاوزها.


الترقية مع أعضاء الواجهة الافتراضية


وافق الفريق على التنفيذ الافتراضي على الأرجح: خصم ولاء للعملاء.


يجب أن توفر الترقية وظيفة تعيين خاصيتين: عدد الطلبات المطلوبة لتكون مؤهلة للحصول على الخصم ، والنسبة المئوية للخصم. يمكنك إضافة طريقة إلى واجهة ICustomer ، وتوفير التنفيذ الأكثر احتمالا ، حيث يمكن لجميع التطبيقات الحالية وأي تطبيقات جديدة استخدام التطبيق الافتراضي ، أو تقديم تطبيقات خاصة بها.


أولاً ، أضف الطريقة الجديدة إلى التنفيذ:


 // Version 1: public decimal ComputeLoyaltyDiscount() { DateTime TwoYearsAgo = DateTime.Now.AddYears(-2); if ((DateJoined < TwoYearsAgo) && (PreviousOrders.Count() > 10)) { return 0.10m; } return 0; } 

كتب مؤلف المكتبة أول اختبار للتحقق من التنفيذ:


 SampleCustomer c = new SampleCustomer("customer one", new DateTime(2010, 5, 31)) { Reminders = { { new DateTime(2010, 08, 12), "childs's birthday" }, { new DateTime(1012, 11, 15), "anniversary" } } }; SampleOrder o = new SampleOrder(new DateTime(2012, 6, 1), 5m); c.AddOrder(o); o = new SampleOrder(new DateTime(2103, 7, 4), 25m); c.AddOrder(o); // Check the discount: ICustomer theCustomer = c; Console.WriteLine($"Current discount: {theCustomer.ComputeLoyaltyDiscount()}"); 

لاحظ الجزء التالي من الاختبار:


 // Check the discount: ICustomer theCustomer = c; Console.WriteLine($"Current discount: {theCustomer.ComputeLoyaltyDiscount()}"); 

هذا يلقي من SampleCustomer إلى ICustomer ضروري. لا تحتاج الفئة SampleCustomer إلى توفير تطبيق لـ ComputeLoyaltyDiscount ؛ التي توفرها واجهة ICustomer . ومع ذلك ، لا ترث الفئة SampleCustomer الأعضاء من SampleCustomer . هذه القاعدة لم تتغير. من أجل استدعاء أي طريقة تم الإعلان عنها وتنفيذها في الواجهة ، يجب أن يكون المتغير هو نوع الواجهة ، ICustomer في هذا المثال.


توفير المعلمات


هذه بداية جيدة. ولكن ، التطبيق الافتراضي مقيد للغاية. قد يختار العديد من مستهلكي هذا النظام عتبات مختلفة لعدد المشتريات أو مدة عضوية مختلفة أو خصم مئوية مختلفًا ، ويمكنك تقديم تجربة ترقية أفضل لمزيد من العملاء من خلال توفير طريقة لتعيين هذه المعلمات. دعنا نضيف طريقة ثابتة تحدد هذه المعلمات الثلاث التي تتحكم في التنفيذ الافتراضي:


 // Version 2: public static void SetLoyaltyThresholds( TimeSpan ago, int minimumOrders = 10, decimal percentageDiscount = 0.10m) { length = ago; orderCount = minimumOrders; discountPercent = percentageDiscount; } private static TimeSpan length = new TimeSpan(365 * 2, 0,0,0); // two years private static int orderCount = 10; private static decimal discountPercent = 0.10m; public decimal ComputeLoyaltyDiscount() { DateTime start = DateTime.Now - length; if ((DateJoined < start) && (PreviousOrders.Count() > orderCount)) { return discountPercent; } return 0; } 

هناك العديد من القدرات اللغوية الجديدة الموضحة في جزء الشفرة الصغير ، ويمكن الآن أن تتضمن الواجهات أعضاء ثابتة ، بما في ذلك الحقول والأساليب ، كما يتم تمكين معدّلات وصول مختلفة. الحقول الإضافية خاصة ، والطريقة الجديدة عامة. أي من المعدلات مسموح بها على أعضاء الواجهة.


لا تحتاج التطبيقات التي تستخدم الصيغة العامة لحساب خصم الولاء ، ولكن معاملات مختلفة ، إلى توفير تطبيق مخصص ؛ يمكنهم تعيين الوسائط من خلال طريقة ثابتة. على سبيل المثال ، تحدد التعليمة البرمجية التالية "تقدير العميل" الذي يكافئ أي عميل بأكثر من عضوية شهر واحد:


 ICustomer.SetLoyaltyThresholds(new TimeSpan(30, 0, 0, 0), 1, 0.25m); Console.WriteLine($"Current discount: {theCustomer.ComputeLoyaltyDiscount()}"); 

تمديد التنفيذ الافتراضي


توفر الشفرة التي أضفتها حتى الآن تطبيقًا مناسبًا لتلك السيناريوهات التي يريد المستخدمون فيها شيئًا ما مثل التنفيذ الافتراضي ، أو لتوفير مجموعة غير مرتبطة من القواعد. للحصول على ميزة أخيرة ، دعنا نعيد تشكيل الشفرة قليلاً لتمكين السيناريوهات التي قد يرغب المستخدمون في البناء على التطبيق الافتراضي.


النظر في بدء التشغيل الذي يريد جذب عملاء جدد. أنها توفر خصم 50 ٪ من طلب العميل الجديد الأول. خلاف ذلك ، يحصل العملاء الحاليون على الخصم القياسي. يحتاج مؤلف المكتبة إلى نقل التطبيق الافتراضي إلى طريقة protected static بحيث يمكن لأي فئة تنفذ هذه الواجهة إعادة استخدام الرمز في تنفيذها. يستدعي التطبيق الافتراضي لعضو الواجهة هذه الطريقة المشتركة أيضًا:


 public decimal ComputeLoyaltyDiscount() => DefaultLoyaltyDiscount(this); protected static decimal DefaultLoyaltyDiscount(ICustomer c) { DateTime start = DateTime.Now - length; if ((c.DateJoined < start) && (c.PreviousOrders.Count() > orderCount)) { return discountPercent; } return 0; } 

في تنفيذ فئة تنفذ هذه الواجهة ، يمكن للتجاوز استدعاء طريقة المساعدة الثابتة ، وتوسيع هذا المنطق لتوفير خصم "عميل جديد":


 public decimal ComputeLoyaltyDiscount() { if (PreviousOrders.Any() == false) return 0.50m; else return ICustomer.DefaultLoyaltyDiscount(this); } 

يمكنك الاطلاع على الشفرة النهائية بالكامل في [عينات الريبو الخاصة بنا على جيثب] (يمكنك الحصول على تطبيق بدء التشغيل على عينات الريبو الخاصة بنا على جيثب .


هذه الميزات الجديدة تعني أنه يمكن تحديث الواجهات بأمان عندما يكون هناك تطبيق افتراضي معقول لهؤلاء الأعضاء الجدد. صمم بعناية واجهات للتعبير عن الأفكار الوظيفية الفردية التي يمكن تنفيذها بواسطة فئات متعددة. يعمل ذلك على تسهيل ترقية تعريفات الواجهة هذه عند اكتشاف متطلبات جديدة لتلك الفكرة الوظيفية نفسها.

Source: https://habr.com/ru/post/ar456238/


All Articles