الكود النظيف: الهندسة للبشر
تتم قراءة الكود 10 مرات أكثر مما هو مكتوب. دليل تقني للتسمية، ومبدأ المسؤولية الفردية، ولماذا يعتبر "الرمز الذكي" في الواقع دينًا تقنيًا.
“يمكن لأي أحمق أن يكتب تعليمات برمجية يمكن للكمبيوتر أن يفهمها. أما المبرمجون الجيدون فيكتبون تعليمات برمجية يمكن للبشر فهمها.” - مارتن فاولر.
هذا الاقتباس هو أساس الثقافة الهندسية المحددة في Maison Code Paris. نحن لا نقوم بتحسين “أسطر التعليمات البرمجية”. نحن لا نقوم بتحسين “سرعة الكتابة”. نحن نعمل على تحسين قابلية الصيانة.
لا يهتم المترجم إذا قمت بتسمية المتغير الخاص بك x أو daysUntilExpiration. وتقوم وحدة المعالجة المركزية بتنفيذ ذلك في نفس النانو ثانية بالضبط.
لكن المطور المبتدئ الذي يستيقظ في الساعة 3:00 صباحًا لإصلاح خطأ فادح يهتم بشدة.
إذا اضطروا إلى قضاء 10 دقائق في فك رموز أسماء المتغيرات الخاصة بك، فستخسر الشركة المال.
البرمجة النظيفة هي عمل من أعمال التعاطف.
لماذا تتحدث Maison Code عن هذا
في Maison Code Paris، نعمل كضمير معمari لعملائنا. غالبًا ما نرث حزمًا “حديثة” تم بناؤها دون فهم أساسي للحجم.
نناقش هذا الموضوع لأنه يمثل نقطة تحول حاسمة في النضج الهندسي. التنفيذ الصحيح يميز MVP الهش عن منصة مؤسسية مرنة يمكنها التعامل مع حركة مرور الجمعة السوداء.
1. التسمية: أصعب مشكلة في علوم الكمبيوتر
يجب أن تكشف الأسماء النية. يجب أن يخبرك اسم المتغير بثلاثة أشياء:
- ما يفعله.
- سبب وجودها.
- كيفية استخدامه.
قاعدة “عدم التخطيط الذهني”
سيء:
ثابت د = 10؛ // أيام
قائمة ثابتة = []؛ // المستخدمين
يجب على القارئ أن يترجم d -> أيام في رأسه. يستخدم هذا الحمل المعرفي (RAM).
** جيد **:
أيام ثابتةSinceLastLogin = 10؛
const activeUsers = [];
يقرأ الكود مثل النثر الإنجليزي.
قاعدة طول النطاق
- النطاق الصغير (الحلقة): الأسماء المختصرة مقبولة.
ل(دع i = 0; i < 10; i++)جيد. - نطاق واسع (عالمي/فئة): يجب أن تكون الأسماء صريحة. “أنا” ممنوع. استخدم “globalRetryCounter”.
2. الوظائف: افعل شيئًا واحدًا
ينطبق مبدأ المسؤولية الفردية (SRP) على الوظائف، وليس على الفئات فقط. يجب أن تحتوي الدالة على مستوى واحد من التجريد.
** سيئة (وظيفة الله) **:
وظيفة غير متزامنة تسجيل المستخدم (req) {
// 1. التحليل
const { البريد الإلكتروني، كلمة المرور } = req.body؛
// 2. التحقق من الصحة
إذا (!email.includes('@')) طرح خطأ جديد('بريد إلكتروني غير صالح');
// 3. منطق قاعدة البيانات
مستخدم ثابت = في انتظار db.users.create({
البريد الإلكتروني,
كلمة المرور: bcrypt.hashSync (كلمة المرور)
});
// 4. منطق البريد الإلكتروني
في انتظار mailgun.messages().send({ to: email, text: "Welcome!" });
// 5. منطق الاستجابة
إرجاع { الحالة: 200، المعرف: user.id }؛
}
تتغير هذه الوظيفة إذا:
- تتغير قاعدة البيانات (Postgres إلى Mongo).
- يتغير مزود البريد الإلكتروني (Mailgun إلى SendGrid).
- يتغير تنسيق API. إنها هشة.
** جيد (المنسق) **:
وظيفة غير متزامنة تسجيل المستخدم (req) {
const accountInfo = parseRequest(req);
validateAccount(accountInfo);
const user = انتظار createUserInDatabase(accountInfo);
في انتظار الإرسالWelcomeEmail(user);
إرجاع formatResponse(user);
}
الآن، أصبح “registerUser” مجرد منسق. إنها تحكي قصة. تفاصيل التنفيذ مخفية في وظائف صغيرة ومركزة.
3. التعليقات: فشل التعبير
كبار المهندسين يكتبون تعليقات أقل، وليس أكثر. لماذا؟ لأن التعليقات عبارة عن رائحة رمزية. إذا كان عليك كتابة تعليق لشرح ما تفعله التعليمات البرمجية، فإن التعليمات البرمجية الخاصة بك معقدة للغاية. أعد تشكيلها.
سيء:
// تحقق مما إذا كان المستخدم مؤهلاً للحصول على خصم كبير
إذا (user.age > 65 && user.purchases > 10 && user.country === 'FR') {
ApplyDiscount();
}
** جيد **:
إذا (user.isEligibleForSeniorDiscount()) {
ApplyDiscount();
}
متى يجب التعليق؟
علق بـ لماذا وليس ماذا. يشرح الكود ما يحدث. يشرح التعليق سياق العمل أو الحل البديل الغريب.
// نستخدم هنا تأخيرًا قدره 500 مللي ثانية لأن واجهة برمجة تطبيقات الدفع الخارجية
// لديه حالة سباق إذا تم الاستعلام عنها مباشرة بعد الإنشاء.
// انظر التذكرة رقم 452.
انتظر التأخير(500);
يحفظ هذا التعليق المطور التالي من “تحسين” التأخير.
4. الشروط الشرطية: تجنب رمز السهم
“رمز السهم” هو عندما تنشئ عبارات if المتداخلة شكلاً مثل السهم >.
إنه يدفع المنطق إلى الجانب الأيمن من الشاشة ويجعل من الصعب تتبع الحالة.
سيء:
عملية الدفع (الطلب) {
إذا (أمر) {
إذا (order.isPaid) {
إذا (order.amount > 0) {
// المنطق
}
}
}
}
جيد (شروط الحراسة): العودة في وقت مبكر. قم بقتل الوظيفة في أسرع وقت ممكن.
عملية الدفع (الطلب) {
إذا (! النظام) العودة؛
إذا عاد (!order.isPaid)؛
إذا كان (order.amount <= 0) يعود؛
// المنطق (بدون مسافة بادئة)
}
5. الهوس البدائي
لا تمرر السلاسل والأرقام الخام حولك. قم بتمرير الكائنات التي تفرض القواعد.
سيء:
وظيفة bookFlight (الأصل: سلسلة، الوجهة: سلسلة)
هل “مدينة نيويورك” صالحة؟ هل “نيويورك” صحيحة؟ هل “JFK” صالح؟
** جيد **:
وظيفة bookFlight (الأصل: رمز المطار، الوجهة: رمز المطار)
تضمن فئة “AirportCode” وجود رموز IATA الصالحة المكونة من 3 أحرف فقط في النظام.
أنت تجعل الحالات غير الصالحة غير قابلة للتمثيل.
7. الاختبار كوثائق
أفضل التوثيق هو اختبار الوحدة.
أصبحت المستندات قديمة. الاختبارات لا.
إذا كنت تريد معرفة كيفية عمل calculateDiscount()، فاقرأ حالات الاختبار.
it('يجب تطبيق 10% للمستخدمين الجدد')it('يجب أن تفشل إذا كانت سلة التسوق فارغة')اختبارات الكتابة تجبرك على كتابة كود نظيف. إذا كان من الصعب اختبار الوظيفة، فهي رمز سيء. “لا يمكنني اختبار هذا لأنه يستعلم عن قاعدة البيانات داخل الوظيفة.” Refactor: أدخل تبعية قاعدة البيانات. الآن أصبح قابلاً للاختبار.
8. ثقافة مراجعة القواعد
مراجعة الكود ليست للعثور على الأخطاء. هذا هو الغرض من CI. مراجعة الكود مخصصة لـ مشاركة المعرفة. إنها جلسة إرشادية. “لماذا اخترت مجموعة بدلاً من مصفوفة هنا؟” “هذا النمط مثير للاهتمام، هل يمكننا استخدامه في وحدة المستخدم أيضًا؟” لا ينبغي لكبار المهندسين أن يقولوا “LGTM” فحسب. يجب أن يشرحوا لماذا شيء ما جيد أو سيئ. نحن نطلب “Nitpick” أو “Suggestion” واحدًا على الأقل لكل علاقة عامة. إنه يفرض المشاركة.
9. قاعدة الكشافة
“اترك المخيم دائمًا أنظف مما وجدته عليه.”
هذا هو الترياق للديون الفنية.
أنت تعمل على إصلاح خطأ في وحدة “التسعير”. لاحظت وجود متغير اسمه x.
أعد تسميتها.
لاحظت دالة طويلة جدًا.
تقسيمها.
لا تطلب الإذن. لا تقم بإنشاء تذكرة “تسعير إعادة التصنيع”. فقط افعل ذلك كجزء من عملك.
إذا قام كل مهندس بتنظيف 1% من التعليمات البرمجية التي لمسها، فستظل قاعدة التعليمات البرمجية نظيفة إلى الأبد.
7. الجفاف مقابل الرطب (فخ التجريد)
لقد تعلمنا الجاف (لا تكرر نفسك).
إنها قاعدة جيدة. لكنه خطير.
إذا رأيت قطعتين من التعليمات البرمجية متشابهتين، فيمكنك دمجهما في وظيفة مشتركة.
المشكلة: الآن يعتمد كلا المكانين على هذه الوظيفة.
إذا كانت الميزة أ تحتاج إلى تغيير طفيف في الوظيفة، فيمكنك إضافة علامة منطقية.
الوظيفة تفعل الشيء (isFeatureA)' ثم تحتاج الميزة (ب) إلى التغيير. وظيفة doThing(isFeatureA, isFeatureB)`
قريبًا، لديك وظيفة إلهية بها 10 أعلام.
** WET (اكتب كل شيء مرتين) ** غالبًا ما يكون أفضل.
الازدواجية أرخص من التجريد الخاطئ.
إذا كانت هناك ميزتان عن طريق الخطأ تشتركان في المنطق ولكن لديهما أسباب عمل مختلفة لتغييرهما، انسخ الرمز والصقه.
8. نظرية “النوافذ المكسورة”.
في علم الجريمة، إذا كان المبنى يحتوي على نافذة واحدة مكسورة ولم يتم إصلاحها، فسوف يقوم المخربون بكسر جميع النوافذ قريبًا. الرمز هو نفسه. إذا تركت وظيفة واحدة فوضوية، فسيفكر المطور التالي: “هذا الملف غير مهم على أي حال، سأقوم فقط باختراق الإصلاح.” إذا كان الملف نظيفًا، فسوف يشعرون بالضغط الاجتماعي لإبقائه نظيفًا. ** كن البستاني **. تخلص من الفوضى يوميًا.
9. الاستنتاج
الكود النظيف لا يتعلق بالجماليات. يتعلق الأمر بـ الاقتصاد. تعفن رمز فوضوي. لقد أصبح “رمزًا قديمًا” يخشى الجميع لمسه. تستغرق الميزات وقتًا أطول للبناء. تظهر الأخطاء في كثير من الأحيان. الكود النظيف هو أحد الأصول. يسمح لك بالتحرك بسرعة إلى أجل غير مسمى.
قاعدة التعليمات البرمجية في حالة من الفوضى؟
هل تتباطأ سرعتك بسبب “رمز السباغيتي”؟
حدد موعدًا لمراجعة الكود. اقرأ عن اختبار الوحدة وإعادة البناء.
الكود النظيف لا يتعلق بالجماليات. يتعلق الأمر بـ الاقتصاد. تعفن رمز فوضوي. لقد أصبح “رمزًا قديمًا” يخشى الجميع لمسه. تستغرق الميزات وقتًا أطول للبناء. تظهر الأخطاء في كثير من الأحيان. الكود النظيف هو أحد الأصول. يسمح لك بالتحرك بسرعة إلى أجل غير مسمى.
اكتب الكود للإنسان الذي سوف يقرأه. لأنه بعد 6 أشهر من الآن، سيكون هذا الإنسان هو أنت.
قاعدة التعليمات البرمجية في حالة من الفوضى؟
هل تتباطأ سرعتك بسبب “رمز السباغيتي”؟