كل فريق تطوير لديه قصة مشابهة. يبقى طلب سحب (pull request) مفتوحًا لنصف يوم. ليس لأن المنطق البرمجي معطل أو لأن عقد واجهة برمجة التطبيقات (API contract) قد تغير، ولكن لأن مراجعَين اختلفا حول ما إذا كانت كائنات (object literals) تحتاج إلى فاصلة لاحقة (trailing commas). يزداد النقاش طولاً. ينشر أحدهم رابط دليل التنسيق (style guide). ويعترض آخر بدليل مختلف. وبحلول الوقت الذي يتم فيه دمج الكود، يكون كل المعنيين قد فقدوا التركيز على الميزات التي كانوا يبنونها بالفعل.
هذه النزاعات مكلفة. فهي تستهلك ساعات من وقت كبار المهندسين، وتخلق استياءً طفيفًا بين أعضاء الفريق، وتدرب المطورين المبتدئين على الاعتقاد بأن هندسة البرمجيات تدور في معظمها حول الفوز بالنقاشات حول الفواصل المنقوطة. والجزء الأسوأ؟ المنتج لا يكترث. لن يلاحظ مستخدموك أبدًا الفرق بين المسافة (space) وعلامة الجدولة (tab). لكنهم سيلاحظون الخطأ البرمجي الذي لم تقم بإصلاحه لأنك كنت مشغولاً بالجدال حول علامات الاقتباس.
الاتساق أمر مهم. فمجموعة الكود (codebase) التي تبدو وكأن شخصًا واحدًا قد كتبها تكون أسهل في القراءة، وأسهل في المراجعة، وأسهل في تصحيح الأخطاء. الخطأ هو محاولة فرض هذا الاتساق يدويًا.
أتمتة المهام المملة
الحل بسيط. قم بإزالة التقدير البشري من عملية التنسيق تمامًا. وسلم المهمة لأدوات ليس لديها "أنا" (egos) ولا تشعر بالتعب.
هناك ثلاث أدوات تتعامل مع هذا الأمر بسلاسة.
Prettier تأخذ الكود الخاص بك وتعيد تنسيقه تلقائيًا. هي لا تطلب الإذن. ستتوقف عن التفكير في أطوال الأسطر، أو أنماط علامات الاقتباس، أو كيفية تقسيم توقيع دالة طويلة عبر عدة أسطر. ما عليك سوى حفظ الملف، وستجعله Prettier متسقًا.
ESLint تتعامل مع المشكلات التي لن تلمسها Prettier. فهي تكتشف المتغيرات غير المستخدمة، والكود الذي لا يمكن الوصول إليه، والاعتمادات المفقودة في React hooks، والأنماط التي تؤدي تاريخيًا إلى حدوث أخطاء. عندما يتم تكوينها بشكل صحيح، تبتعد عن التنسيق وتركز على جودة الكود الفعلية.
Husky تقوم بتثبيت pre-commit hook يمنع أي شيء من دخول مستودعك (repository) حتى تجتاز الفحوصات المؤتمتة. إنها تحول خط أنابيب Git الخاص بك إلى حارس بوابة بدلاً من مجرد صندوق اقتراحات.
معًا، يشكلون حلقة عمل محكمة. يمكنك كتابة الكود بالطريقة التي تريدها محليًا. وعندما تقوم بعمل commit، تقوم الأدوات بتنظيفه وفحصه. عندها فقط يغادر الكود جهازك.
لماذا تنجح هذه المجموعة (Stack) تحديدًا
يمكنك قضاء أسابيع في ضبط قواعد ESLint يدويًا. قاوم هذه الرغبة. الهدف هنا هو التوقف عن الجدال حول الأسلوب، وليس إنشاء وظيفة جديدة بدوام كامل كمنسق لدليل التنسيق.
تتميز Prettier بأنها تفرض أسلوبًا محددًا (opinionated) عن قصد. فهي توفر خيارات تكوين محدودة لأن كل خيار قد يتحول إلى جدال مستقبلي. الإعدادات الافتراضية منطقية. اختر مجموعة صغيرة من التجاوزات (overrides)، واكتبها مرة واحدة، وامضِ قدمًا.
أما ESLint، فإذا تُركت لشأنها، ستحاول فرض كل من جودة الكود وقواعد التنسيق مثل استخدام الفاصلة المنقوطة وحجم المسافة البادئة. وهذا يخلق احتكاكًا مع Prettier لأن كلتا الأداتين ستحاولان تعديل نفس الأحرف. تحل حزمة eslint-config-prettier هذه المشكلة عن طريق تعطيل جميع قواعد ESLint التي تتعارض مع Prettier. هذا الفصل في المهام أمر بالغ الأهمية؛ Prettier تتولى الجوانب الجمالية، بينما تتولى ESLint المنطق البرمجي.
إن تشغيل الفحوصات في التكامل المستمر (CI) فقط هو أمر متأخر جدًا. فبحلول الوقت الذي يفشل فيه الـ CI، تكون قد قمت بالفعل بعمل commit لكود غير منظم، وانتقلت ذهنياً إلى مهمة أخرى، وربما فتحت طلب سحب (pull request). يتطلب إصلاحه عملية commit أخرى، و push آخر، ودورة انتظار أخرى. تعمل Husky على تقصير حلقة التغذية الراجعة هذه إلى ثوانٍ معدودة. كما تجعل أداة lint-staged العملية سريعة من خلال تشغيل الأدوات فقط على الملفات التي قمت بتغييرها بالفعل، بدلاً من فحص المستودع بأكمله عند كل commit.
إعدادها خطوة بخطوة
يستهدف الإعداد التالي مشروع JavaScript أو React حديثًا، ولكن النمط ينطبق أيضًا على TypeScript أو Vue أو Node مع تعديلات طفيفة. قم بتشغيل كل خطوة من جذر المشروع (project root).
ابدأ بتثبيت كل شيء كاعتمادات تطوير (dev dependencies):
npm install -D prettier eslint husky lint-staged eslint-config-prettier
