اذهب إلى المحتوى

قواعد تنسيق الشيفرات ودور المنسق Black في بايثون


محمد الخضور

يعرَّف تنسيق الشيفرة بأنه تطبيق مجموعة من القواعد على الشيفرة المصدرية لمنحها مظهرًا معينًا. ورغم عدم أهمية تنسيق الشيفرة بالنسبة للحاسوب المُحلِّل للبرامج، إلا أنه أمر بالغ الأهمية من ناحية سهولة قراءة الشيفرة، وهذا ما يسهل مراجعتها. فإذا كانت الشيفرة صعبة الفهم على البشر (عليك أو على أحد زملائك) فما بالك بإصلاح الأخطاء فيها أو إضافة ميزات جديدة إليها، سيكون الأمر أصعب بكل تأكيد، فتنسيق الشيفرة ليس بالمسألة الجمالية فحسب، ولعل أحد أهم أسباب شعبية لغة بايثون هي سهولة قراءتها.

سنتعرف في هذا المقال على منسِّق الشيفرات Black في بايثون وهو أداة لتنسيق الشيفرات، إذ تنسق الشيفرة المصدرية تلقائيًا إلى شكلٍ مقروء ومتناغم، دون التأثير على سلوك البرنامج وأداءه، وتكمن أهمية Black في كونها تجنب المستخدم التنسيق المُمل للشيفرات في محرر النصوص أو بيئة التطوير المتكاملة IDE، إذ سنتعرف على آلية اختيار Black لنمط الشيفرة المحدد.

فوضى شيفراتك ستفقدك أصدقائك وتنفر زملائك في العمل

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

spam = ['dog', 'cat', 'moose']

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

spam= [ 'dog'  ,'cat',"moose"]

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

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

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

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

الدليل الإرشادي PEP 8 لكيفية تنسيق الشيفرات

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

يمكنك الاطلاع على الدليل PEP 8 بزيارة python.org. ويرى العديد من مبرمجي بايثون الدليل PEP 8 كمجموعة من القواعد المبالغ بصرامتها، في حين يرى منشؤوه العكس. إذ يذكّر القسم "رفض التغيير هو سمة العقول غير الناضجة" من الدليل القراء بأن الدافع الرئيسي لاتباع دليل إرشادي موحّد هو زيادة مقروئية الشيفرات في المشاريع من خلال الحفاظ على تنسيق معيّن بدلًا من التنسيقات الفردية المختلفة.

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

ونظرًا لاستخدامنا منسّق Black، فإن شيفراتنا ستتبع في تنسيقها دليل Black الإرشادي المتوافق تمامًا مع قواعد PEP 8. ولابد من تعلمك لهذه الأصول وكيفية تطبيقها يدويًا، فقد لا يكون منسّق Black متوفر دائمًا بسهولة، ناهيك عن كون القواعد التنسيقية التي ستتعلمها في هذا المقال عامّة وتتطبق على لغات البرمجة الأخرى، والتي قد لا تتضمّن منسقًا تلقائيًا.

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

التباعد الأفقي

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

استعمال مفتاح المسافة الفارغة Space لإنشاء مسافة بادئة

تعرّف المسافة البادئة بأنها ذلك الفراغ المتموضع في بداية أحد أسطر الشيفرة، ولإضافتها من الممكن استخدام أحد مفتاحي إضافة المحارف الفارغة في لوحة المفاتيح، وهما مفتاح المسافة الفارغة Space ومفتاح الجدولة Tab. ورغم كون أي منهما يؤدّي هذا الغرض، إلا أن استخدام مفتاح المسافة الفارغة يعد الإجراء الأفضل.

والسبب في ذلك يعود لكون كل من المفتاحين يعمل بطريقة مختلفة، ففي حين يُصيَّر مفتاح Space على الشاشة بهيئة قيمة محرفية تساوي فراغًا واحدًا بالشكل ‘ ‘، إلا أن مفتاح Tab يُصيّر على هيئة قيمة محرفية تقابل محرف الهروب t\ ما يجعل حجم الفراغات غامضًا، فعلى الغالب يعرض هذا المفتاح حجمًا متغيرًا للفراغات مُحددًا علامة جدولة ليبدأ النص التالي بعدها، إذا تتموضع علامة الجدولة عند كل ثمان فراغات وفقًا لعرض المستند، والمثال التالي يبيّن الفرق من خلال شيفرة مكتوبة في الصَدَفَة التفاعلية، إذ استخدمنا بدايةً مفتاح Space للفصل بين الكلمات ومن ثم مفتاح Tab:

>>> print('Hello there, friend!\nHow are you?')
Hello there, friend!
How are you?
>>> print('Hello\tthere,\tfriend!\nHow\tare\tyou?')
Hello   there,  friend!
How     are     you?

وبذلك وبما أن علامات الجدولة تُحدّد مسافات بيضاء متفاوتة العرض، فيجب تجنب استخدامها في الشيفرة المصدرية. مع ملاحظة أن معظم محررات النصوص وبيئات التطوير المتكاملة تُدرج تلقائيًا أربع أو ثمان محارف فراغ لدى الضغط على مفتاح Tab، بدلًا من استخدام علامة جدولة (متغيرة مع عرض الملف).

كما أنه من غير الممكن استخدام كلا المفتاحين في إنشاء المسافات البادئة في نفس الكتلة من الشيفرة، ولطالما كان استخدامهما معًا في إنشاء المسافات البادئة مصدرًا لأحد الأخطاء المزعجة في إصدارات بايثون القديمة، لدرجة أن الإصدار الثالث من بايثون لن يشغّل شيفرة بمسافات بادئة مبنية بهذه الطريقة، مُظهرًا رسالة الاستثناء الآتي:

 TabError: inconsistent use of tabs and spaces in indentation 

دلالةً على الاستخدام غير المتناسق لعلامات الجدولة والفراغات في إنشاء المسافات البادئة، في حين أنّ المنسّق Black يحوّل أي علامة جدولة مضافة كمسافة بادئة إلى أربعة فراغات تلقائيًا.

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

def getCatAmount():
....numCats = input('How many cats do you have?')

....if int(numCats) < 6:

........print('You should get more cats.')

ولاستخدام مسافة بادئة بأربعة محارف ميزاتٍ عديدة مقارنةً بأي خيار آخر، فمثلًا استخدام ثمان فراغات لكل مستوى من مستويات المسافة البادئة سيؤدي بالنتيجة إلى تجاوز الحد الأقصى لعدد المحارف في السطر الواحد، في حين أن استخدام فراغين فقط سيجعل ملاحظة وجود مسافة بادئة أصلًا أمرًا صعبًا نظرًا للفرق البسيط مع الأسطر العادية، أما باقي الاحتمالات من قبيل استخدام ثلاثة أو ستة فراغات فهو أمر غير شائع لدى المبرمجين، فهم كعالم الحوسبة إجمالًا، متحيزين لمضاعفات العدد 2 أي 2 و4 و6 و8 وهكذا.

التباعد ضمن السطر الواحد

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

استخدم فراغ واحد ما بين العمليات والمعرفات

إن لم تترك فراغًا ما بين العمليات والمعرفات (المتغيرات، الدوال، الكائنات …)، ستبدو الشيفرة وكأنها متداخلة. فمثلًا السطر التالي يتضمّن فراغات ما بين العمليات والمتغيرات:

YES: blanks = blanks[:i] + secretWord[i] + blanks[i + 1 :]

وفي حال حذف تلك الفراغات، فسيبدو بالشكل:

NO:  blanks=blanks[:i]+secretWord[i]+blanks[i+1:]

تستخدم هذه الشيفرة في كلتا الحالتين معامل الجمع + لجمع ثلاثة قيم، ولكن في حالة عدم استخدام فراغات، قد يبدو معامل الجمع الموجود ضمن المتغير [:blanks[i+1 على أنّه عملية جمع رابعة، إلا أن استخدام الفراغات سيوضح أن معامل الجمع هذا جزء من قيمة الشريحة slice (بنية في بايثون تمكننا من الوصول إلى أجزاء من التسلسلات مثل السلاسل النصية والجداول والقوائم) الموجودة بين القوسين.

لا تضع مسافات قبل الفواصل وضع مسافة واحدة بعدها

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

YES: def spam(eggs, bacon, ham):
YES:     weights = [42.0, 3.1415, 2.718]

وإلا سينتهي الأمر بشيفرة مجمّعة ذات مقروئية منخفضة، كما يلي:

NO:  def spam(eggs,bacon,ham):
NO:      weights = [42.0,3.1415,2.718]

كما من الضروري عدم وضع مسافة قبل الفاصلة، لأن ذلك سيجذب النظر نحوه:

NO:  def spam(eggs , bacon , ham):
NO:      weights = [42.0 , 3.1415 , 2.718]

يضيف منسّق Black تلقائيًا مسافة بعد كل فاصلة، كما يحذف أي فراغات مُضافة قبلها.

لا تستخدم أي فراغات قبل أو بعد النقاط

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

YES: 'Hello, world'.upper()

أما في حال استخدام مسافة قبل النقطة أو بعدها، فقد يبدو الكائن وسمته غير مرتبطان، كما في الحالة:

NO:  'Hello, world' . upper()

يحذف منسق Black تلقائيًا أي مسافات قبل أو بعد النقاط.

لا تضع مسافات بعد أسماء الدوال أو التوابع أو حاويات البيانات

من السهل تمييز أسماء الدوال والتوابع كونها تُتبع دومًا بقوسين، لذا يجب عدم وضع مسافة بين اسم الدالة أو التابع وقوس البداية، فعادةً ما يتم استدعاء الدوال بالشكل:

YES: print('Hello, world!')

ومع استخدام مسافة قبل قوس البداية، قد يبدو استدعاء الدالة الواحدة على أنه أمران مستقلان، كما في المثال:

NO:  print ('Hello, world!')

لذا يحذف منسّق Black أي مسافات بين اسم الدالة أو التابع وقوس بدايتها.

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

YES: spam[2]
YES: spam[0:3]
YES: pet['name']

ومع إضافة مسافات قد تبدو الشيفرة مجددًا وكأنها أمران منفصلان:

NO:  spam [2]
NO:  spam    [0:3]
NO:  pet ['name']

لذا يحذف منسّق Black أي مسافات كائنة بين اسم المتغير وقوس البداية المعقوف.

لا تضع مسافات بعد أقواس البداية أو قبل أقواس النهاية بأنواعها

يجب عدم استخدام مسافات في فصل الأقواس بأنواعها الهلالية () والمعقوصة {} والمعقوفة [] عن محتوياتها، فيجب أن تبدأ المعاملات في عبارة تصريح عن دالة ما أو القيم ضمن قائمة بعد قوس بدايتها وتنتهي قبل قوس نهايتها مباشرةً.

YES: def spam(eggs, bacon, ham):
YES:     weights = [42.0, 3.1415, 2.718]

إذ يجب عدم إضافة أي مسافات بعد قوس البداية أو قبل قوس النهاية، سواء كانت هذه الأقواس هلالية أم معقوفة:

NO:  def spam( eggs, bacon, ham ):
NO:      weights = [ 42.0, 3.1415, 2.718 ]

فإضافة هذه الأقواس لا يحسّن من مقروئية الشيفرة وبالتالي لا تقدّم أي قيمة مضافة، لذا يحذف منسّق Black هذه المسافات تلقائيًا في حال وجودها.

ضع فراغين قبل تعليقات نهاية السطر

إن أردت إضافة تعليق إلى نهاية أحد أسطر الشيفرة، فيجب إضافة مسافتين بعد نهاية السطر البرمجي وقبل المحرف # الدال على بداية التعليق، كما في المثال:

YES: print('Hello, world!')  # Display a greeting.

فبوجود الفراغين يصبح من السهل تمييز الشيفرة عن التعليق، أما في حال وجود مسافة واحدة أو عدم وجود مسافة أبدًا كأسوأ سيناريو، سيكون من الصعب الفصل بصريًا بين الشيفرة والتعليق.

NO:  print('Hello, world!') # Display a greeting.
NO:  print('Hello, world!')# Display a greeting.

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

التباعد الرأسي

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

ويشتمل الدليل PEP 8 على العديد من الإرشادات حول إدراج الأسطر الفارغة ضمن الشيفرات، إذ ينص على وجوب فصل كل من الدوال والأصناف بسطرين فارغين، وفصل التوابع الموجودة ضمن الأصناف بسطر فارغ واحد، ويتبع منسّق Black هذه القواعد تلقائيًا، مضيفًا الأسطر الفارغة اللازمة وحاذفًا الزائد منها، ليحوّل مثلًا شيفرة مكتوبة بالشكل:

NO:  class ExampleClass:
         def exampleMethod1():
             pass
         def exampleMethod2():
             pass
     def exampleFunction():
         pass

لتصبح تلقائيًا بالشكل:

YES: class ExampleClass:
         def exampleMethod1():
             pass

         def exampleMethod2():
             pass


     def exampleFunction():
         pass

مثال على التباعد الرأسي

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

لنأخذ على سبيل المثال صنف التحقق من البريد الإلكتروني EmailValidator من الملف validators.py في إطار عمل تطبيق ويب محرك القوالب جانغو، مع ملاحظة أنه من غير الضروري الآن فهم آلية عمل هذه الشيفرة، بل سنركّز على كيفية الفصل ما بين توابع الاستدعاء ()__call__ باستخدام الأسطر الفارغة إلى أربعة مجموعات:

--snip--
    def __call__(self, value):
    1 if not value or '@' not in value:
            raise ValidationError(self.message, code=self.code)

    2 user_part, domain_part = value.rsplit('@', 1)

    3 if not self.user_regex.match(user_part):
            raise ValidationError(self.message, code=self.code)

    4 if (domain_part not in self.domain_whitelist and
                not self.validate_domain_part(domain_part)):
            # Try for possible IDN domain-part
            try:
                domain_part = punycode(domain_part)
            except UnicodeError:
                pass
            else:
                if self.validate_domain_part(domain_part):
                    return
            raise ValidationError(self.message, code=self.code)
--snip--

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

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

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

أفضل الممارسات حيال التباعد الرأسي

لعل إحدى ميزات بايثون غير المعروفة على نطاق واسع هي إمكانية الفصل بين عدة عبارات في السطر واحد باستخدام الفاصلة المنقوطة، بمعنى أنّه مثلًا من الممكن كتابة السطرين:

print('What is your name?')
name = input()

على سطر واحد بشرط الفصل بينهما بفاصلة منقوطة:

print('What is your name?'); name = input()

وكما هو الحال مع استخدام الفاصلة العادية، يجب عدم إضافة مسافة قبل الفاصلة المنقوطة، وإضافة مسافة واحدة بعدها.

أمّا بالنسبة للعبارات البرمجية التي تنتهي بنقطتين رأسيتين، كعبارات if و for و while و def أو جمل بناء الأصناف، فمن الممكن كتابتها على سطر واحد، فمثلًا من الممكن كتابة استدعاء الدالة ()print في الشيفرة التالية:

if name == 'Alice':
    print('Hello, Alice!')

على نفس السطر مع العبارة الشرطية if، بالشكل:

if name == 'Alice': print('Hello, Alice!')

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

وكذلك الأمر بالنسبة لاستيراد الوحدات، إذ من الممكن استيراد عدة وحدات باستخدام أمر واحد في سطر واحد، كما في المثال:

import math, os, sys

ومع ذلك، فإن الدليل PEP 8 يوصي بفصل هذه العبارات، لتتم عملية استيراد كل وحدة في سطر مستقل، بالشكل:

import math
import os
import sys

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

كما ينصح الدليل PEP 8 بتجميع عبارات الاستيراد ضمن ثلاث مجموعات، كما يلي:

  • الوحدات من مكتبة بايثون المعيارية، مثل الوحدة math و os و sys.
  • الوحدات الخارجية، مثل Selenium و Requests و Django.
  • الوحدات الداخلية التي تمثّل جزءًا من البرنامج.

وإجمالًا لا يغير منسق Black من تنسيق الاستيرادات في الشيفرة، نظرًا لكون الإرشادات المتعلقة بالاستيرادات اختيارية.

الخاتمة

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

يمكن عد بناء جمل بايثون البرمجي أمرًا مرنًا من ناحية نمط التنسيق، وفي الواقع في حال لدى كتابتك لشيفرة لن يقرأها أحد سواك، فلك مطلق الحرية بتنسيقها كما تريد، إلا أن معظم أعمال التطوير البرمجية جماعية وليست فردية، فسواءً كنت تعمل مع مبرمجين آخرين على مشروعٍ ما، أو كنت ببساطة ستطرح سؤالًا متعلقًا بشيفرتك على أحد المبرمجين الخبراء طالبًا مساعدته، في كلتا الحالتين يعد تنسيق الشيفرة وفق النمط المقبول المعتمد أمرًا بالغ الأهمية.

إن تنسيق الشيفرات يدويًا ضمن المحررات قد تكون مهمَّة مملة، إذ من الممكن أتمتتها باستخدام أداة مثل Black.

استعرضنا في هذا المقال عددًا من الإرشادات التي يتبعها Black جاعلًا شيفرتك بمقروئية أعلى، بما يتضمّن التباعد الأفقي والرأسي اللذان يجنباننا اكتظاظ الشيفرات، ما يسهل قراءتها بالنتيجة، بالإضافة إلى تحديد العدد الأعظمي من المحارف المتاح للسطر الواحد، إذ يعمل Black على فرض هذه القواعد، مجنبًا الفريق البرمجي أي جدالات محتملة حول آلية التنسيق الأفضل.

لقد استعرضنا في هذا المقال التنسيقات الأساسية التي يجريها Black، ويمكنك الاطلاع على دليل Black الإرشادي لكامل التنسيقات بزيارة black.readthedocs.io.

ترجمة -وبتصرف- للجزء الأول من الفصل الثالث Code Formatting With Black من كتاب Beyond the Basic Stuff with Python لصاحبه Al Sweigarti.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...