سؤال

بعد قراءة كتب إيفان ونيلسون، ما زلت غير متأكد من كيفية إدارة الوصول إلى البيانات في مشروع يعتمد على المجال.هل ينبغي أن تكون أساليب CRUD جزءًا من المستودعات، أي؟OrderRepository.GetOrdersByCustomer(customer) أو يجب أن يكونوا جزءًا من الكيانات:Customer.GetOrders().يبدو النهج الأخير أكثر OO، ولكنه سيوزع الوصول إلى البيانات لنوع كيان واحد بين كائنات متعددة، أي.Customer.GetOrders()، Invoice.GetOrders()، ShipmentBatch.GetOrders()، إلخ.ماذا عن الإدراج والتحديث؟

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

المحلول

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

CustomerRepo.GetThoseWhoHaventPaidTheirBill()

// or

GetCustomer(new HaventPaidBillSpecification())

// is better than

foreach (var customer in GetCustomer()) {
    /* logic leaking all over the floor */
}

يجب أيضًا أن تكون أساليب الكتابة "حفظ" جزءًا من المستودع.

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

هذا هو بلدي $.02.

نصائح أخرى

عادةً ما يفضل DDD نمط المستودع على نمط السجل النشط الذي تلمح إليه باستخدام Customer.Save.

أحد الجوانب السلبية في نموذج Active Record هو أنه يفترض إلى حد كبير نموذجًا واحدًا للاستمرارية، باستثناء بعض التعليمات البرمجية المتطفلة بشكل خاص (في معظم اللغات).

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

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

إذا لم يكن لديك الكثير من منطق المجال، فمن المحتمل أنك لا تحتاج إلى DDD.يعد ActiveRecord مناسبًا تمامًا للعديد من المشكلات، خاصة إذا كان لديك معظم البيانات وقليل من المنطق.

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

customer.Orders;

لذا، للإجابة على سؤالك، فإن عمليات CRUD موجودة في مستودعات الجذر المجمعة.

CustomerRepository.Add(customer);
CustomerRepository.Get(customerID);
CustomerRepository.Save(customer);
CustomerRepository.Delete(customer);

لقد فعلت ذلك في كلا الاتجاهين اللذين تتحدث عنهما، النهج المفضل لدي الآن هو أسلوب الجهل المستمر (أو PONO - Plain Ole' .Net Object) حيث تهتم فئات المجال الخاصة بك فقط بكونها فئات مجال.إنهم لا يعرفون شيئًا عن كيفية استمرارهم أو حتى إذا استمروا.بالطبع عليك أن تكون عمليًا بشأن هذا في بعض الأحيان وتسمح بأشياء مثل المعرف (ولكن حتى ذلك الحين أستخدم فقط طبقة من النوع الفائق الذي يحتوي على المعرف حتى أتمكن من الحصول على نقطة واحدة حيث تعيش أشياء مثل القيمة الافتراضية)

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

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

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

حتى في DDD، أود أن أبقي فئات وإجراءات الوصول إلى البيانات منفصلة عن الكيانات.

الأسباب هي

  1. تتحسن قابلية الاختبار
  2. فصل الاهتمامات والتصميم المعياري
  3. أكثر قابلية للصيانة على المدى الطويل، حيث تقوم بإضافة كيانات وإجراءات

أنا لست خبيرا، مجرد رأيي.

الشيء المزعج في تطبيق Nilsson DDD&P هو أنه يبدأ دائمًا بـ "لن أفعل ذلك في تطبيق حقيقي ولكن ..." ثم يتبع مثاله.العودة إلى الموضوع:أعتقد أن OrderRepository.GetOrdersByCustomer(customer) هو الحل الأمثل، ولكن هناك أيضًا مناقشة حول القائمة البريدية لـ ALT.Net (http://tech.groups.yahoo.com/group/altdotnet/) حول DDD.

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