كيفية كتابة تطبيقات قوية في كل مرة ، باستخدام "الهندسة المعمارية النظيفة"

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

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

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

في هذه المقالة ، سوف أشرح نموذج الهندسة المعمارية الذي اقترحه روبرت سي مارتن ، العم بوب في عام 2012. وهو مؤلف الكلاسيكيات مثل Clean Code و The Clean Coder. في شهر أكتوبر من هذا العام ، سيطلق كتابًا آخر هو "الهندسة المعمارية النظيفة".

يحتوي النموذج على نفس اسم الكتاب ، وهو مبني على مفاهيم بسيطة:

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

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

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

يمكنك العثور على عرض توضيحي للتطبيق هنا ، وستكون نماذج الأكواد في TypeScript. بعض الرموز الموجودة أدناه تستخدم React و Redux. بعض المعرفة حول هذه الحلول يمكن أن تساعد في فهمها. ومع ذلك ، فإن مفاهيم الهندسة المعمارية النظيفة أكثر عالمية. سوف تكون قادرًا على فهمه حتى دون معرفة سابقة بالأدوات المذكورة.

جهات

الكيانات في المخطط باسم قواعد أعمال المؤسسة. الكيانات تشمل قواعد العمل التي تعتبر عالمية لشركة. وهي تمثل الكيانات الأساسية لمنطقة عملها. هم المكونات مع أعلى مستوى من التجريد.

في عينة العدادات الخاصة بنا ، هناك كيان واضح للغاية: العداد نفسه.

استخدم حالات

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

في نموذجنا ، لدينا حالة استخدام لزيادة أو تقليل عدادنا:

لاحظ أن وظيفة المصنع لـ ChangeCounterInteractor تتلقى معلمة من النوع CounterGateway. سنناقش وجود هذا النوع في وقت لاحق في المقال. ولكن يمكننا أن نقول أن العبارات هي ما يقف بين حالات الاستخدام والطبقة التالية.

محولات واجهة

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

في عينة لدينا ، لدينا عدة محولات واجهة. واحد منهم هو مكون React الذي يعرض العداد وضوابطه على الزيادة والنقصان:

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

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

الأطر والسائقين

الأدوات التي يستخدمها نظامك للتواصل مع العالم الخارجي تؤلف الطبقة الخارجية. لا نكتب عادةً رمزًا في هذه الطبقة ، بما في ذلك المكتبات مثل React / Redux ، واجهات برمجة التطبيقات للمستعرض ، إلخ.

قاعدة التبعية

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

يجب ألا يعتمد العنصر على أي عنصر ينتمي إلى طبقة خارجها.

على سبيل المثال ، لا يمكن لأي عنصر في طبقة Use Cases معرفة أي فئة أو وحدة نمطية مرتبطة بـ GUI أو استمرار البيانات. وبالمثل ، لا يمكن لأي جهة معرفة حالات الاستخدام التي تستخدمها.

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

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

قد لا تحتاج إليها

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

حسنا ... ماذا في ذلك؟

باستخدام هذه المقالة ، اكتشفنا طريقة لفصل كيانات أنظمتنا. هذا يجعلها أسهل في الصيانة والتوسع. على سبيل المثال ، لإنشاء نفس التطبيق باستخدام Vue.js ، سيكون علينا فقط إعادة كتابة مكونات CounterPage و CounterWidget. الكود المصدري لتطبيق العينة موجود في الرابط أدناه:

تمت ترجمة هذه القصة إلى البرتغالية من قبلي! إنه متاح هنا.

ما إيجابيات وسلبيات ترى في هذا النهج؟ هل استخدمت شيئا مشابها في الإنتاج؟ تبادل الخبرات الخاصة بك في الردود. إذا كنت مثل هذه المادة ، يرجى التصفيق بالنسبة لي!