منتدى فيجوال بيسك لكل العرب | منتدى المبرمجين العرب
تعلم كيف تستخدم MVP Pattern فى ASP.Net - نسخة قابلة للطباعة

+- منتدى فيجوال بيسك لكل العرب | منتدى المبرمجين العرب (http://vb4arb.com/vb)
+-- قسم : قسم برمجة وتطوير المواقع (http://vb4arb.com/vb/forumdisplay.php?fid=51)
+--- قسم : قسم ASP.NET (http://vb4arb.com/vb/forumdisplay.php?fid=52)
+---- قسم : قسم مقالات ASP.NET (http://vb4arb.com/vb/forumdisplay.php?fid=54)
+---- الموضوع : تعلم كيف تستخدم MVP Pattern فى ASP.Net (/showthread.php?tid=5752)



تعلم كيف تستخدم MVP Pattern فى ASP.Net - RaggiTech - 15-10-12

كاتب الموضوع : Ahmed Moosa

تعلم كيفية إستخدام MVP Pattern فى ASP. Net

تمهيد :-

لن تترك العمل مع ASP. Net ولكنك ستحسن العمل فقط , هذا هو الهدف من إستخدام MVP Pattern . لن تضيف شيئاً لم تعرفه من قبل , ولن تضيف مكتبة أكواد خارجية (Third Party)و لن تستغنى عن Code-behind , ولكن هى حيلة للعمل بمبدأ الفصل بين مكونات العمل ,وأيضاً توفير الفرصة لإجراء الإختبارات Unit Test مع ASP. Net .

مقدمة :-

قد تحتاج إلى تحسين العمل مع ASP. Net والتى تعمل كما تعرفنا فى مقالات سابقة على Pattern يسمى Page Controller , فظهرت لنا ASP. Net MVC والتى تفصل بين مكونات التطبيق ولكن هى Framework مستقل , أى ستجد بها خلافات بينها وبين asp. Net العادية ولكن ليس بنسبة 100% .وجاءت بعد ذلك MVP لتعلن إمكانية إستخدام نفس المبدأ الذى يستخدمه MVC ولكن مع ASP. Net العادية .

ملحوظة :-

هذة الأنماط مثال Page Controller و MVC و MVP موجودة منذ عشرات السنين ,وليست من إنتاج مايكروسوفت , أى قبل إنشاء ASP. Net نفسها .ولكن ما يحدث هنا , هو , العمل مع asp. net من خلال هذة الأنماط . أى إستخدام النمط الواحد فى طريقة العمل ,للإستفادة من مزاياه .

تعريف MVP Pattern

تعتبر MVP Pattern ,واحدة من أنماط العرض , والتى تستخدم فى التعامل مع واجهات المستخدم (UI) , وفى الحقيقة هى مشتقة وإن شئت قل تحسين من MVC Pattern .وتهدف على كتابة كود نظيف , يعمل على مبدأ الفصل بين مكونات النظام , ما بين تعامل مع واجهة المستخدم والتى تتمثل فى أدوات وبعضاً من الصور ,وبين الأكواد المستخدم فى إمداد هذة الأدوات بالبيانات وأى طبقة اخرى , كإستخدام نوعاً من انواع Service وغيرها . وبالطبع كلما زادت فرصة فصل الأكواد عن بعضها , وكذلك كلما توفرت فرصة الإستقلالية , ظهر ,بل ,وزاد الأمر يسراً عند الحديث عن إختبار الكود وما نعرفه بـ Unit Testing .

ملحوظة:-

أنماط العرض (Presentation Patterns) يقصد بها ,أى نمط يعمل مع واجهة مستخدم .ومعنى كلمة نمط (Pattern) ,حل يتم إتباعه لمشكلة شائعة,أى أنه خطوات عمل نسير عليها لنصل إلى حل جيد لمشكلة ما, ومثال أنماط العرض Template View المستخدم فى asp وPHP وJSPوpage Controller المستخدم فى ASP. Net وأيضاًMVC و MVP ولا ننسى Front Controller القائم عليه MVC , وغيرهم كثير .

ملحوظة:-

Unit Testing هى عملية إختبار الكود بطريقة محددة , لضمان عمل الكود بالطريقة المعد لها .وليس أمراً ضرورياً إذا كان المشروع بسيط .وله أدواته .ويعمل على أصغر وحدة من الكود وهى هنا كتكلة واحدة هى الـ Method . فهو يختبر Method , هل تعمل بنجاح؟ , نعم , إذاً , ننتقل لغيرها , وهكذا الأمر .ولكن يتطلب أن تكون هناك إستقلالة فى الكود ,أى لايوجد تبعيه لأحد على أحد حتى لا يتعقد الأمر.

أركان MVP Pattern

وتقوم MVP Pattern على ثلاثة أركان وهم :-

Model

View

Presenter

فهيا بنا ناخذ كل واحدة منهم على حده :-

Model

يقصد به مكان التعامل مع البيانات التى ستعرض فى الصفحة (View), وتجسد بدورها الـ View . ويمثل Model فى الكود Interface أو Class .

View

يقصد بها صفحة كود التصميم ,وما هى إلا الصفحة العادية التى تعرفها والتى تحتوى على أدوات الصفحة .وتمثله فى الكود الصفحة ذات الإمتداد aspx او ascx .

Presenter

يقصد بها هنا, الوسيط ما بين المستخدم والتطبيق ,أى ما بين view وباقى التطبيق وهو المسئول عن عرض البيانات فى View ولكن من خلال التعامل مع الـ Model , وما هى إلا طبقة إضافية نبنيها فوق ملف Code -Behind ويمثل Presenter فى الكود Class عادية جداً (ملف .cs ).

وإليك الشكل الذى يوضح شكل وطريقة عمل MVP Pattern :-



يوضح هذا الشكل مفهوم العمل مع MVP Pattern , أى ان المستخدم يقوم بطلب شئ من الموقع , اى ربما قد يقوم بالضغط على Button ما , فيقوم الحدث button Click الموجود فى ملف Code-behind بتوجيه الطلب إلى Class مستقلة ,هذة الـ Class هى Presenter وتكمن المهمة فى تنفيذ دالة داخل هذا الـ Presenter .وخلاصة القول , أن المستخدم يقوم بالضغط على Button ليصدر أمر التنفيذ لدالة موجودة فى Presenter .يقوم الـ Presenter ,داخل هذة الدالة بمعالجة الطلب , وتكمن هذة المعالجة فى التعامل مع الـ Model , تلك الـ Interface ,التى تمثل بدورها الصفحة (View ) بل وتنتحل شخصيتها لدى الـ Presenter ,فنجد أن الـ Presenter لايعرف شئ عن View ولكن يعرف عن Model . وحيث ان التعامل مع Model داخل الـ Presenter يجسد التعامل مع View ولكن بشكل غير مباشر . فنجد أى تغيير لابد وأن يؤثر فى View . وما سيأتى بعد قليل ,سيوضح لك هذا إن شاء الله .

خلاف MVC مع MVP

تأتى MVP على خلاف مع MVC فى بعض الأمور ,حيث نجد ان View فى MVP لا يعرف شئياً عن Model . ,وعلى العكس فى MVC فإن View تأخذ وتعطى إلى Model . كما ان controller فى MVC يمكن ان يقوم على خدمة أكثر من View ,ولكن نجد Presenter فى MVP يقوم فى العادة على خدمة View واحدة (او قد يخدم أكثر من view ولكن يشترط هنا التشابه بينهم , اى لهم نفس الوظائف ).

قد يبدو الأمر معقداً , هكذا رأيته, عندما بدأت بتعلم MVP Pattern ولكن سرعان ما تلاشى هذا الشعور بالتعقيد , حين رأيت طريقة العمل من داخل الكود . فسألقى على الشاشة امامك شكلاً آخراً , يوضح كيفية العمل من داخل الكود :-


تلخيص الشكل الذى تراه بالأعلى هو , كالتالى :-

يقوم الـCode Behind بعمل Implemtnt للـ Model الذى قمنا بإنشائه , ثم بعد ذلك يقوم بإنشاء نسخة من Presenter وتمرير نفسه لهذة النسخة , على انها نسخة من Model ,ليقوم الـ Presenter بالعمل مع هذة النسخة من قراءة وكتابة للتأثر بدورها الصفحة تلقائياً . وهذا الأمر ستضح , كالشمس فى ضحاها إن شاء الله , عند رؤية المثال القادم .

نعم هذة مزايا MVP Pattern ولكن ما عيوبها :-
فى البداية , هى ليست عيوب .ولكن هى صعاب , فتجد انك تكتب المزيد من الأكواد , ولاشك ياتى مع الزيادة فى كتابة الأكواد بعض التعقيد . لذلك ليس جيداً كفاية بإستخدام MVP مع المشاريع الصغيرة, وكذلك الحال , ليس من المنطق إستخدام Unit Testing مع المشاريع الصغيرة. فالمشروع فى الأصل بسيط , فماذا ستختبر ؟ وأيضاً مادام انه مشروعاً بسيط , فلماذا ستحتاج ان تكتب بعض الأكواد للعمل مع MVP وقد تكون أكبر من الكود الذى ستكتبه لمشروعك .أذكر هذا الكلام هنا , حتى لا تنزعج أثناء العمل مع المثال القادم لإن الخطوات معقدة قليلاً, ولكن ستستمتع إن شاء الله , بالعمل لإنها بالفعل ممتعة .

مثال :-

حان الآن موعد أخذ مثال , لعله إن شاء الله أن يزيد الأمر وضوحاً , ولنستعن بخطوات فى ترتيب سنمر عليه وهو كتالى :-

إنشاء Model ونعنى به (Interface أو Class) يجسد الـ View .
عمل Implement للـ Model داخل الـ View .
إنشاء Presenter ليقوم على خدمة الطلبات القادمة من المستخدم .
إنشاء Instance من الـ Presenter داخل الـ View .
تمرير الـ View إلى الـ Instance المأخوذ من الـ Presenter .
إستقبال الـ View على هيئة Model فى الـ Presenter والعمل معها .
التعديل فى هذا الـModel داخل الـPresenter لتتأثر الـ View بدورها بالتعديلات.

ملحوظة :-

كلمة يجسد بالأعلى , نقصد بها هنا,أى ان الـ Model سيكون لها نفس خصائص الـView كأنها هى .

إنشاء Model

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

فعلى سبيل المثال صفحة كهذة :-



ملحوظة:-

أردت ان يكون العمل بسيط , فنحن هنا نركز على المفهوم وليس كبر المثال من صغره. وكذلك نشير إلى هذا البرنامج الرائع http://www.balsamiq.com والذى تم إستخدامه فى رسم هذة الصورة , والذى يقدم طريقة رائعة لرسم نماذج متكاملة لمواقع الإنترنت .

نحتاج الإن ان نجسد هذة الصفحة فى Model Interface , وقبل ذلك نحتاج أن نحدد الأدوات المستخدمه فى الإدخال والإخراج . وهم هنا ,TextBox كإدخال و GridView و Label كمخرجات .

سنقوم بعمل خاصية تمثل كل أداه منهم داخل Model Interface هكذا :-



كما ترى فإن SearchTerm تمثل TextBox والذى سيتم كتابة نص البحث فيه وlistOfPersons تمثل GridView وهى المسؤلة عن عرض النتائج واخيراً Message لتمثل Label ,وهو المسئول عن عرض الوقت الذى تم إخراج الناتج فيه .

عمل Implement للـ Model داخل الـ View .

نذهب فى الحال إلى صفحة Default.aspx لنقوم بعمل Implement للـModel Interface:-


فكما ترى من الشكل , كل خاصية ستؤثر فى اداة فى الصفحة . سواء بالأخذ او العطاء .

فعلى سبيل المثال عند إعطاء قيمة إلى الخاصية ListofPersons فكاننا قمنا بإعطاء قيمة إلى GridView وقمنا بعمل DataBind لها . وهكذا الحال مع باقى الادوات .

إنشاء Presenter :-

كما إتفقنا سيقوم الـ Presenter بإستقبال نسخة من الView ولكن على هيئة Model والذى يتمثل هنا فى Interface بإسم IDefaultView . وإليك الكود المستخدم :-



كما ترى , تم إنشاء Instance من IDefaultView ولاحظ , انه قد أخذ قيمته من الـ Instance القادم من الخارج . والذى يمثل هنا الصفحة .ثم بعد ذلك تم التعامل مع الصفحة على انها مجموعة من الخصائص ,فقط ,سواء كتابة او قراءة (Set or Get ) .

فنجد ان Presenter ما هى إلا Class بها بعض الدوال ,وظيفتها العمل مع IDefaultView او Object يقوم بعمل Implement لها.وهذا كان القصد حين ذكرنا ان الـ Presenter يمكن أن يعمل مع أكثر من view بشرط الإتفاق فى الوظائف . وهنا نقول انه يمكن للـ Presenter ان يعمل مع اكثر من view بشرط أن الجميع يقوم بعمل Implement لنفس الـInterface .

وهنا ياتى سؤال , كيف سيعرف الـ Presenter بأمر الصفحة , أليس من المنطق ان يكون هناك إتصال بينهما . فكما ترى فهو ينتظر Instance من IDefaultView عند تعريفه , فإين ستمرر هذة النسخة ؟

الجواب ياتى فى الخطوة التالية :-

إنشاء Instance من الـ Presenter داخل الـ View.



نعم فى Page_Load , حتى تصل إلى Presenter نسخة محدثة من الصفحة فى كل مرة يتم تحميل الصفحة فيها . وهذا شئ حسن .ولاحظ انه قد تم تمرير Instance من الصفحة إلى الـPresenter بإستخدام الكلمة (this) . رجوعاً إلى كود Presenter , نجده يقوم بتحويل الصفحة إلى الـ IDefaultnterface برمجياً , ليقوم بحجب بقية الخصائص ,ليبقى فقط الخصائص المعرفة داخل الـ Interface .

لنأخذ الحدث button Click كمثال للتطبيق :-

عند ضغط المستخدم على Search بعد كتابة نص البحث ,يفترض أن تعود النتائج لتعرض فى اداة GridView , فلابد ان نعالج الحدث Click الخاص بـ button و لكن ماذا سيفعل؟

لاشئ , سوا أنه سيوجهنا إلى دالة SearchNow الموجودة داخل Presenter كما ترى:-




لنعود قليلاً إلى الدالة مرة اخرى :-



لاحظ ان الدالة لا تاخذ شئ من الـ View عند الضغط على الـ Button وأيضاً لا تعود بشئ . هى فقط .تعطى الأمر بالتنفيذ .ومنها نجد ان Presenter ما هو إلا موجه .

وفى النهاية نجد النتائج على هذا الشكل : -




هذا المثال , مبسط , وودت أن يكون اكثر تعقيداً , ولكن ليس من الجيد ان تلقى لطالب العلم فى البداية تعقيداً أو غموضاً . فقد يأتى هناك أمثلة أخرى او حديثاً آخر لجوانب أخرى فى إستخدام هذا الـ Pattern مع ASP. Net .

الختام :-

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

أحمد .