نقاط من كتاب Clean Architecture

بسم الله الرحمن الرحيم

هذه نقاط وفوائد من كتاب Clean Architecture لـ Robert C. Martin, أحدث هذه التدوينة بشكل أسبوعي تقريبا على حسب الإنجاز. الباب الأول, الحديث عن إثبات فاعلية وجدوى Software Design وأهميته.

  • بدأ الباب الأول بهذا السؤال الرائع, مالغاية من تصميم البرمجيات -Software Design-؟
    ثم أجاب: لتقليل عدد الموارد البشرية التي تبني وتحافظ على البرنامج.
    ونعني بتحافظ هنا, أنها تقوم بإضافة المميزات الجديدة -features-, ومعالجة الـ bugs السابقة.
  • هناك حقيقة في تطوير البرمجيات تقول:
    الطريقة الوحيدة للانطلاق بسرعة, هي الانطلاق بشكل جيد.

    The only way to go fast, is to go well

 

الباب الثاني عن القيمتين المهمتين, مميزات البرمجيات, ومعماريتها. 

  • لدينا قيمتين نريد تحقيقهم من خلال بناء التطبيق, الأولى طريقة عمل التطبيق (Behavior), والثانية المعمارية (Architecture)
    • المطور يوظف لغرض أن يقوم بجعل الأجهزة تعمل بطريقة تحفظ أو تحقق المال لصاحب التطبيق (stakeholder), بأن يقوم بعمل الوظائف المميزات التي يريدها صاحب التطبيق, وفي حال ظهرت بعض المشاكل -bugs- يقوم المطور باستخدام أدواته لصيانة التطبيق, لكن الإشكال أن المطور يظن أن هذه فقط هي مهمته.
    • ليحقق المطور كامل مهمته, يجب أن يقوم ببناء برمجيات سهلة التعديل, فلو قرر صاحب التطبيق إضافة ميزة أو إلغاء إخرى, يكون الأمر سهل وعملي.
  • جميل جدا, تساءل المؤلف تساؤلا عن القيمتين السابقتين, أيهما أهم, هل طريقة عمل التطبيق, أم معماريته؟ , ثم أعطى مثالين لحالتين يستطيع المتأمل معرفة الإجابة منها.
    • لو كان هناك برنامج يعمل بشكل رائع لكن يستحيل التعديل عليه, سيصبح عديم الفائدة
    • لو كان هناك برنامج لا يعمل, ولكن بني بشكل جيد, فستسطيع جعله يعمل, وتستمر في إضافة المميزات والعمل عليه.
  • مبدأ إيزنهاور هو أحد المبادئ المشهورة في التخطيط, والذي يقسم المهام إلى أربع أقسام,
    1- عاجل ومهم
    2- مهم وغير عاجل
    3- عاجل وغير مهم
    4- غير مهم وغير عاجل
    مميزات التطبيق هي دائما ذلك الشيء العاجل, ومعمارية التطبيق دائما هي الشيء المهم, نلاحظ أن معمارية التطبيق تقع ثانياً من ناحية الأهمية بينما المميزات تأتي في المرتبة الأولى والثالثة, الخطأ الذي يقع فيه مدراء المشاريع والمطورين أنهم يعطون دائما الأشياء العاجلة الأولولية على الأشياء المهمة, بمعنى أخر أنهم يخطئون في الفصل بين المميزات العاجلة والغير العاجلة فيقدمونها على الأشياء المهمة (المعمارية جيدة), الإشكال الذي يواجهه المطور هو أن مدراء المشاريع لا يعطون -يدركون أهمية- التوازن بين إطلاق مميزات جديدة والاهتمام بمعمارية النظام, لكن هذا يعتبر من صميم عمل المطور.
  • لذا ختم المؤلف هذا بالباب بموضوع عنونه بـ قاتل من أجل المعماريه (Fight for the Architecture), فريق التطوير الجيد, لابد أن يكون في يناضل من أجل الأشياء التي يؤمن أنها أفضل لمصلحة البرنامج, وتذكر كمطور تعد صاحب التطبيق -حتى وإن كنت فقط مطور-, لذلك اهتم ببناء تطبيق سهل التعديل والتطوير, أخيرا في هذا الباب حينما تأتي المعمارية في الأخير سيكون البرنامج مكلف في التطوير, وعمليا يعد التعديل مستحيلا, وحينما نصل لهذه المرحلة ندرك أن فريق التطوير لم يكن يناضل بشكل جيد لما يدرك أنه مهم.

أساليب البرمجة Programming paradigms
الباب الثالث عبارة عن نظرة عامة على الأساليب

هذا الباب كان تقديم عن الأساليب البرمجية التي ستناقش في الأبواب الثلاث القادمة وهي

  • Structure programming
  • Object Oriented programming
  • Functional programming

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

الباب الرابع  Structure programming

صاحب هذا الأسلوب البرمجي هو Edsger Wybe Dijkstra, الكتاب فصل فيه من ناحية الدافع لصاحب هذا الأسلوب والغاية من اتباعه هذا الأسلوب وطريقة اختباره, فقد كان Dijkstra يرى أن البرمجة شيء صعب, وأن المبرمجين لا يقومون بالبرمجة بشكل جيد, فاتبع هذا الأسلوب في تقسيم البرنامج لعدة أجزاء صغيرة.
ما هو الـ Structure programming ؟, نستطيع أن نقول أنه يتألف من:

1- control structure وهي أربعة أمور

  • Sequence, ونقصد فيها استدعاء الجمل والدوال بنفس الترتيب
  • Selection, ونقصد فيها جمله أو أكثر يتم تنفيذها بناء على حالة البرنامج, غالبا نستخدم معها if/else
  • Iteration, وهي جمل تتم تكرارها حتي يصل البرنامج لحالة محددة كـ for/ while
  • Recursion, وهي دالة تستمر في استدعاء نفسها حتى تصل لشرط التوقف

2- subroutines, هو المكون الثاني لـ Structure programming ونعني به الدوال (functions)

3- blocks, هو أسلوب معرف لجمع مجموعة من الجمل في مكان واحد حيث تنفذ كأنها جملة واحدة.

يسمى هذا الأسلوب البرمجي كثيرا بـ modular programming لأنه كما ذكرنا يعمد إلى تقسيم الكود لأجزاء صغيرة, حاليا جميعنا نكتب بهذا الأسلوب, ليس عن طريق الأختيار بل لأن اللغات التي نكتب بها تجبرنا على هذا الأسلوب.

كما يشدد في هذا الأسلوب البرمجي على عدم استخدام جملة goto, ونشر فيها Dijkstra مقالة بعنوان go to statement considered harmful, والتي لم تعد موجودة في عدد من لغات البرمجة الحديثة.

الباب الخامس  Object oriented programming

بدأ الكاتب هذا الباب بالتعريفات المشهوره لهذا الـ paradim -الأسلوب-: هو عبارة عن بيانات ودوال, وبين أنه تعريف ليس بالجيد, وهذا واضح جدا فجميع الأساليب البرمجية ماهي إلا عبارة عن بيانات ودوال, ثم ذكر تعريف أخر وهو أن هذا الأسلوب هو تمثيل لمشكلة حقيقة, ثم بين بعدها أن هذا بلا شك ليس تعريفا يعطي المعنى الحقيقي لهذا الأسلوب -عبّر عنه بتعريف مخادع-, لا شك أننا نستطيع القول أن OOP يمثل الحل بطريقة تشبه الواقع لكن لا يسمى ذلك تعريفا, لكن نستطيع التعبير عن طبيعة هذا الأسلوب بثلاث كلمات سحرية -على حد قوله- وهي, encapsulation -التغليف- و Inheritance -الوراثة- و polymorphism -التعددية-
لم يفصل الكاتب في هذا الباب في مفاهيم الـ OOP بل نوه إلى أهم المفاهيم وهي التي ذكرنا سابقا, ثم استطرد في ضرب أمثلة بـ sturcture programming بلغة C وكيف يمكن عن طريقها تحقيق المفاهيم الأساسية في OOP, ليبين أنه فعليا هذه المفاهيم موجودة ومطبقة بغير الـ OOP (رغم أني أرى أن بعض الأمثلة التي طبقها ليست بنفس المرونة الموجودة في OO ولا يمكن تطبيقها على تطبيقات أكبر من التي مثل عليها), وبعد ذلك تكلم الـ dependency inversion وشرع بتوضيحه بطريقة رسومية واستخدم UML digram, ليوصل في نهاية هذا الباب أن الإضافة الحقيقة لهذا الأسلوب البرمجي هي أنه يمكّن المبرمج من تطوير تطبيقات بطريقة ما سماه plugin architecture وهي أن يقسم التطبيق لوحدات -modules- تحوي قواعد عامة لتطبيق, وأخرى تحوي تفاصيل التطبيق الدقيقة.

OO is the ability, through the use of polymorphism, to gain absolute control over every source code dependency in the system. It allows the architect to create a plugin architecture, in which modules that contain high-level policies are independent of modules that contain low-level details

الباب السادس  Functional programming

هذا الأسلوب البرمجي يعتمد بشكل كبير على مفهوم λ-calculus ما يعرف بـ lambda المخترع عن طريق العالم الرياضي الأمريكي Alonzo Church في عام 1930م.

بدأ الكاتب هذا الباب بإعطاء نظرة سريعة عن ماهية هذا الأسلوب فقام بوضع هذا المثال

كود بسيط بلغة جافا يطبع مربع ٢٥ رقم, ثم مثل مثالا أخر بلغة Clojure يقوم بنفس العملية

ليفصل بعد ذلك في كيفية عمل هذا الكود وماذا يعني كل قوس وكلمة فيه, لينهي هذا التفيصل المبسط بأنه ليس الغرض من هذا الباب شرح Clojure أو الـ Functional programming, لكن كان الغرض من هذا المثال الأشارة للفرق الجوهري بين جافا و Clojure أو بين OOP و FP وهو mutable variable -المتغير الذي يغير حالته -state- أثناء عمل البرنامج-, وهو المتغير i داخل loop حيث نرى أنه تتغير قيمته فيزيد في كل دورة من 0 إلى 25 بينما المتغير x في Clojure لم ولن يتغير طوال عمل البرنامج, هذا يقودنا إلى جملة مهمة وهي: المتغيرات في Functional programming لا تتغير.

جميل جدا, مالذي يجعل موضوع immutability مهما؟, فعليا كثير من الإشكالات تحدث من المتغيرات القابلة لتغيير, أو بعبارة أبسط معظم المشاكل التي نواجهها في concurrent applications -التطبيقات التي تتطلب أكثر من thread- لا يمكن أن تحدث إذا كان لم هناك mutable variable.

فالتطبيقات ذات المعمارية الجيدة تفصل التطبيق لعدة أجزاء منها ما يمنع تغير الحالة -Immutable- وأخرى تسمح بذلك-mutable-.

 

بعد الحديث عن الثلاث أساليب في كتابة الكود نصل إلى ثلاث تعريفات واجهت مشكلة في ترجمتها ففضلت نقلها كما هي:

• Structured programming is discipline imposed upon direct transfer of control.
• Object-oriented programming is discipline imposed upon indirect transfer of control.
• Functional programming is discipline imposed upon variable assignment.

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

فيقول الكاتب في نهاية الحديث عن أساليب كتابة الكود, إن البرمجيات تتألف من sequence, selection, iteration, و indirection, لا أقل من ذلك ولا أكثر.

 

اترك تعليقاً