كيفية فصل التحقق من صحة البيانات من وجهة نظري كائنات المجال بسيطة (POCOs)؟

StackOverflow https://stackoverflow.com/questions/409495

سؤال

وهذا السؤال هي اللغة الملحد ولكن أنا C # الرجل ولذا فإنني استخدام مصطلح POCO على أنها تعني كائن تخزين البيانات التشكيل فقط، وعادة ما تستخدم جالبة واضعة المجالات.

وأنا مجرد إعادة صياغة بلدي نموذج المجال أن تكون فائقة المخادع POCO، وأنا تركت مع اثنين من المخاوف بشأن كيفية ضمان أن قيمة العقارات منطقية فيتن المجال.

وعلى سبيل المثال، ENDDATE من الخدمة يجب أن لا يتجاوز ENDDATE العقد أن الخدمة قيد. ومع ذلك، فإنه يبدو وكأنه انتهاك الصلبة لوضع الاختيار إلى واضع Service.EndDate، ناهيك عن أن مثل عدد التصديقات التي تحتاج إلى أن يتم ينمو صفوفي POCO سوف تصبح تشوش.

ولدي بعض الحلول (سيتم نشر في الأجوبة)، ولكن لديهم عيوب وأنا أتساءل ما هي نهج بعض المفضلة في حل هذه المعضلة؟

هل كانت مفيدة؟

المحلول

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

نصائح أخرى

وأسمع دائما الناس حجة ل "التحقق من صحة" أو "IsValid" الأسلوب.

وأنا شخصيا أعتقد أن هذا قد تعمل، ولكن مع معظم المشاريع DDD التي عادة ما تنتهي مع التصديقات المتعددة التي هي المسموح به تبعا لحالة معينة للكائن.

لذلك أنا أفضل "IsValidForNewContract"، "IsValidForTermination" أو ما شابه ذلك، لأنني أعتقد معظم المشاريع في نهاية المطاف مع العديد من هذه المصادقون / الدول في الصف الواحد. وهذا يعني أيضا أن أحصل على أي واجهة، ولكن أستطيع أن أكتب المصادقون المجمعة أن <م> قراءة بشكل جيد للغاية تعكس ظروف العمل وأنا مؤكدة.

وأنا حقا لا أعتقد أن الحلول العامة في هذه الحالة في كثير من الأحيان تأخذ التركيز <م> بعيدا من ما هو مهم - ما تقوم به رمز - لتحقيق مكاسب طفيفة للغاية في الأناقة التقنية (واجهة، مندوب أو أيا كان ). فقط بالتصويت لي أسفل بالنسبة لها؛)

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

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

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

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

وحل واحد هو أن يكون DataAccessObject كل كائن نلقي قائمة المصادقون. عندما يتم استدعاء حفظه التشكيل شيك ضد كل مدقق:

public class ServiceEndDateValidator : IValidator<Service> {
  public void Check(Service s) {
    if(s.EndDate > s.Contract.EndDate)
      throw new InvalidOperationException();
  }
}

public class ServiceDao : IDao<Service> {
  IValidator<Service> _validators;
  public ServiceDao(IEnumerable<IValidator<Service>> validators) {_validators = validators;}
  public void Save(Service s) {
    foreach(var v in _validators)
      v.Check(service);
    // Go on to save
  }
}

والفائدة، وشركة نفط الجنوب واضحة جدا، والعيب هو أننا لا تحصل على الاختيار حتى يتم استدعاء حفظ ().

في الماضي لقد عادة تفويض المصادقة إلى خدمة خاصة به، مثل ValidationService. هذا الإعلان من حيث المبدأ لا يزال يسمع لفلسفة DDD.

وعلى الصعيد الداخلي هذا من شأنه أن تحتوي على مجموعة من المصادقون ومجموعة بسيطة جدا من الطرق العامة، مثل التحقق من صحة () التي يمكن أن تعود مجموعة من وجوه الخطأ.

وببساطة شديدة، شيئا من هذا القبيل في C #

public class ValidationService<T>
{
  private IList<IValidator> _validators;

  public IList<Error> Validate(T objectToValidate)
  {
    foreach(IValidator validator in _validators)
    {
      yield return validator.Validate(objectToValidate);
    }
  }
}

والمصادقون يمكن إما المضافة داخل منشئ افتراضي أو حقنه من خلال بعض فئة أخرى مثل ValidationServiceFactory.

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

وهناك احتمال آخر هو أن يكون كل من دروسي تنفيذ

public interface Validatable<T> {
  public event Action<T> RequiresValidation;
}

ويكون لكل اضع لكل فئة رفع الحدث قبل وضع (ربما أتمكن من تحقيق ذلك عن طريق الصفات).

وميزة هي في الوقت الحقيقي التحقق من صحة تدقيق. ولكن كود مسير وليس من الواضح الذي يجب أن تقوم به وإرفاق.

وهنا احتمال آخر. ويتم المصادقة عليها من خلال وكيل أو الديكور على الكائن المجال:

public class ServiceValidationProxy : Service {
  public override DateTime EndDate {
    get {return EndDate;}
    set {
      if(value > Contract.EndDate)
        throw new InvalidOperationexception();
      base.EndDate = value;
    }
  }
}

وميزة: المصادقة الفورية. يمكن بسهولة أن يتم تكوين عن طريق اللجنة الاولمبية الدولية.

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

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