السبت، 24 يناير، 2015

نصيحة ذهبية: قلل اعتماديات برامجك التي لا لزوم لها قدر الإمكان

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

في البداية فإن من ضمن الاعتماديات التي أتحدث عنها (و النقطة التي سنركز عليها في هذا المقال) أن يكون برنامجك يستعين بمكتبات إضافية في عمله ليست من برمجة المطورين القائمين عليه، سواء أكانت تلك المكتبات مفتوحة المصدر أو مغلقة المصدر. كأن تريد إضافة ميزة الـOCR (اختصار لـOptical character recognition) إلي أحد برامجك، و لأن هذه ميزة معقدة للغاية، فبالتالي سيكون من الأفضل بكثير أن تستعين بمكتبة خارجية لتقوم بتلك العملية، مثل مكتبة tesseract-ocr، و هكذا يمكنك أن تركز جهدك كله علي الأمور التي يتميز بها برنامجك بدون الحاجة لبناء ما بناه الآخرون بالفعل، كما أنك بهذه الطريقة ستستفيد في المستقبل من التحسينات و الإصلاحات التي يطبقونها علي مكتبتهم بدون أي جهد من ناحيتك.
 
 
 
أين المشكلة إذاً ؟!
 
المشكلة أن المبالغة في عدد المكتبات الخارجية التي يستعين بها البرنامج لأداء عمله يؤدي في النهاية إلي تعقيد الأمور. صحيح أنه يؤدي إلي زيادة المميزات التي يتمتع بها برنامجك، إلا أنه رويداً رويداً تزداد المصاعب التي تنتج عن ذلك الدمج البرمجي حتي تصل لمرحلة تخرج عن السيطرة إن لم تنتبه للأمر جيداً.

بينما الاعتماديات الأقل تعني حجماً أقل لحزمة التنصيب installation package، و تنصيباً أكثر سرعة و أقل تصديعاً للرأس. و لو اشترك معك أحد في تطوير البرنامج فسيكون من السهل بالنسبة له التعديل في الأكواد، ثم عمل ترجمة compile و بناء build للمشروع، بدون الصداع الرهيب الذي سيصيبه إن كان للبرنامج عدد كبير من الاعتماديات؛ لأن تلك الاعتماديات يجب ترقية أكوادها كلما صدرت نسخة جديدة مُحسَّنة منها، أو علي الأقل كلما صدرت ترقيعة لثغرة أمنية خطيرة بها (فكر في حالة اعتمادك علي مكتبة OpenSSL في التشفير، و اضطرارك بعد ظهور ثغرة heartbleed للاعتماد علي الإصدارة الجديدة من المكتبة أو التعديل في الإصدارة التي تعتمد عليها حالياً).

عن نفسي كانت لي تجربة واقعية سيئة بهذا الشأن، حيث طلب أحد العملاء مني التعديل في برنامج open-sankore مفتوح المصدر - و هو برنامج قوي يختص بالتعليم التفاعلي- بحيث أضيف له إمكانيات جديدة ليست فيه، و أجعله أكثر تناسباً مع احتياجات شركته، و قد وجدتُ أن الأمر ليس شديد الصعوبة بحمد الله تعالي. و رغم أنني أعمل بالـjava و لا أحب العمل بالـ++C، و لم أستخدم مكتبة الـQt من قبل في الفترة التي كنتُ أعمل فيها بالـ++C، إلا أنني بذلت جهدي لتحصيل اللازم بسرعة و بدأت أولي الخطوات.

المشكلة أن مطوري open-sankore جعلوه يعتمد علي كثير من المكتبات الخارجية (مثل xpdf و freetype و quazip) لكي يستطيع القيام بوظائفه، و هذا أدي إلي أن التعديل في أكواده أصبح عذاباً أليماً؛ فلكي تقوم بعمل build مبدئي له عليك أن تقوم بعمل build لكل الاعتماديات و علي رأس تلك الاعتماديات نسخة معدلة من مكتبة الـQt !
نعم: لقد عدَّلوا مكتبة الـQt لتتماشي مع أكواد برنامجهم، و رغم أنه أمر عادي في عالم البرمجيات مفتوحة المصدر إلا أنه جعل التعامل مع open-sankore كلعب كرة القدم في حقل ألغام؛ فقد واجهتُ الكثير من المشاكل مع الأدوات المختلفة مثل nmake الخاص بالـvisual studio و غيره لكي أصل لمرحلة التكويد فقط !
 
من الإشكاليات الكبري في open-sankore أنه لا يعتمد فقط علي نسخة معدلة من مكتبة الـQt، بل أنهم حينما وضعوا روابط للنسخة المعدلة لم تكن تلك النسخة علي هيئة مكتبات dll جاهزة للربط بالأكواد، بل كانت علي هيئة أكواد عادية يجب أن تقوم أنت أيها المسكين بعمل configure ثم make لها (لأنهم لا يعلمون أي نظام تشغيل و أي معالج تستخدم)، و الكارثة هنا أن هذه العملية تستغرق ساعات طويلة من العمل المتواصل من الحاسوب جيد المواصفات لتكتمل (أرجو أن تلاحظوا أنني قلتُ "العمل المتواصل"!)، و في حالتي الشخصية فنظراً لأنني كنتُ أعمل علي جهاز تخيلي virtual machine بنظام Windows XP له ذاكرة متطايرة RAM بمقدار 1 GB فقط، فقد اضطررت إلي الانتظار لأكثر من يومين متواصلين حتي تكتمل العملية.


عمل configure ثم make للنسخة المعدلة من QT


و ليست المشكلة في هذا فقط؛ بل الكارثة أنه رغم أنني قمتُ بتوفير كل الاعتماديات التي يحتاج إليها البرنامج للعمل، إلا أن عملية الـmake فشلت في آخر مرحلة من المراحل، و لكم أن تقدروا الحسرة التي كنتُ فيها حينما رأيتُ أن جهد أكثر من يومين من العمل المتواصل ذهبت هكذا بلا قيمة.
ثم اكتشفتُ فيما بعد أن هناك اعتمادية معينة لم تأت توثيقات البرنامج علي ذكرها، و حينما قمتُ بتخطي عقبتها واجهتني صعوبات من نوع جديد، حيث وجدتُ أن هناك مشاكل تظهر عند العمل علي Windows XP لا تظهر عند العمل علي Windows 8 !، و هكذا اضطررتُ لتنصيب كل الأدوات التي أحتاجها علي نظام التشغيل الأساسي و ليس علي آلة وهمية (و أنا لا أحب أن أفعل هذا إلا مع أدوات البرمجة بالـjava؛ للحفاظ علي النظام الأساسي من أي مشاكل محتملة).
 
ثم في النهاية ظهرت أمامي مشكلة لم أجد لها حلاً مطلقاً، كانت تحدث (حسبما فهمتُ حتي الآن) لأن مكتبة الـQt تضم مكتبة خارجية إليها في عملية الـlinking، ثم يقوم برنامج open-sankore باستخدام ذات المكتبة في الـlinking و بالتالي يحدث التعارض.
و الإشكال هنا أنني أستخدم نفس الأدوات التي طلب مبرمجو open-sankore استخدامها، و اتبعتُ نفس الخطوات التي طلبوا اتباعها، ثم في النهاية فوجئتُ بخطأ يدل علي أن هناك أحد الإعدادات يجب تعديله لتسير الأمور بشكل عادي، و هنا يأتي السؤال: "كيف لا يواجهون هم نفس المشكلة ما دامت الأدوات و الإعدادات واحدة ؟!".

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

الشاهد من وراء كل ما فات أن زيادة حجم الاعتماديات الخاص ببرامجك (مع القدرة علي الاستغناء عن كثير منها) يجعل الأمور في غاية السوء، و ستزداد الأمور سوءاً لو أن تلك الاعتماديات دقيقة للغاية، و لا تكتفي بتحديد هويات البرامج و المكتبات فقط، بل تزيد علي ذلك بتحديد هويات الإصدارات المعينة التي تعتمد عليها من تلك البرامج و المكتبات؛ ففي ذلك النوع الأخير من الاعتماديات يزداد مقدار الصعوبة عاماً وراء عام، و خاصة لو كان في تلك الاعتماديات منتج تجاري دورة تطويره و إخراج إصدارات جديدة منه (تختلف عن سابقاتها في أمور غير قليلة) سريعة (مثل الـvisual studio).

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

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



------------------------------------------
نشر هذا المقال أول مرة علي موقع Drolint.com  و أعدتُ نشره هنا مع بعض التصرف؛ لأن الموقع غير متوافر حالياً فلم أنسخ المقال منه بل اعتمدتُ علي مسودته عندي، وغيرتُ فيها بما يختلف قليلاً عن المقال المنشور هناك.

هناك تعليق واحد: