قصة Holivarny عن linter

كلنا نكتب الكود. الكثير من التعليمات البرمجية. بالطبع ، هناك أخطاء. في بعض الأحيان يكون هذا مجرد رمز ملتوية ، وأحيانًا يكون ثمن الخطأ عبارة عن سفينة فضائية انفجرت. بالطبع ، لا أحد يصنع عضادات مقصودة ، يحاول الجميع مراقبة الجودة بأفضل ما يمكن ، ولكن بدون أدوات التحليل الثابتة ، يصعب التأكد من أن كل شيء مثالي.

تساعد Linters على جلب الكود إلى نمط واحد وتجنب الأخطاء. صحيح ، فقط إذا كنت مستعدًا للمعاناة ، ولا تتجاهل أخيرًا "pylint: تعطيل" ، فقط لتتخلف عن الركب. ما الذي يجب أن يكون لنتير ، ولماذا لا تستطيع بيلينت فعله ، يعرف نيكيتا سوبوليفن ، الذي يفهم ويحب اللتر كثيراً لدرجة أنه قام حتى بتسمية شركته حتى لا يزعجهم - خدمات wemake.services.

الصورة

في ما يلي النص النصي للتقرير الخاص بموسكو Python Conf ++ عن البطانات ، وكيفية القيام بها بشكل صحيح وكيفية عدم القيام بذلك. كان للعرض التقديمي الكثير من التفاعل ، عبر الإنترنت والتواصل مع الجمهور. أجرى المتحدث ، على طول الطريق ، استطلاعات الرأي وحاول إقناع الجمهور: نظر إلى الاتجاه ، وكما في النقاش ، حاول تحقيق التوازن بين النسبة وتغيير الرأي العام. وقع جزء من استطلاعات الرأي في فك التشفير ، ولكن ليس كل شيء ، لذلك يتم إرفاق مقطع فيديو لإكمال الصورة.



لماذا نحتاج إلى شراب؟


المهمة الأكثر أهمية من linter هي جعل الشفرة موحدة . هناك العديد من الخيارات لكتابة نفس الشيء في Python: ضع فاصلة هنا أو هناك ، أو نسيت إغلاق الأقواس ، أو لا تنسَ. عندما يكتب الناس الكود لفترة طويلة ، يصبح مثل لحاف خليط من القطع المختلفة مخيط في أوقات مختلفة. من غير الجيد العمل مع مثل هذه البطانية ، ولا يشجع قراءة الكود ، وهو أمر سيء للغاية.

يجعل لونتنتس حياة أسهل على مراجعة . لقد جئت إلى مراجعة التعليمات البرمجية وأعتقد: "لا أريد القيام بذلك! الآن ستكون هناك مساحات إضافية وهراء آخر! " أود أن يقوم شخص آخر بإعداد رمز جيد ، وبعد ذلك سوف أقدر الأشياء المفاهيمية العظيمة.

في بعض الأحيان ، أنظر إلى الكود وأظن أن كل شيء على ما يرام ، ثم أرى في بعض الوظائف متغيرات كثيرة أو خطأ لم ألاحظه. سوف تجد أتمتة هذا الخطأ ، لكنني نظرت. حتى لا يقع في مثل هذه الحالات - أستخدم linter - يجد كل ما هو مخفي ويصعب العثور عليه.

ما هي المشروبات؟


أبسط منها تحقق فقط من النمط ، على سبيل المثال ، Flake8 . إلى حد ما ، أسود أيضًا ، ولكنه بالأحرى عبارة عن أداة إنشاء تلقائي. يختبر Linters دلالات أكثر صعوبة ، وليس فقط الأساليب: ما الذي تفعله ، ولماذا ، ويضربك على يديك إذا كتبت بأخطاء. ومن الأمثلة الجيدة على ذلك بيلينت ، التي نعرفها جميعًا ونستخدمها ونحبها . أنا أسمي هذه الملابس - أفضل الممارسات . النوع الثالث هو التحقق من النوع ، وهذه linter قليلا قبالة إلى الجانب. التحقق من النوع في Python جديد ، ويتم الآن بواسطة منصتين متنافستين: Mypy و Pyre .

كيفية استخدام linter؟


أنا لا أدعي أن linter هو الدواء الشافي واستبدال لكل شيء. هذا ليس كذلك. Linter - الخطوة الأولى من الهرم ، والتي يدخل الكود حيز الإنتاج.

هناك ثلاث خطوات في الهرم:

  • إطلاق linter . إنه سريع للغاية ولا يحتاج إلى أي شيء سوى شفرة المصدر - لا بنية تحتية ، لا إعدادات. دققي: اجتاز الفحص الصحي الأول - كل شيء على ما يرام ، نحن نعمل عليه.
  • مرحلة الاختبار . هذه العملية أكثر تعقيدًا وأطول بسبب الأخطاء غير البرمجية. سنحتاج بالفعل إلى الإعداد الصحيح والكامل للتطبيق بأكمله.
  • مراجعة المرحلة .



هذه هي الخطوات الضرورية للدخول في الإنتاج. إذا لم تمر بخطوة واحدة أو نسيت شيئًا ما ، أو قال المراجع إنها لن تنجح ، فستشاهد النقش: فشل - الكود السيئ لا يدخل حيز الإنتاج.

هل تستخدم linter في العمل؟


إذا سألت المطورين من مؤسسة قاسية ، يعملون فيها 7 أيام في الأسبوع ، ما إذا كانوا يستخدمون linter ، ثم اتضح أن ثلثهم على الأقل يستخدمون الشراشف بطريقة صارمة للغاية: تسقط CI ، تكون عمليات الفحص شديدة . يطبق الباقي بشكل متساوٍ تقريباً على linter على أسلوب الاختبار ، ولن يستخدم كنظام إعداد التقارير : يبدأ تشغيل linter ، ويقوم بإنشاء تقرير ويرى مدى سوء كل شيء. يتم استخدام Linters ، وهذا جيد. في شركتنا ، تم بناء كل شيء بقسوة: الربط الصعب ، والكثير من الشيكات ، ومراجعة الكود المزدوج.

مراجعة الكود


المشاكل تنشأ فقط في هذه المرحلة. هذه هي الخطوة الأولى والأكثر صعوبة في الهرم: لا يمكن إجراء مراجعة تلقائية للكود ، وإذا أمكن ، سيؤدي ذلك إلى أتمتة كتابة التعليمات البرمجية. ثم لن تكون هناك حاجة المبرمجين.

تبدو العملية القياسية كما يلي: تأتي الشفرة للمراجعة ، وأجد الأخطاء ، ولا أرغب في ارتكابها بعد الآن. على سبيل المثال ، رأيت أن المطور اكتشف BaseException: "لا تفعل ذلك. من فضلك لا يمسك! " بعد 10 أيام ، نفس الشيء. أذكرك مرة أخرى:

- نحن لا نقبض على BaseException.
" جيد ، لقد فهمت ذلك."

يمر عام - نفس الخطأ. رجل جديد يأتي - نفس الخطأ. أعتقد - كيف يمكننا أتمتة كل شيء حتى لا يحدث هذا الموقف مرة أخرى ، ويتبادر إلى الذهن فقط: " هيا بنا نلعب؟ »لنقم بإنشاء حزمة مفتوحة ، ونضع فيها جميع القواعد التي نستخدمها في العمل ونقوم بالتحقق من القواعد تلقائيًا بحيث لا نكتب في كل مرة باليد. نحن أتمتة كل شيء بشكل جيد وعلى الفور!

وبطبيعة الحال ، يمكنك أن تقول: " يوجد بالفعل سجاد جاهز بالفعل ، ويعملون ، والجميع يستخدمهم - لماذا يفعلون بهم؟" ، وستكونون على حق تمامًا ، لأن هناك بالفعل سجائر. دعونا نرى أي منها وماذا يفعلون.

بيلينت


على عنوان " لماذا لا بيلينت؟" "لقد سمعت هذا السؤال عدة مرات. سأجيب عليه ليونة. Pylint هي أداة رائعة لنجم موسيقى الروك لرمز Python ، لكنها تحتوي على ميزات لا أريد رؤيتها في برنامج linter.

يمزج كل شيء معًا: اختبارات أسلوبية ، وأفضل الممارسات ، وفحص النوع . فحص Pylint Type غير متطور لأنه لا توجد معلومات حول النوع: إنه يحاول عرضه بطريقة أو بأخرى ، لكنه لا يعمل بشكل جيد. لذلك ، غالبًا عندما أكتب model_name.some_property على Django ، أستطيع أن أرى الخطأ: "عذرًا ، لا توجد خاصية من هذا القبيل - لا يمكنك استخدامها!" أتذكر أن هناك مكونًا إضافيًا ، أقوم بتثبيته ، ثم أستخدم Celery ، كما أنه يبدأ بعض المشكلات ، أقوم بتثبيت المكون الإضافي لـ Celery ، واستخدام مكتبة سحرية أخرى ، ونتيجة لذلك ، أنا فقط أكتب في كل مكان: "pylint: تعطيل" ... هذا ليس كذلك ما أريد الحصول عليه من linter.

ميزة أخرى مخفية عن المستخدم هي أن Pylint له تطبيقه الخاص لشجرة بناء الجملة Abstract في Python . هذه هي الطريقة التي يظهر بها الرمز عند تحليله والحصول على معلومات حول شجرة العقد التي تشكل الرمز. لا أثق حقًا في تطبيقاتي ، لأنها دائماً خاطئة.

بالإضافة إلى Pylint ، هناك أنواع أخرى من النبيذ التي تؤدي وظيفتها أيضًا.

Sonarquube


أداة رائعة ، لكنها منفصلة تعيش في مكان قريب من مشروعك.

  • لن تتمكن SonarQube من التشغيل بشكل متكرر : يجب نشرها في مكان ما أو مشاهدتها أو مراقبتها أو تكوينها.
  • هو مكتوب بلغة جافا . إذا كنت ترغب في إصلاح linter الخاص بك لـ Python ، فستكتب الرمز في Java. أعتقد أن هذا خطأ من الناحية النظرية - يجب أن يكون المطور الذي يمكنه الكتابة في Python قادراً على كتابة التعليمات البرمجية لاختبار Python.

الشركة التي تقوم بتطوير SonarQube تبحث بشكل خاص في مفهوم تطوير المنتجات. هذا يمكن أن يكون مشكلة.

تتمثل ميزة SonarQube في أنه يحتوي على عمليات فحص رائعة جدًا تظهر التعقيد والأخطاء المخفية المحتملة والأخطاء. أنا أحب الشيكات ، وأود تركها ، وتغيير النظام الأساسي.

فليك 8


اللنتير الرائع بسيط للغاية ، لكن مع مشكلة واحدة: هناك القليل من القواعد التي تتحقق من مدى جودة كتابة الكود. في الوقت نفسه ، يحتوي Flake8 على الكثير من الإضافات البسيطة للغاية: الحد الأدنى للمكوّن الإضافي هو طريقتان يجب تنفيذهما. لقد فكرت - دعنا نأخذ Flake8 كأساس لكتابة المكونات الإضافية ، ولكن من خلال فهمنا لمزايا الشركة. وكذلك فعلنا.

الأكثر صرامة linter في العالم


لقد صنعنا أداة جمعنا فيها كل شيء نعتقد أنه مناسب لبيثون ويطلق عليه دليل wemake-python-style . تم نشر المكوّن الإضافي بشكل عام ، حيث أعتقد أن Open Source by Default هي ممارسة جيدة . أنا مقتنع تمامًا أن العديد من الأدوات ستستفيد إذا تم تحميلها إلى "المصدر المفتوح". بالنسبة لأدواتنا ، توصلنا إلى الشعار: "الأكثر صرامة في العالم!"

الكلمة الأساسية في linter لدينا هي صارمة ، مما يعني الألم والمعاناة.

إذا كنت تستخدم linter ، وهذا لا يجعلك تعاني حتى تضغط رأسك: "لماذا لا تعجبك ، اللعنة عليك" ، فهذا أمر سيء. إنه يتخطى الأخطاء ، ولا يراقب بشكل جيد جودة الشفرة ، ونحن لسنا بحاجة إليها. نحن بحاجة إلى الأكثر صرامة في العالم ، والذي يتحقق كثيرًا. لدينا الآن حوالي 250 اختبارًا مختلفًا في كلتا الفئتين : الأسلوبية وأفضل الممارسات ، ولكن دون التحقق من النوع. تشارك Mypy في ذلك ، نحن لا نهتم به بأي شكل من الأشكال.

لدينا linter لا يوجد لديه حل وسط . ليست لدينا قواعد من الفئة "لا أريد القيام بذلك ، ولكن إذا كنت تريد ذلك حقًا ، فيمكنك ذلك". لا ، نحن نتحدث دائمًا بقسوة - لا نفعل ذلك ، لأنه أمر سيء. ثم يأتي الناس ويقولون: "هناك 2.5 حالة استخدام حيث يكون ذلك ممكنًا من حيث المبدأ!". إذا كانت هناك مثل هذه الحالات ، فاكتب بوضوح أن هذا الخط مسموح أن يتجاهله اللنتير ، لكن اشرح السبب. يجب أن يكون تعليقًا على سبب السماح ببعض الممارسات الغريبة ولماذا تقوم بذلك. هذا النهج مفيد أيضًا في توثيق الكود.

linter الأكثر صرامة لا يتطلب إعدادات (WIP) . لا يزال لدينا إعدادات ، لكننا نريد التخلص منها: بالحرية ، سيقوم المستخدم بالتأكيد بالتشكيل حتى لا يعمل linter بشكل صحيح.

لا تحتاج الأداة الجيدة إلى إعدادات - فهي تحتوي على قيم افتراضية جيدة.

مع هذا النهج ، ستكون الشفرة متسقة وستعمل بنفس الطريقة مع الجميع ، نظريًا على الأقل. لا نزال نعمل على ذلك ، وبينما توجد إعدادات ، يمكنك استخدام الأداة الخاصة بنا وتخصيصها بنفسك.

من نحن نعتمد عليها؟


من عدد كبير من الأدوات.

  • فليك 8 .
  • يعد Eradicate مكونًا رائعًا يبحث عن الأجزاء المعلقة في الكود ويجعلك تحذفها ، لأن تخزين الكود الميت في مشروع سيء. غير مسموح لنا بالقيام بذلك.
  • Isort هي أداة تجبرك على فرز عمليات الاستيراد بشكل صحيح: بالترتيب ، والتهجير ، والاقتباسات الجميلة.
  • يعد Bandit أداة رائعة لفحص أمان التعليمات البرمجية بشكل ثابت. يجد كلمات مرور سلكية ، واستخدام خرقاء assert في الكود ، ويدعو إلى Popen ، sys.exit ويقول إنه لا يمكن استخدام كل هذا ، ولكن إذا أردت ، يطلب منك كتابة السبب.
  • وأكثر من 20 ملحقًا يتحقق من الأقواس والاقتباسات والفواصل.

ما الذي نتحقق منه؟


هناك 4 مجموعات من القواعد التي نستخدمها وننفذها.

التعقيد هي أكبر مشكلة. لا نعرف ما هو التعقيد ولا نراه في الكود. نحن ننظر إلى الكود الذي نعمل به كل يوم ويبدو أنه ليس معقدًا - خذها وقراءتها وكل شيء يعمل. هذا ليس كذلك. رمز بسيط هو رمز مألوف. التعقيد له معايير واضحة نختبرها. حول المعايير نفسها - في وقت لاحق. إذا كان الرمز ينتهك المعايير ، فإننا نقول: "الرمز معقد ، أعد كتابة!"

تعتبر أسماء المتغيرات مشكلة برمجة لم يتم حلها. الذي سوف يقرأ متى وفي أي سياق غير واضح. نحاول جعل الأسماء متسقة ومفهومة قدر الإمكان ، ولكن على الرغم من أننا نحاول ، فإن المشكلة لم تحل بالكامل.

لتحقيق الاتساق ، لدينا قاعدة بسيطة - اكتب نفس الشيء في كل مكان. إذا كان هناك أي نهج معتمد ، استخدمه في كل مكان. لا يهم إذا كنت ترغب في ذلك أم لا ، والاتساق هو أكثر أهمية.

نحن نحاول استخدام أفضل الممارسات فقط . إذا علمنا أن بعض الممارسات ليست جيدة جدًا ، فإننا نمنع استخدامها. إذا أراد المطور استخدام الممارسة المحظورة ، فإننا نتوقع منه الحجج: لماذا ولماذا التقدم بطلب. ربما ، أثناء عملية الوصف ، سيأتي فهم لماذا هو سيء.

ما هو التعقيد؟


يحتوي التعقيد على مقاييس محددة يمكنك النظر إليها وتحديد ما إذا كان الأمر صعبًا أم لا. هناك الكثير منهم.

التعقيد الحلقي - التعقيد السيكلومي المفضل لدى الجميع. إنه يجد في الكود عددًا كبيرًا من العناصر المتداخلة if ، for للهياكل الأخرى ، ويشير إلى تفرع كبير للكود وصعوبة في القراءة. كل شيء سيء مع الكود المضمن: تقرأ ، تقرأ ، تقرأ ، عادت ، قرأت ، قرأت ، قرأت ، ثم قفزت إلى دورة أخرى. من المستحيل تمرير هذا الرمز بأمان من أعلى إلى أسفل.

الحجج والبيانات والعائدات. هذه مقاييس كمية: عدد الوسائط الموجودة في الوظيفة أو في الطريقة ، وعددها داخل نص هذه الوظيفة أو طريقة العبارات والإرجاع.

التماسك والاقتران من مقاييس OOP الشائعة. يظهر التماسك ترابط الطبقة في الداخل. على سبيل المثال ، هناك فئة ، وداخلك تستخدم جميع الأساليب والخصائص - كل ما أعلنته. هذه فئة جيدة مع اتصال عالي بالداخل. الاقتران هو مقدار اتصال الأجزاء المختلفة من النظام: الوحدات النمطية والفئات. نريد تحقيق أقصى قدر من الاتصال داخل الفئة والحد الأدنى من الاتصال بالخارج. ثم يتم صيانة النظام بسهولة ويعمل بشكل جيد.

تعقيد جونز - لقد اقترضت هذا المقياس ، ولكن فقط لأنه قنبلة! يحدد جونز المعقدة تعقيد الخط - كلما زاد تعقيد الخط ، زاد صعوبة فهمه ، لأن الذاكرة البشرية قصيرة الأجل لا يمكنها معالجة أكثر من 5-9 أشياء في آن واحد. هذا هو ما يسمى محفظة ميلر .

نحن ننظر إلى هذه المقاييس المهمة وبعضها الآخر ، وهو أكبر من ذلك بكثير ، ونحدد ما إذا كانت الشفرة مناسبة أم لا. في فهمنا ، التعقيد هو شلال .

صعوبة الشلال


تبدأ الصعوبة بحقيقة أننا كتبنا السطر ، وهي لا تزال جيدة. ولكن بعد ذلك يأتي النشاط التجاري ويقول إن الأسعار قد تضاعفت ، وقد تضاعفنا بواقع 2. في هذه المرحلة ، يصبح جونز المعقدة مجنونًا ويذكر أن الخط الآن معقد للغاية - هناك الكثير من المنطق.

حسنًا ، نبدأ في تشغيل متغير جديد ، ويقول محلل تعقيد الوظيفة:

- لا ، هذا ليس كذلك - يوجد الآن الكثير من المتغيرات داخل الوظيفة.

سأقدم طريقة جديدة ، وسأنقل إليها الحجج. الآن التحقق من عدد وسائط الدالة ، أو عدد الأساليب داخل الفصل ، يقول إن هذا مستحيل أيضًا - الفصل معقد جدًا ويجب تقسيمه إلى جزأين. تحطمت من خلال تسليط الضوء على فئة أخرى. يوجد الآن المزيد من الفصول وكل شيء على ما يرام ، ولكن التحقق من تعقيد الوحدة النمطية يفيد بأن الوحدة الآن معقدة للغاية وتحتاج إلى إعادة تشكيلها. لماذا؟

وهذا ما يسمى المعاناة. هذا هو السبب في أنني أقول أن linter يجب أن تجعلك تعاني. لقد بدأنا بضرب 2 في سطر واحد ، وانتهى بنا الأمر بإعادة بناء النظام بأكمله . تؤدي إضافة جزء صغير من التعليمات البرمجية إلى إعادة تشكيل الوحدات بالكامل ، لأن التعقيد ينتشر مثل الشلال ، ويغطي كل شيء ممكن.

"تحتاج إلى refactor" - هذا الشيء يجعلك refactor رمز. لا يمكنك الجلوس فقط: "أنا لا أتطرق إلى هذا الرمز ، يبدو أنه يعمل". لا ، في يوم ما ستقوم بتغيير الشفرة في مكان آخر ، وسيقوم شلال التعقيد بإغراق الوحدة التي لم تلمسها وسوف تضطر إلى إعادة تفعيلها. أعتقد أن إعادة بيع المباني أمر جيد ، وكلما زاد الأمر ، كان نظامك أكثر استقرارًا وأفضل. وكل شيء آخر غير شخصي!

الآن دعنا نتحدث عن الأذواق. هذا جزء كلي وتفاعلي!

هوليفار


دعنا ندعم ، التعليقات مفتوحة. أولاً ، اسمحوا لي أن أذكرك بأن الأسماء مشكلة معقدة ولم يتم حلها. يمكنك القتال حول كيفية تسمية متغير ، ولكن لدينا بعض الأساليب التي تساعد على الأقل في عدم ارتكاب أخطاء واضحة.

أسماء


كيف تحب: var ، القيمة ، العنصر ، obj ، البيانات ، النتيجة ؟ ما هي البيانات ؟ بعض البيانات. ما هي النتيجة ؟ نوع من النتيجة. غالبًا ما أرى متغير النتيجة ودعوة لبعض الأساليب الجهنمية في فصل غير مفهوم - وأعتقد: "ما هذه النتيجة؟ لماذا هو هنا؟

هناك العديد من المطورين الذين يختلفون معي ويقولون إن القيمة هي اسم متغير طبيعي تمامًا:

- أنا دائما استخدام المفتاح والقيمة!
- لماذا لا تستخدم المفتاح والقيمة ، ولكن قل أن المفتاح هو الاسم والقيمة هي الاسم الأخير؟ لماذا يستحيل تسمية first_name و last_name - الآن يوجد سياق.

عادة ما يتفق الناس ، لكنهم يقولون على أي حال. هذا شيء كلي للغاية: لقد قضى ثلاثة أشخاص على الأقل ساعة من حياتهم لي للتجادل حول هذا الأمر معي.

هل هو موافق لتسمية المتغيرات بحرف واحد؟


على سبيل المثال ، ف ؟ نعلم جميعًا الحالة الكلاسيكية: for i in some_iterable: ما انا ؟ في C ، هذه ممارسة قياسية ، وكل شيء يأتي منها. لكن في بيثون ، المجموعات والتكرارات. تحتوي المجموعات على عناصر لها أسماء - دعنا نسميها بطريقة مختلفة.

يعتقد نصف المطورين أن استدعاء المتغيرات i و x و y و z أمر طبيعي.

أعتقد أنه لا يمكنك تسمية أسماء بحرف واحد. أريد المزيد من السياق ومن الجيد أن يتفق النصف الثاني من المطورين معي. إذا كان هذا في C ما زال مسموحًا به إلى حد ما بسبب التراث التاريخي ، فهذا يمثل مشكلة كبيرة جدًا في بيثون ولا تحتاج إلى القيام بذلك.

الاتساق


دعنا فقط نختار طريقة واحدة للخروج من الكثيرين ونقول ، "دعونا نفعل ذلك". سواء أكان هذا جيدًا أم سيئًا - لم يعد مهمًا - فهو ثابت.

نحن نتحدث فقط عن بيثون 3 ، لا يعتبر Legacy على الإطلاق.

لدي حجة: عندما نرث من شيء ما ، يجب أن نعرف ما - سيكون من الجيد أن نرى اسم الوالد. الشيء المضحك هو أننا عادة ما نرى اسم الوالد ، إلا عندما يكون هذا كائنًا . لذلك ، قمت بصياغة قاعدة لنفسي: عندما أكتب فصلاً ، أرثت شيئًا من شيء - أكتب دائمًا اسم الوالد. لا يهم ما سيكون عليه - نموذج أو كائن أو أي شيء آخر.

إذا كان هناك خيار لكتابة Class Some(object) أو class Some ، فسوف أختار الأول. من ناحية ، يُظهر أننا نكتب دائمًا ما نرثه دائمًا. من ناحية أخرى ، لا يوجد أي فعل خاص فيه : لا نفقد شيئًا من بعض ضربات المفاتيح الإضافية.

ثلثي المطورين أكثر دراية بالخيار الثاني ، وأنا أعرف السبب. فرضيتي: كل هذا لأننا انتقلنا لفترة طويلة من الإصدار الثاني من بيثون إلى الإصدار الثالث ، والآن نظهر أننا نكتب في بيثون الثالث. لا أدري كيف أن الفرضية صحيحة ، لكن يبدو لي أن هذا صحيح.

خطوط F هي فظيعة؟


خيارات الإجابة:

  • نعم: إنهم يفقدون السياق ويضعون المنطق في القالب ولا يرون - (38٪).
  • لا! إنها معجزة! - (62 ٪).

هناك فرضية مفادها أن الخطوط المفرطة رهيبة. إنهم يشقون أي شيء فيهم! خطوط f ليست هي نفسها .format ، الاختلافات مثيرة. عندما نعلن عن قالب ، ثم ننسقه ، فإننا ننفذ إجراءين بشكل منفصل: أولاً نحدد القالب ، ثم ننسقه. عندما نعلن عن خط f ، فإننا نقوم بإجراءين في وقت واحد: نعلن على الفور القالب وننسقه في نفس الوقت.

هناك مشكلتان مع f الخطوط. أعلنا قالب لل f- خط ويعمل كل شيء. ثم نقرر نقل القالب 2 إلى الأعلى أو نقله إلى وظيفة أخرى - وكل شيء ينفصل. الآن لا يوجد سياق يسمح لنا بتنسيق السلاسل ، ولا يمكننا معالجتها بشكل صحيح. المشكلة الكبيرة الثانية مع الخطوط f: تسمح لك بالقيام بالشيء الرهيب - التمسك بالمنطق في القالب . لنفترض أن هناك خطًا نضيف فيه ببساطة اسم المستخدم وكلمة "Hello" - هذا طبيعي. لا يوجد شيء فظيع بشكل خاص ، ولكن بعد ذلك نرى أن اسم المستخدم يأتي بأحرف كبيرة ، نقرر ترجمته إلى حالة عنوان والكتابة مباشرة في قالب username.title() . بعد ذلك ، تظهر الشروط والدورات والاستيراد في القالب. وجميع الأجزاء الأخرى من php.

كل هذه المشاكل تجعلني أقول إن السطور هي موضوع سيء ، ونحن لا نستخدمها. الطريف في الأمر أنه ليس لدينا حالة ليست فيها سوى خطوط f مناسبة لنا. عادة ما يكون أي تنسيق مناسبًا ، لكننا اخترنا .format - كل شيء آخر مستحيلًا - لا % ، أو f - خطوط. يتم عمل .format أيضًا ، لأنه بداخله يمكنك وضع علامات اقتباس مجعد وكتابة اسم المتغير أو ترتيبه.

خلال هذا التقرير ، زاد عدد خصوم الخطوط من 33 إلى 38٪ - وهذا انتصار صغير ، لكن.

الأرقام


هل تحب الأرقام مثل هذا: final_score = 69 * previous result / 3.14 . هذا يبدو وكأنه سطر قياسي من التعليمات البرمجية ، ولكن ما هو 69؟ غالبًا ما تنشأ مثل هذه الأسئلة عندما أنظر إلى الكود الذي كتبته منذ فترة ، ويقول المدير في تلك اللحظة:

- من فضلك اضرب 147.
- لماذا في 147؟
- لدينا مثل هذه التعريفات.

لقد تضاعفت ونسيت ، أو لفترة طويلة التقطت بعض قيمة المعامل بحيث يعمل كل شيء - وبعد ذلك نسيت كيف التقطته ولماذا. اتضح أن العمل البحثي المهم ظل مخفيًا وراء رقم بلا عنوان. لا أعرف حتى ما هو هذا الرقم ، لكن لا يمكنني العثور عليه أو تذكره واستعادته بطريقة أو بأخرى عن طريق الالتزام لاحقًا.

لماذا لا تفعل ذلك بشكل مختلف - ضع كل الأرقام المعقدة في المتغير الخاص بك مع الاسم والوثائق؟ على سبيل المثال ، بالنسبة للرقم 69 ، اكتب أن هذا هو المؤشر المتوسط ​​في السوق ، والآن الثابت له اسم وسياق. سأكتب تعليقًا أخذت فيه ثابتًا في موقع مثل هذه الدراسة. إذا تغير البحث في المستقبل ، فعندئذ سأأتي وأحدث البيانات.

وبالتالي ، فإننا نضمن عدم وجود أرقام سحرية من خلال التعليمات البرمجية لدينا وتعقيدها من الداخل. إنهم يشقون طريقهم من خلال التحقق من تعقيد كل سطر ويقولون: "هنا هو الرقم 4766. ما هو ، لا أعرف ، قم بتصنيفه بنفسك!" كان هذا اكتشافًا رائعًا بالنسبة لي.

نتيجةً لذلك ، أدركنا أننا نحتاج إلى اتباع ذلك ، ولا نفوت أي أرقام سحرية في الشفرة. من الجيد أن حوالي 100٪ من زملائنا يتفقون معنا ، كما أنهم لا يستخدمون هذه الأرقام.

ولكن هناك استثناءات - فهذه أرقام من 10 إلى 10 ، والأرقام 100 و 1000 وما شابه ذلك ، لمجرد العثور عليها وبدونها صعبة. نحن صعبون ، لكن ليس ساديًا ونفكر قليلاً.

هل تستخدم 'staticmethod'؟


دعونا نفكر في ما staticmethod . هل تساءلت يوما عن سبب وجودها في بيثون؟ انا لا. كان لدي بيلينت جميل يقول:

- انظر ، أنت لا تستخدم self ، cls - تفعل staticmethod!
- حسنا ، بيلينت ، سأفعل staticmethod.

ثم قمت بتدريس بيثون للمبتدئين ، وسألوا ما هو staticmethod ولماذا هو مطلوب. لم أكن أعرف الإجابة وفكرت فيما إذا كان من الممكن كتابة الشيء نفسه باستخدام دالة ، أو عدم استخدام self في وظيفة عادية ، لمجرد أنها فئة من هذا القبيل وحدث شيء ما. لماذا نحتاج إلى بناء staticmethod؟

غوغل السؤال ، واتضح أنه عميق مثل حفرة أرنب. هناك العديد من لغات البرمجة الأخرى التي staticmethod هو أيضا لا يحب. وسبب جيد - staticmethod يكسر نموذج الكائن. نتيجة لذلك ، أدركت - staticmethod ليس هو المكان هنا ، وقد شاهدناه. الآن ، إذا استخدمنا ديكور staticmethod ، فإن linter سيقول: "لا ، آسف ، refactor!"

يختلف معظم المطورين معي ، لكن ما زال نصفهم يعتقدون أنه من الأفضل أن تكتب طرقًا عادية أو وظائف عادية بدلاً من staticmethod.

المنطق في __init __. رو - جيد أم سيء؟


هذا هو موضوعي المفضل. بالتأكيد ، عندما تنشئ حزمة جديدة وتسميها بطريقة أو بأخرى - فإنها تخلق __init __. رو وتتساءل ماذا تضعها؟ ما يجب وضعه في __init __. Ru ، و - في الملفات جنبًا إلى جنب؟ بالنسبة لي ، كان هذا سؤالًا غير تافه ، وكنت دائمًا ضائعًا: ربما كان شيئًا أكثر أهمية؟ ثم فكرت - لا ، على العكس ، سأضع الأهم في السياق الأكثر قابلية للفهم. إذا وضعت شيئًا ما في __init __. Ru ، ثم قمت باستيراده بالكامل ، فقد تبين أن الواردات الدورية هي أيضًا سيئة.

نظرت إلى العديد من المكتبات الشعبية ، وتسلقت __init __. Ru ، ولاحظت أنه يوجد إما توافق في القمامة أو إلى الخلف. بالنسبة لي ، نشأ هذا السؤال بشكل حاد عندما بدأت في إنشاء حزم كبيرة مع العديد من الحزم الفرعية - تضيع. , . Python, , , __init__. , 90% .

— , API, , - , , ? , , . API . , __init__. - : , , .

, I_CONTROL_CODE — . , . , , __init__. — . , , , - , .

hasattr ?


hasattr ? , , Python — . hasattr , ().

, , hasattr , , . , hasattr, , . - , Python -, hasattr . , . getattr « , ». hasattr — getattr, exception .

50 50 — , , .



, layer-linter . ? : , , , . , - . - . .

cohesion . , . Cohesion , . False Positive , — , , .

vulture Python . - , Python , . ohesion.

Radon , : Halstead , Maintainability Index , . , — .

Final type


Final- Python. Typing Extensions, , . , - , — , . , - - , ? لا حاجة . - — , , , .

Gratis


, .



, .

, . , . , Python- , .

, Moscow Python Conf++ , . , , Python-.

. . , , , .








Source: https://habr.com/ru/post/ar433480/


All Articles