25 вересня 2023 р.

Стандарт оформлення коду

Наш код повинен бути настільки зрозумілим та читабельним, наскільки це можливо.

Насправді мистецтво програмування — це брати складну задачу і писати код, який одночасно і розв’язує задачу, і залишається зрозумілим людині. Саме тут хороший стиль коду стає у пригоді.

Синтаксис

Деякі запропоновані правила наведені у цій шпаргалці (нижче розписано більш детально):

Давайте детальніше розглянемо ці правила і причини їх появи.

Немає обов’язкових правил

Залізних правил немає. Все це стильові уподобання, а не релігійні догми.

Фігурні дужки

У більшості JavaScript проєктів фігурні дужки написані у так званому “Єгипетському” стилі, де дужка що відкриває блок знаходиться не на новому рядку, а на тому ж, що й відповідне ключове слово. Також потрібно додавати перед нею пробіл. Наприклад:

if (condition) {
  // зробити це
  // ...і це
  // ...і це
}

Чи потрібно ставити дужки, коли конструкція складається лише з одного рядка, наприклад if (condition) doSomething()?

Нижче наведені різні варіанти розташування дужок з коментарями, щоб ви змогли самостійно вирішити який варіант є найбільш читабельним.

  1. 😠 Початківці іноді використовують таку конструкцію. Це поганий приклад, фігурні дужки не потрібні:
    if (n < 0) {alert(`Степінь ${n} не підтримується`);}
  2. 😠 Ніколи не розподіляйте конструкцію на декілька рядків без фігурних дужок – дуже легко зробити помилку при додаванні нового рядка:
    if (n < 0)
      alert(`Степінь ${n} не підтримується`);
  3. 😏 Писати в один рядок без дужок є прийнятним варіантом, якщо рядок короткий:
    if (n < 0) alert(`Степінь ${n} не підтримується`);
  4. 😃 Найкращий варіант:
    if (n < 0) {
      alert(`Степінь ${n} не підтримується`);
    }

Для дуже короткого коду один рядок є прийнятним, наприклад if (cond) return null. Але блок коду (останній варіант) зазвичай є більш читабельним.

Довжина рядка

Ніхто не любить читати довгий горизонтальний рядок коду. Хорошою практикою є розподіляти його на декілька рядків.

Наприклад:

// Зворотні апострофи ` дозволяють розподіляти рядок на декілька
let str = `
  Робоча група TC39 організації ECMA International -
  це група JavaScript-розробників, спеціалістів з інтеграції, науковців тощо,
  які працюють разом зі спільнотою над підтримкою та розвитком мови JavaScript.
`;

Або для if:

if (
  id === 123 &&
  moonPhase === 'Зростаючий місяць' &&
  zodiacSign === 'Терези'
) {
  letTheSorceryBegin();
}

Максимальну довжину рядка визначається командою. Зазвичай це 80 або 120 символів.

Відступи

Є два види відступів:

  • Горизонтальні відступи: 2 або 4 пробіли.

    Горизонтальний відступ робиться за допомогою двох або чотирьох пробілів, або за допомогою табуляції (клавіша Tab). Який відступ вибирати – вирішувати вам. Відступ з пробілами більш поширений на сьогодні.

    Однією з переваг пробілів є те, що пробіли дозволяють більш гнучку конфігурацію відступів, ніж табуляція.

    Наприклад, ми можемо вирівняти параметри відносно відкритої дужки:

    show(parameters,
         aligned, // 5 пробілів зліва
         one,
         after,
         another
      ) {
      // ...
    }
  • Вертикальні відступи: пусті рядки для розподілу коду на “логічні блоки”.

    Навіть окрема функція може бути розподілена на логічні блоки. У наведеному нижче прикладі, ініціалізація змінних, основний цикл та повернення результату розподілені вертикально:

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

    Вставляйте додатковий рядок в тому випадку, коли це робить код зрозумілішим. Не повинно бути понад дев’яти рядків коду підряд без вертикального розподілу.

Крапка з комою

Крапку з комою треба ставити після кожного виразу, навіть тоді, коли є можливість їх пропустити.

Є мови програмування, у яких крапка з комою є дійсно необов’язковими та рідко використовуються. Проте у JavaScript є ситуації коли перенесення строки не інтерпретується як крапка з комою, залишаючи код вразливим до помилок. Більше детально про це знайдете у розділі Структура коду.

Якщо ви досвідчений JavaScript програміст, ви можете обрати стиль коду без крапки з комою, наприклад 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.

Наприклад, дві конструкції нижче є ідентичними.

Перша:

function pow(x, n) {
  if (n < 0) {
    alert("Від'ємні значення 'n' не підтримуються");
  } else {
    let result = 1;

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

    return result;
  }
}

Друга:

function pow(x, n) {
  if (n < 0) {
    alert("Від'ємні значення 'n' не підтримуються");
    return;
  }

  let result = 1;

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

  return result;
}

Друга конструкція є більш зрозумілою, тому що умова n < 0 обробляється з самого початку. Коли перевірка закінчена ми можемо переходити до “головного” коду без потреби у додатковому рівні вкладеності.

Розташування функцій

Якщо ви пишете декілька допоміжних функцій і код, що їх використовує, є три способи організувати функції.

  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. Змішаний варіант: функція оголошена там, де вона вперше використовується.

Зазвичай, віддають перевагу другому варіанту.

Причиною цього є те, що коли ми читаємо код, перш за все ми хочемо зрозуміти що він робить. Якщо головний код іде першим – це стає зрозумілим з самого початку. Тоді, можливо ми навіть не будемо читати функції взагалі, особливо якщо їх імена відповідають тому, що вони роблять.

Посібники зі Стилю Коду

Посібник зі стилю коду містить загальні правила “як писати” код, наприклад, які лапки використовувати, скільки пробілів ставити для відступу, максимальну довжину рядка, і таке інше. Тобто, багато дрібниць.

Коли всі члени команди використовують посібник зі стилю, код виглядає однаковим, незалежно від того, хто з команди його написав.

Звичайно, кожна команда може завжди створити свій посібник зі стилю, але зазвичай в цьому не має потреби. Є багато посібників, серед яких можна вибрати найбільш відповідний.

Деякі популярні посібники:

Якщо ви початківець, почніть зі шпаргалки наведеної в початку цього розділу. Потім ви зможете обрати один з чинних посібників, щоб визначити ті правила, які вам більше підходять.

Автоматичні засоби перевірки (лінтери)

Автоматичні засоби перевірки, так звані “лінтери” – це інструменти, що автоматично перевіряють стиль коду та вносять пропозиції щодо його вдосконалення.

Найкраще в них те, що вони також можуть знайти деякі програмні помилки, наприклад друкарську помилку у назві змінної чи функції. Завдяки цій особливості, рекомендують використовувати лінтер навіть тоді, коли ви не збираєтесь дотримуватись якогось конкретного “стилю коду”.

Ось декілька добре відомих засобів для перевірки:

  • JSLint – один з перших лінтерів.
  • JSHint – має більше налаштувань ніж JSLint.
  • ESLint – напевно, найсучасніший лінтер.

Всі вони роблять свою справу. Автор використовує ESLint.

Більшість лінтерів інтегровані в популярні редактори: просто увімкніть відповідний плагін в редакторі й налаштуйте стиль.

Наприклад, для ESLint вам потрібно зробити наступне:

  1. Встановіть Node.js.
  2. Встановіть ESLint, використовуючи команду npm install -g eslint (npm – це менеджер JavaScript пакетів (модулів)).
  3. Створіть файл конфігурації .eslintrc в корні вашого JavaScript проєкту (у директорії, що містить всі ваші файли).
  4. Встановіть/увімкніть плагін для вашого редактора, який інтегрується з ESLint. Більшість редакторів мають такий плагін.

Ось приклад файлу .eslintrc:

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

Директива "extends" означає, що конфігурація базується на наборі налаштувань “eslint:recommended”. Після цього, ви вказуєте ваші власні.

Крім того, можна завантажити набори правил з мережі та розширити їх. Дивіться https://eslint.org/docs/user-guide/getting-started для отримання більш детальної інструкції зі встановлення.

Також, деякі середовища розробки (IDE) мають вбудовані засоби перевірки коду, що є зручним, але не таким гнучким в налаштуванні рішенням, як 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) );
}
Навчальна карта

Коментарі

прочитайте це, перш ніж коментувати…
  • Якщо у вас є пропозиції, щодо покращення підручника, будь ласка, створіть обговорення на GitHub або одразу створіть запит на злиття зі змінами.
  • Якщо ви не можете зрозуміти щось у статті, спробуйте покращити її, будь ласка.
  • Щоб вставити код, використовуйте тег <code>, для кількох рядків – обгорніть їх тегом <pre>, для понад 10 рядків – використовуйте пісочницю (plnkr, jsbin, codepen…)