يقرأ كود نقي مثل نثر مكتوب بشكل جيد.
جرادي بوتش في كود النظيفة
Rebus كرمز

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

الرمز يشبه السند
رمز البرنامج لديه شيء مشترك مع rebus: لديه أيضًا "ماذا" و "كيف". كما يجب أحيانًا فك تشفيرها.
إن "ماذا" من التعليمات البرمجية هو غرضها ومعناها وتأثيرها والنتيجة النهائية التي نتوقعها منها.
ما الذي
يفعله بالضبط.
"كيف" من المدونة - بأي طريقة ملموسة ستفي بـ "ماذا" ، مع ما هي التعيينات والمضاعفات والمقارنات المحددة ؛ تنفيذ الخوارزمية ، تعليمات للمعالج. إنها لغة رمز مسموح بها ، ترسانتها من الوسائل التعبيرية.
يتحدث مارتن فاولر عن الأمر بهذه الطريقة (
"طول الوظيفة" ،
الأصلي ):
عملت سمالتالك في تلك السنوات على الآلات السوداء والبيضاء. إذا كنت بحاجة إلى تسليط الضوء على النص أو الرسومات ، كان عليك عكس الفيديو. احتوت الفئة في Smalltalk ، المسؤولة عن الجدول ، على طريقة "تمييز" ، وفي تنفيذها كان هناك سطر واحد فقط - استدعاء لأسلوب "عكس". كان اسم الطريقة أطول من التطبيق ، ولكن لا يهم ، لأن هناك مسافة كبيرة بين نية وتنفيذ هذا الكود.
هنا تسليط الضوء على "ماذا". في مصطلحات مارتن -
النية : "إبراز جزء من الصورة". يعبر الاسم عن وظيفة هذه الوظيفة. العكس هو كيفية
التنفيذ .
كيف يتم تنفيذ التظليل بالضبط (باستخدام عكس الصورة). هذا هو الفرق بين "ماذا" و "كيف".
على الرغم من حقيقة أن اسم الطريقة أطول من تنفيذها ، فإن وجود مثل هذه الطريقة منطقي لسبب بسيط للغاية. عندما نرى مكالمة عكسية في الشفرة ، يجب أن نفهم أو نتذكر أن عكس الصورة يستخدم لجعل هذه الصورة أكثر وضوحًا. عندما نرى تسليط الضوء ، نقرأ فقط: "اجعل هذا الجزء أكثر وضوحًا." في الحالة الأولى ، ننفق القليل من الجهد العقلي لفهم المهمة المعينة للكود ، في الحالة الثانية - لا. في الحالة الأولى ، نرى أمامنا توبيخًا يتطلب فك التشفير ، في الحالة الثانية - قصة بلغة مفهومة.
المبرمج ، عندما يكتب برنامجًا ، يشبه السخرية. يقوم المبرمج بتشفير الوصف البشري للخوارزمية باستخدام أدوات لغة البرمجة المتاحة (أكثر بدائية من اللغة البشرية). تشفير "ماذا" بـ "كيف". وفي وقت لاحق ، يقرأ هو أو زميله الشفرة ، ويفك رموز
هذه إعادة الترميز الوصف الأولي للخوارزمية.
إذا لم نتمكن أثناء عملية قراءة الكود من فهم النتيجة التي سيؤدي إليها تنفيذ كل جزء على الفور ، أي الغرض من الكود ، ومعنى هذا الكود ، فإن هذا الكود هو عبارة عن توبيخ ، ويجب إعادة كتابته بلغة واضحة.مشكلة الألغاز في الكود هي أنهم يحتاجون
دائمًا إلى جهد عقلي. حتى إذا لم نقم بتنفيذ مجموعة كاملة من عمليات فك التشفير في أذهاننا ، ولكن فقط نتذكر بغباء معنى بعض التوبيخ ، فإنه سيظل يخلق حمولة: أولاً ، لتذكر معناها ، وثانيًا ، في وقت تسجيل التحول rebus في هذه القيمة.
فك شفرة إعادة الكتابة أثناء قراءة الرمز هو التحول العقلي للغاية الذي يتحدث عنه Tim Ottinger في كتاب Clean Code. صحيح أنه يناقشها في سياق تعيين أسماء واضحة للمتغيرات ، لكن المشكلة تتأثر بنفس الشيء بالضبط. كلمة إلى تيم:
كقاعدة عامة ، المبرمجون أذكياء جدًا. ويحب الأشخاص الأذكياء أحيانًا إظهار قوة الذكاء ، مما يدل على قدرتهم على التلاعب عقليًا. في النهاية ، إذا كنت تتذكر أن المتغير r يحتوي على عنوان URL مع مضيف بعيد ونظام تم تحويله إلى أحرف صغيرة ، فهذا يدل بوضوح على عقلك.
أحد الاختلافات بين المبرمج الذكي والمحترف هو أن المحترف يفهم: الوضوح أمر بالغ الأهمية. يستخدم المحترفون قوتهم من أجل الخير وكتابة التعليمات البرمجية التي يمكن فهمها من قبل الآخرين.
يمكن أن تتحول حتى حمولة صغيرة من كل rebus إلى مشكلة إذا كان هناك العديد من هذه rebuses. من المحتمل أنك صادفت رمزًا تكون قراءته مرهقة ببساطة.
اعرف: اللوم في الكود هو المسؤول عن التعب. تؤدي التفاقمات إلى تفاقم إرهاق حتى مؤلفها مباشرة في عملية كتابة التعليمات البرمجية. بعد كل شيء ، أثناء كتابة التعليمات البرمجية ، يقوم المبرمج أيضًا بإعادة قراءة ما تم كتابته باستمرار. على الرغم من حقيقة أن المؤلف لا يقوم بفك تشفير الألغاز الخاصة به ، ولكنه يتذكر ببساطة ، أنها لا تزال تخلق عبئا. الفخ هو أن
المؤلف ببساطة لا يرى الألغاز في التعليمات البرمجية الخاصة به ! حاول أن تتخيل مقدار الجهد العقلي الذي يمكنك توفيره في المساء ، إذا بدأت في التخلص من الألغاز في شفرتك في الصباح!
لذلك ، للحد من التعب من كتابة وقراءة التعليمات البرمجية ، تحتاج إلى تجنب الألغاز. ولكن كيف نفعل ذلك؟
لغة الكود. قوة المعرف
أتفق مع تصريح جرادي بوتش بأن الشفرة النظيفة تقرأ مثل النثر الجيد. هذا شرط ضروري ، وإن لم يكن كافياً. سيفهم معظمنا بشكل بديهي ما هو على المحك ، لكني أود أن أحصل على الأقل على تعريف: ما هو - النثر الجيد.
سألت زملائي الكتاب: كيف يختلف النثر الجيد عن النثر السيئ؟ أجاب الجميع بشكل مختلف ، لكنهم بطريقة ما أكدوا على أهمية اللغة: يجب أن تكون غنية ، يجب أن تخلق صورًا واضحة في ذهن القارئ وروحه. عندما يكون لدى القارئ بسهولة صورة واضحة أراد المؤلف رسمها له ، فإننا نتعامل مع النثر الجيد.
يخبر الكود المعالج ما يجب أن يفعله. رمز جيد في نفس الوقت يخبر المبرمج - علاوة على ذلك ، بصدق! - ماذا يفعل هنا. أي أنها تحدد خوارزمية لها أقرب ما يمكن من الطريقة التي كان بها المؤلف نفسه قد فعلها بلغة طبيعية. يجب أن تعمل شفرتنا بشكل جيد للغاية ، وإلا فقد يأتي
مجنون إلى منزلنا. لا يجب أن يكون الرمز rebus.
ما هي الأدوات التي يمتلكها الكود لكي لا تكون كومة؟
سوف يفهم الشخص بسهولة قصة نيابة عن الكود إذا كان الكود نفسه يتحدث بلغة بشرية. لا يمكن تحقيق ذلك إلا بمساعدة المعرّفات: أسماء الوظائف والفئات والمتغيرات والثوابت - لأنه
فقط في المعرّفات يمكننا استخدام أي كلمات من اللغة البشرية التي نحتاجها .
بالطبع ، الكلمات الرئيسية في لغة البرمجة هي أيضًا كلمات بشرية ، لكن مفرداتهم بائسة جدًا. شيء مثل لغة Ellochka the Ogre - لا يمكنك كتابة نثر جيد عليها.
لذلك ، من الضروري أن يحتوي رمز البرنامج على أكبر عدد ممكن من المعرّفات المختارة بشكل صحيح. بحيث يشكل مجموعهم النثر المكتوب بشكل جيد للغاية.
شاهد مدى سهولة قراءة سطور التعليمات البرمجية عند اختيار أسماء المتغيرات والأساليب بشكل جيد:
pageData.hasAttribute("Test") dom_tree.to_html() emails_str.split(',')
بالنظر إلى هذه العبارات القصيرة ، من السهل فهم ما يتحدثون عنه. نحن نعرف النتيجة التي نحصل عليها ، لأن المحددات تخبرنا عنها. تخيل الآن أنه في كل مكان يتم فيه تنفيذ هذه المكالمة - إلى أي مدى ستنخفض سرعة قراءة هذا الرمز "المشفر"؟
العديد من أبسط تقنيات إعادة الهيكلة: الثوابت المسماة ، واختيار طريقة ، واستبدال متغير باستدعاء أسلوب ، ومتغير تفسيري ، وتقسيم متغير مؤقت ، وما إلى ذلك ، كلها تدور حول
كيفية جعل الشفرة تتحدث اللغة البشرية ، وبعبارة أخرى ، كيفية تجنب الألغاز .
طريقة Rebus
عندما قرأت Pure Code ، كنت أقوم بزيارة دورية للفكر: "ماذا بحق الجحيم!".
من ذروة 40 عامًا من الخبرة ، يقدم لنا روبرت مارتن نصائح حول كيفية جعل الشفرة أفضل. على سبيل المثال:
القاعدة الأولى: يجب أن تكون الوظائف مضغوطة. القاعدة الثانية: يجب أن تكون الوظائف أكثر إحكاما.
ثم يعترف بأنه لا يستطيع إثبات ادعاءه علميا. بصراحة ، غير علمي ، هو أيضا ضعيف. بدأ شرط ضغط الوظيفة يبدو وكأنه عقيدة - ولهذا السبب لم يهدأ
الجدل حول مسألة طول الوظيفة لعدة عقود.
ويعرض بوب أيضًا كتابة كل وظيفة بحيث تؤدي عملية واحدة فقط. علاوة على ذلك ، ما هي هذه العملية الواحدة - ليست واضحة أيضًا. علينا أن ندعو إلى المساعدة على مبدأ مستوى واحد من التجريد ، مما يزيد من إرباك الوضع. كل هذا ضبابي جدا.
مارتن فاولر أكثر واقعية.
يبدو لي أن الجدل حول الفصل بين النية والإدراك له معنى أكبر. إذا كنت ، عند النظر إلى جزء من الرمز ، تحتاج إلى بذل جهد لفهم ما تفعله ، فأنت بحاجة إلى وضعه في وظيفة وإعطائه اسمًا وفقًا لـ "ماذا". ثم في المرة القادمة سيكون الغرض من الوظيفة واضحًا على الفور ، وفي معظم الحالات لن تهتم بكيفية قيام الوظيفة بوظيفتها.
الأصللكن الحجة الأكثر منطقية بالنسبة لي هي الفصل بين النية والتنفيذ. إذا كان عليك بذل جهد في النظر إلى جزء من التعليمات البرمجية لمعرفة ما تقوم به ، فيجب عليك استخراجه في وظيفة وتسمية الوظيفة بعد ذلك "ماذا". وبهذه الطريقة عندما تقرأها مرة أخرى ، فإن الغرض من الوظيفة يقفز إليك مباشرة ، وفي معظم الوقت لن تحتاج إلى الاهتمام بكيفية تحقيق الوظيفة للغرض منها - وهو جسم الوظيفة.
أفضل بالفعل. ترى الآن ما أراد مارتن أن يقوله في هذا المقطع؟ قصده: دعنا نزيل الألغاز. دع الكود نفسه يخبرنا ما ستكون النتيجة ، وكيف - دعه يكون مخفيًا في مكان آخر بعيدًا ، في تعريف الوظيفة. دعونا يتم فك تشفير جميع الألغاز. لا ألغاز - لا جهد.
في أي حال من الأحوال يجب عليك تطبيق طرق إعادة بناء عمياء. هذا أمر واضح للغاية ، ولكن كيف نفهم متى تكون إعادة البيع ضرورية بالفعل ، ومتى لا؟
تقول طريقة إعادة التوطين: إذا لم يختف التراجع بعد إعادة التعمير ، فلا حاجة إلى إعادة الهيكلة .
إذا لم تتمكن من العثور على اسم لوظيفة جديدة تشرح بوضوح ما يحدث فيها ، فمن الجائز أنك تفعل شيئًا خاطئًا هنا. حاول تحديد جزء رمز مختلف قليلاً في الوظيفة - حيث يمكنك العثور بسرعة على اسم قصير ومفهوم.مثال على فك الألغاز في الكود (غير ناجح للغاية)
على هذا النحو ، سأذكر جزءًا من كتاب "Clean Code" الذي أعجبني. قبل إعادة الهيكلة ، نرى رمزًا مليئًا بالألغاز. تم إجراء إعادة الهيكلة من قبل مؤلف الكتاب وفقًا لقواعد الكود الجيد الذي روج له ، و- مجرد مصادفة - يبدو الكود المعاد تشفيره تمامًا مثل الكود الذي يتم فيه فك الترميز.
قام مؤلف إعادة الهيكلة بتطبيق معرفات قابلة للقراءة بشكل كامل (أسماء الفئات والأساليب والمتغيرات) للإشارة إلى ما يفعله الرمز بالفعل. إنه لأمر مؤسف أنه لم يتم بنجاح في كل مكان ، وفي بعض الأماكن ظهرت ألغاز جديدة بدلاً من الألغاز السابقة.
على سبيل المثال ، طريقة التضمين الأكثر استخدامًا في هذا المقطع
private void include(String pageName, String arg) throws Exception { WikiPage inheritedPage = findInheritedPage(pageName); if (inheritedPage != null) { String pagePathName = getPathNameForPage(inheritedPage); buildIncludeDirective(pagePathName, arg); } }
الاسم لا يعكس على الإطلاق ما يحدث في التنفيذ. ماذا يشمل وأين؟
بالنظر إلى استدعاء هذه الطريقة:
include("TearDown", "-teardown");
من المستحيل تحديد النتيجة التي سيحققها صاحب الكود هنا.
التالي: ماذا يفعل buildIncludeDirective؟ إذا حكمنا من خلال الاسم ، فيجب عليه أن يضع نوعًا من توجيه الإدماج ، وماذا بعد؟ تعيدها؟ لكن لا. يضيفها على الفور إلى النتيجة الإجمالية.
وهنا تحديث آخر PageContent. ماذا يخبرنا updatePageContent عن النتيجة التي نحصل عليها بعد استدعاء الطريقة؟ لا شيء. بعض محتوى الصفحة هناك سيتم استبداله بأحد لا يعرف ماذا. لماذا تم إعادة الهيكلة تسمى استخلاص الطريقة هنا؟ هل ساعد في التخلص من التوبيخ؟ لم يساعد ، ولكن فقط ارتبك أكثر من الرمز. هنا لدينا الحالة التي يفضل فيها جسم الطريقة. البناء
pageData.setContent(newPageContent.toString());
أكثر وضوحا من التحديث المشفر PageContent ().
كوسيلة ترفيه ، أقترح على القراء البحث عن الأماكن السيئة الأخرى في
الرمز المعاد صياغته .
لتبرير بوب ، يمكنني القول أن هذا الرمز لم يعد في الإصدار الحالي من FitNesse. على ما يبدو ، بدوره ، تم إعادة هيكلته مرة واحدة.
الخلاصة
طول الوظيفة غامض للغاية وهو معيار لتحديد جودة الوظيفة. "الوظائف القصيرة" لا تساوي "الوظائف الجيدة". طول الوظيفة ليس معيارًا ، ننسى كل شيء.
يجب أن يعطي الكود الجيد إجابات على أسئلة المبرمج - لماذا هو (الكود) هنا ، ما
الذي يفعله هنا
بحق الجحيم ،
إنه يحقق النتيجة. يمكن تقديم هذه الإجابات فقط باستخدام المعرّفات.
كمثال على نوع الإجابات التي لا يجب أن تعطيها الشفرة ، أريد أن أقدم مقتطفًا من كتاب ممتع واحد.
قال ببطء "أنا رونان ، فكتور الشر". - وهذا هو تارل. نريدك بعض
اطرح الأسئلة. إذا كذبت ، تموت. حسنًا
"أنا ، عمي ، إلى الأبد ،" تنفس. - من فضلك. سأقول كل شيء.
وتابع رونان: "هذا أمر جيد". - الاسم؟
- رونان ، الفائز في الشر.
- نعم ، ليس لي ، أيها الأحمق!
أجاب الفتى باعتذار "آه ، نعم ، ثم تارلي".
- وليس لي! تارل تمتم. - اسمك ، نادي! الاسم الأول!
تمتم Orc "الاسم هو الاسم الذي أستخدمه لتمييز نفسي عن الآخرين".
- حسنًا ، أعط هذا الاسم هنا! صاح يارل.
فجر Orka فجأة.
- آه! بثرة!
"لذا يا بثرة ، ماذا تفعل هنا؟"
جاء الجواب الصادق: "أضعها في سروالي".
تجعد رونان من أنفه بالاشمئزاز.
"لا ، أسأل ما الذي تفعله عصابة العفاريت هنا!"
استدارت عيون البثور بسرعة ، ونظرت حول المشهد.
تمتم "معظم الناس بلا رأس هنا".
لمست Tarle رونان على الكتف.
قال لي بثقة: "دعني أحاول" ، والتفت إلى "أوركا" الخائفة. - قل لي ،
بثرة ، "لماذا ، أنت هنا؟"
- أوه ، عمي ، ولا تسأل. الفلسفة الوجودية بالنسبة لي ليست سوى غابة مظلمة.
"استمع ، أنت تجشؤ التنين" ، دمدم بكتم. - كان لديك عصابة من العفاريت الخاصة
سبب المجيء إلى هنا. ما الأمر ، في الغابة؟
- هناك الكثير من الأشجار.
انتفخت عيون رونان ، واستدار تارلي. بدأت البثور ، وهي تشعر بأنها لم تعط الإجابة المتوقعة ، بالتمتم أكثر.
- وإذا كنت تريد أن تعرف السبب ، وليس عن الغابة ، فذلك كله لأن ذلك الشخص في الحانة
دفع لنا أن نأتي هنا ونقتلك.
جيمس بيبي ، رونان البربري