كانت مراجعات الكود جحيماً: كيف أنقذنا إطار pre-commit من جدالات التنسيق التافهة؟

يا الله شو بتذكر هداك اليوم… كان يوم خميس، وكنا على وشك إطلاق ميزة جديدة ومهمة في المشروع. واحد من الشباب الطيبة في الفريق، شب شاطر واسمه “خالد”، فتح طلب سحب (Pull Request) فيه الشغل كله. أنا كمسؤول عن الفريق، فتحت الكود لأعمل مراجعة، وتوقعت أناقش معه منطق العمل، أو أداء جزئية معينة، أو حتى بنية الكود المعمارية.

لكن اللي صار إشي ثاني خالص. أول ما فتحت الكود، عيني وقعت على أسطر Python مكتوبة بعلامات تنصيص مفردة (‘)، وفريقنا متفق (نظرياً) على استخدام المزدوجة (“). وتحت شوي، لقيت مسافة زايدة في آخر سطر (trailing whitespace). وقبل ما أكتب أي تعليق، لقيت زميل ثاني سبَقني وكتب: “يا خالد، لو سمحت استخدم double quotes حسب الـ style guide”. وبعدها بخمس دقايق، دخل زميل ثالث وعلّق على المسافة الزايدة.

خلال نص ساعة، الـ Pull Request تحوّل لساحة جدال عقيم. خالد يدافع عن حاله إنه محرر الكود (IDE) تبعه هيك إعداداته، والشباب الثانيين مصرّين على تطبيق “المعايير”. وولّعت بين الشباب على إشي تافه ما بستاهل. ضاع وقت ثمين، وتوترت الأجواء، والأهم من كل هاد، إنه ولا واحد فينا ناقش منطق الكود نفسه! وقتها صفنت وقلت لحالي: “يا أبو عمر، مش منطق هالحكي! لازم نلاقي حل جذري يخلّصنا من هالقصص هاي للأبد”.

الكيل طفح: عندما قررنا أن الجدال يجب أن يتوقف

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

الحل واضح: الأتمتة. يجب أن نوكل هذه المهمة للآلات، ونحرر عقولنا للتركيز على ما يهم حقًا: حل المشكلات وبناء برمجيات ذات قيمة. قررنا أن أي كود يصل إلى مرحلة طلب السحب (Pull Request) يجب أن يكون منسقًا وخاليًا من الأخطاء الأسلوبية الشائعة بشكل تلقائي. وهنا بدأت رحلة بحثنا عن الأداة المثالية، وهي الرحلة التي انتهت بنا إلى بطل قصتنا: إطار pre-commit.

الحل السحري: تعرف على إطار pre-commit

ببساطة، pre-commit هو إطار عمل لإدارة وتشغيل “خطافات Git” أو ما يعرف بـ (Git Hooks). والـ Git Hook هو مجرد سكربت صغير يتم تشغيله تلقائيًا عند نقاط معينة في دورة حياة Git، مثل قبل عملية الـ commit (وهذا هو الـ pre-commit hook) أو قبل عملية الـ push.

قد يقول قائل: “ما أنا بقدر أكتب سكربتاتي الخاصة وأحطها في مجلد .git/hooks يدويًا”. صحيح، ولكن pre-commit يقدم مزايا جبارة تجعل الطريقة اليدوية شيئًا من الماضي:

  • مركزي وقابل للمشاركة: يتم تعريف كل الإعدادات في ملف واحد اسمه .pre-commit-config.yaml تضعه في مشروعك. هذا يعني أن كل أعضاء الفريق سيستخدمون نفس الأدوات والقواعد بمجرد سحبهم للمشروع.
  • إدارة تلقائية للأدوات: هل تريد استخدام أداة مثل black لتنسيق كود بايثون؟ لا حاجة لتثبيتها يدويًا عند كل زميل. pre-commit سيقوم بتنزيلها وإدارتها في بيئة معزولة خاصة به.
  • متعدد اللغات: يدعم عددًا هائلاً من الأدوات لمختلف اللغات والتقنيات (Python, JavaScript, Terraform, YAML, Dockerfiles, والمزيد).
  • سهولة الاستخدام: بمجرد إعداده، يصبح استخدامه شفافًا تمامًا للمطور.

خطوات عملية: كيف طبقنا pre-commit في مشروعنا؟

دعونا ننتقل من التنظير إلى التطبيق. سأريكم بالضبط كيف قمنا بإعداد pre-commit في أحد مشاريع بايثون لدينا. العملية بسيطة ومباشرة.

الخطوة الأولى: التثبيت

أولاً، يجب تثبيت الأداة نفسها. نحن نستخدم بايثون، فالأمر بسيط باستخدام pip:

pip install pre-commit

هذا الأمر يتم تشغيله مرة واحدة على جهاز كل مطور.

الخطوة الثانية: إنشاء ملف الإعدادات

في جذر المشروع، أنشئ ملفًا جديدًا باسم .pre-commit-config.yaml. هذا هو قلب النظام. سنبدأ ببعض الخطافات العامة والمفيدة جدًا لأي مشروع:

# .pre-commit-config.yaml
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0  # استخدم دائمًا أحدث إصدار مستقر
    hooks:
    -   id: trailing-whitespace   # يزيل المسافات الزائدة في نهاية الأسطر
    -   id: end-of-file-fixer     # يتأكد من وجود سطر فارغ في نهاية كل ملف
    -   id: check-yaml            # يتأكد من صحة بناء ملفات YAML
    -   id: check-added-large-files # يمنع إضافة ملفات كبيرة الحجم عن طريق الخطأ

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

الخطوة الثالثة: إضافة أدوات التنسيق والتدقيق (Linters & Formatters)

الآن نضيف الأدوات المتخصصة. في عالم بايثون، هناك أداتان لا أستغني عنهما أبدًا:

  • Black: أداة تنسيق كود “عنيدة” (The Uncompromising Code Formatter). جمالها يكمن في أنها لا تترك لك أي خيار. هي تفرض أسلوبًا واحدًا فقط، وبذلك تقتل كل الجدالات الأسلوبية.
  • Ruff: أداة تدقيق (linter) سريعة جدًا جدًا، مكتوبة بلغة Rust. تبحث عن الأخطاء المحتملة، الكود غير المستخدم، والممارسات السيئة.

لنضفهما إلى ملف الإعدادات:

# .pre-commit-config.yaml
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer
    -   id: check-yaml
    -   id: check-added-large-files

-   repo: https://github.com/psf/black
    rev: 24.3.0
    hooks:
    -   id: black

-   repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.1.6
    hooks:
    -   id: ruff
        args: [--fix] # نجعل ruff يصلح الأخطاء البسيطة تلقائيًا
    -   id: ruff-format

الخطوة الرابعة: تثبيت الـ Hooks في مستودع Git المحلي

بعد إعداد الملف، كل ما على المطور فعله هو تشغيل هذا الأمر مرة واحدة فقط بعد استنساخ المشروع (clone):

pre-commit install

هذا الأمر يقوم بقراءة ملف .pre-commit-config.yaml وبتثبيت الخطافات (hooks) في مجلد .git/hooks الخاص بالمستودع المحلي. انتهى! الآن النظام جاهز للعمل.

الحياة بعد pre-commit: من جحيم الجدال إلى نعيم الإنتاجية

الآن، تخيل معي السيناريو الجديد. زميلنا خالد انتهى من كتابة الكود الخاص به. يفتح الطرفية (terminal) ويكتب:

git commit -m "feat: add user authentication"

قبل أن تتم عملية الـ commit، يبدأ pre-commit بالعمل تلقائيًا. يمر على كل الملفات التي تم تعديلها ويشغل الأدوات التي حددناها:

  • trailing-whitespace يجد مسافة زائدة ويحذفها.
  • black يجد أن خالد استخدم علامات تنصيص مفردة، فيقوم بإعادة تنسيق الملف بالكامل ليستخدم علامات مزدوجة.
  • ruff يكتشف متغيرًا لم يتم استخدامه، فيعرض رسالة خطأ.

لأن بعض الأدوات قامت بتعديل الملفات (مثل black)، ستفشل عملية الـ commit الأولى، وستظهر رسالة تخبر خالد أن الملفات قد تم تعديلها. كل ما عليه فعله هو مراجعة التعديلات وإضافتها مرة أخرى (git add .) ثم إعادة محاولة الـ commit. هذه المرة، ستمر العملية بنجاح لأن الكود أصبح نظيفًا ومنسقًا.

النتيجة؟ طلب السحب (Pull Request) الذي يصلني الآن هو طلب سحب نظيف 100% من الناحية الأسلوبية. مراجعات الكود تحولت من جدالات حول الفواصل والمسافات إلى نقاشات مثمرة حول بنية الكود، والمنطق، والأداء. صارت مراجعة الكود ممتعة ومفيدة. حتى أني سمعت أحد الشباب يقول لي: “أبو عمر، والله ريّحتنا. صرت أفتح الـ PR وأنا مرتاح البال، عارف إنه الأساسيات كلها تمام”.

نصائح من خبرة أبو عمر

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

  • ابدأ بسيطًا: لا تضف 20 خطافًا من اليوم الأول. ابدأ بالأدوات الأساسية (مثل pre-commit-hooks و black) ثم أضف المزيد تدريجيًا كلما احتاج الفريق لذلك.
  • الاتفاق هو المفتاح: قبل فرض أداة تنسيق، يجب أن يتفق الفريق عليها. الهدف هو الاتساق، وليس فرض أسلوب شخص واحد. أدوات مثل black أو prettier (لعالم JavaScript) ممتازة لأنها “ديكتاتورية” ولا تترك مجالاً للنقاش.
  • لا تنسَ الـ CI/CD: أضف خطوة في مسار التكامل المستمر (CI pipeline) الخاص بك لتشغيل pre-commit. هذا يضمن أنه حتى لو قام أحدهم بتجاوز الخطافات محليًا (باستخدام git commit --no-verify)، سيتم اكتشاف المشكلة على الخادم. يمكنك استخدام الأمر: pre-commit run --all-files.
  • تخصيص الأدوات: معظم أدوات التدقيق (Linters) تسمح لك بتخصيص قواعدها. على سبيل المثال، يمكنك إنشاء قسم [tool.ruff] في ملف pyproject.toml لتجاهل قواعد معينة أو لتحديد طول السطر الأقصى.
  • لكل لغة دوائها: تذكر أن pre-commit ليس حكرًا على بايثون. استكشف قائمة الخطافات المتاحة، ستجد كنوزًا لكل لغة وتقنية تستخدمها.

الخلاصة: استثمر في الأتمتة، واربح وقتك 🏆

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

إطار pre-commit كان بمثابة المنقذ لفريقنا، حيث حوّل عملية مراجعة الكود من مهمة محبطة إلى فرصة للتعلم والتركيز على ما هو مهم حقًا. جربوها يا جماعة، وادعولي. صدقوني، راح تتذكروا أيّام الجدالات التافهة وتضحكوا عليها. 😉

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

اختبارات الاداء والجودة

كان نظامنا مستقراً في الاختبار وينهار في الإنتاج: كيف أنقذتنا ‘هندسة الفوضى’ من جحيم الأعطال؟

أشارككم قصة حقيقية عن إطلاق منتج كاد أن يفشل فشلاً ذريعاً، وكيف أن تبنينا لمفهوم "هندسة الفوضى" (Chaos Engineering) حوّل أنظمتنا من الهشاشة إلى الصلابة،...

13 مايو، 2026 قراءة المزيد
​معمارية البرمجيات

خدماتنا تتحدث بلغات مختلفة: كيف أنقذ نمط BFF (الواجهة الخلفية للواجهات الأمامية) مشروعنا من فوضى الـ API؟

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

13 مايو، 2026 قراءة المزيد
ذكاء اصطناعي

كان نموذجنا اللغوي يهلوس بلا توقف: كيف أنقذنا ‘التوليد المعزز بالاسترجاع’ (RAG) من جحيم الإجابات الخاطئة؟

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

12 مايو، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

كان تطبيقنا حصناً منيعاً أمام المكفوفين: كيف أنقذتنا سمات ARIA من جحيم الإقصاء الرقمي؟

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

12 مايو، 2026 قراءة المزيد
البودكاست