عندما لا يكون "يعمل" هو الشيء الرئيسي
\nتخيل موقفًا: تفتح طلب سحب (pull request) لشخص آخر بلغة C++. الكود يترجم، الاختبارات تمر، المنطق صحيح. لكنك تقضي 40 دقيقة لفهم ما يحدث. المتغيرات مسماة a و b و ptr2، المسافات البادئة تتأرجح من 2 إلى 8 مسافات، وفي ملف واحد يتم خلط snake_case و camelCase. هل هذا مألوف؟
في التطوير الفردي، يمكن تحمل هذه الفوضى. ولكن بمجرد ظهور مطور ثانٍ أو ثالث أو عاشر في المشروع، فإن غياب أسلوب كود C++ موحد يحول الكود إلى "مستنقع". يكتب الجميع بالطريقة التي اعتادوا عليها، ويزداد وقت مراجعة الكود بشكل هائل.
\nفي هذه المقالة، سنناقش أي اتفاقيات C++ تعمل حقًا في الفريق، وكيفية تطبيقها دون ألم، ولماذا ستوفر لك الأعصاب والمال. هيا بنا!
\n\nلماذا أسلوب الكود ليس متعلقًا بـ "الجمال"، بل بالمال
\nيعتقد الكثيرون أن الجدال حول أسلوب الكود هو مضيعة للوقت. في الممارسة العملية، تظهر الأبحاث (مثل تلك من Google و Microsoft) أن: قابلية قراءة الكود تؤثر بشكل مباشر على عدد الأخطاء. عندما يبذل المطور جهدًا أقل في فك تشفير ما هو مكتوب، فإنه يخطئ بشكل أقل أثناء إعادة الهيكلة ويجد المشكلات بشكل أسرع.
\nيمنح معيار كود C++ الموحد الفريق ثلاث مزايا رئيسية:
\n- \n
- سرعة الانضمام للفريق. العضو الجديد لا يتخمّن كيف يُكتب الكود هنا - بل ينظر ببساطة إلى أي ملف ويرى النمط. \n
- الحد الأدنى من النزاعات في مراجعة الكود. بدلاً من "أعد كتابة المسافات البادئة"، تناقش البنية والمنطق. \n
- الأتمتة. تتولى أدوات التنسيق والفحص (Formatters & Linters) المهام الروتينية، مما يحرر العقل للإبداع. \n
الخبر السار: لست بحاجة لاختراع العجلة. هناك أفضل الممارسات C++ مثبتة يمكن تكييفها مع أي مشروع.
\n\nاتفاقيات C++ الأساسية: من التسمية إلى التنسيق
\nدعنا نستعرض الكتل الرئيسية التي يجب تثبيتها في دليل أسلوب الكود. لكل نقطة، سأقدم مثالاً "سيئًا" و"جيدًا".
\n\n1. التسمية: snake_case مقابل CamelCase مقابل PascalCase
\nفي C++، تطور تاريخيًا نهج هجين. تستخدم المكتبة القياسية snake_case، والعديد من الشركات (Google, Microsoft) تفضله أيضًا للمتغيرات والدوال. بالنسبة للفئات والهياكل، غالبًا ما يُستخدم PascalCase.
مثال على تسمية سيئة:
\nclass datamanager {\n int numberOfElements;\n void ProcessData(int* ptr) { ... }\n};\nالمشاكل: الفئة بـ snake_case، الطريقة بـ CamelCase، لا يوجد سياق. الأفضل هكذا:
\nclass DataManager {\n int number_of_elements_;\n void ProcessData(int* data_ptr) { ... }\n};\nما تم تصحيحه هنا:
\n- \n
- الفئة —
PascalCase. \n - الحقول —
snake_caseمع لاحقة شرطة سفلية للأعضاء الخاصة (أسلوب Google). \n - الطريقة —
PascalCase(أوsnake_caseإذا كان متبعًا في الفريق). \n - المعامل —
snake_caseمع لاحقة_ptr، ليتضح فورًا أنه مؤشر. \n
نصيحة: اختر نمطًا واحدًا للمشروع بأكمله. خلط getValue() و get_value() في ملف واحد هو طريق مؤكد للارتباك.
2. التنسيق: المسافات، الأقواس وطول الأسطر
\nالمصدر الأكثر شيوعًا للخلافات — أين توضع القوس الافتتاحي: في نفس السطر أم في السطر التالي؟ في C++، من المعتاد وضعها في نفس السطر (أسلوب K&R)، ولكن هناك اختلافات.
\nمثال على أسلوب متناسق:
\nvoid CalculateSum(const std::vector<int>& values) {\n int sum = 0;\n for (size_t i = 0; i < values.size(); ++i) {\n sum += values[i];\n }\n return sum;\n}\nهنا كل شيء موحد: القوس بعد if، fo