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

يجب أن تكون الشيفرة البرمجية مرتبة ونظيفة وسهلة القراءة قدر الإمكان.

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

الصياغة

في الصورة أدناه يوجد صفحة تحوي بعض القواعد المهمة في تركيب الشيفرات البرمجية.

code-style.png

سنناقش هذه القواعد وأسبابها بالتفصيل.

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

الأقواس المعقوصة (Curly Braces)

تُكتب الأقواس المعقوصة في معظم مشاريع JavaScript المعقوصة بالطريقة "المصرية" بوضع قوس الفتح في نفس السطر الذي يحوي الكلمة المفتاحية - ليس في سطر جديد. يجب وضع مسافة قبل القوس الافتتاحي كما يلي:

if (condition) {
  // افعل هذا
  //…. وذاك
  //…. وذاك
}

التعليمة المكونة من سطر واحد مثل if(condition) doSomething()‎ تعد حالة طرفية مهمة، فهل يجب استخدام الأقواس فيها؟

فيما يلي بعض البدائل المشروحة. يمكنك قراءتها والحكم على درجة سهولة قراءتها بنفسك:

1- يقوم بعض المبتدئون أحيانًا بما يلي. ما يعد ممارسة خاطئة. فلا حاجة لِلأقواس المعقوصة هنا:

if (n < 0) {alert(`Power ${n} is not supported`);}

2- الانتقال إلى سطر جديد بدون استخدام أقواس. تجنب هذا الأمر لأنه يسبب بعض الأخطاء:

if (n < 0)
  alert(`Power ${n} is not supported`);

3- سطر واحد بدون أقواس يُعد مقبولا في حال كان السطر قصيرًا:

if (n < 0) alert(`Power ${n} is not supported`);

4- أفضل الطرق:

if (n < 0) {
  alert(`Power ${n} is not supported`);
}

يمكن استخدام سطر واحد في حالة الشيفرات البرمجية المختصرة مثل: if (cond) return null. لكن استخدام شيفرة برمجية كتلية (كما في رقم 4) هو الأفضل من ناحية سهولة القراءة.

طول السطر

لا يحب أحدٌ قراءة سطر برمجي طويل. أصبح فصل الأسطر الطويلة ممارسة عامة لدى الجميع.

إليك المثال التالي:

// تسمح أقواس الفاصلة العليا المائلة ` بتقسيم النص إلى عدة أسطر
let str = `
  Ecma International's TC39 is a group of JavaScript developers,
  implementers, academics, and more, collaborating with the community
  to maintain and evolve the definition of JavaScript.
`;

بالنسبة للتعليمة البرمجية if:

if (
  id === 123 &&
  moonPhase === 'Waning Gibbous' &&
  zodiacSign === 'Libra'
) {
  letTheSorceryBegin();
}

يتم الاتفاق على الحد الأقصى لطول السطر البرمجي على مستوى فريق العمل. يكون طول السطر البرمجي غالبا 80 أو 120 محرفَا.

مسافة البادئة

يوجد نوعان من البادئة "Indents":

  • البادئة الأفقية: 2 أو 4 مسافات:

تُصنع البادئة الأفقية بوضع 2 أو 4 مسافات أو باستخدام رمز البادئة الأفقية (الزر Tab). وُجدت اختلافات قديمة حول أيهما أفضل، لكن المسافات هي الأكثر شيوعا هذه الأيام.

تتميز المسافات عن الزر Tab بكونها أكثر مرونة أثناء التعديل. مثلًا، يمكننا إزاحة المتغيرات داخل قوس مفتوح كالتالي:

show(parameters,
     aligned, // 5 spaces padding at the left
     one,
     after,
     another
  ) {
  // ...
}
  • البادئة العمودية: الأسطر الفارغة لفصل الشيفرات البرمجية إلى أجزاء منطقية:

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

function pow(x, n) {
  let result = 1;
  //              <--
  for (let i = 0; i < n; i++) {
    result *= x;
  }
  //              <--
  return result;
}

يمكنك وضع سطر فارغ حيثما تريد لجعل الشيفرة البرمجية مقروءة بسهولة. لا يجب أن يوجد أكثر من 9 أسطر بدون بادئة عمودية.

الفواصل المنقوطة ";"

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

يوجد بعض اللغات حيث يكون استخدام الفاصلة المنقوطة اختياريا وتُستخدم نادرا. لكن في بعض الحالات في JavaScript لا يحل السطر الجديد محل الفاصلة المنقوطة مما يجعل الشيفرة البرمجية عرضة للخطأ. يمكنك الاطلاع أكثر عن ذلك في جزء بنية الشيفرة البرمجية.

إن كنت مبرمجًا متمرسًا في JavaScriptK، يمكنك اختيار نمط تكويد بدون فاصلة منقوطة مثل StandardJS. أو يُفَضَّل استخدام فواصل منقوطة لتجنب الأخطاء. أغلب المبرمجين يضعون فواصل منقوطة.

مستويات التداخل

تجنب تداخل الشيفرة البرمجية للعديد من المستويات. مثلًا، في الحلقة المتكررة يُفَضَّل استخدام التعليمة continue لتجنب التداخل العميق.

مثلا، بدلا من إضافة if شرطية داخلية كالتالي:

for (let i = 0; i < 10; i++) {
  if (cond) {
    ... // <- مستوى تشعيب إضافي
  }
}

يمكننا كتابة:

for (let i = 0; i < 10; i++) {
  if (!cond) continue;
  ...  // <- لا مزيد من التشعيبات
}

يمكن استخدام الأسلوب ذاته مع if/else و return. مثلًا، نحتاج لجزئين في المثال أدناه.

خيار 1:

function pow(x, n) {
  if (n < 0) {
    alert("Negative 'n' not supported");
  } else {
    let result = 1;

    for (let i = 0; i < n; i++) {
      result *= x;
    }

    return result;
  }
}

خيار 2:

function pow(x, n) {
  if (n < 0) {
    alert("Negative 'n' not supported");
    return;
  }

  let result = 1;

  for (let i = 0; i < n; i++) {
    result *= x;
  }

  return result;
}

يُعد الخيار 2 أسهل قراءةً من الخيار 1 لأن الحالة الخاصة n < 0 فُحصت مسبقًا. بعد فحص قيمتها يمكننا الانتقال إلى جزء الشيفرة البرمجية الرئيسية بدون الحاجة لتداخل أكثر.

موضِع الدوال

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

1- تعريف الدوال أعلى الشيفرة البرمجية التي تستخدمها:

// تعريفات الدوال
function createElement() {
  ...
}

function setHandler(elem) {
  ...
}

function walkAround() {
  ...
}

// الشيفرة التي تستخدمها
let elem = createElement();
setHandler(elem);
walkAround();

2- الشيفرة البرمجية أولا ثم الدوال:

// الشيفرة التي تستخدم الدوال
let elem = createElement();
setHandler(elem);
walkAround();

// --- دوال مساعدة ---
function createElement() {
  ...
}

function setHandler(elem) {
  ...
}

function walkAround() {
  ...
}

3- الطريقة المختلطة: تُعرَّف الدالة في أول مكان تستخدم فيه.

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

شروحات لأنماط كتابة الشيفرة

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

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

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

بعض الخيارات الشهيرة:

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

منقحات الصياغة التلقائية (Automated Linters)

منقحات الصياغة (Linters): هي عبارة عن أدوات يمكنها فحص نمط الشيفرة البرمجية تلقائيا واقتراح تعديلات لتحسينها.

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

هنا بعض أدوات تنقيح الصياغة المعروفة مثل:

  • JSLint – تُعد من أدوات تنقيح الصياغة الأولى.
  • JSHint – تحوي اعدادات أكثر من JSLint.
  • ESLint – الأحدث تقريبا.

كلها تؤدي الغرض ذاته. الكاتب هنا يستخدم ESLint. معظم هذه الأدوات تكون مدمجة مع العديد من المحررات الشهيرة: يجب عليك أن تُفَعِّل الإضافة في المحرر وتحدد نمط التكويد الذي تريده.

مثلا، لاستخدام ESLint اتَّبع ما يلي:

  1. ثبت Node.js.
  2. ثبت ESLint باستخدام الأمر npm install -g eslint (يُعد npm مُثَبِّت حزم JavaScript).
  3. أنشئ ملف إعداد وسمِّه "‎.eslintrc" في ملف مشروع JavaScript الرئيسي (الملف الذي يحتوي على جميع الملفات).
  4. ثبت/فعِّل الإضافة لمحررك الذي يدعم ESLint. معظم المحررات تدعم ESLint.

هنا مثال على ملف "‎.eslintrc":

{
  "extends": "eslint:recommended",
  "env": {
    "browser": true,
    "node": true,
    "es6": true
  },
  "rules": {
    "no-console": 0,
    "indent": ["warning", 2]
  }
}

التعليمة "extends" هنا تعني أن الإعداد يعتمد على مجموعة إعدادات ESLint الافتراضية "eslint:recommended". يُمكننا تعديل الإعدادات التي نريدها لاحقًا.

يمكن أيضا تنزيل مجموعة قواعد نمط التكويد وتوسيعها بدلا من ذلك. انظر في الرابط http://eslint.org/docs/user-guide/getting-started للمزيد من التفاصيل حول كيفية التثبيت.

تحتوي بعض المحررات على منقح صياغة مدمج فيها إلا أنها ليست بدقة ESLint.

الخلاصة

تهدف جميع قواعد بناء الجمل في هذا الفصل (وفي باقي مراجع أنماط التكويد) لرفع مستوى سهولة قراءة الأكواد. وجميع القواعد قابلة للنقاش.

عند التفكير في كتابة شيفرة برمجية بشكل أفضل، يجب أن نسأل أنفسنا: "ما الذي يجعل الشيفرة البرمجية أسهل للقراءة والفهم؟" و "ما الذي قد يساعدنا لتجنب الأخطاء؟" يوجد العديد من الأشياء التي يجب الانتباه لها أثناء اختيار نمط تكويد معين.

سيتيح لك قراءة العديد من أنماط التكويد معرفة أحدث الأفكار عن أنماط التكويد وأفضل الممارسات.

تمارين

نمط تكويد سيء

الأهمية: 4

ما الخطأ في نمط التكويد أدناه؟

function pow(x,n)
{
  let result=1;
  for(let i=0;i<n;i++) {result*=x;}
  return result;
}

let x=prompt("x?",''), n=prompt("n?",'')
if (n<=0)
{
  alert(`Power ${n} is not supported, please enter an integer number greater than zero`);
}
else
{
  alert(pow(x,n))
}

قم بإصلاحه.

الحل

يمكنك ملاحظة ما يلي:

function pow(x,n)  // <- لا يوجد مسافات بين المُعاملات
{  // <- قوس الفتح في سطر مستقل
  let result=1;   // <- عدم وجود مسافات قبل أو بعد =
  for(let i=0;i<n;i++) {result*=x;}   // <- لا يوجد مسافات
  // يجب أن يكون محتوى { ... } في سطر جديد
  return result;
}

let x=prompt("x?",''), n=prompt("n?",'') // <-- ممكنة تقنيا، 
// لكن يُفَضَّل جعلها في سطرين، بالإضافة إلى عدم وجود مسافات وعدم وجود ;
// 
if (n<0)  // <- لا يوجد مسافات بين (n < 0), ويجب وجود سطر فارغ قبلها
{   // <- قوس الفتح في سطر مستقل
  // يمكن فصل الأسطر الطويلة في الأسفل حتى تصبح سهلة القراءة
  alert(`Power ${n} is not supported, please enter an integer number greater than zero`);
}
else // <- يمكن كتابتها في سطر واحد هكذا: "} else {"
{
  alert(pow(x,n))  // لا يوجد مسافات ولا يوجد ;
}

بعد تصحيح الأخطاء تصبح الشيفرة البرمجية كما يلي:

function pow(x, n) {
  let result = 1;

  for (let i = 0; i < n; i++) {
    result *= x;
  }

  return result;
}

let x = prompt("x?", "");
let n = prompt("n?", "");

if (n < 0) {
  alert(`Power ${n} is not supported,
    please enter an integer number greater than zero`);
} else {
  alert( pow(x, n) );
}

ترجمة -وبتصرف- للفصل Coding Style من كتاب The JavaScript Language

اقرأ أيضًا


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

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



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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.


×
×
  • أضف...