قراءة التعليمات البرمجية



يستخدم الرمز لإنشاء واجهات. لكن الكود نفسه هو واجهة.


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

في الوقت نفسه ، على وجه اليقين ، كان على الجميع التعامل مع رمز يتوافق مع هذه القواعد ، ولكن لسبب ما نوع من الفوضى.

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

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

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

لماذا هناك حاجة للقراءة


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

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

قراءة النص وقراءة التعليمات البرمجية ليست هي الشيء نفسه.

ترجمت إلى ألكونوست

يستخدم الرمز لإنشاء واجهات. لكن الكود نفسه هو واجهة.

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

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

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

أي رمز هو أسهل لتحرير؟


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

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

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

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

مع وضع ذلك في الاعتبار ، ضع في اعتبارك هذه الأمثلة لمسارات المستخدم:

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

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

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

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

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

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

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




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

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

للاستغناء عن تشغيل الكود ، يجب استيفاء شرطين:

  1. يفهم المستخدم ما يحاول الكود القيام به.
  2. المستخدم متأكد من أن الكود يقوم بما يدعي.

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

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




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

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

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

element.visible = true/false 

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

 element.visibility = .visible/.hidden 

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


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

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

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

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

باختصار: يجب أن تكون الشفرة المقروءة سهلة الاستخدام. و - كأثر جانبي - يمكن أن تبدو جميلة.

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

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

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

 (loaded, playing) 

سوف يسمح المترجم بإدخال قيم غير صالحة

 (loaded: false, playing: true) 

وإذا كنت تستخدم التعداد

 (.buffering/.loaded/.playing) 

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




تم تعطيل المجموعات غير الصالحة مسبقًا ؛ لا يحتاج المستخدمون إلى التفكير في التكوينات غير المتوافقة. لقطة شاشة - Apple

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

  • هل سيكون من السهل على المستخدم البحث عن قطعة الكود المرغوبة؟ هل ستشوش نتائج البحث بوظائف لا علاقة لها بالاستعلام؟
  • هل يمكن للمستخدم ، بعد العثور على الكود اللازم ، التحقق من صحة سلوكه بسرعة؟
  • هل توفر بيئة التطوير تحريرًا آمنًا وإعادة استخدام الرمز؟

باختصار: يجب أن تكون الشفرة المقروءة سهلة الاستخدام. و - كأثر جانبي - يمكن أن تبدو جميلة.

تعليق


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


عن المترجم

تمت ترجمة المقال من قبل Alconost.

تقوم Alconost بترجمة الألعاب والتطبيقات والمواقع بـ 70 لغة. مترجمون من اللغة الأم ، واختبار لغوي ، ومنصة سحابة مع واجهة برمجة التطبيقات ، والتعريب المستمر ، ومديري المشاريع على مدار الساعة وطوال أيام الأسبوع ، أي تنسيق لموارد السلسلة.

نحن أيضًا نصنع مقاطع فيديو للإعلان والتدريب - للمواقع التي تبيع ، الصور ، الإعلانات ، التدريب ، المضايقون ، المستكشفون ، المقطورات لجوجل بلاي ومتجر التطبيقات.

اقرأ المزيد

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


All Articles