مراجعة كود JavaScript: ما الذي يزعج الخبراء حقًا
\n\nكل مطور، في مرحلة ما، يتلقى طلب سحب (pull request) مع تعليق مثل "من الأفضل إعادة كتابة هذا" أو "هذا نمط سيء". إذا كنت مطورًا مبتدئًا أو متوسطًا، قد تبدو هذه التعليقات مجرد انتقادات. لكن خلف كل كلمة من الخبير تكمن خبرة حقيقية: مشكلة في الإنتاج، خطأ في الثالثة صباحًا، أو انهيار في الأداء.
\n\nلقد جمعنا أكثر التعليقات شيوعًا التي يتركها الخبراء أثناء مراجعة كود JavaScript. هذه ليست مجرد قائمة "هذا سيء وهذا جيد". إنها تحليل لماذا يعتبر نهج معين سيئًا وبماذا يمكن استبداله.
\n\nهذه المقالة مفيدة لكل من يكتب بلغة JS: من المبتدئين إلى المطورين ذوي الخبرة الذين يرغبون في تحسين جودة كودهم.
\n\n1. تغيير البيانات المدخلة: الخطيئة الكبرى
\n\nمن أكثر الأخطاء شيوعًا في مراجعة الكود هو تغيير الكائنات أو المصفوفات التي تم تمريرها إلى الدالة. يكره الخبراء هذا لأن التغيير يكسر مبدأ عدم القابلية للتغيير (immutability) ويؤدي إلى أخطاء يصعب تتبعها.
\n\nمثال سيء
\nfunction addUser(users, newUser) {\n users.push(newUser); // تغيير المصفوفة الأصلية!\n return users;\n}\n\nconst allUsers = [{ id: 1 }, { id: 2 }];\nconst updated = addUser(allUsers, { id: 3 });\nconsole.log(allUsers.length); // 3 — تم تغيير المصفوفة الأصلية!\n\nالطريقة الصحيحة
\nfunction addUser(users, newUser) {\n return [...users, newUser]; // إرجاع مصفوفة جديدة\n}\n\nconst allUsers = [{ id: 1 }, { id: 2 }];\nconst updated = addUser(allUsers, { id: 3 });\nconsole.log(allUsers.length); // 2 — الأصل لم يتغير\n\nلماذا هذا مهم: عندما تقوم بتغيير البيانات المدخلة، فإن أي كود آخر يشير إلى نفس الكائن سيتلقى تغييرات غير متوقعة. هذا طريق مباشر للأخطاء في العمليات غير المتزامنة (asynchronous)، مخازن Redux، وحالات React.
\n\n2. الأرقام والنصوص السحرية: قاتلة readability
\n\nغالبًا ما يكتب الخبراء في التعليقات: "ما هذا الرقم 86400؟" أو "من أين جاء هذا النص؟". القيم السحرية تجعل الكود غير مفهوم وتعقد صيانته.
\n\nمثال سيء
\nfunction calculateDiscount(price) {\n if (price > 1000) {\n return price * 0.9;\n }\n return price * 0.95;\n}\n\nالطريقة الصحيحة
\nconst DISCOUNT_THRESHOLD = 1000;\nconst HIGH_DISCOUNT_RATE = 0.9;\nconst STANDARD_DISCOUNT_RATE = 0.95;\n\nfunction calculateDiscount(price) {\n if (price > DISCOUNT_THRESHOLD) {\n return price * HIGH_DISCOUNT_RATE;\n }\n return price * STANDARD_DISCOUNT_RATE;\n}\n\nنصيحة: ضع جميع الثوابت في متغيرات مسماة أو ملف تكوين منفصل. هذا يبسط مراجعة كود JavaScript ويجعله موثقًا ذاتيًا.
\n\n3. أخطاء async/await والـ Promises
\n\nالكود غير المتزامن هو المجال الذي يتعثر فيه حتى المطورون المتوسطون. يركز الخبراء في المراجعة على نقطتين رئيسيتين: المعالجة الخاطئة للأخطاء والخلط بين الصيغ.
\n\nمثال سيء (Promise بدون catch)
\nasync function loadData() {\n const response = await fetch('/api/data');\n const data = await response.json();\n return data;\n}\n\nالطريقة الصحيحة
\nasync function loadData() {\n try {\n const response = await fetch('/api/data');\n if (!response.ok) {\n throw new Error(`خطأ HTTP! الحالة: ${response.status}`);\n }\n const data = await response.json();\n return data;\n } catch (error) {\n console.error('خطأ في تحميل البيانات:', error);\n throw error; // إعادة رمي الخطأ إذا لزم الأمر\n }\n}\n\nمهم: لا تتجاهل الأخطاء أبدًا. catch فارغ هو شر. إذا حدث خطأ، يجب على الأقل تسجيله، والأفضل معالجته بشكل صحيح.
خطأ شائع آخر: نسيان await
\nfunction processUsers(users) {\n users.forEach(async (user) => {\n await updateUser(user);