سؤال

لقد رأيت الكثير من الأسئلة المتعلقة برسم الخرائط DTOs إلى كائنات المجال، لكنني لم أشعر أنهم أجابوا على سؤالي.لقد استخدمت العديد من الأساليب من قبل ولدي آرائي الخاصة ولكني أبحث عن شيء أكثر واقعية.

الوضع:

لدينا العديد من كائنات المجال.نحن نستخدم نموذج CSLA بحيث تكون كائنات المجال الخاصة بنا معقدة جدًا وتحتوي على إمكانية الوصول إلى البيانات الخاصة بها.أنت لا تريد تمرير هذه الأشياء على السلك.سنقوم بكتابة بعض الخدمات الجديدة التي ستعيد البيانات بعدد من التنسيقات (.Net، وJSON، وما إلى ذلك).لهذا (ولأسباب أخرى) نقوم أيضًا بإنشاء كائن بسيط لنقل البيانات لتمريره عبر السلك.

سؤالي هو:كيف يجب أن يتم توصيل كائن DTO والمجال؟

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

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

هل هناك طرق أخرى؟هل إحدى الطرق المذكورة أعلاه تستحق الاستخدام؟إذا كان الأمر كذلك أم لا، لماذا؟

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

المحلول

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

أنا شخصياً أحاول إبقاء عملية التعيين خارج كيانات النطاق الخاصة بي وأضع المسؤولية على عاتق ما أسميه "طبقة المدير/الخدمة".هذه هي الطبقة التي تقع بين التطبيق والمستودع (المستودعات)، وتوفر منطق الأعمال مثل تنسيق سير العمل (إذا قمت بتعديل A، فقد يتعين عليك أيضًا تعديل B حتى تعمل الخدمة A مع الخدمة B).

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

نصائح أخرى

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

نستخدم قوالب T4 لإنشاء فئات التعيين.

Pro's - كود يمكن قراءته بواسطة الإنسان ومتوفر في وقت الترجمة، وهو أسرع من مخطط وقت التشغيل.التحكم بنسبة 100% في الكود (يمكن استخدام أساليب جزئية/نمط القالب لتوسيع الوظائف على أساس مخصص)

السلبيات - استبعاد بعض الخصائص ومجموعات كائنات المجال وما إلى ذلك، وتعلم بناء جملة T4.

حل آخر ممكن: http://glue.codeplex.com.

سمات:

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

كيف ترى تنفيذ مُنشئ داخل فئة DTO يأخذ كائن المجال كمعلمة؟

يقول...شيء من هذا القبيل

class DTO {

     // attributes 

     public DTO (DomainObject domainObject) {
          this.prop = domainObject.getProp();
     }

     // methods
}

يمكنك أيضًا تجربة Otis، وهو أداة رسم الخرائط من كائن إلى كائن.تشبه المفاهيم تعيين NHibernate (السمة أو XML).

http://code.google.com/p/otis-lib/wiki/GettingStarted

يمكنني اقتراح أداة قمت بإنشائها وهي مفتوحة المصدر مستضافة في CodePlex: الكياناتToDTOs.

يتم تنفيذ التعيين من DTO إلى الكيان والعكس من خلال طرق التمديد، والتي تشكل جانب المجمع من كل طرف.

تنتهي برمز مثل:

Foo entity = new Foo();
FooDTO dto = entity.ToDTO();
entity = dto.ToEntity();

List<Foo> entityList = new List<Foo>();
List<FooDTO> dtoList = entityList.ToDTOs();
entityList = dtoList.ToEntities();

لماذا لا نستطيع أن نفعل مثل هذا؟

class UserDTO {
}

class AdminDTO {
}

class DomainObject {

 // attributes
 public DomainObject(DTO dto) {
      this.dto = dto;
 }     

 // methods
 public function isActive() {
      return (this.dto.getStatus() == 'ACTIVE')
 }

 public function isModeratorAdmin() {
      return (this.dto.getAdminRole() == 'moderator')
 }

}


userdto = new UserDTO();
userdto.setStatus('ACTIVE');

obj = new DomainObject(userdto)
if(obj.isActive()) {
   //print active
}

admindto = new AdminDTO();
admindto.setAdminRole('moderator');

obj = new DomainObject(admindto)
if(obj.isModeratorAdmin()) {
   //print some thing
}

@ فريدريك بريجك (أو شخص ما:الرجاء الاقتراح.في المثال أعلاه، يعتمد DomainObject على DTO.بهذه الطريقة يمكنني تجنب الكود للقيام بتعيين كائن المجال dto <-->.

أو فئة DomainObject يمكن أن تمتد إلى فئة DTO؟

خيار آخر سيكون للاستخدام ModelProjector.وهو يدعم جميع السيناريوهات الممكنة وهو سهل الاستخدام للغاية وبأقل قدر من المساحة.

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

إن الاحتفاظ بمنطق التعيين داخل الكيان الخاص بك يعني أن كائن المجال الخاص بك أصبح الآن على علم بـ "تفاصيل التنفيذ" التي لا يحتاج إلى معرفتها.بشكل عام، DTO هو بوابتك إلى العالم الخارجي (إما من طلب وارد أو عبر قراءة من خدمة/قاعدة بيانات خارجية).نظرًا لأن الكيان جزء من منطق الأعمال الخاص بك، فمن الأفضل الاحتفاظ بهذه التفاصيل خارج الكيان.

سيكون الاحتفاظ بالخرائط في مكان آخر هو البديل الوحيد - ولكن إلى أين يجب أن تذهب؟لقد حاولت تقديم كائنات/خدمات رسم الخرائط، ولكن بعد كل ما قيل وفعل، بدا الأمر وكأنه هندسة زائدة (وربما كان كذلك).لقد حققت بعض النجاح في استخدام Automapper وما شابه ذلك للمشاريع الصغيرة ولكن أدوات مثل Automapper تأتي بمزالقها الخاصة.لقد واجهت بعض الصعوبات في العثور على المشكلات المتعلقة بالتعيينات لأن تعيينات Automapper ضمنية ومنفصلة تمامًا عن بقية التعليمات البرمجية الخاصة بك (ليس مثل "فصل الاهتمامات" ولكن أشبه بـ "أين يعيش التعيين المهجور") لذا فهم قد يكون من الصعب في بعض الأحيان تعقبها.لا يعني أن Automapper ليس له استخداماته، لأنه يفعل ذلك.أعتقد فقط أن رسم الخرائط يجب أن يكون واضحًا وشفافًا قدر الإمكان لتجنب المشكلات.

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

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