في هذه التدوينة سأشارك بعض النصائح التي يمكن استخدامها لتحسين جودة الكود. كما ستساعدك على عدم إلحاق الضرر بنفسك لاحقًا في هذه العملية.
كما يعلم الكثيرون، يعد Django إطار عمل ويب رائعًا. فهو يسمح ببناء تطبيقات الويب والنماذج الأولية وما إلى ذلك بسرعة فائقة. لقد كنت أستخدمه في معظم مشروعاتي، ولم أشعر بخيبة أمل أبدًا. يعمل Django بشكل رائع في قواعد التعليمات البرمجية الصغيرة والمتوسطة. تبدأ المشكلات في الظهور عندما تبدأ قواعد التعليمات البرمجية في النمو إلى ملايين من مئات النماذج.
نصيحة رقم 1: لا تبالغ في تقدير كل شيء
إحدى وظائف Django هي إنشاء سياقات محدودة، أو في مصطلحات Django، تطبيقات. يجب تسجيل كل تطبيق في قائمة INSTALLED_APPS. يمكن لكل تطبيق أن يكون له نماذجه الخاصة. كل شيء على ما يرام هنا.
تظهر المشكلة عندما يبدأ المطورون في استخدام النماذج من التطبيق أ في التطبيق ب. وبهذا، تكون قد أدخلت ارتباطًا وثيقًا بين التطبيقين أ وب. وهذا له العديد من السلبيات:
- يصعب تتبع الآثار الجانبية.
- صعوبة اختبار التدفق التشغيلي.
- يمكن أن تكون إعادة الهيكلة أمرًا مزعجًا
- الواردات الدورية تؤدي إلى استيراد محلي.
كيف يمكن تجنب ذلك؟ قم بإنشاء خدمات بأساليب عامة يمكن استخدامها بعد ذلك في تطبيقات خارجية. بعبارة أخرى، قم بإنشاء واجهة برمجة تطبيقات لكل تطبيق. بهذه الطريقة يمكنك الحصول على مدخل واضح لتطبيقك.
مثال:
BAD:
def some_method_in_app_A():
...
ModelFromB().save()
GOOD:
# App A:
def some_method_in_app_A():
...
appB.services.save_model_b()
# App B:
def save_model_b():
ModelFromB().save()
عندما تقوم بفصل المسؤوليات إلى سياقها المحدود الخاص بها، يصبح من الأسهل اختبار/محاكاة الوظائف.
النصيحة رقم 2: اجتهد في إجراء اختبارات الوحدة أكثر من الاختبارات التكاملية
يعرف الكثير منكم الفرق بين اختبارات الوحدة واختبارات التكامل. بالنسبة لأولئك الذين لا يعلمون => تقوم اختبارات الوحدة باختبار كتل بسيطة من التعليمات البرمجية دون أي خدمات خارجية، مثل قاعدة البيانات أو ذاكرة التخزين المؤقت.
من ناحية أخرى، تختبر اختبارات التكامل الوظائف الأوسع للنظام. هل تريد اختبار بعض الوظائف التي تسترد الكيانات من قاعدة البيانات أو تحفظ البيانات في قاعدة البيانات؟ إنه اختبار تكامل.
على الرغم من أن اختبارات التكامل قد تكون مريحة في الكتابة، إلا أنها قد تكون أبطأ بشكل ملحوظ من اختبارات الوحدة، إذا تم استخدام قاعدة البيانات في الاختبار. وقد يؤدي هذا إلى إبطاء خط الأنابيب الخاص بك إذا كان عدد الاختبارات كبيرًا. كما أن وجود المزيد من اختبارات الوحدة قد يؤدي أيضًا إلى تقليل فاتورة خط الأنابيب الخاص بك في نهاية الشهر.
الآن ربما تتساءل كيف يمكنني اختبار بعض التعليمات البرمجية التي تستخدم قاعدة البيانات؟ حسنًا، الأمر بسيط. استخرج التعليمات البرمجية التي تقوم بإجراء مكالمات إلى قاعدة البيانات لفصل الوظائف وسخر منها باستخدام unittest.mock.
النصيحة رقم 3: استخدم pytest بدلاً من برنامج تشغيل الاختبار الخاص بـ Django
Pytest هو إطار عمل لاختبار تطبيقات بايثون. ويمكن استخدامه أيضًا لاختبار كود Django بمساعدة pytest-django. في تجربتي، إنه أسرع من برنامج تشغيل الاختبار الخاص بـ Django. يحتوي على العديد من سكريات الاختبار التي ستمكنك من كتابة اختبارات أفضل باستخدام كود أقل. جربه.
يقدم Pytest-django، من بين أمور أخرى، مُزخرف مفيدًا واحد: @pytest.mark.django_db
. سيمكنك هذا المزخرف من استخدام قاعدة البيانات في الاختبار الخاص بك وسوف “ينفجر” إذا تم استخدام قاعدة البيانات بدون المزخرف.
باستخدام هذا، يمكنك معرفة ما إذا كان لديك بعض الزيارات غير المتوقعة لقاعدة البيانات والتي يمكن استغلالها.
النصيحة رقم 4: لا تستخدم النماذج مباشرة في العروض
لماذا لا؟ حتى برنامج Django التعليمي يستخدم النماذج مباشرة في العروض!
نعم، إنه أمر مريح وبسيط. لكنه ممارسة سيئة، لأنه يربط بشكل وثيق بين منطق العرض وقاعدة البيانات ويجعل من الصعب كتابة اختبارات الوحدة للعروض.
أحد الحلول هو استخدام بنية ثلاثية الطبقات.
مثال على الهندسة المعمارية ذات الثلاث طبقات:
1 طبقة العرض
- يتعامل مع دورة الطلب/الاستجابة.
- يتعامل مع المصادقة/التفويض.
- التحقق من صحة بيانات الإدخال من الطلبات
- طبقة خدمة المكالمات
2 طبقة الخدمة
- يحتوي على منطق الأعمال والمجال
- إجراء عمليات التحقق المختلفة
- طبقة استمرارية المكالمات
3 طبقة الثبات
- يعالج التواصل مع قاعدة البيانات.
إذا كنت تعتقد أن هذا أمر مبالغ فيه بالنسبة لمشروعك، فيمكنك بسهولة دمج طبقة الخدمة وطبقة الثبات في طبقة واحدة. والأمر المهم هنا هو أنه يمكنك الحصول على واجهات يسهل اختبارها ومنطق عمل خارج وجهات النظر.
بهذه الطريقة، عندما تختبر العروض، يمكنك بسهولة محاكاة أساليب طبقة الخدمة التي تم استدعاؤها.
النصيحة رقم 5: لا تستخدم النماذج مباشرة في القوالب
يا إلهي، هذا مهم للغاية. نعم، إنه مريح وسهل. لكنه يربط بين النماذج والقوالب (طبقة العرض) بشكل وثيق.
هناك العديد من الأسباب التي تجعل استخدام النماذج مباشرة في القوالب فكرة سيئة.
- من الصعب جدًا تصحيح الأخطاء إذا حدث خطأ ما. يمكن أن تكون تتبعات المكدس غامضة إذا تم رفع استثناء ما في عرض القالب
- يمكن أن تحدث مشكلات N+1 بسهولة تامة ويكون من الصعب اكتشافها.
- يقدم Django بعض الأساليب السحرية على النماذج. أحد الأمثلة على ذلك هو
ChoiceField
الذي يضيف طريقةget_<fieldname>_display
على النموذج. هذا أمر سيئ في رأيي، لأنه قد يجعل صيانة الكود صعبة.
الحل لهذه المشكلة هو تحويل بيانات النموذج إلى DTO أو قاموس بسيط. يمكن بعد ذلك تمرير DTO إلى سياق القالب وستعرف بالضبط سبب عرض بعض البيانات في HTML.
النصيحة رقم 6: استخدم النماذج والمتسلسلات فقط للتحقق من صحة الإدخال
كما تعلم، يحتوي Django على نماذج ويحتوي DRF على Serializers للتحقق من صحة الإدخال. وكلاهما مفيدان للغاية في وظيفتهما. ولكن هنا أريد أن أتحدث عن ModelForm
وModelSerializer
، وهما فئتان فرعيتان من فئتي Form
وSerializer
. يمكن لكل منهما إنشاء اتصال مباشر بالنموذج الخاص بك. وهذا يجعل حفظ البيانات في النماذج المتصلة مهمة سهلة.
في حين أن هذا مناسب مرة أخرى، فإنك تحصل في المقابل على اقتران وثيق بين نظام التحقق من صحة الإدخال وقاعدة البيانات. ماذا لو كنت تريد حفظ شيء آخر في نفس المُسلسل؟ عليك تجاوز التابع save()
ووضع منطق إضافي هناك. يبدو الأمر وكأنه فوضى، أليس كذلك؟ يمكن أن تكون فوضى كبيرة، ويصعب صيانتها واختبارها.
الحل لهذه المشكلة هو التخلص من ModelForm
وModelSerializer
واستبدالهما بـ Form
وSerializer
على التوالي. دع هاتين الوظيفتين تقومان بالتحقق من صحة الإدخال ثم تمرير البيانات التي تم التحقق من صحتها إلى طبقة الخدمة.
في حالة احتياجك إلى أداء أفضل، يمكنك أيضًا استخدام مكتبات أخرى للتحقق من صحة البيانات. راجع هذا المعيار.
أحب استخدام marshmallow الذي لا يعتمد على إطار عمل أو ORM. يمكنك استخدامه في أي مشروع، حيث يلزم التحقق من صحة الإدخال.
نصيحة رقم 7: تنزيل ملفات بذرة لـ Django
إذا كنت تستخدم أحدث إصدارات بايثون، فمن الضروري أن تستخدم التعليقات التوضيحية للنوع. حتى إذا كانت بايثون لغة ديناميكية، فإن إعلان تلميحات نوع المتغير يجعل قراءة الكود وفهمه أسهل. من المرجح أن توفر بيئة التطوير المتكاملة الخاصة بك ميزات إكمال تلقائي أفضل، إذا تم توفير تلميحات النوع.
يأتي Django بدون أنواع أساسية بشكل افتراضي. من خلال تنزيل أنواع أساسية من جهات خارجية مثل https://github.com/typeddjango/django-stubs، ستحصل على تلميحات أفضل للأنواع عند استخدام وحدات Django. في النهاية، من لا يريد أنواعًا في الكود الخاص به.
قد تبدو بعض هذه النصائح جذرية للغاية. قد تحتاج إلى استثمار بعض الوقت لاتباع هذه النصائح. ولكن في النهاية، سيكون الأمر يستحق العناء. خاصة إذا بدأت في التحرك خارج منطقة MVP/POC.
اكتشاف المزيد من بايثون العربي
اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.