۱۸ ژوئیه ۲۰۲۲

سبک کدنویسی

کد ما باید تا حد امکان تمیز و خوانا باشد

این در واقع هنر برنامه نویسی است – گرفتن یک کار پیچیده و نوشتن کد آن به روشی که هم درست باشد و هم برای انسان قابل خواندن باشد. یک سبک کدنویسی خوب است که در آن بسیار کمک می‌کند.

سینتکس

این یک برگهٔ تقلب با قوانین پیشنهادی است(عکس زیر را برای جزئییات بیشتر مشاهده کنید)

خب حالا بیاید در مورد قوانین و علت آن باهم بحث کنیم

هیچ قوانین “بایدی” وجود ندارد

Nothing is set in stone here. These are style preferences, not religious dogmas. هیچ وحی منزلی درکار نیست.این ها ترجیحات سبک کد زنی است نه عقاید مذهبی

آکولاد

در اکثر پروژه‌های جاوااسکریپت آکولاد به روش «مصری» و با سبک باز کردن آکولاد در خط مشابه کلمه کلیدی متناظر و نه در خط جدید نوشته میشود. همچنین قبل از بازکردن یک آکولاد یک فاصله نیز باید وجود داشته باشد، مانند زیر:

if (condition) {
  // do this
  // ...and that
  // ...and that
}

یک سازه تک‌خطی ، مانند 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. ولی برای یک بلاک کد، آخرین مثال حالت خواناتری است

طول خط

هیچکس دوست ندارد یک خط طولانی افقی را بخواند. بهترین حالت آن است که آن‌ها را بشکنیم.

برای مثال :

// backtick quotes ` allow to split the string into multiple lines
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 کاراکتر است.

تورفتگی

دو نوع تورفتگی وجود دارد :

  • تو رفتگی افقی : ۲ یا ۴ فاصله

    یک تورفتگی افقی با استفاده از 2 یا 4 فاصله یا کلید تب ساخته می‌شود (کلید Tab).کدام یک را انتخاب کنید یک جنگ مقدس قدیمی است. امروزه فاصله بیشتر رایج هستند

    یکی از مزایای استفاده از فاصله به جای تب این است که فاصله از پیکربندی‌های انعطاف‌پذیرتری از تب‌ها استفاده می‌کنند.

    برای نمونه, مامی‌توانیم پارامترهای ورودی و آکولاد باز را باهم تراز کنیم، مانند زیر:

show(parameters, aligned, // 5 spaces padding at the left
one, after, another ) { // … } ```

  • تو رفتگی عمودی: خط های خالی برای شکستن کد به قسمت های منطقی.

    حتی یک فانکشن می‌تواند به قسمت‌های منطقی تقسیم شود. در مثال زیر، تعریف متغیر، حلقهٔ اصلی و بازگزداندن مقدار(return) به صورت عمودی شکسته شده‌اند

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

    افزودن یک خط خالی اضافه باعث میشود کد خواناتر شود. نباید بیشتر از ۹ خط کد بدون تورفتگی عمودی وجود داشته باشد.

نقطه ویرگول (semicolon)

بعد از هر عبارت باید یک نقطه ویرگول وجود داشته باشد، حتی اگر احتمالاً قابل رد شدن باشند

زبانهایی وجود دارد که نقطه ویرگول واقعاً اختیاری است و بندرت از آن استفاده می شود. اگرچه در JavaScript مواردی وجود دارد که شکستن خط به عنوان نقطه ویرگول تعبیر نمی شود و کد را در برابر خطاها آسیب پذیر می کند. برای اطلاعات بیشتر قسمت مربوطه را مشاهده کنید ساختار کد

اگر شما یک توسعه دهنده جاوااسکریپت حرفه ای باشید شاید شما سبک کد زنی بدون نقطه ویرگول را مانند StandardJS انتخاب کنید.در غیر اینصورت از نقطه ویرگول حتما استفاده کنید چون باعث جلوگیری از خطاهای ناخواسته میشود.

سطح تورفتگی

از تو رفتگی عمیق در کد خود دوری کنید.

برای مثال، در حلقه‌ها بعضی اوقات ایده خوبی است که از continue برای جلوگیری از سطح زیاد تورفتگی جلوگیری کرد.

به طور مثال به جای افزودن if به صورت تورفته مثل زیر :

for (let i = 0; i < 10; i++) {
  if (cond) {
    ... // <- one more nesting level
  }
}

ما می‌توانیم بنویسم :

for (let i = 0; i < 10; i++) {
  if (!cond) continue;
  ...  // <- no extra nesting level
}

موارد مشابه میتواند با if/else و return‍ انجام گیرد…

به عنوان مثال ، دو حالت زیر یکسان هستند.

حالت اول :

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;
  }
}

حالت دوم :

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;
}

حالت دوم خواناتر است به این دلیل که حالت خاص n < 0 در ابتدا بررسی شده است. بعد از اینکه بررسی به اتمام رسید ما می‌توانیم به قسمت اصلی کد برویم بدون اینکه به تورفتگی خاصی احتیاج داشته باشیم.

جای تابع

اگر شما از چندین تابع کمکی در کد خود استفاده میکنید، سه راه برای سازمان‌دهی کردن آنها وجود دارد.

  1. تابع را بالای کدی که می‌خواهید استفاده کنید تعریف کنید :

    // function declarations
    function createElement() {
      ...
    }
    
    function setHandler(elem) {
      ...
    }
    
    function walkAround() {
      ...
    }
    
    // the code which uses them
    let elem = createElement();
    setHandler(elem);
    walkAround();
  2. اول کد بعد تابع :)

    // the code which uses the functions
    let elem = createElement();
    setHandler(elem);
    walkAround();
    
    // --- helper functions ---
    function createElement() {
      ...
    }
    
    function setHandler(elem) {
      ...
    }
    
    function walkAround() {
      ...
    }
  3. ترکیبی : یک تابع جای تعریف شود که اولین جای استفاده آن است.

اکثر مواقع حالت دوم ترجیح داده می‌شود.

به این خاطر که زمانی که ما کد را میخوانیم٬ ما ابتدا می‌خواهیم بدانیم چه کاری انجام میدهد. اگر کد در ابتدا قرار می‌گیرد درهمان ابتدا کد تمیز است.سپس، شاید شما اصلا لازم نباشد که تابع را بخوانید به خصوص اگر که نام آن ها توضیح دهنده عمکلرد آن‌ها باشد.

راهنمای سبک (Style Guides)

راهنمای سبک شامل قوانین کلی درباره “نحوه نوشتن کد” است برای مثال کدام نوع کوتیشن استفاده شود، تعداد فاصله‌ها برای تو رفتگی، حداکثر طول خط و غیره. و خیلی چیزهای جزئی دیگر.

وقتی همه اعضای یک تیم از یک راهنمای سبک یکسان استفاده می‌کنند، فارغ از اینکه کدام یک از اعضای تیم آن را نوشته است، کد یکنواخت به نظر می‌رسد.

البته ، یک تیم همیشه می‌تواند راهنمای سبک خود را بنویسد، اما معمولاً نیازی به این کار نیست. راهنماهای موجود زیادی برای انتخاب وجود دارد.

برخی انتخاب‌های محبوب :

اگر یک توسعه‌دهنده تازه‌کار هستید، با برگهٔ تقلب در ابتدای این فصل شروع کنید. سپس می‌توانید سایر راهنماهای سبک را مرور کنید تا ایده‌های بیشتری به دست بیاورید و تصمیم بگیرید کدام یک را بیشتر دوست دارید.

لینترهای خودکار

لیتنرها ابزاری هستند که می‌توانند به طور خودکار سبک کد شما را بررسی کرده و پیشنهادهای را برای بهبود کد ارائه دهند.

نکته قابل توجه در مورد آنها این است که بررسی سبک می تواند اشکالاتی مانند اشتباه تایپی در نام متغیر یا نام تابع را نیز پیدا کند. به دلیل این ویژگی ، استفاده از لینتر حتی اگر نمی‌خواهید به یک “سبک کد” خاص پایبند باشید ، توصیه می‌شود

برخی از ابزارهای لینت کردن شناخته شده :

  • JSLint --یکی از اولین لینترها.
  • JSHint – تنظیمات بیشتری نسبت به JSLint.
  • ESLint --شاید یکی از جدیدترین ها.

همه‌ی آنها می‌توانند کارشان را انجام دهند. نویسنده از ESLint استفاده میکند.

اکثر لینترها میتواند با ویرایشگرهای محبوب ادغام شوند : فقط کافیست پلاگین مربوطه رو نصب و سبک(style) را پیکربندی کنید.

برای نمونه٬ برای ESLint این کارها را باید انجام دهید :

  1. نصب Node.JS.
  2. نصب ESLint با کامند npm npm install -g eslint نصب کننده پکیج های جاوا اسکریپت است.
  3. یک فایل تنظیمات به نام .eslintrc در مسیر کف پروژه جاوااسکریپت(فولدری که شامل همه فولدر ها هستند)
  4. نصب/فعال کردن پلاگین برای ویرایشگر خودتان برای ادغام با ESLint. اکثر ویرایشگرها یک پلاگین دارند:

این یک مثال از فایل .eslintrc است :

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

در اینجا دستورالعمل "extends" نشان می‌دهد که پیکربندی براساس مجموعه تنظیمات “eslint: recommended” است. پس از آن، ما مشخصات خود را مشخص می‌کنیم.

همچنین می‌توان مجموعه قوانین سبک را از وب دانلود و به جای آن گسترش داد. برای اطلاعات بیشتر در مورد نصب ، به http://eslint.org/docs/user-guide/getting-started مراجعه کنید

همچنین IDE های مشخصی linting داخلی دارند که راحت است اما به اندازه ESLint قابل تنظیم نیست.

خلاصه

تمام قوانین سینتکسی توصیف شده در این فصل (و همه آنهای که در راهنماهای سبک اشاره شده بود) با هدف افزایش خوانایی کد شما است. همه آنها قابل بحث است.

وقتی به نوشتن کد “بهتر” فکر می کنیم ، سوالاتی که باید از خود بپرسیم این است: “چه چیزی کد را خواناتر و آسان تر می کند؟” و “چه چیزی می تواند به ما کمک کند تا از خطا جلوگیری کنیم؟” اینها اصلی ترین مواردی است که باید هنگام انتخاب و بحث در مورد سبک کد به خاطر بسپارید.

خواندن راهنماهای سبک محبوب به شما امکان می‌دهد با جدیدترین ایده ها در مورد سبک کدهای رو به رشد و بهترین روش ها به روز باشید.

تمارین

اهمیت: 4

What’s wrong with the code style below?

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))
}

Fix it.

You could note the following:

function pow(x,n)  // <- no space between arguments
{  // <- figure bracket on a separate line
  let result=1;   // <- no spaces before or after =
  for(let i=0;i<n;i++) {result*=x;}   // <- no spaces
  // the contents of { ... } should be on a new line
  return result;
}

let x=prompt("x?",''), n=prompt("n?",'') // <-- technically possible,
// but better make it 2 lines, also there's no spaces and missing ;
if (n<=0)  // <- no spaces inside (n <= 0), and should be extra line above it
{   // <- figure bracket on a separate line
  // below - long lines can be split into multiple lines for improved readability
  alert(`Power ${n} is not supported, please enter an integer number greater than zero`);
}
else // <- could write it on a single line like "} else {"
{
  alert(pow(x,n))  // no spaces and missing ;
}

The fixed variant:

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) );
}
نقشه آموزش