Чистий javascript.Об'єкти і структури даних. Асинхронність. Обробка помилок

Переклад книги Райана Макдермота clean-code-javascript

Зміст:



Об'єкти і структури даних

Використовуйте геттери і сетери

В javascript відсутні ключові слова private і public, що ускладнює реалізацію класів. Краще використовувати геттери і сетери для доступу до властивостей об'єкта, що безпосередньо до них звертатися. Ви запитаєте: «Навіщо?». Ось кілька причин:
  • Якщо ви хочете реалізувати довше ніж просто доступ до властивостей, вам треба буде поміняти реалізацію в одному місці, а не по всьому коду.
  • Валідацію легко реалізувати на рівні реалізації сетера
  • Інкапсуляція внутрішнього стану об'єкта
  • Легко додати логування та обробку помилок на рівні геттеров і сеттерів
  • Наслідуючи цей клас, ви можете перевизначити функціональність за замовчуванням
  • Ви можете ліниво довантажувати властивості вашого об'єкта, наприклад, з сервера.
Погано:

class BankAccount {
constructor() {
this.balance = 1000;
}
}

const bankAccount = new BankAccount();

// Купуємо, наприклад, взуття...
bankAccount.balance -= 100;

Добре:

class BankAccount {
constructor(balance = 1000) {
this._balance = balance;
}

set balance(amount) {
if (verifyIfAmountCanBeSetted(amount)) {
this._balance = amount;
}
}

get balance() {
return this._balance;
}

verifyIfAmountCanBeSetted(val) {
// ...
}
}

const bankAccount = new BankAccount();

// Купуємо, наприклад, взуття...
bankAccount.balance -= shoesPrice;

// отримуємо баланс
let balance = bankAccount.balance;

Реалізуйте приватні властивості ваших об'єктів

Це можливо за допомогою замикань.
Погано:

const Employee = function(name) {
this.name = name;
};

Employee.prototype.getName = function getName() {
return this.name;
};

const employee = new Employee('John Doe');
console.log(`Employee name: ${employee.getName()}`); 
// Employee name: John Doe
delete employee.name;
console.log(`Employee name: ${employee.getName()}`); 
// Employee name: undefined

Добре:

const Employee = function (name) {
this.getName = function getName() {
return name;
};
};

const employee = new Employee('John Doe');
console.log(`Employee name: ${employee.getName()}`); 
// Employee name: John Doe
delete employee.name;
console.log(`Employee name: ${employee.getName()}`);
// Employee name: John Doe


Асинхронність

Використовуйте промисы замість колбеков

Колбеки призводять до надмірної вкладеності і поганий читабельність коду.
Погано:

require('request').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin', (requestErr, response) => {
if (requestErr) {
console.error(requestErr);
} else {
require('fs').writeFile('article.html', response.body, (writeErr) => {
if (writeErr) {
console.error(writeErr);
} else {
console.log('File written');
}
});
}
});

Добре:

require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
.then((response) => {
return require('fs-promise').writeFile('article.html', response);
})
.then(() => {
console.log('File written');
})
.catch((err) => {
console.error(err);
});

Async/Await робить код чистіше, ніж промисы

Промисы дуже хороша альтернатива колбекам, але в ES2017 / ES8 специфікації з'явився аѕупс/аwait, який пропонує ще краще рішення. Все, що вам потрібно, це написати функцію з префіксом async, всередині якої ви можете писати вашу асинхронну логіку імперативно. аѕупс/аwait можна використовувати прямо зараз за допомогою babel.
Погано:

require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
.then((response) => {
return require('fs-promise').writeFile('article.html', response);
})
.then(() => {
console.log('File written');
})
.catch((err) => {
console.error(err);
});

Добре:

async function getCleanCodeArticle() {
try {
const response = await require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin');
await require('fs-promise').writeFile('article.html', response);
console.log('File written');
} catch(err) {
console.error(err);
}
}


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

Не ігноруйте відловлені помилки

Нічого не роблячи з спійманої помилкою ви втрачаєте можливість виправити помилку або відреагувати на неї коли-небудь. Висновок помилки в консоль(console.log(error)) не дає кращого результату, тому що помилка може загубитися серед виведених записів в консоль. Якщо ви завертаєте шматок коду в try / catch, значить ви припускаєте виникнення помилки. В такому випадку ви повинні мати запасний план на цей випадок.
Погано:

try {
functionThatMightThrow();
} catch (error) {
console.log(error);
}

Добре:

try {
functionThatMightThrow();
} catch (error) {
// Один з варіантів (більш помітний, ніж console.log):
console.помилка(error);
// Інший варіант, повідомити користувача про помилку:
notifyUserOfError(error);
// Та ще варіант, відправити помилку на сервер :
reportErrorToService(error);
// Або використовуйте всі три варіанти!
}

Не ігноруйте помилки виникли в промисах

Ви не повинні ігнорувати помилки виникли в промисе з тієї ж причини що виловлені помилки в try / catch.
Погано:

getdata()
.then((data) => {
functionThatMightThrow(data);
})
.catch((error) => {
console.log(error);
});

Добре:

getdata()
.then((data) => {
functionThatMightThrow(data);
})
.catch((error) => {
// Один з варіантів (більш помітний, ніж console.log):
console.помилка(error);
// Інший варіант, повідомити користувача про помилку:
notifyUserOfError(error);
// Та ще варіант, відправити помилку на сервер :
reportErrorToService(error);
// Або використовуйте всі три варіанти!
});

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.