سؤال

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

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

النظر في عقد الواجهة التالية لطبقة الخدمة:

public interface IFooDataService
{
   ICollection<Foo> GetFoosBySpecification(Specification<Foo> specification);
   ICollection<Foo> GetFooByPredicate(Func<Foo,bool> predicate);
   ICollection<Foo> GetFooBySearchArgs(FooSearchArgs searchArgs);
}

لذلك ، بعض النقاط الأولية:

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

الآن ، على التنفيذ:

public ICollection<Foo> GetFoosBySpecification(Specification<Foo> specification)
{
    return fooDataRepository
            .Find()
            .Where(f => specification.IsSatisfiedBy(f))
            .ToList();
}

public ICollection<Foo> GetFooByPredicate(Func<Foo, bool> predicate)
{
    return fooDataRepository
            .Find()
            .Where(predicate)
            .ToList();
}

public ICollection<Foo> GetFooBySearchArgs(FooSearchArgs searchArgs)
{
    return fooDataRepository
            .Find()
            .WhereMeetsSearchCriteria(searchArgs)
            .ToList();
}

نقاط في التنفيذ:

  • الثلاثة جميعهم بسيطون للغاية في التنفيذ (سطر واحد من التعليمات البرمجية المتسلسلة)
  • المواصفات والبحث ARGS تم تصفيتها خارجيا.
  • تستخدم طريقة Search Args ببساطة طريقة تمديد غير قابلة للتطبيق لفحص ARGS

لذلك ، هذا ما يقال ، في أي ظروف ستستخدم واحدة من 3 تقنيات أعلاه؟

أفكاري في نمط المواصفات:

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

أفكاري حول طرق التمديد (الأنابيب والمرشحات):

  • "ثقل" في المنطق ، ولكن لا يزال يؤدي إلى نفس البساطة.
  • عزل منطق الاستعلام من طبقة الخدمة إلى الأساليب الثابتة
  • لا يزال يتطلب "انعكاسًا" من النوع (تفتيش Args البحث المقدم وبناء الاستعلام)
  • يتيح لك رمز الهندسة المعمارية (المستودع ، طبقة الخدمة) أولاً ، دون التفكير في متطلبات عمل محددة (وهو مفيد في سيناريوهات معينة)

أفكاري حول طريقة المسند:

  • يمكن استخدامها حيث تحتاج إلى سيطرة حبيبية خشنة على الاستعلامات.
  • جيد للمشاريع الصغيرة ، حيث قد تكون المواصفات مبالغ فيها

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

ولكن بالنسبة للتطبيق الذي يمثل "بدء التشغيل" ، ستتطور متطلبات IE بمرور الوقت ولديها العديد من الطرق لاسترداد البيانات دون التحقق من الصحة المعقدة ، وسأستخدم أساليب الأنابيب والمرشحات.

ما رأيك؟ هل واجه أي منكم مشاكل مع أي من الأساليب المذكورة أعلاه؟ أي توصيات؟

على وشك بدء مشروع جديد حتى تكون هذه الأنواع من الاعتبارات أمرًا بالغ الأهمية.

شكرا للمساعدة.

تحرير للتوضيح على نمط المواصفات

هنا هو نفس الاستخدام لنمط المواصفات.

Specification<Foo> someSpec; // Specification is an abstract class, implementing ISpecification<TEntity> members (And, Or, Not, IsSatisfiedBy).
someSpec = new AllFoosMustHaveABarSpecification(); // Simple class which inherits from Specification<Foo> class, overriding abstract method "IsSatisfiedBy" - which provides the actual business logic.    
ICollection<Foo> foos = fooDataService.GetFoosBySpecification(someSpec);
هل كانت مفيدة؟

المحلول

من تجربتي الصغيرة:

  1. يتغير متطلبات المستخدم دائمًا ولا أعرف لماذا يسمح مديري دائمًا بالتغييرات التي ستأتي. لذلك +1 للمواصفات
  2. البرامج هنا يشبه "العامل اليدوي" أكثر من "عامل المعرفة". أنت تعرف .. الشخص الذي يكتب طوال اليوم. باستخدام المواصفات ، يمكنني التأكد من أن الجميع "أنواع". هذا مدعوم من طبيعة مشروعي. يحتاج إلى العديد من التنفيذ المختلفة لنفس الغرض. لا تسألني لماذا.
  3. استخدم نمط التصميم الذي يمنحك أعلى مستوى ومرونة وبالطبع قابلية الاختبار. هذه قصة صغيرة.
    في يوم جيد ، أخبرني رفيقتي أنه كتب فصلًا مكّننا من حساب 32 نوعًا من طريقة حساب X. وقد قام بالفعل بتنفيذ كل ذلك. هوهو ، كان هذا برمجة بطولية على ما أعتقد. قضى عدة أسابيع في القيام بذلك في منتصف الليل. لقد كان يعتقد أنه كان مبرمجًا جيدًا ، لذا أصر على استخدام الجميع.
    نحن ، في ذلك الوقت ، لم نهتم باختبار الوحدة ، لذلك استخدمنا تحفة. ماذا حدث بعد ذلك؟ تحطمت الكود طوال الوقت. حسنًا ، من ذلك الوقت أدركت مدى أهمية اختبار الوحدة والنموذجية.

نصائح أخرى

حسنًا ، أولاً ، سأكتب طريقة المسند ، حتى لو تم استخدامها فقط كتفاصيل تنفيذ خاصة للآخرين:

private ICollection<Foo> GetFoosBySpecification(Specification<Foo> spec) 
{ 
    return GetFooByPredicate(f => spec.IsSatisfiedBy(f));
} 

ستكون وظيفة وسيطة البحث بمثابة خط واحد مماثل.

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top