Original Repository: ryanmcdermott/clean-code-javascript
- Kirish
- O'zgaruvchilar
- Funksiyalar
- Obyektlar va ma'lumotlar strukturasi
- Klasslar
- SOLID
- Testlash
- Paralellik
- Error'lar bilan ishlash
- Formatlash
- Kommentlar
- Tarjima
Robert C. Martinning "Clean Code" kitobidan dasturiy ta'minot muhandisligi tamoyillari, JavaScript uchun moslashtirildi. Bu uslublar bo'yicha qo'llanma emas. Bu JavaScript-da o'qilishga, o'zgartirishga oson va qayta ishlatiladigan dasturiy ta'minot yaratish bo'yicha qo'llanma.
Bu yerdagi barcha prinsplarga qat'iy rioya qilish shart emas. Bular shunchaki ko'rsatmalar boshqa hech narsa emas, lekin ular Clean code mualliflari tomonidan ko'p yillik jamoaviy tajriba orqali yig'ilgan.
Bizning dasturiy ta'minot muhandisligi (software engineering) bo'yicha tajribamiz 50 yildan biroz oshgan va biz hali ham ko'p narsalarni o'rganmoqdamiz. Dasturiy ta'minot arxitekturasi arxitekturaning o'zi kabi qari bo'lsa, bizda amal qilish qiyinroq qoidalar bo'lishi mumkin. Hozircha ushbu ko'rsatmalar siz va sizning jamoangiz yozadigan kodining sifatini baholash uchun asosiy mezon bo'lib xizmat qilsin.
Yana bir narsa: bularni bilishingiz sizni darhol yaxshi dasturchiga aylantirib qo'ymaydi va bu qoidalar bilan ko'p yil ishlash orqali xatolardan to'liq qutula olmaysiz. Har bir kod bo'lagi birinchi qoralama sifatida boshlanadi, huddi yumshoq loy o'zining yakuniy qattiq shakliga aylanganidek. Va nihoyat, biz boshqalar bilan birgalikda ishlab kamchiliklarni yo'q qilamiz. Hom qoralamalarni yaxshilayman deb o'zingizni mag'lub etmang! Buni o'rniga kodni o'zini mag'lub eting!
Yomon:
const yyyymmdstr = moment().format("YYYY/MM/DD");
Yaxshi:
const currentDate = moment().format("YYYY/MM/DD");
Yomon:
getUserInfo();
getClientData();
getCustomerRecord();
Yaxshi:
getUser();
Biz yozganimizdan ko'ra ko'proq kodni o'qiymiz. Muhimi, o‘qilishi va izlanishi oson bolgan kod yozishimiz. Tushunarsiz o'zgaruvchilar yaratishimiz orqali biz kodimizni o'qiydiganlarni qinaymiz. O'zgaruvchilaringiz qidirishga oson bo'lsin. Buddy.js va ESLint kabi vositalar nomsiz konstantalarni aniqlashga yordam beradi.
Yomon:
// What the heck is 86400000 for?
setTimeout(blastOff, 86400000);
Yaxshi:
// Declare them as capitalized named constants.
const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000; //86400000;
setTimeout(blastOff, MILLISECONDS_PER_DAY);
Yomon:
const address = "One Infinite Loop, Cupertino 95014";
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
saveCityZipCode(
address.match(cityZipCodeRegex)[1],
address.match(cityZipCodeRegex)[2]
);
Yaxshi:
const address = "One Infinite Loop, Cupertino 95014";
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
const [_, city, zipCode] = address.match(cityZipCodeRegex) || [];
saveCityZipCode(city, zipCode);
Yomon:
const locations = ["Austin", "New York", "San Francisco"];
locations.forEach(l => {
doStuff();
doSomeOtherStuff();
// ...
// ...
// ...
// Wait, what is `l` for again?
dispatch(l);
});
Yaxshi:
const locations = ["Austin", "New York", "San Francisco"];
locations.forEach(location => {
doStuff();
doSomeOtherStuff();
// ...
// ...
// ...
dispatch(location);
});
Agar klass/obyekt nomi kerakli ma'noni anglatsa, buni o'zgaruvchigiz(property) nomida ham takrorlamang.
Yomon:
const Car = {
carMake: "Honda",
carModel: "Accord",
carColor: "Blue"
};
function paintCar(car, color) {
car.carColor = color;
}
Yaxshi:
const Car = {
make: "Honda",
model: "Accord",
color: "Blue"
};
function paintCar(car, color) {
car.color = color;
}
Default argumentlar ko'pincha qisqaroq va tozaroq. Shuni yodda tutingki, funksiyangiz faqat aniqlanmagan argumentlar uchun default qiymatlarni beradi. ''
, ""
, false
, null
, 0
, va NaN
kabi boshqa "falsy" qiymatlar default qiymat bilan almashtirilmaydi.
Yomon:
function createMicrobrewery(name) {
const breweryName = name || "Hipster Brew Co.";
// ...
}
Yaxshi:
function createMicrobrewery(name = "Hipster Brew Co.") {
// ...
}
Funksiya parametrlarining miqdorini cheklash juda muhim, chunki bu funksiyani test qilishni osonlashtiradi. Uchdan ortiq parameterlar bo'lishi kombinatorli portlash ga olib keladi, yani siz tonnalab turli hil holatlarni test qilishingizga to'gri keladi.
Bir yoki ikkita argument ideal holat bo'lib, iloji bo'lsa, uchdan qochish kerak. Agar uchdan kopayib ketsa ularni birlashtirish kerak. Odatda, sizda ikkitadan ko'p argument bo'lsa, sizning funksiyangiz juda ko'p narsani qilishga harakat qilmoqda.
JavaScript sizga obyektlarni klass'larsiz yaratishga imkon berganligi sababli, sizga koplab argumentlar kerak bo'lganida, obyektdan foydalanishingiz mumkin.
Funksiya qanday xususiyatlarni(properties) kutayotganini aniq ko'rsatish uchun siz ES2015/ES6 destructuring sintaksisidan foydalanishingiz mumkin. Bu bir nechta afzalliklarga ega:
- Kimdir funksiya imzosiga (function signature) qarasa, qaysi xususiyatlar ishlatilayotgani aniq ko'ra oladi.
- Nomlangan parametrlarni simulyatsiya qilish uchun foydalanish mumkin.
- Destructuring argumentning belgilangan primitiv qiymatlarini klonlaydi. Bu nojo'ya ta'sirlarning(side effect) oldini olishga yordam beradi. Eslatma: argument obyektdan olingan (destructured) obyekt va massivlar klonlanmaydi.
- Linterlar sizni foydalanilmagan xususiyatlar haqida ogohlantiradi, bu destructuring yordamisiz ilojsiz.
Yomon:
function createMenu(title, body, buttonText, cancellable) {
// ...
}
createMenu("Foo", "Bar", "Baz", true);
Yaxshi:
function createMenu({ title, body, buttonText, cancellable }) {
// ...
}
createMenu({
title: "Foo",
body: "Bar",
buttonText: "Baz",
cancellable: true
});
Bu dasturlashdagi eng muhim qoidadur. Funksiya bir nechta ishni bajarsa uni har hil joyda ishlatish, test qilish va tushunish qiyinlashadi. Funksiyani faqat bir maqsadli qilsangiz, uni qayta refactor qilish va o'qish ancha ossonlashadi. Agar siz bu qollanmadan hech narsaga amal qilmasdan faqat shu qoidaga amal qilsangiz, siz ko'plab dasturchilardan oldinlab ketgan bo'lasiz.
Yomon:
function emailClients(clients) {
clients.forEach(client => {
const clientRecord = database.lookup(client);
if (clientRecord.isActive()) {
email(client);
}
});
}
Yaxshi:
function emailActiveClients(clients) {
clients.filter(isActiveClient).forEach(email);
}
function isActiveClient(client) {
const clientRecord = database.lookup(client);
return clientRecord.isActive();
}
Yomon:
function addToDate(date, month) {
// ...
}
const date = new Date();
// It's hard to tell from the function name what is added
addToDate(date, 1);
Yaxshi:
function addMonthToDate(month, date) {
// ...
}
const date = new Date();
addMonthToDate(1, date);