المعلوماتية > برمجيات

4 منهجية العوامل الإثني عشر

استمع على ساوندكلاود 🎧

عادةً ما يتمّ تسليم وإنهاء البرمجيّات على أساس أنّها خِدماتٌ برمجيّةٌ في العصر الحديث. حيث يُطلق عليها مسمّى برمجيّات ويب (web apps) أو برمجيّاتٌ كخِدمة (software-as-a-service). تأتي منهجيّة (12-factor app) لبناء برمجيّةٍ-كخدمة، وتتميز بأنّها:

- تحوي صِيَغاً صريحةً لعمليّة الأتمتة، ما يخفضُ الوقتَ والجهدَ اللازمين عند انضمام مبرمجين جدد.

- توفّرُ قابليّةً عاليةً للعمل على أكثرِ من نظامٍ تشغيلٍ واحد.

- تتميّزُ بقابليتها على العملِ على منصاتِ الحوسبة السّحابيّة الحديثة وهو الأمر المهم في تفادي الحاجة إلى إدارة الأنظمة المشغِّلة أو المخدّمات.

- تقليلُ التّباين بين عمليّتي التّطوير والإنتاج (development and production)، ما يُمكّنُ المطوّرين من نشر التّطبيق (deployment) بشكلٍ مستمر.

- تُوفِّرُ القابليّةَ لتطوير التّطبيق وتوسيع مهامه وإضافة الميزات دون الحاجة إلى إعادة بناءٍ، أو تعديلِ الأساسيّات المبنيّ عليها أو حتّى تطويرِ الحالات المختلفة.

هذا بالإضافة إلى أنّ هذه المنهجية قابلةٌ للتّطبيق على كلِّ البرمجيّات المكتوبة بكلِّ لغاتِ البرمجة، وعلى اختلافِ طُرُقِ الدّعم إن كانت قواعدَ بياناتٍ أم غيرها.

وللوصول إلى كُلِّ ما ذُكِرَ آنفاً، تعتمد هذه المنهجيّة على اثني عشر عاملٍ أو ممارسة، حيثُ يستطيع المطوّرون -باتّباعِها وتطبيقِها- تطويرَ برمجيّاتٍ-كخدمة بالشّكل الأمثل، سنذكرها بشكلٍ مبسّط تالياً:

1. الكود الأساسي (Codebase): حيث يحتوي على الكود المصدريّ ويتمّ تتبُّعُه من خلال نظام تحكّمٍ بالمصادر، والسّماح بعمل نشرٍ له أكثرَ من مرّة. فمثلاً يمكن من البداية وضعُ الكود المصدريّ في Git Repository واحدة، وعندما يكبر الكود المصدريّ يمكن أن يَنتُجَ لدينا تطبيقاتٌ متعددة تتواصل سويّةً، وفي هذه الحالة نستطيع تقسيمها على أكثرِ من مستودع (repository) لكنْ داخلَ نفسِ المستودع الكبير، وداخلَ نفسِ نظام التّحكم بالمصادر الأساسيّ، أي Git في هذا المثال.

2. التّبعيّات/الاعتماديّة (Dependencies): حيث يجب أن تكون معلنةً بشكلٍ صريح لجميع المطوّرين وأن تكون معزولة. فمهما كانت بيئة التّطوير لا بدَّ من وجود بعض الاعتماديّات كقواعدِ البيانات أو مكتبةٍ أو أداتِ تطويرٍ خاصة. وبدمجها في البرمجيّة الجاري تطويرُها نستطيع ضمان استمراريّةِ تطويرِ التّطبيق مع جميع المطوّرين على اختلاف بيئات التّطبيق، وحفظِ الوقت والجهد المبذولين في تنصيب هذه الاعتماديات لدى كلِّ مطوّر.

3. الإعدادات (Configuration): بتعريفٍ مبسّط للإعدادات، هي كل ما يتغيّر مع تغيّرِ بيئة التّطوير بعكس الكود المصدريّ الّذي لا يختلف مهما اختلفت بيئة التّطوير. فمثلاً الكود المصدريّ المسؤول عن التّواصل مع قاعدة البيانات هو دائماً نفسه، لكنَّ موقعَ قاعدةِ البيانات وأيَّ جهازٍ تعملُ عليه سيختلف على اختلاف الموقع الجغرافيّ للمطوّرين، وهناك إعداداتٌ لا يمكن تغييرها مثلَ الإعدادات الدّاخلية للتّطبيق كالإعدادات الّتي تحدّدُ كيفيّة عمل الكود مع البيئة.

وتُعتبر بياناتٌ كـ اسم المستخدم وكلمات السّر للسيرفرات أو الخدمات جزءاً من الإعدادات، ولا يجب أن تكونَ مخزّنةً في الكود المصدريّ أبداً. يعني هذا أنّ ملفات الإعدادات يجب أن تكون مخزّنةً في أماكنَ منفصلةٍ عن الكود المصدريّ وجاهزةً للقراءة من قِبَل الكود المصدريّ في أيّ وقت.

4. خدمات الدّعم (Backing Services): تقول المنهجيّة أنّه يجب معاملتُها كمواردَ مرفقة، وبالتّالي لا يجب على الكود أن يختلف على اختلافها. فمثلاً يتواصل الكود المصدريّ بالتّأكيد مع خدمة بريدٍ إلكترونيّ أو قاعدةِ بياناتٍ أو غيرِها. حيثُ يجب على الكود التّواصل معها من خلالِ رابطٍ بسيط (URL) فقط، حيث يعاملها الكود المصدريّ على أنّها مصادرُ من نوعٍ واحد.

يتيحُ هذا المزيدَ من المرونة، حيث يستطيع أيٌّ من المطوّرين نقلَ/تعديلَ أيَّ خدمةٍ من هذه الخدمات دون الحاجة للتّعديل على الكود المصدريّ.

5. الإصدارات والنّسخ البرمجيّة ( Build، Release، Run): حيث تعتمد المنهجيّة على الفصل التّام بين كلٍّ من هذه المراحل الثّلاث. فعمليّة البناء عمليّةٌ معقّدةٌ وتحتاج لجهدٍ كبير خاصةً من قِبَل بيئة التّطوير، وتهتم بتحويل الشّيفرة المصدريّة ضمن المستودع إلى نسخةٍ تنفيذيّة، وتكون عمليّة الإصدار هي النُسَخُ المعتمدة من قِبَل المطوّر والّتي تحوي إعدادات البرنامج أو التّطبيق والّتي تجعله صالحاً للنّشر، بينما عمليّة التّشغيل هي تشغيل التّطبيق ضمنَ بيئةِ التّنفيذ، ويجب أن تكون مبسّطةً ومحصّنةً تماماً بحيثُ يستطيع المطوّرون الاعتمادَ على أنّه مهما حدث للخادم، كانقطاع الكهرباء والحاجة لإعادة تشغيله أوتوماتيكيّاً، فإنّ ذلك لن يؤثر على عمل التّطبيق حيث أنّه سيعمل تلقائيّاً أو سيعود للعمل تلقائيّاً حالما يتمُّ إصلاحُ الخلل.

6. العمليّات الحوسبيّة (processes): حيث يجب أن يتمّ تنفيذ التّطبيق كعمليّةٍ واحدةٍ أو أكثر محايدةِ الحالة (stateless).

فمن المتوقّع أن يعمل البرنامج على أكثرِ من خادمٍ واحد، لذلك يجب أن يكون التّطبيق محايدَ الحالة. فتعثُّر أحدِ الخوادم لا يعني بالضّرورة توقّفَ التّطبيق عن العمل على جميع الخوادم كما في عمل الأنظمة الموزّعة. وبذلكَ فإنّ توقفَ التّطبيق على السيرفر خلال عمليّة التّسجيل لمستخدمٍ جديدٍ على سبيل المثال، لن يُوقفَ العمليّة، حيث يستطيعُ أحدُ الخوادم الأخرى من استلام العمليّة وإكمالِها.

7. Port Binding: عادةً ما تقومُ التّطبيقاتُ تلقائيّاً بتدبير التّواصل مع الخدمات، وذلك لأننا نستخدمُ مكتباتِ كودٍ مصدريٍّ جاهزة أو بسبب أنّ أجزاءَ من التّطبيق تعملُ داخل حاوياتٍ برمجيّةٍ كـ Tomcat Server. لكنّ إلزامَ بعض المصادر باستخدام منفذٍ وحيد دون آخر يزيدُ من سرعةِ تناقلِ المعلومات، ويُضيف قليلاً من الحماية، كفصلِ المنفذ المُستخدم من عموم المستخدمين لخدمةٍ معيّنة والمنفذ المستخدم من قبل أحد الخوادم لنفس الخدمة، وبعبارةٍ أخرى بسيطة ربما يكون أحد التّطبيقات عبارةً عن خدمةِ دعمٍ لتطبيق آخر، عبر استخدام URL لطلب تشغيل التّطبيق!

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

9. سهولة الإنهاء (Disposability): ويعني هذا سرعة بدء وإنهاء العمليّات في التّطبيق مما يؤدي إلى سهولةٍ في التّوسع والنّشر وتغيير الإعدادات. فأحد الحالات هي عندما يود المطوّر نشر كودٍ برمجيٍّ جديد أو نسخةٍ جديدةٍ للتّطبيق فمن المؤكد أنّه يوّد لو تعمل النّسخة الجديدة حالَ نشرها وتبدأَ باستقبال وإرسال البيانات. لكنْ غالباً ما تصطدم هذه الرّغبة بحاجةِ التّطبيق إلى كمٍّ كبير من البيانات وتجهيزِها في الذّاكرة وغير ذلك مما يستغرق بعضاً من الوقت، ما يؤدي إلى توقف حركة البيانات لفترةٍ من الوقت. يكمن الحلّ في تجهيز كل ما تحتاجه النّسخة الجديدة من بياناتٍ وإعداداتٍ في قاعدةِ بياناتٍ شديدةِ السّرعة في نقل البيانات أو في ذواكرَ تخزينٍ احتياطيّة (Cache).

10. تكافؤ عمليّتي التّطوير والإنتاج (Dev/p> d parity): يجب على المطوّرين جعلُ عمليّات التّطوير والإنتاج وما بينها متشابهةً قدر الإمكان. فالفارق بالتّوقيت بين الوقت المستغرق لإنهاء عمليّة التّطوير برمجيّاً ونشرِها على الخوادم؛ لا يجب أن يكون طويلاً، مما يؤثر على الإنتاجيّة للفريق. كما أنّ هناك فارقاً بين عمليّتي التّطوير والنّشر (deploy) حيث أنّها غالباً ما تحتاج لمهندسين أحدهما يطوّر والآخر يقوم بالنّشر. بالإضافة إلى الفارق بين الأدوات المستخدمة من كلا المهندسَين. لذلك وبجعلِ العمليّات المختلفة متشابهةً قدر الإمكان، يمكننا حفظ الكثير من الوقت والجهد الضّائعَين في التّنقل بين هذه المراحل.

11. السّجلات (Logs): تكمن أهميّة السّجلات في توفيرها لنافذةٍ عن سلوك التّطبيق وحُسن سَيرِ العمليّات الحاسوبيّة. في هذه المنهجيّة، تُكتَب الأحداثُ المباشرة على ملف (stdout) لكلِّ عمليّةٍ من العمليّات في التّطبيق. وبذلك يستطيع المطوّرون قراءةَ السّجلات لحظةً بلحظة أثناء عمليّة التّطوير ومراقبة سير العمليّات على شاشة الحاسب مباشرةً. ثم بعد ذلك وبعد إتمام مرحلة نشر التّطبيق نقوم بتحويل هذه التّيارات إلى وجهةٍ نهائيّةٍ كملف أو غيره، وعادةً ما نترك لبيئة التّنفيذ تقريرَ ذلك. حيث أنّ هناك العديد من البرمجيّات مفتوحة المصدر الّتي تساعدنا في ذلك كـ Logplex.

12. العمليّات الإداريّة (Admin Processes): غالباً ما يحتاج المطوّرون لعمل بعض الأمور الإداريّة كدمجِ قواعد البيانات أو تنفيذ script معيّنة، لذلك تحثُّ المنهجيّة على تجهيز هذه الأكواد والعمليّات كغيرها وبذلك تستطيع قراءة السّجلات وقراءة الإعدادات لتنفيذ عمليّات الصّيانة البرمجيّة حالَ حصول أخطاء أو مشاكل.

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

================================

المصادر:

هنا