نمط التصميم MVC تحت المجهر، المبادئ والتجربة والمستقبل!

على مر السنين، طرأ على تطوير البرمجيات العديد من التغييرات. وأحد أكبر تلك التغييرات في الآونة الأخيرة: استخدام نمط تصميم البرمجيات MVC لتطوير البرامج وتطبيقات الويب. يمكننا اعتبار نمط التصميم (نموذج Model – عرض View- وحدة التحكم Controller) أو ما يُطلق عليها اختصارًا MVC نمطًا معماريًا يفصل التطبيق إلى المكونات الثلاث آنفة الذكر. صُمم كل مكون من هذه المكونات للتعامل مع جوانب تطوير محددة للتطبيق. يعد MVC أحد أكثر أطر تطوير الويب القياسية المستخدمة في المجال لإنشاء مشاريع قابلة للتوسيع والتجديد. تم استخدامه سابقًا لواجهات المستخدم الرسومية لسطح المكتب، ولكن -في الوقت الحاضر- فهو يستخدم في تصميم تطبيقات الأجهزة الذكية وتطبيقات الويب.

المستويات الثلاث لنمط التصميم MVC

(1) النموذج Model 

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

(2) العرض View

العرض هو التمثيل المرئي لنمط التصميم MVC أو بعبارة أدق: واجهة المستخدم المسؤولة عن تقديم البيانات إلى المستخدم أو إدارة تفاعله مع التطبيق.

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

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

(3) وحدة التحكم Controller

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

مثال على نمط تصميم MVC من الحياة اليومية

لنفترض أنك قررت تناول غداءك في مطعم. بالطبع، لن تذهب إلى المطبخ وتحضّر الطعام (وإلا لكنت تناولته في منزلك!). بدلاً من ذلك، ستجلس وتنتظر قدوم النادل.

  • الآن يأتي النادل إليك وتطلب الطعام فحسب. يجهل النادل من أنت وماذا تريد، وإنما يكتب تفاصيل طلبك فحسب ويأخذه إلى المطبخ.

  • لن يحضرّ النادل طعامك في المطبخ، وإنما الطاهي من سيفعل؛ سيُعطيه النادل طلبك مع رقم طاولتك.

  • سيبدأ الطاهي بتحضير الطلب، وفي سبيل ذلك سيجلب المكونات من الثلاجة مثلًا.

  • وما إن ينتهي، سيحين دور النادل ثانيةً لنقل وجبتك خارج المطبخ.

  • الآن، يعرف النادل الطعام الذي طلبته وكيف سيُقدمه لك.

بالعودة إلى نمط التصميم MVC:

  • العرض = أنت
  • النادل = وحدة التحكم
  • عملية الطهي = الموديل
  • الثلاجة = البيانات

كيفية عمل نمط التصميم MVC 

يفصل نمط تمصمي MVC بين المدخلات والمعالجة والمخرجات للتطبيق. بحيث يقسّم عملية التطوير إلى ثلاثة مكونات مترابطة تسمى النموذج ، العرض، والمتحكم/وحدة التحكم. صُممت جميعها للتعامل مع بعض جوانب التطوير المحددة لأي تطوير تطبيقات ويب أو (.net)

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

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

لنلق نظرة على مثال بسيط:

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

سيقوم المتصفح بعد ذلك بإرسال الطلب إلى (وحدة التحكم) للحصول على قائمة الأفلام. بعد ذلك، ستطلب (وحدة التحكم) من (النموذج) العثور على قائمة الأفلام من قاعدة البيانات.

شكراً لصديق مدونة علوم “مهتدي محمد” على تصحيح الكود أدناه

router.get('/',ensureAuth, async (req,res)=>{ 
	try{ 
		const movies = await Movies.find() (*) 
		res.render('movies/index', { movies (*) }) }
  } 
   
	catch(err){ console.error(err) 
		res.render('error/500') } }) 

ثم يبحث (النموذج) في قاعدة البيانات ويعيد قائمة الأفلام إلى (وحدة التحكم).

const mongoose = require('mongoose') 
const MovieSchema = new mongoose.Schema
({ 
	name:{ 
        type:String, 
        required:true 
    }, 
	description:{ 
    	type:String 
    } 
}) 

module.exports = mongoose.model('Movies',MovieSchema)

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

router.get('/',ensureAuth, async (req,res)=>{ 
	try{ const movies = await Movies.find() 
		res.render('movies/index', { movies (*) }) } 

	catch(err){ 
    console.error(err) res.render('error/500') } 
})

عندئذٍ سيتلقى (العرض) الطلب ويعيد قائمة الأفلام المعروضة إلى (وحدة التحكم) بتنسيق HTML.

<div class="col" style="margin-top:20px;padding-bottom:20px">
    <div class="ui fluid card"> 
        <div class="content"> 
        <div class="header">{{movie.title}}</div> 
        	</div> <div class="extra content"> 
            <a href="/movies/{{movie._id}}" class="ui blue button"> More from {{movie.description}} </a> 
        </div> 
    </div>
</div>

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

مثال ل MVC بلغة جافا 

سنقوم بإنشاء كائن “Student” يعمل كنموذج (model)، وسيكون StudentView عبارة عن صنف “class ” للعرض يمكنه طباعة تفاصيل الطالب على وحدة التحكم ويكون StudentController هو صنف وحدة التحكم المسؤولة عن تخزين البيانات في كائن “Student ” وتحديث عرض StudentView وفقًا لذلك.

الخطوة #1: إنشاء النموذج

Student.java

public class Student {
   private String rollNo;
   private String name;
   
   public String getRollNo() {
      return rollNo;
   }
   
   public void setRollNo(String rollNo) {
      this.rollNo = rollNo;
   }
   
   public String getName() {
      return name;
   }
   
   public void setName(String name) {
      this.name = name;
   }
}

الخطوة #2: إنشاء العرض

StudentView.java

public class StudentView {
   public void printStudentDetails(String studentName, String studentRollNo){
      System.out.println("Student: ");
      System.out.println("Name: " + studentName);
      System.out.println("Roll No: " + studentRollNo);
   }
}

الخطوة #3: إنشاء وحدة التحكم

StudentController.java

public class StudentController {
   private Student model;
   private StudentView view;

   public StudentController(Student model, StudentView view){
      this.model = model;
      this.view = view;
   }

   public void setStudentName(String name){
      model.setName(name);		
   }

   public String getStudentName(){
      return model.getName();		
   }

   public void setStudentRollNo(String rollNo){
      model.setRollNo(rollNo);		
   }

   public String getStudentRollNo(){
      return model.getRollNo();		
   }

   public void updateView(){				
      view.printStudentDetails(model.getName(), model.getRollNo());
   }	
}

الخطوة #4: استخدم منهجيات StudentController لتوضيح استخدام نمط تصميم MVC

MVCPatternDemo.java

public class MVCPatternDemo {
   public static void main(String[] args) {

      //fetch student record based on his roll no from the database
      Student model  = retriveStudentFromDatabase();

      //Create a view : to write student details on console
      StudentView view = new StudentView();

      StudentController controller = new StudentController(model, view);

      controller.updateView();

      //update model data
      controller.setStudentName("Tarek");

      controller.updateView();
   }

   private static Student retriveStudentFromDatabase(){
      Student student = new Student();
      student.setName("Ahmed");
      student.setRollNo("10");
      return student;
   }
}

الخطوة #5: التحقق من المخرجات

Student:
Name: Ahmed
Roll No: 10
Student: Name: Tarek
Roll No: 10

متى يفضل استخدام MVC 

على الرغم من أنه يمكننا القيام بأي شيء بأي نمط، إلا أن كل نمط معماري له مزايا وعيوب، لا أحد أفضل من الآخر، ولكن كل واحد لديه حالات استخدام يمكن أن يكون الخيار الأفضل عند استخدامه، فمتى يُستحسن اللجوء إلى نمط التصميم MVC؟

استخدام نمط تصميم MVC
استخدام نمط تصميم MVC

يكون تطوير التطبيقات وصيانتها أسهل بكثير إذا كان للمكونات المختلفة لتطبيق الويب مسؤوليات واضحة ومميزة. وهو ما يضمنه نمط التصميم MVC كما أسلفنا.

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

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

مزايا  استخدام MVC 

من أهمّ مزايا طريقة البرمجة هذه هي اختبار مكون نموذج MVC بشكل منفصل عن المستخدم. علاوة على ذلك:

  • سهولة صيانة الأكواد والتوسع في وظائفها. يدعم MVC التطوير السريع والمتوازي. إذا اُستخدم نمط تصميم MVC لتطوير تطبيق الويب، فيمكن أن يعمل أحد المبرمجين على العرض في ذات الوقت الذي يعمل الآخر على وحدة التحكم لإنشاء منطق عمل للتطبيق. وبهذا، يمكن إتمام التطبيق المُطور باستخدام نمط تصميم MVC أسرع بثلاث مرات من التطبيقات المُطورة باستخدام أنماط التطوير الأخرى.
  • توفير عدة طرق عرض. اليوم، ثمّة طلب متزايد على طرق جديدة للوصول إلى تطبيقك ومن المؤكد أن التطوير باستخدام نمط تصميم MVC هو حل رائع. علاوة على ذلك، لا داعي لتكرار الأكواد في هذه الحالة، لأن نمط التصميم يفصل البيانات ومنطق العمل عن العرض.
  • دعم تقنية عدم التزامن (Asynchronous Technique). نظرًا لتكامل بنية MVC مع إطار عمل JavaScript. فيمكن جعل تطبيقات MVC تعمل حتى مع ملفات PDF والمتصفحات الخاصة بالموقع وأيضًا مع أدوات سطح المكتب. ومع دعم MVC أيضًا تقنية عدم التزامن (وذلك حين يختار البرنامج الرئيسي عدم الانتظار عند مواجهته أمر محظور،  وإنما ينتقل لأداء مهام أخرى) يمكن للمبرمجين تطوير تطبيق أسرع في التحميل.
  • تكامل مع تحسين محركات البحث (SEO). يدعم نمط التصميم MVC تطوير صفحات/تطبيقات الويب المتوافقة مع تحسين محركات البحث. فعبر استخدامها من السهل جدًا تطوير عناوين URL صديقة للسيو لتوليد المزيد من الزيارات من تطبيق معين. يستخدم نممط التصميم هذا بشكل شائع في تطبيقات التطوير المستند إلى الاختبار. علاوة على ذلك، يمكن دمج لغات البرمجة النصية مثل JavaScript و jQuery مع MVC لتطوير تطبيقات ويب غنية بالميزات.
  • لا يؤثر التعديل على النموذج بأكمله. بالنسبة لأي تطبيق ويب، تميل واجهة المستخدم إلى التغيير بشكل متكرر أكثر من قواعد العمل الخاصة بشركة تطوير الشبكة! فكمطور، لن تتوقف لحظة عن إجراء تعديلات متكررة في تطبيق الويب خاصتك (ل تغيير الألوان والخطوط وتخطيطات الشاشة وإضافة دعم جديد للأجهزة للهواتف المحمولة أو الأجهزة اللوحية). علاوة على ذلك ، من السهل جدًا إضافة نوع جديد من العرض في نمط MVC لأن جزء (النموذج) لا يعتمد على جزء (العرض). لذلك، لن تؤثر أي تغييرات في النموذج على الهيكلة بأكملها.
  • إرجاع البيانات بدون تنسيق. تُعيد نمط التصميم MVC البيانات دون تطبيق أي تنسيق. ومن ثم، يمكن استخدام نفس المكونات واستدعاء استخدامها مع أي واجهة. على سبيل المثال، يمكن تنسيق أي نوع من البيانات باستخدام HTML ولكن يمكن أيضًا تنسيقها باستخدام Macromedia Flash أو Dream viewer.

عيوب استخدام MVC

  • من الصعب فهم نمط التصميم MVC وتغييره واختباره وإعادة استخدامه. يمكن أن يكون التنقل في إطار العمل معقدًا بعض الوقت لأنه يقدم طبقات جديدة من التجريد (Abstraction) والتي تتطلب من المستخدمين التكيف مع معايير التحلل الخاصة بـ MVC.
  • صعوبة استخدام MVC مع واجهة المستخدم الحديثة.
  • هناك حاجة للعديد من المبرمجين لإجراء البرمجة المتوازية/اللامتزامنة.
  • تتطلب معرفة تقنيات متعددة.
  • تحتاج وحدة التحكم صيانة مستمرة للأكواد.

مقارنة بين MVC و React

React هي مكتبة جافا سكريبت طورتها شركة الفيسبوك، وهي مصممة لإنشاء واجهات مستخدم تفاعلية (كالمُستخدمة في الماسنجر). تتمثل ميزاتها الرئيسية  في 3 نقاط:

  1. أنها مكتبة وصفية. إذ يختلف تصميم طرق عرض باختلاف حالة، والتي سيتم تحديثها وإعادة تقديمها بكفاءة.
  2. قائمة على المكونات. حيث تتيح بناء المكونات التي تدير حالتها الخاصة وتنظمها معًا في واجهات مستخدم أكثر تعقيدًا.
  3. تعرض العناصر التي تم تغييرها فقط. وذلك عبر احتفاظها بتمثيل داخلي لواجهة المستخدم المقدمة (“DOM الافتراضي”).

هل أدى دمج MVC مع React لظهور Flux؟

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

هل انتهى زمن التطوير بنمط التصميم MVC؟

ربما تكون الإجابة المباشرة أقرب إلى نعم، ولننظر لم في الأسطر التالية.

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

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

رأي #1

ولكن، خلال السنوات القليلة الماضية، لم يعد يهتم مطورو مواقع ويب Back-End Developer بالعرض. فعوضًا عن إرسال أي نوع من أنواع HTML، باتوا -في الغالب- يرسلون JSON بدلاً من ذلك.

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

وبغياب العرض View، تغيب الحاجة إلى وحدة التحكم Controller (نظرًا لأن مهمتها الوحيدة أن تكون بمثابة حاجز/حد بين المكونين الأخريين).

رأي #2

يحتاج مطورو مواقع الويب اليوم إلى أنماط جديدة، أو بعبارة أدق، يحتاجون إلى تعلم الأنماط القديمة لتحل محل MVC. مثل ماذا؟ على سبيل المثال، يحتوي node.js على إطار عمل Express، والذي يطبّق على نطاق واسع نمط الوسيط للسماح للمطورين بتحويل الطلب -في أي عدد من الخطوات المنفصلة- إلى استجابة بيانات بتنسيق JSON.

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

هذا يعني أن بمقدور أي مطور ويب محترف التخلي عن أطر MVC القديمة، لأن كل لغة تحتوي على حزم لكل شيء تقريبًا وكل واحدة منها تتيح تنفيذ أنماط التصميم هذه.

إذا ماذا يحمل المستقبل؟

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

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

في الختام

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

‫2 تعليقات

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

زر الذهاب إلى الأعلى