سؤال

لدي مشروع حيث نستخدم شاشة DTO لتغليف البيانات بين طبقة الخدمة و ال طبقة العرض.في حالتنا، طبقة العرض هي ASP.Net.

الفئات الوحيدة التي تعرف عن DTO هي فئات طبقة الخدمة والصفحات/عناصر التحكم التي تستدعي هذه الخدمات وتعرض DTO.

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

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

إليك إعلان الواجهة وDTO حتى تتمكن من رؤية ما أتحدث عنه:

public interface IBlogTasks
{
    BlogPostDisplayDTO GetBlogEntryByTitleAndDate(int year, int month, string urlFriendlyTitle);
}

public class BlogPostDisplayDTO 
{
    public string Title { get; set; }
    public DateTime PostDate { get; set; }
    public string HtmlContent { get; set; }
    public string ImageUrl { get; set; }        
    public string Author { get; set; }
    public int CommentCount { get; set; }
    public string Permalink { get; set; }
}   

يحرر

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

public interface IAuthenticationTasks
{
    bool AuthenticateUser(AuthenticationFormDTO authDTO);
}

public class AuthenticationFormDTO
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public bool persistLogin { get; set; }
}

لنفترض أن المصادقة الخاصة بي تتطلب فجأة معلمة عنوان IP.يمكنني الآن إضافة هذه الخاصية إلى DTO دون الحاجة إلى تغيير واجهة العقد الخاص بي.

لا أريد تمرير الكيانات إلى طبقة العرض التقديمي الخاصة بي.لا أريد أن يكون الكود الخاص بي قادرًا على الذهاب BlogPost.AddComment(new Comment())

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

المحلول

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

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

نصائح أخرى

هل تستخدم خدمات فعلية (الويب أو WCF)؟إذا كان الأمر كذلك، فحدد DTOs في طبقة الخدمة وسيحتوي الوكيل الذي تم إنشاؤه عند إضافة مرجع خدمة (أو ويب في حالة استخدام ASMX القديم) على جميع أنواع DTO.هذه هي أبسط طريقة للقيام بذلك وتحافظ فقط على الاقتران غير المحكم بين مشروع ASP.NET ومشروع الخدمة الخاص بك - لا يلزم وجود مرجع مباشر للمشروع في أي من الاتجاهين.عندما تقوم بتحديث DTOs الخاص بك، كل ما عليك فعله هو تحديث مرجع الخدمة الخاص بك وسوف يعرض التحديثات تلقائيًا لمشروع الويب الخاص بك عبر فئة الوكيل التي تم إنشاؤها.

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

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

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