مراجعة الكود في Go: ما يجب التحقق منه وكيفية تقديم الملاحظات
\nمراجعة الكود (Code review) ليست مجرد فحص شكلي قبل دمج طلب السحب (pull request). إنها أداة قوية لتحسين جودة الكود، وتبادل المعرفة في الفريق، ومنع الأخطاء في المراحل المبكرة. بالنسبة لمطوري Go المبتدئين، قد تبدو المشاركة في المراجعة مرهقة: الخوف من تلقي الملاحظات أو، على العكس، تفويت خطأ حرج. في هذه المقالة، سنشرح ما يجب الانتباه إليه عند مراجعة كود Go، وكيفية تقديم الملاحظات بطريقة مفيدة وليست مهينة.
\n\nلماذا تعتبر مراجعة الكود مهمة بشكل خاص في Go؟
\nتم تصميم لغة Go مع التركيز على البساطة، وسهولة القراءة، والموثوقية. ومع ذلك، فإن بساطة بناء الجملة لا تلغي تعقيد المنطق. المشكلات النموذجية في مشاريع Go: تجاهل الأخطاء، والتعامل غير الصحيح مع goroutines، وتسرب الموارد. تساعد مراجعة الكود الجيدة في اكتشاف هذه المشكلات وغيرها قبل وصولها إلى بيئة الإنتاج.
\n\nما يجب التحقق منه في كود Go: قائمة تحقق للمبتدئين
\nلجعل المراجعة منهجية، استخدم قائمة تحقق. فيما يلي النقاط الرئيسية التي يجب التحقق منها في كل طلب سحب.
\n\n1. معالجة الأخطاء (error handling)
\nفي Go، الأخطاء هي قيم، ولا يمكن تجاهلها. تحقق من أن كل دالة تُرجع error تقوم بمعالجته أو تمريره صراحةً إلى الأعلى.
// سيء: تجاهل الخطأ\nfile, _ := os.Open("config.yaml")\n\n// جيد: معالجة الخطأ\nfile, err := os.Open("config.yaml")\nif err != nil {\n log.Fatalf("cannot open config: %v", err)\n}\ndefer file.Close()\nتحقق أيضًا من أن الأخطاء يتم تغليفها باستخدام fmt.Errorf("...: %w", err) لنقل السياق، بدلاً من مجرد تسجيلها وابتلاعها.
2. التسمية وسهولة القراءة
\nفي Go، من المعتاد استخدام أسماء قصيرة للمتغيرات (مثل r للقارئ، w للكاتب) وأسماء طويلة للدوال المُصدّرة. تحقق من أن:
- \n
- الدوال والأنواع والمتغيرات المُصدّرة تحتوي على تعليقات (تبدأ باسم الكيان). \n
- أسماء المتغيرات تعكس الغرض منها (وليس
aأوbأوtmp). \n - لا توجد اختصارات غير ضرورية (من الأفضل استبدال
calcبـcalculate). \n
3. العمل مع goroutines والتزامن
\nGoroutines أداة قوية ولكنها خطيرة. تحقق من:
\n- \n
- وجود آلية مزامنة (قنوات، mutexes) للبيانات المشتركة. \n
- عدم إنشاء goroutines متسربة (goroutine leak). استخدم السياق (
context.Context) للإلغاء. \n - عدم حظر goroutine إلى الأبد (deadlock). \n
// مثال على العمل الآمن مع goroutine\nfunc worker(ctx context.Context, jobs <-chan int, results chan<- int) {\n for {\n select {\n case job, ok := <-jobs:\n if !ok {\n return\n }\n results <- job * 2\n case <-ctx.Done():\n return\n }\n }\n}\n\n4. إدارة الموارد (defer)
\nتحقق من أن جميع الملفات المفتوحة، واتصالات الشبكة، ومعاملات قاعدة البيانات تُغلق باستخدام defer. يجب أن يتم ذلك فورًا بعد فتح المورد بنجاح.
// صحيح: الإغلاق فورًا\nconn, err := net.Dial("tcp", "example.com:80")\nif err != nil {\n return err\n}\ndefer conn.Close()\n\n5. الاختبار
\nغالبًا ما ينسى المبتدئون الاختبارات. تأكد من كتابة اختبارات الوحدة (unit tests) للمنطق الجديد. تحقق من:
\n- \n
- تغطية الاختبارات ليس فقط المسار السعيد (happy path) ولكن أيضًا الحالات الحدودية. \n
- استخدام
t.Runللاختبارات الفرعية. \n - عدم وجود اختبارات تعتمد على موارد خارجية (قاعدة بيانات، شبكة) بدون استخدام mock. \n
كيفية تقديم الملاحظات: 5 قواعد للمبتدئين
\nالجانب التقني هو نصف المهمة. النصف الآخر هو مهارة التواصل. إليك ك