FA AR EN

كيف نبني برمجيات مخصصة ناجحة؟ | تجارب واقعية لمبرمج

المقدمة

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

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

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

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

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

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

1. لماذا تفشل مشاريع البرمجيات؟

عندما نتحدث عن فشل مشروع، فنحن لا نعني فقط المشروع الذي تم التخلي عنه في منتصف الطريق أو الذي لم يصل أبدًا إلى مرحلة التنفيذ.

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

أهم أسباب فشل مشاريع البرمجيات هي:

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

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

2. تحديد احتياجات العميل والتحليل الدقيق قبل بدء البرمجة

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

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

2.1. عندما لا يكون الطلب الأولي هو كل احتياجات العميل

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

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

لذلك صممت البرنامج بناءً على هذا الوصف الأولي، دون أن أراجع معه عملية المراسلات كاملة وأعتمدها بشكل نهائي.

بعد التثبيت، تم إرسال أول رسالة؛ لكن ظهرت مباشرة أسئلة أخرى:

كيف يرد القسم الإداري؟ كيف يرى المدير الرد؟ كيف يتم التوقيع؟ كيف تُرسل الرسالة إلى قسم آخر وكيف تتم متابعتها؟

عندها أدركت أن ما بدا في البداية مجرد «إرسال رسالة واحدة»، كان في الواقع جزءًا من عملية مراسلات كاملة.

علّمتني هذه التجربة أن ما يذكره العميل في البداية لا يمثل دائمًا كامل احتياجه الحقيقي. وقبل بدء البرمجة، يجب فهم عملية العمل الفعلية وطرح الأسئلة اللازمة حولها.

2.2. عندما لا يكون النموذج البسيط مجرد نموذج

في مشروع آخر، طُلب مني تصميم نموذج إلكتروني لتسجيل بيانات مشتري أجهزة نقاط البيع وتفعيل الجهاز.

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

لذلك قدّرت مدة تنفيذ المشروع بأكثر مما كان متوقعًا للوهلة الأولى.

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

يمكنكم قراءة تفاصيل هذه التجربة في تجربة «عندما استغرق نموذج بسيط 20 يومًا» .

خلاصة هذا القسم

توضح هاتان التجربتان، كل منهما من زاوية مختلفة، نقطة مشتركة:

قبل كتابة الكود، يجب فهم المشكلة الحقيقية وعملية العمل بشكل صحيح.

أحيانًا يكون الطلب الأولي مجرد جزء من الاحتياج الحقيقي للعميل، وأحيانًا يكون ما يبدو بسيطًا معقدًا جدًا في الخلفية.

لذلك، يُعد التحليل الدقيق قبل بدء البرمجة من أهم مراحل بناء البرمجيات المخصصة.

3. ما الذي يجب تحديده والاتفاق عليه قبل بدء المشروع البرمجي؟

من أهم الأعمال في بداية أي مشروع برمجي تحديد إطاره وتفاصيله الأساسية.

بعد دراسة احتياجات العميل وعمليات العمل لديه بشكل صحيح، يجب تحديد ما الذي سيتم بناؤه بالضبط، وما المخرجات التي يجب تسليمها، وما مسؤوليات كل طرف، وما الجدول الزمني للمشروع وتاريخ التسليم، وكيف سيتم احتساب التكلفة ودفعها.

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

3.1. يجب تحديد نطاق المشروع

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

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

لذلك يجب أن يكون واضحًا ما الذي يدخل ضمن المشروع وما الذي يُعد طلبًا جديدًا.

3.2. يجب تحديد الجدول الزمني وتاريخ التسليم

يجب تحديد مدة تنفيذ المشروع بناءً على حجم العمل والتعقيد ومراحل التنفيذ والتزامات الطرفين.

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

من الأفضل أن يتم تحديد الجدول الزمني للمشروع وفق مراحل والتزامات واضحة.

3.3. يجب أن تكون التكلفة وآلية الدفع واضحة

يجب تحديد المبلغ المطلوب للمشروع منذ البداية، وما الذي يشمله تحديدًا من وظائف وخدمات، وفي أي مراحل يتم الدفع، وما تأثير طلب وظائف جديدة في التكلفة.

يمكن أن تؤدي تغييرات المشروع إلى تغيير وقت وتكلفة تنفيذه؛ لذلك يجب تحديد آلية التعامل مع التغييرات منذ البداية.

3.4. يجب تحديد مسؤوليات الطرفين

لا تقتصر مسؤوليات المشروع البرمجي على منفذ المشروع وحده.

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

إذا لم تكن هذه المسؤوليات واضحة، فقد يؤدي التأخير في تقديم المعلومات أو اتخاذ القرارات إلى توقف المشروع، وفي النهاية إلى حدوث خلافات.

3.5. يجب تحديد حقوق الملكية وملكية البرمجيات منذ البداية

من الموضوعات التي قد تسبب خلافًا بعد انتهاء المشروع، ملكية البرمجيات والشيفرة المصدرية.

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

من الأفضل الاتفاق قبل بدء المشروع على أمور مثل:

  • من يملك البرمجيات؟
  • هل يحصل العميل أيضًا على الشيفرة المصدرية؟
  • ما حقوق العميل في استخدام البرمجيات أو تطويرها؟
  • هل يمكن التنازل عن البرمجيات أو نقلها إلى شخص أو جهة أخرى؟
  • في حال تسليم الشيفرة المصدرية، فمن يتحمل مسؤولية تطويرها وصيانتها؟

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

يمكنكم قراءة تفاصيل هذه التجربة في تجربة «عندما طلب العميل الشيفرة المصدرية بعد تسليم المشروع» .

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

3.6. يجب تحديد شروط التسليم والالتزامات بعده

يجب تحديد المقصود بـ«تسليم المشروع» بشكل دقيق.

هل يعني تثبيت البرمجيات انتهاء المشروع؟ هل تدريب المستخدمين جزء من الالتزامات؟ هل يجب على العميل اختبار الوظائف واعتمادها؟ كيف سيتم التعامل مع الأخطاء بعد التسليم؟

كما يُفضل تحديد وضع الدعم ومسؤوليات الطرفين بعد التسليم منذ البداية.

لذلك، يجب تحديد مراحل التسليم وآلية الاعتماد والالتزامات بعد التسليم منذ البداية.

3.7. في النهاية، ما الذي يجب أن يكون واضحًا قبل بدء المشروع؟

باختصار، من الأفضل الاتفاق قبل بدء المشروع على الأمور التالية:

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

لا يعني ذلك أنه يجب تحديد جميع تفاصيل المشروع البرمجي منذ اليوم الأول، لكنه يساعدنا على بدء المشروع بقدر كافٍ من الفهم والاتفاق.

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

4. تصميم الخوارزمية واعتمادها قبل كتابة الكود

بعد تحديد المتطلبات الحقيقية للمشروع، لا ينبغي لنا الدخول مباشرة في مرحلة البرمجة.

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

على سبيل المثال، إذا قال العميل:

«أريد برنامجًا لإدارة الشيكات.»

فهذا الوصف غير كافٍ لبدء البرمجة.

يجب تحديد كيفية تسجيل الشيكات، وكيفية إدارة حالة الشيك المرتجع، وكيفية تسجيل نقل الشيك، وكيفية متابعة مواعيد الاستحقاق، وكيفية إتاحة السجلات والتقارير للمستخدم.

ما لم تتضح الإجابات عن هذه الأسئلة، فإن بدء البرمجة سيكون مبكرًا.

الكود في الواقع هو نتيجة للقرارات التي تم اتخاذها قبله.

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

لذلك أفضل أن يتم تحديد عملية العمل أولًا، وبعد مراجعتها واعتمادها، أنتقل إلى مرحلة التصميم والبرمجة.

في المشاريع الأكبر والأكثر تعقيدًا، يمكن استخدام أدوات مثل Use Case وActivity Diagram وFlowchart لمراجعة العمليات وتوثيقها. وليس الهدف هنا شرح هذه المخططات؛ بل إن النقطة الأساسية هي أن منطق البرمجيات وعملياتها يجب أن تكون واضحة قبل بدء البرمجة، وأن تتم مراجعتها واعتمادها من الأشخاص المسؤولين في الجهة.

تجربة واقعية؛ عندما كانت البرمجيات صحيحة لكن المستخدم لم يتقبلها

في أحد المشاريع، وبعد نحو عام من الاستخدام، أخبرني العميل أن البرمجيات ليست كما كان يتوقع.

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

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

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

يمكنكم قراءة المزيد من تفاصيل هذه التجربة في تجربة «عندما قال العميل: هذا ليس ما أردناه» .

لماذا يُعد اعتماد الخوارزمية مهمًا؟

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

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

تغيير الخوارزمية يعني تغييرًا في المشروع

إذا كانت البرمجيات تعمل خلافًا للخوارزمية المعتمدة، فهذا خطأ ويجب إصلاحه.

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

التوثيق؛ ذاكرة المشروع

من الأفضل تسجيل المتطلبات والخوارزميات والتغييرات والاعتمادات المهمة.

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

ما الذي طُلب، وما الذي تم الاتفاق عليه، وما الذي تم تنفيذه في النهاية.

لذلك، من المبادئ التي ألتزم بها في المشاريع البرمجية:

قبل كتابة الكود، يجب أن نكون قد اتفقنا على المنطق والعملية التي سيقوم الكود بتنفيذها.

5. تصميم البرمجيات للتغييرات والتطويرات المستقبلية

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

وبالطبع، لا يعني التصميم للمستقبل تنفيذ جميع الوظائف المحتملة للسنوات القادمة منذ البداية. المقصود هو أن تكون بنية البرمجيات قابلة للتطوير والتغيير ضمن حدود منطقية.

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

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

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

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

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

أظهرت لي هذه التجربة أن تحليل البرمجيات لا يقتصر على الإجابة عن السؤال:

«ما الوظائف التي نحتاج إليها اليوم؟»

بل يجب، ضمن حدود منطقية، طرح سؤال آخر أيضًا:

«إذا تغيرت احتياجاتنا مستقبلًا، إلى أي مدى ستكون هذه البرمجيات قادرة على التغيير؟»

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

يمكنكم قراءة تفاصيل هذه التجربة في تجربة «عندما لم تكن احتياجات اليوم كافية لعام واحد» .

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

وفي هذا المجال يمكنكم أيضًا قراءة تجربة «عندما تصبح البرمجيات بطيئة مع نمو البيانات» .

6. النشر والتدريب والدعم؛ انتهاء البرمجة لا يعني انتهاء المشروع

لا ينتهي بناء البرمجيات بتسليم الكود وتثبيت البرنامج. فالنشر الصحيح، وتدريب المستخدمين، والدعم بعد التشغيل كلها جزء من نجاح المشروع.

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

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

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

لذلك بساطة البرمجيات لا تعني عدم الحاجة إلى التدريب.

عندما يقول المستخدم «البرنامج فيه خطأ»

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

بينما قد يكون السبب إدخال بيانات بشكل خاطئ، أو استخدام النظام بطريقة غير صحيحة، أو إعدادات الخادم، أو الشبكة، أو صلاحيات الوصول، أو الاتصال بخدمة أخرى.

في مثل هذه الحالات، لا ينبغي حل كل مشكلة من خلال تغيير الكود. يجب أولًا تحديد السبب الحقيقي للمشكلة، ثم اختيار الحل المناسب.

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

يمكنكم قراءة تفاصيل هذه التجربة في «عندما يجد العميل نفسه عالقًا بين المبرمج وخبير الخادم» .

علّمتني هذه التجربة أنه في المشكلات التقنية، ليس المهم العثور على المسؤول؛ بل المهم العثور على السبب الحقيقي للمشكلة.

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

يمكنكم قراءة تفاصيل هذه التجربة في «عندما لا تكون المشكلة في البرمجيات، لكن الجميع يعتقد أنها خطأ برمجي» .

أحيانًا لا تتسبب البرمجيات في المشكلة؛ بل تكشف مشكلة كانت موجودة مسبقًا.

الدعم لا يقتصر على إصلاح الأخطاء

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

على سبيل المثال:

  • هل تم إدخال البيانات بشكل صحيح؟
  • هل تلقى المستخدم التدريب اللازم؟
  • هل صلاحيات الوصول صحيحة؟
  • هل الخادم والشبكة في حالة مناسبة؟
  • هل الاتصال بالخدمات الأخرى يعمل بشكل صحيح؟
  • هل المشكلة ناتجة عن الإعدادات أو البنية التحتية؟
  • وفي النهاية، هل هناك حاجة فعلية إلى تغيير البرمجيات؟

قد يكون الحل هو تعديل الكود، لكن في بعض الحالات يكون الحل الصحيح هو تدريب المستخدم، أو تعديل الإعدادات، أو تغيير عملية العمل.

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

7. التغييرات والتطويرات بعد التسليم؛ لماذا ليست كل التغييرات الصغيرة بسيطة؟

بعد تثبيت البرمجيات واستخدامها فعليًا، تظهر عادةً طلبات جديدة. وهذا أمر طبيعي؛ إذ قد لا يتضح أحيانًا ما التغييرات أو الوظائف المطلوبة إلا بعد استخدام النظام فعليًا.

لكن المشكلة تبدأ عندما نعتقد أن إضافة كل وظيفة جديدة تعني فقط كتابة بضعة أسطر من الكود.

البرمجيات عبارة عن مجموعة من الأجزاء المترابطة، وقد يؤثر التغيير في جزء واحد في أجزاء أخرى مثل قاعدة البيانات والحسابات والتقارير أو العمليات المرتبطة.

لذلك، قبل تنفيذ أي تغيير، من الأفضل تحديد:

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

ليس كل طلب جديد إصلاحًا لخطأ

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

إذا تم تسليم البرمجيات وفق المتطلبات المعتمدة، ثم قرر العميل لاحقًا إضافة وظيفة أو عملية جديدة، فهذا يُعد عادةً طلب تطوير، وليس إصلاحًا لخطأ.

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

يساعد وضوح هذا الأمر على منع الخلافات اللاحقة حول الوقت والتكلفة.

تجربة مع برمجيات سابقة لدى بعض العملاء

بعض العملاء الذين راجعوني لبناء برمجيات جديدة كانوا يقولون عن برمجياتهم السابقة عبارة شبيهة بهذه:

«كلما غيّرنا شيئًا، يتعطل شيء آخر في مكان مختلف.»

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

توضح هذه التجربة أن تطوير البرمجيات لا يعني مجرد إضافة وظيفة جديدة؛ بل يجب أيضًا دراسة تأثيرها في النظام بأكمله.

يمكنكم قراءة تفاصيل إحدى هذه التجارب في «عندما يؤدي تغيير صغير إلى تغيير بنية البرمجيات بأكملها» .

كثرة الوظائف لا تعني بالضرورة أن البرمجيات أفضل

أحيانًا يُعتقد أنه كلما أضيفت وظائف أكثر إلى البرمجيات، أصبحت البرمجيات أفضل.

لكن إضافة وظائف متعددة دون الاهتمام بالاحتياجات الحقيقية قد تجعل البرمجيات أكثر تعقيدًا وتصعّب صيانتها.

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

لا ينبغي إيقاف التغيير؛ بل يجب التحكم فيه

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

لذلك، الهدف ليس منع التغيير؛ بل يجب تنفيذ التغيير بوعي وتحت السيطرة.

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

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

وفي النهاية، يجب ألا ننسى نقطة مهمة:

ليس كل تغيير صغير تغييرًا بسيطًا بالضرورة.

قبل تنفيذ أي تغيير يجب أن نسأل:

«ما المشكلة التي يحلها هذا التغيير، وما الأجزاء التي سيؤثر فيها؟»

التطوير الصحيح يعني تغيير البرمجيات دون التضحية بالأجزاء التي كانت تعمل بشكل صحيح من قبل.

8. الأمن والنسخ الاحتياطية والاستعداد للظروف غير المتوقعة

لا تُصمم البرمجيات الاحترافية للظروف العادية فقط.

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

أظهرت لي الخبرة أن الجودة الحقيقية للنظام وطريقة دعمه قد تظهر أحيانًا عندما يحدث أمر غير متوقع.

لا ينبغي تأجيل النسخ الاحتياطية إلى يوم وقوع المشكلة

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

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

كانت لهذه التجربة رسالة مهمة:

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

يمكنكم قراءة تفاصيل هذه التجربة في «عندما لا يكون وجود نسخة احتياطية كافيًا» .

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

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

الأمن لا يقتصر على كتابة كود آمن

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

من وجهة نظر المستخدم، كانت البرمجيات بطيئة؛ لكن مصدر المشكلة كان في البنية التحتية للشبكة.

وبعد الفحص واتخاذ الإجراءات اللازمة، تم حل المشكلة.

أظهرت لي هذه التجربة أن أمن النظام لا يقتصر على كتابة كود آمن.

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

الوصول الأكبر ليس دائمًا أفضل

أحيانًا يطلب المستخدمون صلاحيات وصول إضافية، لأنهم يعتقدون أن قلة القيود ستجعل العمل أسرع.

لكن كل صلاحية إضافية تعني أيضًا مسؤولية ومخاطر أكبر.

يجب تحديد صلاحيات المستخدمين بناءً على مهامهم الفعلية ، وليس فقط بناءً على سهولة العمل.

ماذا يحدث إذا توقف النظام عن العمل غدًا؟

يجب طرح هذا السؤال البسيط منذ مرحلة تصميم البرمجيات وتنفيذها:

  • ماذا سنفعل إذا أصبح الخادم غير متاح؟
  • ماذا يحدث إذا تعرضت قاعدة البيانات للتلف؟
  • إذا حُذفت البيانات بالخطأ، فهل يمكن استعادتها؟
  • إذا حدثت مشكلة في الشبكة، فما أجزاء النظام التي ستتأثر؟
  • ما تاريخ آخر نسخة قابلة للاستخدام من البيانات؟

الأمن لا يعني فقط منع وقوع الحوادث؛ فالاستعداد للاستعادة بعد وقوع الحادث جزء من الأمن أيضًا.

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

الخلاصة؛ من أين يبدأ بناء برمجيات ناجحة؟

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

نجاح المشروع يتحدد قبل كتابة أول سطر من الكود بوقت طويل.

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

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

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

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

إذا أردت تلخيص جميع التجارب التي طرحتها في هذا المقال في جملة واحدة:

لا تُبنى البرمجيات الناجحة بالبرمجة الجيدة وحدها؛ بل يجب أولًا فهم المشكلة بشكل صحيح، وتحليل الاحتياجات والعمليات وتصميمها بطريقة صحيحة، ثم تطوير البرمجيات بحيث تكون قابلة للاستخدام وموثوقة ومستعدة للتغيير والتطوير مستقبلًا.

لذلك، عند بدء مشروع برمجي، لا ينبغي أن نسأل فقط:

«ما البرنامج الذي تريدونه؟»

بل يجب أن نسأل:

«ما المشكلة التي تواجهونها، وكيف تعملون، وما التغيير الذي يُفترض أن تحدثه هذه البرمجيات في عملكم تحديدًا؟»

في رأيي، هذا السؤال هو نقطة البداية لأي مشروع برمجي ناجح.

المزيد من التجارب من المشاريع الواقعية

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

مشاهدة التجارب الواقعية ←

تعليقك

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

0 / 3000 حرف
لم يتم تسجيل أي تعليق على هذه المقالة حتى الآن.