تعلم البرمجة باستخدام JavaScript


الدرس: اكتب وظائف نظيفة


الصفحة السابقة

لماذا تعتبر نظافة الكود مهمة؟



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

JavaScript
كود نظيف

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

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

تخيل الآن أنك ورثت الدرج الفوضوي أو الخزانة أو غرفة النوم من شخص آخر لم يعد يعيش هناك. هذا ما يبدو عليه العمل على الكود من شخص لم يحافظ عليه نظيفًا!

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

الآن بعد أن عرفت سبب حاجتك إلى البرمجة بشكل نظيف ، دعنا نرى كيف !

أن تكون وظيفة أو لا تكون



متى يجب استخدام الوظائف؟ كم يجب أن أكتب؟ كم من الوقت يجب أن تكون؟

دعنا نلقي نظرة على بعض المواقف حيث تساعد الوظائف في الحفاظ على نظافة التعليمات البرمجية الخاصة بك.

لا تكرر نفسك


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

يتمثل كود إعادة البناء في تغيير بنية جزء من التعليمات البرمجية دون تغيير سلوكه.

ضع في اعتبارك الكود التالي:


if (firstUser.online) {

 

if (firstUser.accountType === "normal") {

 

    console.log("Hello " + firstUser.name + "!");

 

} else {

 

   console.log("Welcome back premium user " + firstUser.name + "!");

 

}

 

}

 

if (secondUser.online) {

 

if (secondUser.accountType === "normal") {

 

    console.log("Hello " + secondUser.name + "!");

 

} else {

 

   console.log("Welcome back premium user " + secondUser.name + "!");

 

}

 

}

 

if (thirdUser.online) {

 

if (thirdUser.accountType === "normal") {

 

    console.log("Hello " + thirdUser.name + "!");

 

} else {

 

   console.log("Welcome back premium user " + thirdUser.name + "!");

 

}

 

}
 
نحن هنا نكرر نفس المهمة عدة مرات لمستخدمين مختلفين. هذه فرصة جيدة لتضمين الكود الخاص بك في دالة:

const sendWelcomeMessageToUser = (user) => {

 

if (user.online) {

 

if (user.accountType === "normal") {

 

       console.log("Hello " + user.name + "!");

 

} else {

 

      console.log("Welcome back premium user " + user.name + "!");

 

}

 

}

 

}

 

sendWelcomeMessageToUser(firstUser);

 

sendWelcomeMessageToUser(secondUser);

 

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

DRY -Don't Repeat Yourself    (لا تكرر نفسك ) - هو مبدأ البرمجة التي تقلل اكثر ما يمكن تكرار الكود.

تدرب على مبدأ DRY


JavaScript
إليك نشاط حيث يتعين عليك معرفة المكان الذي تتطلب فيه الكود التخصيم ، وكيفية القيام بذلك.

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

ومع ذلك ، في الوقت الحالي ، يتكرر نفس الكود لكل سلسلة. المكان المثالي لوظيفة!

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

الحل المقترح


هل انتهيت ؟ إذن هنا CodePen جديد مع حل.

هل يعرف أي شخص ماذا تفعل هذه الأشياء؟


باستخدام الوظائف التي تقوم بشيء واحد فقط (والتي يصف اسمها ما تفعله) ، يمكنك جعل الكود الخاص بك أكثر وضوحًا وأسهل في الفهم:

دعونا نرى الوظيفة التالية:


const printStringStats = (stringToTest) => {

 

const wordArray = stringToTest.split(" ");



const wordCount = wordArray.length;



let letterCount = 0;



for (let word of wordArray) {



word.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");



letterCount += word.length;



}



const averageWordLength = parseFloat((letterCount / wordCount).toFixed(2));



const stringStats = {



wordCount: wordCount,



letterCount: letterCount,



averageWordLength: averageWordLength



};



console.log(stringStats);



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

الآن دعنا نرى إعادة البناء هذه:


const getWordCount = (stringToTest) => {

 

const wordArray = stringToTest.split(" ");



return wordArray.length;



}



const getLetterCount = (stringToTest) => {



const wordArray = stringToTest.split(" ");



let totalLetters = 0;



for (let word of wordArray) {



word.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");



totalLetters += word.length;



}



return totalLetters;



}



const getAverageWordLength = (stringToTest) => {



return parseFloat((getLetterCount(stringToTest) / getWordCount(stringToTest)).toFixed(2));



}



const printStringStats = (stringToTest) => {



console.log({



wordCount: getWordCount(stringToTest),



letterCount: getLetterCount(stringToTest),



averageWordLength: getAverageWordLength(stringToTest)



})



}
 
على الرغم من أن هذا الإصدار أطول ، إلا أن هناك ثلاث وظائف -   getWordCount  (التي تُرجع عدد الكلمات) ،    getLetterCount  (التي تُرجع عدد الأحرف) ، و    getAverageWordLength  (التي تُرجع متوسط ​​طول الكلمات) - تسمى بواسطة الوظيفة    printStringStats  (التي تطبع إحصائيات السلسلة) .

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

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

ترك تعليقات



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

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


const getWordCount = (stringToTest) => {

 

const wordArray = stringToTest.split(' ');



return wordArray.length;



}



const getLetterCount = (stringToTest) => {



const wordArray = stringToTest.split(' ');



let totalLetters = 0;



for (let word of wordArray) {



// إزالة علامات الترقيم لحساب الأحرف فقط



word.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");



totalLetters += word.length;



}



return totalLetters;



}



/*



** إرجاع متوسط طول الكلمة



** تقريب لأقرب منزلتين عشريتين



*/



const getAverageWordLength = (stringToTest) => {



return parseFloat((getLetterCount(stringToTest) / getWordCount(stringToTest)).toFixed(2));



}



const printStringStats = (stringToTest) => {



console.log({



wordCount: getWordCount(stringToTest),



letterCount: getLetterCount(stringToTest),



averageWordLength: getAverageWordLength(stringToTest)



})


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

اكتب الكود بأسلوب



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

ما في الاسم؟


استخدم اصطلاحات التسمية


كما رأيت حتى الآن ، تتم كتابة أسماء المتغيرات والوظائف في JavaScript عادةً بأحرف الجمل الصغيرة ( getWordCount   ،    numberOfCats  ) ، بينما تتم كتابة أسماء الفئات بأحرف جمل كبيرة (     PremiumAccount  ،    SpecialGuest  ) . ليس عليك استخدام هذه الاتفاقية ؛ ومع ذلك ، فإنه يجعل قراءة التعليمات البرمجية الخاصة بك أسهل لأنها تحظى باحترام الغالبية العظمى من المطورين.

اختر اسمًا


"يجب عليك اختيار اسم متغير بنفس العناية لطفلك الأول."
- روبرت سي مارتن ، الكود النظيف: دليل براعة البرمجيات الرشيقة

الأسماء الواضحة والوصفية للمتغيرات والوظائف أسهل في القراءة من الأسماء المختصرة أو الغامضة أو العشوائية. انظر على سبيل المثال الوظيفة:


const lc = (s) => {

 

const w = s.split(' ');



let l = 0;



for (let wel of w) {



wel.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");



l += wel.length;



}



return l;



}
 
هذه الوظيفة تفعل بالضبط ما يفترض أن تفعله. لكن ماذا تفعل هي؟

100 نقطة إذا تعرفت عليها على أنها وظيفة عد الحروف في مثالنا السابق!


const getLetterCount = (stringToTest) => {

 

const wordArray = stringToTest.split(' ');



let totalLetters = 0;



for (let word of wordArray) {



// إزالة علامات الترقيم لحساب الأحرف فقط



word.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");



totalLetters += word.length;



}



return totalLetters;



}
 
اختر أسماءك بعناية ، وسيكون الكود الخاص بك واضحًا وسهل القراءة (ولن تضطر إلى كتابة الكثير من التعليقات!).

تنسيق التعليمات البرمجية الخاصة بك


يغطي مصطلح تنسيق التعليمات البرمجية العديد من المجالات ؛ وهنا عدد قليل :

  • • مسافة بادئة بعلامات
    جدولة أو مسافات؟ مسافتان أم أربعة؟ مهما كان اختيارك ، احتفظ بنفس الأسلوب في كل مكان:
    
    if (userOnline) {
    
     
    
    for (let message of user.messages) {
    
    
    
    message.send();
    
    
    
    }
    
    
    
    sendNotification();
    
    
    
    }
     
  • التباعد
    تعمل الإصدارات أدناه بالطريقة نفسها:
    
    if(condition) {
    
     
    
    let i=0;
    
    
    
    i+=condition.thing;
    
    
    
    let j=i-3;
    
    
    
    }`
    
    
    
    if (condition) {
    
    
    
    let i = 0;
    
    
    
    i += condition.thing;
    
    
    
    let j = i - 3;
    
    
    
    }
     
    بشكل عام ، ستؤدي إضافة مساحة صغيرة إلى تسهيل قراءة الكود ، لكن كلاهما صحيح من الناحية الفنية. ومع ذلك ، يمكنك اختيار واحد فقط!
  • وضع الأقواس
    
    if (condition) {
    
     
    
    doTheThing();
    
     
    
    } else {
    
     
    
    doTheOtherThing();
    
     
    
    }
    
     
    
    if (condition)
    
     
    
    {
    
     
    
    doTheThing();
    
     
    
    }
    
     
    
    else
    
     
    
    {
    
     
    
    doTheOtherThing();
    
     
    
    }
     
تنسيق الكود هو مصدر الكثير من النقاش بين المطورين ، وغالبًا ما يعتمد على بقية أعضاء فريقك. لكتابة التعليمات البرمجية الخاصة بك ، اختر النمط الذي تفضله والتزم به !

تدرب على كتابة كود نظيف


JavaScript
إليك كود js مع العديد من الوظائف والممارسات السيئة المختلفة التي تجعل الكود غير نظيف. هدفك هو إنشاء وظيفة لجعل التعليمات البرمجية الخاصة بك أخف .

قبل التعليق على الكود ، ستتمكن من العثور على الرمز غير نظيف على CodePen في هذا العنوان  .

حاول أن تجعل الكود نظيفًا بنفسك ، وبعد ذلك يمكنك المقارنة مع الكود النظيف الموجود على CodePen في هذا العنوان

شرح تصحيح التمرين


ينقسم التمرين إلى 3 أجزاء:

الكود ليس DRY


الكود قبل التصحيح:


//variable de différentes personnes
let personne1 = "Jean";
let personne2 = "Paul";
let person3 = "Marcel";

//On met la première lettre en majuscule, on salue la première personne et on donne le nombre de lettre dans son prénom
personne1 = personne1[0].toUpperCase() + personne1.substr(1);
const longueurPrenom1 = personne1.length;
console.log(`Bonjour ${personne1}, ton prénom contient ${longueurPrenom1} lettres`);

//On met la première lettre en majuscule, on salue la deuxième personne et on donne le nombre de lettre dans son prénom
personne2 = personne2[1].toUpperCase() + personne2.substr(1);
const longueurPrenom2 = personne2.length;
console.log(`Bonjour ${personne2}, ton prénom contient ${longueurPrenom2} lettres`);

//On met la première lettre en majuscule, on salue la troisième personne et on donne le nombre de lettre dans son prénom
personne3 = personne3[2].toUpperCase() + personne3.substr(1);
const longueurPrenom3 = personne3.length;
console.log(`Bonjour ${personne3}, ton prénom contient ${longueurPrenom3} lettres`);
 
الكود بعد التصحيح:

//variable de différentes personnes
let personne1 = "Jean";
let personne2 = "Paul";
let personne3 = "Marcel";

function saluer(prenom){
  //On met la première lettre en majuscule, on salue la personne et on donne le nombre de lettre dans son prénom
  const monPrenom = prenom[0].toUpperCase() + prenom.substr(1);
  const longueurPrenom = monPrenom.length;
  console.log(`Bonjour ${monPrenom}, ton prénom contient ${longueurPrenom} lettres`);
}

//On salue les 3 personnes
saluer(personne1);
saluer(personne2);
saluer(personne3);
 
تفسير:

نحن هنا قمنا بتشغيل ثلاثة اسطر لتجهيز كل من 3 أشخاص (     person1  ،   person2  و   person3  ) . لذلك يتم تكرار الرمز 3 مرات مع متغير واحد فقط يتغير. في هذه الحالة ، نقوم بإنشاء وظيفة فريدة   saluer(prenom)  ستقوم بهذه المعالجة بناءً على المتغير   prenom  . كل ما تبقى هو استدعاء الوظيفة 3 مرات مع 3 أشخاص كمعلمات.

الكود ليس مُسمى جيدا


الكود قبل التصحيح:


//tableau des âges des élèves dans la classe

const lrf = [14, 14, 15, 14, 16, 14, 14, 13];

// Nombre d'élèves

const kf = lrf.length;

// variable pour calculer la somme des âges

let mf = 0;

for(let df of lrf){

mf += df;

}

//moyenne d'âge dans la classe

const mld = mf / kf;

console.log('Il y a ' + kf + " élèves dans la classe et la moyenne d'âge est " + mld);
 
الكود بعد التصحيح:

//tableau des âges des élèves dans la classe

const agesElevesDeClasse = [14, 14, 15, 14, 16, 14, 14, 13];

// Nombre d'élèves

const nombreEleves = agesElevesDeClasse.length;

// variable pour calculer la somme des âges

let sommeAges = 0;

for(let age of agesElevesDeClasse){

sommeAges += age;

}

//moyenne d'âge dans la classe

const moyenneAgesDeClasse = sommeAges / nombreEleves;

console.log('Il y a ' + nombreEleves + " élèves dans la classe et la moyenne d'âge est " + moyenneAgesDeClasse);
 
تفسير:

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

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

كود سيء التنسيق


الكود قبل التصحيح:


const temperature = 25;

 

if(temperature < 10){  console.log("Il fait très froid"); }

else if(temperature < 0){

console.log(

"Il fait froid"

);

}else if(temperature < 10){

console.log(            "Il fait frais");

}else if(temperature < 20){

console.log("Il fait doux");

}else if(temperature < 30){

console.log("Il fait bon");

 

 

 

 

}else{

 

 

 

 

 

console.log("Il fait chaud");

}
 
الكود بعد التصحيح:

const temperature = 25;

 

if(temperature < 10){

console.log("Il fait très froid"); }

else if(temperature < 0){

console.log("Il fait froid");

}else if(temperature < 10){

console.log("Il fait frais");

}else if(temperature < 20){

console.log("Il fait doux");

}else if(temperature < 30){

console.log("Il fait bon");

}else{

console.log("Il fait chaud");

}
 
تفسير:

لقد قمنا هنا بتطبيق مسافة بادئة جيدة ، وقمنا بتنسيق فواصل الأسطر للكتل والأقواس   ({})  وتجنبنا المسافات وفواصل الأسطر غير الضرورية.

باختصار



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

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