Saturday, December 30, 2017

هندسة البرمجيات بالهجايص -- (2) أحط الحاجة فين؟

أصل المقالة دي كانت بوست كتبته على الفيسبوك، فحبيت أعيد نشره لتعم الفائدة...
وده رابط الحلقة الأولى في السلسلة لمن أراد..
"جيت ألم البنطلون الجاكتة ضربت...جيت ألم الجاكتة البنطلون ضرب!" -- سمير غانم 
- الحقيقة احنا بنشوف المرار في البرمجة، تيجي تعدل في حتة في البرنامج ولا تحل bug تلاقي جحيم اتفتح عليك و عمال تعدل في حتة تانية ورا حتة تالتة ورا حتة رابعة. وبيبقى فيه حتت كده في كل برنامج عبارة عن كهف مظلم محدش يجرؤ يقرب له بسبب موضوع تسلسل التعديلات ده. النوع ده من البرامج بيبقى مقاوم للتغيير، بيبقى عامل زي الزجاج كده فيه صلابة rigidity بس فيه هشاشة في نفس الوقت fragility. الوضع ده لما بيكون صفة ملازمة للبرنامج غالبا هاتفكر تهده وتبنيه من أول وجديد، إوعى، وراجع مقالة "إعادة اختراع العجلة في البرمجيات

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

- فيه نوعية تالتة من البرامج لما تحب تعدل فيها أو تحل مشكلة تلاقي الطريقة الصحيحة لعمل ده صعبة بسبب اعتمادية أجزاء الكود على بعضها، و تلاقيك بتكتب hacks و workarounds أكتر ما بتكتب كود كويس. الكود اللي من النوعية دي بيتصف باللزوجة viscosity يعني بيبقى ملزق كده زي الزيت لما يكون في الطاسة، لما تيجي تنظفه تلاقيه مش راضي يطلع.

البرامج اللي بيجتمع فيها البلاوي اللي فوق دي فيه مصطلح ظريف بيعبر عنها اسمه Big Ball Of Mud يعني كرة الطين الكبيرة!
لو تلاحظ المشاكل اللي فوق دي هاتلاقي إن الاعتمادية dependencies هي جزء أساسي في المشكلة، مش الاعتمادية في حد ذاتها، لكن كثرة الاعتمادية و عمقها - زي ما اتكلمنا فوق - و جزء أساسي في شغلك لما تيجي تظبط برنامج مطين أو تصمم برنامج جديد إنك تكسر الاعتمادية دي، و ده موضوع المقالة دي...أحط الحاجة فين؟

- أول مبدأ معانا هو مبدأ الفصل بين المسئوليات Separation of Concerns [الترجمة متصرفة أنا عارف].

تعالوا نضرب أمثلة توضح المقصود على طول:
= لما بيكون المشروع بتاعك مقسم لطبقات layers ما تخليش مسئوليات الطبقات تدخل في بعضها، يعني مثلا الطبقة بتاعت الواجهة front-end/presentation layer تكون مسئولة بس عن واجهة المستخدم user interface ومافيهاش قرارات ليها علاقة بقواعد النظام business rules و طبعا مش بتوصل لقاعدة البيانات! ده على مستوى بنية النظام application architecture.
= في كل طبقة layer ما تجيش تخلط برضو بين المسئوليات في أجزاء الطبقة دي، يعني مثلا يفضل إنك ما تكتبش html و css و javascript في نفس الملف لأن كل حاجة من دول مسئولة عن حاجة مختلفة. و نفس الكلام لما يكون عندك مثلا class مسئولة عن إدارة حسابات المستخدمين ما تحطش فيها كود له علاقة بإدارة الكتب (لو أنت عامل برنامج لمكتبة مثلا).
= نفس الكلام في قاعدة البيانات، ما تجيش تحط حقول columns مالهاش ارتباط الprimary key (و دي اسمها database normalization بس مش هانتكلم عنها عشان دي قصة لوحدها)
...وهكذا في كل مناحي البرنامج.

- المبدأ ده يقودنا لمبدأ تاني هو التخصص الدقيق Single Responsibility Principle [الترجمة متصرفة جدا المرة دي أنا عارف].

المبدأ بيقولك أي جزء برمجي لازم يكون بيعمل حاجة واحدة بس، و بيعملها كويس. و تقدر تقيس الموضوع ده بإن ما يكونش عندك أكتر من سبب لتغييرالجزء البرمجي ده. تعالوا نخش في الأمثلة:
= عندي method اسمها ParseAndCalculate لاحظ وجود الAnd في الاسم ده دليل على إن الmethod بتعمل حاجتين. طبعا الاسم مش دليل كافي، ممكن يكون مسميها بلحة وبتعمل 5 حاجات. الشاهد إن لما أحب أغير في الParse هاعدل في الmethod ولما أحب أغير في الcalculate هاغير فيها برضو، و ده يتنافى مع مبدأ التخصص الدقيق.
= شفت كود الmethod فيت تتجاوز ال3000 سطر بدون أي مبالغة، بس الحقيقة المبرمج حاطط comments كتير وعامل regions جوه الmethod مبين فيها كل حتة بتعمل إيه. ده مؤشر ظريف إن ممكن الregions دي تتقسم لmethods منفصلة.
= الكلام ده لا يسري على الmethods بس، طبقه بقى على كل حاجة من أول بنية النظام و طبقاته، مرورا بالclasses و الmethods و وصولا لقاعدة البيانات.

- فيه مبدأ تالت مرتبط بالمباديء اللي فاتت دي، ألا و هو مبدأ الاقتران Coupling و التماسك Cohesion [بتتنطق كده كوهيجن، بتعطيش الجيم]. يعني إيه الكلام ده؟

= الاقتران coupling معناه قد إيه الحاجات اللي أصلا مالهاش علاقة ببعض في اعتمادية بينها، و دي قصة الdependencies اللي عمالين نهري فيها فوق، فده بيتكلم عن علاقة الحاجات ببعضها من بره.
= أما التماسك cohesion فبيتكلم عن علاقة الحاجات ببعضها من جوة، يعني لما تشوف حاجة في الclass كده و تقول: "إيه اللي جاب القلعة جنب البحر؟" تعرف إن الclass مش متماسكة و بتعمل حاجات مش بتاعتها.
المبدأ ده تقدر تعتبره معيار لقياس هل تغيير الكود بتاعي سهل و لا صعب، إزاي؟
= الحاجات اللي مقترنة ببعضها tightly coupled بتبقى صعبة التعديل، يعني فيه اعتمادية بينها بحيث لو عدلت في جزء محتاج أعدل في جزء تاني. و أنا مش عاوز كده أنا عاوز الارتباط بينها يكون في حده الأدنى loosely coupled.
= الحاجات اللي مش بتطبق مبدأ التخصص الدقيق بتكون غير متماسكة loosely cohesive ودي برضو بتبقى صعبة في التعديل، يعني فيه أكتر من سبب لتعديل الجزء البرمجي ده. و أنا مش عاوز كده برضو، أنا عاوز التماسك يكون عالي جدا tightly cohesive.
= طيب تعالوا نعيد صياغة المبدأ تاني: حاول توصل لأعلى تماسك و أقل ارتبط strive for tight cohesion and loose coupling عشان الكود بتاعك مايبقاش big ball of mud.

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

Sunday, December 24, 2017

إعادة اختراع العجلة في البرمجيات

أصل المقالة دي كانت بوست  كتبته على الفيسبوك، بس حبيت أعيد نشره لتعم الفائدة...

- أول مهمة عمل استلمتها في أول شركة اشتغلت فيها كان مطلوب مني أكمل شغل حد كان بدأ فيه قبلي شوية صغيرين، فأنا بكل ثقة، و كعادة كل المبتدئين قليلي النضج، ما عجبنيش الشغل اللي معمول و هدّيته وبنيته من أول وجديد، وطبعا ده أخد وقت محترم عشان أخلصه.
المهم مديري الفني وقتها كان م. حسن فهمي - ربنا يجزيه عني خيرا - سابني أكمل الشغل لغاية الآخر و بعدين قال لي الآتي:
مش كل حاجة ما تعجبكش تهدها وتبنيها من أول وجديد.
وده كان أول درس عملي لي في البرمجة.
وقتها ما استوعبتش الدرس قوي عشان كنت لسه قليل الخبرة، بس الأيام بتعدي و بتعلم الدرس بالطريقة الصعبة.
- في سبعينيات القرن الماضي، واحد من رواد صناعة البرمجيات اسمه فريدريك بروكس، عمل كتاب اسمه The Mythical Man-Month بيتكلم فيه عن مشكل صناعة البرمجيات وقتها، و الكتاب ده يعتبر من كلاسيكيات الصناعة بتاعتنا وظريف جدا، أنصحكم تقرأوه. المهم الراجل حذر في الكتاب ده من حاجة غريبة جدا، ألا وهي تأثير النظام الثاني The second system effect، و خلاصة الكلام اللي قاله إنه لما يكون عندك برنامج فيه مشاكل و تيجي تعمله من أول وجديد غالبا البرنامج ده هايكون فاشل لأنك هاتحاول تعالج فيه كل المشاكل اللي قابلتك في المشروع الأول و المشاكل اللي متوقع تقابلك مستقبلا و بالتالي هاتهندسه بزيادة over-engineered!
الحقيقة لما قرأت الكلام ده أول مرة استوعبته كويس المرة دي عشان كنت مريت بتجارب عملية على مشروعات فشلت بتأثير النظام الثاني!
- طيب ليه المبرمجين بيحبوا يهدوا اللي معمول و يبنوه من أول وجديد على نظافة -زعموا-؟

فيه مثل عندنا بيقولك: مفيش صنايعي بيعجبه شغل صنايعي تاني. والكلام ده في صناعة البرمجيات له وجه للأسباب التالية:
1- غالبا كل برنامج اتعمل كان له سياق ومشاكل بيحاول يحلها و مبرمجين بخبرات معينة بيشتعلوا عليه ومش شرط أنت تكون ملم بالظروف و السياق ده، و لا عندك نفس الخبرة اللي كانت عند الناس اللي عملوا البرنامج، ربما خبرتك أكتر فتستحقر شغلهم، وربما أقل فتحس إنه خيال علمي.
2- البرنامج مش بيتوقف بعد أول طلعة، و بيفضل يتضاف فيه خصائص و حلول لمشكلات bug fixes و تعديلات بشكل مستمر. مع ضغط الوقت و قلة الخبرة و تغير مطاليب العملاء بتلاقي الدنيا بتعك منهم.
3- فيه خاصية من طبائع البرمجيات، أشار ليها جول سبولسكي - أحد مؤسسي موقع stackoverflow الشهير، و هي أن كتابة الكود أسهل من قراءته، والطبيعة دي بتسري حتى لو أنت بذات نفسك اللي كاتب الكود اللي مش عارف تقرأه ده!
4- فيه مشكلة بقى عند المبرمجين نفسهم لما بييجوا يقيموا برنامج مش هما اللي عاملينه، و هي معايير التقييم: فمثلا ما بيحطوش وزن للسياق اللي اتعمل فيه البرنامج - اللي اتكلمنا عنه في النقطة 1، أو بيقيموه حسب التقنيات الحديثة اللي هما بيعرفوها، و اللي ربما ما كانتش موجودة لما البرنامج اتعمل أول مرة، أو حسب أساليب التصميم الحديثة اللي ما كانتش موجودة برضو لما البرنامج اتعمل أول مرة.
4- في بقى مشكلة تانية عند بعض المبرمجين المطلعين، إنهم بيحبوا يعملوا الحاجة من أول وجديد عشان يجربوا كل حاجة جديدة عشان يكتبوها في سيرهم الذاتية، و على الرغم إن تجربة كل شيء جديد أحد أساليب التعلم اللي فادتني كتير على المستوى الشخصي، بس كانت مكلفة، لأني فشلت كتير بسبب الاعتماد على تقنيات غير ناضجة، أو تجربة حل برمجي للمشكلة الغلط! وكل ما بتزداد خبرتي الموضوع ده كان بيقل معايا.
- طبعا الحل الأمثل لما يكون عندي برنامج خربان بس شغال وله قمية عند العملاء إني أحسن فيه واحدة واحدة، وحتى لو هاعيد بناؤه من الصفر، فلازم ده مايكونش خبطة واحدة، بل يكون التغيير بطيئا ومع الوقت.
- فيه برنامج كنت شغال على النسخة التانية منه، زمايلي كانوا بيقولولي إنهم اكتشفوا في النسخة الأولى منه إن الفيجوال بيسك ما بيقبلش أكتر من 128 بارامتر في الفانكشن (لاحظ اكتشفوا، يعني فضلوا يجربوا لغاية لما فشلوا). و مشروع تاني مش كبير كان بياخد 160 جيجا رامات، و لما حسنوه وصل ل70 جيجا!!
طبعا النوعية دي من البرامج لازم تولع فيها و تنسى كل الهري اللي أنا قلته فوق ده، بس لو عرفت تظبطه بالتدريج يبقى أحسن 
يللا شير في الخير بقى 

Wednesday, December 6, 2017

هندسة البرمجيات بالهجايص: (1) أسمي الحاجة إيه؟

أصل المقالة دي كانت بوست كتبته على الفيسبوك، فحبيت أعيد نشره لتعم الفائدة...

* مقدمة:

بقالي كتير عاوز أكتب سلسلة مقالات أو أعمل سيشنز عن بعض المفاهيم المهمة في تصميم البرمجيات، و بالذات المفاهيم المتعلقة بال Object Oriented Design و ما يتبعها من Design Patterns، بس كالعادة الوقت ما بيبقاش متاح، فقلت أعمل سلسلة على الفيسبوك أتكلم فيها عن المفاهيم دي بالهجايص كده، و أهو أحسن من مفيش.

* مين هايستفيد من الهري ده؟

عشان يكون الكلام مفيد لازم اللي هايقراه يكون عنده خلفية جيدة عن الObject Oriented Programming و إلا هايحس في معظم الأحيان إننا بنتكلم هيروغليفي.

* أول قاعدة:

خلونا نبدأ في الأول بمفاهيم عامة في تصميم البرمجيات و نخش في التفاصيل واحدة واحدة مع الوقت إن شاء الله.
من أهم الحاجات اللي محتاجين ناخد بالنا منها لما نعوز نكتب كود نظيف:
1- نسمي الحاجة إيه؟
2- نحط الحاجة دي فين؟
[الحقيقية اللي اتعلمت منه القاعدة دي واحد ابن حلال اسمه أمير جعفر عامل سلسلة يتيمة على اليوتيوب عن الTest Driven Development (ابقوا بصوا عليها)]
نرجع لشرح المفهوم...

*** نسمي الحاجة إيه؟

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

* إزاي بقى تختار اسم مناسب؟

- الاسم لازم يعبرعن الحاجة اللي بيمثلها، يعني مثلا لو بتختار اسم لclass فالمفروض تفهم من اسمها الكلاس دي بتهبب إيه بالضبط، لو اسم method فالمفروض الاسم يعرفك هي بتعمل إيه بالضبط من غير ما تبص على الكود اللي جواها...إلخ. و خدها قاعدة كده، لو الاسم اللي اخترته محتاج تكتب جنبه comment عشان يشرح معناه إيه، فده مؤشر إن الاسم اللي أنت مختاره وحش.
- بلاش الأسماء المضللة عشان بتتعبنا و الله، يعني مثلا ماتجيش تسمي variable: productList و هو مش list مش جايين نحل فوازير احنا...لقد هرمنا 
- الفرق بين المفاهيم لازم ينعكس في الأسماء، يعني مثلا لو بنعمل method بتنقل ملف من source إلى destination، ما تسميش الvariables:
a1 & a2
لأ سميهم source & destination
- تجنب التلوث البصري في اختيار الأسماء، يعني مثلا لو عندك class اسمها company، ما تجيش بقى في كل الfields اللي فيها و تلزق في اسمها company، فماتقولش companyName، companyId، companyAddress..إلخ. قل لي إيه الإضافة اللي ضفتها لما عملت كده؟ و الأنيل بقى لما تلاقي واحد كاتب لك nameString كأن الاسم ممكن يكون float مثلا.....لقد هرمنا بجد 
- الاسم اللي هاتختاره لازم تكون هاتعرف تقراه، و بالتالي لما تيجي تدور عليه تعرف تلاقيه. بلاش اختصارات في الأسماء، و استخدام الأسماء الطويلة مش عيب و لا حرام على فكرة.
- استخدام الفرانكو في الفيسبوك وحش قوي، و أوحش في الكود. دونت يوز فرانكو إن يور كود بلييييييزززز.
- بلاش أرقام سحرية في الكود، أرقام مستخدمة في كل الكود كده محدش عارف معناها إيه. في اختراعات ظريفة في لغات البرمجة دلوقتي زي الenums و الconstants، المبرمجين الكويسين بيستخدموها...كن مبرمجا كويسا زيهم.
- ما تستخدمش variables من حرف واحد إلا في الloops، عشان دي من الحالات القليلة اللي المبرمجين تلقوها بالقبول.
- أسماء الclasses و الobjects تكون أسماء مش أفعال، مثال: company، account، FileParse. و أسماء الmethods تكون أفعال و أسئلة مش أسماء، مثال: DoSomething، IsValid، HasChildren..إلخ.
- بلاش استظراف في الكود، ما تجيش مثلا تستخدم قفشات من فيلم بتحبه في أسماء الvariables عشان أنت أكيد عارف إن مش كل الناس بتلقط قفشات الأفلام.
- حاول تكون متسق مع ذاتك و تستخدم نفس الاسم للتعبير عن نفس المفهوم في كل حتة، يعني مثلا لو بتحب اسم get لما تعوز تجيب حاجة، افضل استخدمه في كل حته، مش مرة تستخدم get ومرة retrieve و مرة fetch... كمان مرة، خليك متسق مع ذاتك.
- لو مطبق design pattern معين حاول تستخدم اسمه كجزء من اسم الclass أو الmethod بتاعتك، و نفس الكلام لو فيه algorithm أو أي مصطلح يفهمه بتوع البرمجة برضو استخدم اسمه برضو. تذكر إن اللي بيقروا الكود مبرمجين فارفق بهم و ساعدهم يفهوا الكود عشان يدعولك.
- لو ما لقيتش اسم برمجي مناسب بس كان فيه اسم في البزنس اللي أنت شغال عليه ممكن تستخدمه، توكل على الله و استخدم اسم البزنس.
- و لو ما لقيتش اسم مناسب لا للمبرمجين و لا في البزنس، هاتضطر تطلع مهارات الفتي اللي جواك، بس حاول تقلل من استخدام الأسماء المستهلكة زي Manager، Controller، Data، Info بقدر المستطاع عشان كتر استخدامها عمال على بطال بقى مضلل شوية.
- لو اخترت اسم وبعد كده حسيت إنه مش مناسب غيره عادي خالص، مش عيب و الله، خاصة إن التولز دلوقتي بتسهل لك التعديل في كل الأماكن مرة واحدة. و لو غيرته 10 مرات و لسه مش مناسب افضل غير فيه ولا يهمك.
- حاول تقرأ كتاب clean code، أنا نقشت منه حاجات كتير في البوست ده. و دايما بقول لو المبرمج مش هايقرأ غير كتاب واحد في حياته في البرمجة فليكن الكتاب ده.

-------
طيب بقية المفهوم الأول: أحط الحاجة فين؟
مش هاجيب صورة عادل إمام الشهيرة للإجابة على السؤال ده عشان هي قبيحة، بس هاقول لكم نخليها المرة الجاية إن شاء الله 
و لا تنسونا من لايكاتكم و شيراتكم و نصائحكم