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

اختيار أسماء برمجية مفهومة في بايثون


محمد الخضور

"المسألتان الأصعب في علم الحاسوب هما ثلاثة! اختيار الأسماء وحذف أو استبدال محتويات الذاكرة المخبئية cache invalidation وتجنب أخطاء التكرار المنطقية off-by-one" هي إحدى أقدم الدعابات البرمجية، المنسوبة إلى ليون بامبريك والمستوحاة من اقتباس لفيل كارلتون، إلا أنها تشير إلى حقيقة جوهرية، مفادها أن ابتكار أسماء جيدة للمتغيرات والدوال والأصناف وغيرها مما يسمى إجمالًا بالمعرفات ليست بالمهمة السهلة.

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

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

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

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

المتغيرات ذات الأسماء المؤقتة البديلة

عادة ما نستخدم المتغيرات ذات الأسماء المؤقتة البديلة Metasyntactic في المواد التعليمية أو في أمثلة الشيفرات البرمجية كعنصر نائب، إذ نحتاج إلى مجرد اسم فريد للمتغير. فغالبًا ما تسمى المتغيرات في أمثلة بايثون بأسماء عشوائية من قبيل spam و eggs حين يكون اختيار الاسم غير مهم، ولهذا السبب نستخدم في كتابنا هذا النوع من الأسماء في أمثلة الشيفرات التي لا يكون مطلوبًا منك استخدامها في برامجك الفعلية، إذ اقتبسنا هذه الأسماء من مشهد تمثيلي لمجموعة مونتي بايثون البريطانية للكوميديا السيريالية بعنوان البريد العشوائي "Spam (Monty Python sketch)‎".

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

التنسيق المتعلق بحالة الحروف

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

وإحدى هذه الطرق هي طريقة الثعبان مع الحروف الصغيرة snake_case، وفيها نفصل بين الكلمات في اسم المعرف الواحد بشرطة سفلية، والتي تبدو كثعبان متمدد بين الكلمات، وتملي هذه الطريقة على استخدام الحروف الصغيرة بالكامل، عدا في حالات التصريح عن الثوابت، إذ تُستخدم حينها طريقة الثعبان مع أحرف كبيرة UPPER_SNAKE_CASE في الغالب.

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

وطريقة باسكال PascalCase، والتي تُنسب تسميتها إلى استخدامها في لغة البرمجة باسكال، فهي مشابهة لطريقة camelCase إلا أن أول كلمة تبدأ أيضا بحرف كبير.

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

اصطلاحات التسمية وفق دليل بايثون الإرشادي PEP 8

تقدم وثيقة PEP 8 بعضًا من التوصيات حيال اصطلاحات التسميات في بايثون، ومنها:

  • كل الحروف يجب أن تكون وفق نظام الآسكي ASCII، أي حروف إنجليزية بحالتيها الكبيرة والصغيرة دون إشارات الحركات.
  • يجب تسمية الوحدات بأسماء قصيرة وبحروف صغيرة.
  • يجب تسمية الأصناف وفق طريقة PascalCase.
  • يجب تسمية الثوابت وفق طريقة UPPER_SNAKE_CASE.
  • يجب تسمية الدوال والتوابع والمتغيرات وفق طريقة snake_case بحروف صغيرة.
  • يجب تسمية أول وسيط في التوابع باستخدام حروف صغيرة.
  • يجب تسمية أول وسيط في تابع الصنف بالاسم cls وبحروف صغيرة.
  • يجب أن تبدأ السمات الخاصة في الصنف دائما بعلامة الشرطة السفلية.
  • يجب ألا تبدأ السمات العامة في الصنف بعلامة الشرطة السفلية أبدًا.

يمكنك التغاضي عن هذه القواعد وفق الضرورات، فمثلًا وعلى الرغم من كون اللغة الإنجليزية هي المألوفة برمجيًا، إلا أنك تستطيع استخدام محارف أي لغة أخرى، فمثلًا 'コンピューター = 'laptop هي شيفرة برمجية صالحة نحويًا في بايثون، وكذلك يمكن استخدام اللغة العربية كما يلي:

コンピューター = 'laptop'
المنتج = 'laptop'

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

كما يمكنك الاطلاع على قسم "اصطلاحات التسمية" في دليل PEP 8 كاملًا بزيارة python.org.

اختيار الطول المناسب للاسم

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

أسماء قصيرة جدا

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

  • الأسماء المكونة من حرف أو اثنين، كالاسم g الذي يشير عادةً لكلمة تبدأ بهذا الحرف، وما أكثرها! فرغم كون الاختصارات والأسماء المكونة من حرف واحد أو حرفين سهلة للكتابة بالنسبة لك، إلا أنها صعبة القراءة والفهم لغيرك.
  • الاختصارات، فاختصار مثل mon يشير إلى عدد كبير من الكلمات مثل monitor و month و monster وغيرها الكثير.
  • الأسماء المكونة من كلمة واحدة قد تكون غامضة أيضًا، كالاسم start والذي يعني "بداية"، ولكن بداية ماذا؟ إذ يفتقد هذا النوع من الأسماء إلى السياق الواضح عند قراءة الشيفرة من قبل غير كاتبها.

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

وفيما يلي بعض الاستثناءات التي يكون من المناسب فيها استخدام الأسماء القصيرة، فمثلًا من الشائع استخدام i كاسم لمتغير حلقة for التكرارية التي تمر على نطاق من الأعداد أو مؤشرات قائمة ما، كما من الشائع استخدام كلًا من الحرفين j و k (كونهما الحرفان التاليان للحرف i أبجديًا) في حال استخدامك لعدّة حلقات متداخلة، كما في المثال:

>>> for i in range(10):
...     for j in range(3):
...         print(i, j)
...
0 0
0 1
0 2
1 0
--snip--

كما أنّ استخدام الحرفين x و y في تمثيل الإحداثيات الديكارتية يمثّل استثناءً آخر. وفيما عدا ذلك لا أنصح باستخدام أسماء بحرفٍ واحد على الإطلاق، فرغم كونها جذابة للاستخدام، كأن تستخدم الاسم w للدلالة على العرض width والاسم h للدلالة على الارتفاع height والاسم n للدلالة على عدد ما number، إلا أنها لن تكون واضحة ومفهومة للآخرين.

لا تختصر حروفا من شيفرتك المصدرية

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

كما يمكنك استخدام الجمل القصيرة في التسمية بغية زيادة مقروئية شيفرتك، كأن تستخدم الإنجليزية العادية، فمثلًا الاسم number_of_trials الذي يشير إلى عدد المحاولات، ذو مقروئية أعلى من الاسم number_trials.

أسماء طويلة جدا

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

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

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

استخدام البادئات في الأسماء

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

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

ولكن ومن ناحية أخرى، فإنّه من المفيد استخدام بادئات من قبل is بمعنى "أهو؟ أو هو يكون" و has بمعنى "لديه أو ذي" ضمن أسماء المتغيرات المُتضمنة لقيم منطقية أي من النوع Boolean، أو ضمن أسماء الدوال والتوابع التي تعيد قيمًا منطقية، لما لذلك من دور في زيادة المقروئية، فمثلًا في المثال التالي، لاحظ استخدام متغير باسم is_vehicle بمعنى "فإنه مركبة" وتابع باسم ()has_key بمعنى "يملك المفتاح":

if item_under_repair.has_key('tires'): 
  is_vehicle = True

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

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

فمثلًا، فُقد مسبار المريخ الفضائي الآلي المداري عام 1999 بسبب اختلاف وحدات قياس الحسابات الناتجة عن البرمجيات التي أنتجتها شركة Lockheed Martin والتي استخدمت وحدات القياس البريطانية، وتلك الناتجة عن أنظمة وكالة الفضاء الدولية (ناسا) والتي استخدمت وحدات القياس المترية، ما أدى كنتيجة إلى تحديد المسار بشكل خاطئ، وخسائر قدرت بنحو 125 مليون دولار أمريكي.

اللاحقات الرقمية المتتالية

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

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

كذلك الأمر بالنسبة للدوال ذات الأسماء من قبيل (makePayment1(amount و(makePayment2(amount وهكذا، والتي يجب استبدالها بدالة وحيدة تقبل وسيطًا من النوع عدد صحيح، ليصبح استدعاؤها بالشكل: (makePayment(1, amount و(makePayment(2, amount وهكذ.

أما في حال كون تلك الدوال ذات وظائف مختلفة، بما يفرض استخدام دوال مستقلة، فمن الحري بنا في هذه الحالة استبدال الرقم في الاسم بما يوضح دور الدالة، مثل:

  • (makeLowPriorityPayment(amount لتدل على المدفوعات ذات الأولوية الأقل
  • (makeHighPriorityPayment(amount للدلالة على المدفوعات ذات الأولوية الأعلى
  • (make1stQuarterPayment(amount للدلالة على مدفوعات الربع الأول من السنة
  • (make2ndQuarterPayment(amount للدلالة على مدفوعات الربع الثاني من السنة

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

استخدم أسماء يسهل البحث عنها

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

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

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

تجنب النكات والتورية والإشارات الثقافية

خلال عملي -يقول المؤلف- في إحدى شركات تطوير البرمجيات، صادفتني دالة باسم ()gooseDownload، ولم يكن لدي أي تصور حول ما تعنيه، "تنزيل الإوزة!" إذ لم يكن للمنتج الذي نعمل عليه أي صلة بالطيور أو تحميل الطيور، ولدى إيجادي لشريك العمل الأقدم الذي كتب هذه الدالة، شرح لي بأن كلمة إوزة هنا يُقصد بها فعل وليس اسم، كما في الجملة goose the engine (بمعنى تهيئة محرك السيارة بإعطاءه دفعة كبيرة من الوقود مُصدرًا صوتًا يشبه صوت الإوزة).

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

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

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

ولعل الإجراء الأفضل هو كتابة شيفرتك بطريقة تجعل أي متحدث غير ناطق بالإنجليزية يفهمها بسهولة، فلتكن طريقتك مهذبة ومباشرة وبعيدة عن روح الدعابة، فبلا شك قد ظن زميلي السابق في العمل أن طرفته حول الإوزة ()gooseDownload مضحكة، ولكن في الواقع العدو الأكبر للنكات؛ شرحها.

لا تستخدم الأسماء المحجوزة

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

>>> list(range(5))
[0, 1, 2, 3, 4]
1 >>> list = ['cat', 'dog', 'moose']
2 >>> list(range(5))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'list' object is not callable```

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

ولمعرفة فيما إذا كان اسمًا معينًا محجوزًا في بايثون أم لا، يكفي كتابته ضمن الصدفة التفاعلية أو أن نحاول استيراده، فلو حصلنا على أحد الخطأين NameError أو ModuleNotFoundError، فهذا يعني أن الاسم غير محجوز، فمثلًا الأسماء open و test محجوزة في بايثون، في حين spam و eggs ليست كذلك:

>>> open 
<built-in function open >
>>> import test
>>> spam 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'spam' is not defined
>>> import eggs 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'eggs'

ومن أشهر الكلمات المحجوزة التي يستخدمها المبرمجون خطأً هي:

all any data email file format hash id input list min max object open random set str sum test type

فلا تستخدم هذه الأسماء للمعرفات بأنواعها.

ومن الأخطاء الشائعة أيضًا، تسمية ملفات بايثون (ذات اللاحقة ‎.py) بنفس أسماء الوحدات الخارجية، فعلى سبيل المثال في حال تثبيتك للوحدة الخارجية Pyperclip مع وجود ملف بايثون بنفس الاسم أي pyperclip.py، فإن تعليمة استيراد pyperclip ستسورد ملف بايثون صاحب هذا الاسم بدلًا من الوحدة الخارجية، وفي حال استدعائك لإحدى دوال الوحدة pyperclip كالدالة ()copy أو ()paste فستظهر رسالة خطأ مفادها أن هذه الدوال غير موجودة.

>>> # Run this code with a file named pyperclip.py in the current folder.
>>> import pyperclip # This imports your pyperclip.py, not the real one.
>>> pyperclip.copy('hello')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'pyperclip' has no attribute 'copy'

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

أسوأ أسماء المتغيرات على الإطلاق

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

فلطفًا لو احتجت لمتغير يعبّر عن التباين الاحصائي لبيانات درجة الحرارة، اختر الاسم temperatureVariance غير مباليًا بدلالات الثلاثي الشهير tempVarData.

الخاتمة

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

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

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

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

ترجمة -وبتصرف- للفصل الرابع 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.


×
×
  • أضف...