Code Quality and Best Practices

Code Quality and Best Practices

  • 5 червня
  • читати 20 хв
Олександра Донцова
Олександра Донцова Front-end Developer у Sigma Software, Викладач Комп'ютерної школи Hillel.

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

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

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

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

ДОМОВЛЕНІСТЬ ЩОДО НАЙМЕНУВАННЯ ЗМІННИХ

Використання узгоджених іменних конвенцій у всьому коді є критично важливим для написання чистого, зрозумілого й легкого для підтримки коду. Ось деякі загальні конвенції:

1. Базові домовленості:

camelCase для змінних і функцій.

camelCase — стиль, де перше слово пишеться з маленької літери, а кожне наступне слово починається з великої літери. Ця конвенція допомагає розрізняти слова в іменах змінних та функцій.

Приклади:

// Змінні

letuserName="John"; // Коректно

letuser_age=25; // Некоректно (використання нижнього підкреслення)

 

// Функції

functiongetUserInfo() {

// Коректно

}

functionget_user_info() {

// Некоректно (використання нижнього підкреслення)

}

PASCAL CASE ДЛЯ КЛАСІВ

PascalCase — стиль, де кожне слово починається з великої літери. Ця конвенція використовується для іменування класів.

Приклади:

classUserAccount {

constructor(userName, userAge) {

this.userName=userName;

this.userAge=userAge;

  }
 

displayInfo() {

console.log(`${this.userName}, ${this.userAge}`);

  }

}
 

// Використання класу

letuser=newUserAccount("John", 25);

user.displayInfo();

UPPER CASE ДЛЯ КОНСТАНТ

UPPER CASE — стиль, де всі літери пишуться великими, а слова розділяються нижнім підкресленням. Ця конвенція використовується для іменування констант.

Приклади:

constMAX_USERS=100; // Коректно

constmaxUsers=100; // Некоректно (не відповідає конвенції)

 

constAPI_KEY="12345-abcde"; // Коректно

constapiKey="12345-abcde"; // Некоректно (не відповідає конвенції)

2. ОПИС ЗМІННИХ АБО DESCRIPTIVE NAMES

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

Приклади:

// Змінні

letx=10; // Некоректно (незрозуміле ім'я)

letuserAge=10; // Коректно (чітко описує мету змінної)

 

// Функції

functioncalc(x, y) {// Некоректно (неясно, що саме обчислюється)

returnx+y;

}

 

functioncalculateSum(a, b) {// Коректно (чітко описує, що робить функція)

returna+b; 

}

 

// Класи

classU {

// Некоректно (незрозуміла назва класу)

}

 

classUser {

// Коректно (зрозуміла назва класу, що описує об'єкт користувача)

}

3. УНИКАННЯ АБРЕВІАТУР (AVOID ABBREVIATIONS)

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

Приклади:

// Змінні

letusrNm="John"; // Некоректно (використано абревіатури)

letuserName="John"; // Коректно (повне слово)

 

// Функції

functioncalcUsrAge(dob) {

// Некоректно (незрозуміла абревіатура)

letage=newDate().getFullYear() -dob.getFullYear();

returnage;

}

 

functioncalculateUserAge(dateOfBirth) {

// Коректно (повні слова, зрозуміле призначення функції)

letage=newDate().getFullYear() -dateOfBirth.getFullYear();

returnage;

}

 

// Класи

classPrd {

// Некоректно (незрозуміла абревіатура)

}

 

classProduct {

// Коректно (повне слово, зрозуміла назва класу)

}

СТРУКТУРА КОДУ (CODE STRUCTURE)

Правильна структура коду допомагає зробити ваш проєкт більш зрозумілим, легким для підтримки і розширення. Ось деякі основні принципи:

1. Модульність (Modularity)

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

Приклади:

// Велика функція з кількома відповідальностями (Некоректно)

functionprocessUserData(user) {

validateUserData(user);

letprocessedData=transformData(user);

saveDataToDatabase(processedData);

}

 

// Маленькі функції з єдиною відповідальністю (Коректно)

functionvalidateUserData(user) {

// Логіка валідації

}

 

functiontransformData(user) {

// Логіка трансформації даних

returntransformedData;

}

 

functionsaveDataToDatabase(data) {

// Логіка збереження даних

}

2. ОРГАНІЗАЦІЯ ФАЙЛІВ (FILE ORGANIZATION)

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

Приклади:

// Некоректна організація файлів

project/

├── script1.js

├── script2.js

├── script3.js

 

// Коректна організація файлів

project/

├── components/

│   ├── Header.js

│   ├── Footer.js

├── services/

│   ├── apiService.js

│   ├── authService.js

├── utils/

│   ├── helpers.js

3. РОЗДІЛЕННЯ ВІДПОВІДАЛЬНОСТЕЙ (SEPARATION OF CONCERNS)

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

Приклади:

// Без розділення відповідальностей (Некоректно)

functionrenderUserProfile(user) {

letuserData=fetchUserData(user.id); // Логіка обробки даних

letuserProfileHTML=`<div>${userData.name}</div>`; // Логіка UI

document.body.innerHTML=userProfileHTML;

}

 

// З розділенням відповідальностей (Коректно)

functionfetchUserData(userId) {

// Логіка обробки даних

returnuserData;

}

 

functiongenerateUserProfileHTML(userData) {

// Логіка UI

return`<div>${userData.name}</div>`;

}

 

functionrenderUserProfile(userId) {

letuserData=fetchUserData(userId);

letuserProfileHTML=generateUserProfileHTML(userData);

document.body.innerHTML=userProfileHTML;

}

ЧИТАБЕЛЬНІСТЬ (READABILITY)

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

1. Відступи (Indentation)

Відступи допомагають організувати код і роблять його легшим для читання. Зазвичай використовується відступ у 2 або 4 пробіли.

Приклади:

// Відступ у 2 пробіли (Коректно)

functioncalculateTotal(price, tax) {

lettotal=price+tax;

returntotal;

}

 

// Відступ у 4 пробіли (Коректно)

functioncalculateTotal(price, tax) {

lettotal=price+tax;

returntotal;

}

 

// Невідповідний відступ (Некоректно)

functioncalculateTotal(price, tax) {

lettotal=price+tax;

returntotal;

}

2. ДОВЖИНА РЯДКІВ (LINE LENGHT)

Довжина рядків повинна бути помірною, зазвичай не більше 80-100 символів. Це робить код легшим для читання та перегляду.

Приклади:

// Короткі рядки (Коректно)

functiongetUserInfo(userId) {

letuser=fetchUserFromDatabase(userId);

returnuser;

}

 

// Довгі рядки (Некоректно)

functiongetUserInfo(userId) { letuser=fetchUserFromDatabase(userId); returnuser; }

3. КОМЕНТАРІ (COMMENTS)

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

Приклади:

// Очевидні коментарі (Некоректно)

letuserName="John"; // Змінна userName встановлюється значення "John"

 

// Пояснювальні коментарі (Коректно)

letuserName=fetchUserName(); // Отримання імені користувача з бази даних

 

// Складна логіка

functioncalculateDiscount(price, discount) {

// Перевірка, чи знижка не перевищує ціну

if (discount>price) {

returnprice;

  }

returnprice-discount;

}

УНИКНЕННЯ СКЛАДНОСТІ (AVOIDING COMPLEXITY)

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

1. Спрощення логіки (SimplifyLogic)

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

Переваги:

- зрозумілість: код стає легшим для читання і розуміння;
- підтримка: легше знайти та виправити помилки у меншій функції.

Приклади:

// Глибоке вкладення умов (Некоректно)

functionprocessOrder(order) {

if (order.isValid) {

if (order.items.length>0) {

if (order.paymentStatus==='paid') {

// Виконати замовлення

      }

    }

  }

}

 

// Розділення логіки на менші функції (Коректно)

functionisOrderValid(order) {

returnorder.isValid&&order.items.length>0&&order.paymentStatus==='paid';

}

 

functionprocessOrder(order) {

if (isOrderValid(order)) {

// Виконати замовлення

  }

}

2. ПРИНЦИП DRY (DON’T REPEAT YOURSELF)

Принцип DRY (Don'tRepeatYourself) означає повторне використання коду скрізь, де це можливо, щоб уникнути дублювання. Виносьте повторюваний код у функції або модулі.

Переваги:

- зменшення коду: менше коду для підтримки;
- легкість оновлення: зміни потрібно вносити лише в одному місці.

Приклади:

// Дублювання коду (Некоректно)

functioncalculateAreaOfRectangle(width, height) {

returnwidth*height;

}

 

functioncalculateAreaOfTriangle(base, height) {

return0.5*base*height;

}

 

// Використання загальної функції (Коректно)

functioncalculateArea(shape, dimension1, dimension2) {

if (shape==='rectangle') {

returndimension1*dimension2;

  } elseif (shape==='triangle') {

return0.5*dimension1*dimension2;

  }

}

 

// Використання загальної функції

letrectangleArea=calculateArea('rectangle', 5, 10);

lettriangleArea=calculateArea('triangle', 5, 10);

ОБРОБКА ПОМИЛОК (ERROR HANDLING)

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

1. Якісна обробка помилок (ErrorHandling)

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

Переваги:

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

Приклади:

// Якісна обробка помилок

functionfetchUserData(userId) {

try {

letresponse=fetch(`https://api.example.com/users/${userId}`);

if (!response.ok) {

thrownewError('Network response was not ok');

    }

letuserData=response.json();

returnuserData;

  } catch (error) {

console.error('Fetch user data failed:', error);

return { error:'Failed to fetch user data. Please try again later.' };

  }

}

2. ВАЛІДАЦІЯ (VALIDATION)

Валідація означає перевірку вхідних даних для функцій і введених користувачами даних, щоб запобігти виникненню помилок через некоректні дані.

Приклади:

// Валідація вхідних даних

functioncalculateTotal(price, tax) {

if (typeofprice!=='number'||typeoftax!=='number') {

thrownewError('Invalid input: price and tax should be numbers');

  }

returnprice+tax;

}

 

// Валідація користувацького вводу

functionhandleFormSubmit(event) {

event.preventDefault();

letuserName=document.getElementById('userName').value;

if (!userName) {

alert('User name is required');

return;

  }

// Обробка форми

}

ЧОМУ ЦЕ ВАЖЛИВО?

  1. Зручність читання та розуміння коду: використання узгоджених найменувань змінних робить код зрозумілішим і легшим для читання, особливо для нових членів команди. Чіткі й описові імена, спрощена логіка й добре організовані файли сприяють кращому розумінню коду.
  2. Полегшення підтримки: коли весь код написаний в одному стилі та структуруваний логічно, його легше підтримувати, виявляти та виправляти помилки. Валідація та правильна обробка помилок забезпечують надійність і стійкість додатків.
  3. Збільшення продуктивності: узгодженість зменшує час, витрачений на розуміння коду, що дозволяє розробникам швидше орієнтуватися в кодовій базі та зосередитися на розв'язанні задач. Повторне використання коду (принцип DRY) зменшує дублювання і полегшує підтримку.

РЕКОМЕНДАЦІЯ

Підтримуйте єдиний стиль написання коду у всій команді, використовуючи автоматичні інструменти форматування коду, такі як ESLint для JavaScript. Регулярні код-рев'ю, парне програмування і документування також сприятимуть підвищенню якості коду. Запровадження цих практик допоможе створити міцну основу для успішного розвитку й підтримки проєктів, сприятиме професійному зростанню розробників і забезпечить ефективну роботу команди.

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

Рекомендуємо курси по темі