سؤال

لنفترض أن لديك مشروع ASP.NET MVC وتستخدم طبقة خدمة ، كما هو الحال في البرنامج التعليمي مدير الاتصال على موقع ASP.NET: http://www.asp.net/mvc/tutorials/iteration-4-make-the-application-loosely-coupled-cs

إذا كان لديك ViewModels لآرائك ، فهل طبقة الخدمة هي المكان المناسب لتوفير كل ViewModel؟ على سبيل المثال ، في نموذج رمز طبقة الخدمة هناك طريقة

    public IEnumerable<Contact> ListContacts()
    {
        return _repository.ListContacts();
    }

إذا كنت تريد بدلاً من ذلك أنك ترغب في الحصول على طبقة الخدمة ، أو هل هناك مكان آخر هو المكان "الصحيح"؟

ربما بشكل أكثر ملاءمة ، إذا كان لديك طريقة عرض منفصلة لكل عرض مرتبط بـ ContactController ، فيجب أن يكون لدى ContactManagerservice طريقة منفصلة لإرجاع كل ViewModel؟ إذا لم تكن طبقة الخدمة هي المكان المناسب ، فأين يجب تهيئة كائنات ViewModel للاستخدام من قبل وحدة التحكم؟

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

المحلول

عموما ، لا.

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

عن طريق تسريب نماذج العرض في طبقة "خدمة" ، فأنت غير واضح طبقاتك ولديك الآن تطبيق محدد وعروض تقديمية مختلطة مع ما ينبغي أن يركز مع المسؤوليات على مستوى المجال.

نصائح أخرى

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

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

ولكن عندما تصل إلى تنفيذها بنفسك باستخدام إطار الكيان ، MVC ، المستودع وما إلى ذلك ، فإنك تدرك شيئًا آخر.

يتعين على شخص ما تعيين نماذج كيان/ديسيبل مع ViewModels (DTO المذكورة في النهاية). هل يجب القيام بذلك في [A] طبقة واجهة المستخدم (بواسطة وحدة التحكم) ، أو في [B] طبقة الخدمة؟

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

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

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

ولكن ماذا لو كان هناك تطبيق واجهة مستخدم أخرى باستخدام هذه الخدمة؟ ماذا لو كان هناك تطبيق للجوال؟ ما مدى اختلاف أن يكون ViewModel؟ هل يجب أن تصل الخدمة إلى نفس مشروع نموذج العرض؟ هل ستصل جميع مشاريع واجهة المستخدم إلى نفس مشروع ViewModel أم أن لديهم؟

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

أخيرًا ، هناك هذه المناقشة حول DTO. وأيضا حول شرح البيانات في ViewModels. لا يمكن لـ ViewModels باستخدام تعليقات البيانات (microsoft.web.mvc.dataannotations.dll) الإقامة في طبقة الخدمة بدلاً من ذلك يقيمون في طبقة واجهة المستخدم (لكن مكون model.dataannotations.dll يمكن أن يقيم في طبقة الخدمة). إذا كانت جميع المشاريع في حل واحد (.sln) ، فلا يهم الطبقة التي وضعتها. في تطبيقات المؤسسات ، سيكون لكل طبقة حلها الخاص.

لذا فإن DTO هو في الواقع عبارة عن ViewModel لأنه في الغالب سيكون هناك واحد على رسم خرائط واحد بين الاثنين (على سبيل المثال مع السيارات). مرة أخرى ، لا يزال لدى DTO المنطق اللازم لواجهة المستخدم (أو التطبيقات المتعددة) ويقيم في طبقة الخدمة. و UI Layer ViewModel (إذا استخدمنا microsoft.web.mvc.dataannotations.dll) فقط لنسخ البيانات من DTO ، مع إضافة بعض "السلوك"/السمات إليها.

الآن هذه المناقشة على وشك أخذ منعطف مثير للاهتمام اقرأ ...: أنا

ولا تعتقد أن سمات التصنيف للبيانات هي فقط لجهاز واجهة المستخدم. إذا قمت بحد التحقق من الصحة باستخدام system.componentmodel.dataannotations.dll ، فيمكن أيضًا استخدام نفس ViewModel للتحقق من صحة الواجهة الأمامية والخلفية (وبالتالي إزالة واجهة U-View-View-view-copy-of-DTO). علاوة على ذلك ، يمكن أيضًا استخدام السمات في نماذج الكيانات. على سبيل المثال: باستخدام .TT ، يمكن تلقائي نماذج بيانات إطار العمل مع سمات التحقق من الصحة للقيام ببعض عمليات التحقق من DB مثل Max-Length قبل إرسالها إلى النهاية الخلفية. ميزة أخرى هي أنه إذا تغيرت التحقق من صحة الواجهة الخلفية في DB ثم .TT (تقرأ تفاصيل DB وإنشاء السمة لفئة الكيانات) سوف يلتقط ذلك تلقائيًا. يمكن أن يجبر هذا على اختبارات وحدة التحقق من صحة واجهة المستخدم على الفشل أيضًا ، وهي إضافة كبيرة (حتى نتمكن من تصحيحها وإبلاغ جميع مستهلكي واجهة المستخدم/المستهلكين بدلاً من النسيان والفشل بطريق الخطأ). نعم ، المناقشة تتحرك نحو تصميم إطار جيد. كما ترون كل شيء مرتبط: التحقق من الصحة ، استراتيجية اختبار الوحدة ، استراتيجية التخزين المؤقت ، إلخ.

وإن لم يكن مرتبطا مباشرة بالسؤال. "واجهة ViewModel" المذكورة في هذا يجب مشاهدتها رابط القناة 9 يستحق أيضا استكشاف. يبدأ بالضبط في 11 دقيقة 49 ثانية في الفيديو. لأن هذا سيكون الخطوة التالية/الفكر بمجرد فرز سؤالك الحالي أعلاه: "كيفية تنظيم عروض العرض؟"

أيضًا في مثالك "_repository.listContacts ()" يعيد عرض ViewModel من المستودع. هذه ليست طريقة ناضجة. يجب أن توفر المستودعات نماذج كيان أو نماذج DB. يتم تحويل هذا إلى عرض النماذج وهو نموذج العرض الذي يتم إرجاعه بواسطة طبقة الخدمة.

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

إذا كانت "طبقة الخدمة" عبارة عن طبقة مادية ، مثل خدمة الويب ، فلا يوجد بالتأكيد ؛ يجب أن تعرض الخدمات في سياق الخدمية عمليات المجال/الأعمال ، وليس البيانات وليس منطق العرض. لكن اذا الخدمات يتم استخدامه فقط كمفهوم مجردة لمستوى إضافي من التغليف ، لا أرى أي مشكلة في استخدامه بالطريقة التي تتصرف بها.

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

لقد أصبح هذا قليلاً من "هذا يعتمد" حيث أعمل - كان لدينا عمومًا وحدة تحكم تستهلك بعض الخدمات (الخدمات) - ثم الجمع بين DTO's في "عرض ViewModel" الذي سيتم نقله بعد ذلك إلى العميل - إما عبر JSON RESORD ، أو ملزمة في قالب الحلاقة.

الشيء هو ، حوالي 80 ٪ من الوقت - كان تعيين DTO إلى ViewModel 1-1. لقد بدأنا في التحرك نحو "عند الحاجة ، فقط استهلك DTO مباشرة ، ولكن عندما لا يتطابق DTO وما نحتاجه في عميلنا/عرضنا - ثم نقوم بإنشاء نموذج ViewModel ونقوم بالتعيين بين الكائنات حسب الحاجة".

على الرغم من أنني ما زلت غير مقتنع بأن هذا هو الحل الأفضل أو الصحيح - حيث ينتهي الأمر مما يؤدي إلى بعض المناقشات الساخنة حول "هل نضيف X فقط إلى DTO لتلبية احتياجات العرض؟"

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