Temiz ve okunabilir kod… Yeşillikler arasında yürümek, en sevdiğiniz kahvenin kokusunu içinize çekmek ya da pofuduk bir tavşan gibi bir şeydir…
Yazılım geliştirme konusunda tecrübe kazanmış her kişi az çok anlamıştır ki; kodlarımızı makineler için değil gelecekteki kendimiz ve diğer geliştiriciler için yazıyoruz. Sadece çalışan ve işini yapan fakat okuması zor, kötü kod yazmak, o anı kurtarsa da, uzay-zaman içinde bilinmeyen bir yerde, yeni bir serseri tohum oluşması demektir. Bu tohumlar zamanları gelene kadar kendi aralarında eğlenip durur ve bazen birkaçı birleşip daha büyük tohum haline gelir. Görseniz onun tohum değil aslında bal kabağı ya da karpuz olduğunu söylersiniz. Vakit geldiğinde de bir kara deliğin içine girip, kurbanlarının beyninin içinde beliriverirler. Hayat enerjisini sömürürler ve karamsarlık, mutsuzluk, küfür etme isteği enzimleri salarlar.
Bilim bu tohumlar konusunda çaresizdir ve yapabileceği tek şey, bu tohumların rastgele geliştiriciler yerine o tohumun oluşmasına kim sebep olduysa onun beyninde çıkması için dua etmektir.
Halbuki temiz ve okunabilir kod yazmak o kadar da zor değildir. Bunun için size yardımcı olacak araçlar var ama bu yazının konusu değiller. O yüzden ufak bir referans listesi verip geçiyorum;
Javascript yazarken edindiğim tecrübeler ve okuduğum kaynaklardan öğrendiklerimle, birkaç ufak ama etkili olduğuna inandığım bazı “best practice”leri paylaşmak istiyorum.
# Tip Kontrolü
==
yerine ===
tercih et. Minik bir şey gibi görünse de, kod mantığını tamamen etkileyebilir. Ortamlarda “strong type checking” diye de bahsedilir.
0 == false // true 0 === false // false const value = "1"; if (value === 1) { // bu kısım çalışmayacak console.log(value); }
# Değişkenlerin ve Fonksiyonların İsimlendirilmesi
“Her mesleğin bir zorluğu vardır” derler. Yazılım geliştirirken bazen değişkenlere, fonksiyonlara vs… isim vermek zor olabilir. Ne kadar zor olsa da önemli olan değişkenlere isim verirken, o değişkenin amacını anlatan iyi bir isim vermektir. Uzun ya da kısa olması pek de önemli değil. Başka birisi ya da gelecekteki siz, bir değişkeni gördüğünüz zaman ne yaptığını anlayabilmeniz gerek.
// Kötü Örnek let mlvl = 10; let y = getSomething(lv); let allow; if (user.level > 30) { allow = true; } // İyi Örnek const MIN_LEVEL = 10; const userLevelGreaterThanMinLevel = user.level > MIN_LEVEL; // const isUserLevelValid = user.level > MIN_LEVEL;
// Kötü const items = ["Foo", "Bar", "Baz", "Qux"]; items.forEach(i => { runSomething(); anotherFunc(); anotherAnotherFunc(); // ... // ... // Bu noktada i değişkeninin anlamsız gelmesi mümkün runSomethingElse(i); }); // İyi items.forEach(i => { runSomething(); anotherFunc(); anotherAnotherFunc(); // ... // ... // Böyle hayat daha güzel runSomethingElse(item); });
Gereksiz yere değişkenlerin isimlerini uzatmaya gerek yok;
// Kötü const product = { productName: "Flying Fish", productCode: "Penguin-X", productColor: "Gray" }; product.productName; // İyi const product = { name: "Flying Fish", node: "Penguin-X", color: "Gray" }; product.name;
Değişkenlerdeki mantığı fonksiyonları isimlendirirken de kullanmamız gerek. Fonksiyonun işlevini açıklayan isimler seçmeye özen göstermek gerek.
// Kötü function noti(email) { // kodlar } // İyi function notifyUser(email) { // kodlar }
Bazıları da der ki; “Bir fonksiyon çok fazla parametre almamalı. İki ya da daha az iyidir. Hem test etmesi kolay olur.”
// Kötü function getProducts(code, description, fromDate, toDate) { // kodlar } getProducts('foo', 'lorem ipsum', '2019-10-10', '2019-10-12'); // İyi function getProducts({ code, description, fromDate, toDate }) { // kodlar } getProducts({ code: 'foo', description: 'lorem ipsum', fromDate: '2019-10-10', toDate: '2019-10-12' });
Fonksiyonlar içinde parametrelerin varsayılan değerlerini, koşul ifadeleri kullanarak kontrol etmek yerine, parametrelere varsayılan değer vermek daha iyidir.
// Kötü function createMonster(type) { const monsterType = type || "earth"; // kodlar } // iyi function createMonster(type = "earth") { // kodlar }
# Global Objeler ve ES Sınıfları
Buna pek ihtiyacım olmadı ama aklımda bulunması açısından buraya not düşmek iyi olur. Var olan global objelere ekstra işlevler katmak istersek, ES ‘in sunduğu sınıfları kullanmak daha iyi bir yöntem olacaktır.
// Kötü Array.prototype.mySuperFunc = function superFunc() { // kodlar }; // İyi class MySuperArray extends Array { mySuperFunc() { // kodlar } }
ES sınıflarını sadece global objeleri genişletmek için değil, prototype üzerinden fonksiyonlar ile sınıflar oluşturmak yerine de kullanmak, artık daha iyi ve kolay olacaktır.
// Kötü const Person = function(name) { if (!(this instanceof Person)) { throw new Error("Instantiate Person with `new` keyword"); } this.name = name; }; Person.prototype.sayHello = function sayHello() { /**/ }; const Student = function(name, school) { if (!(this instanceof Student)) { throw new Error("Instantiate Student with `new` keyword"); } Person.call(this, name); this.school = school; }; Student.prototype = Object.create(Person.prototype); Student.prototype.constructor = Student; Student.prototype.printSchoolName = function printSchoolName() { /**/ }; // İyi class Person { constructor(name) { this.name = name; } sayHello() { /* ... */ } } class Student extends Person { constructor(name, school) { super(name); this.school = school; } printSchoolName() { /* ... */ } }
# Kod Tekrarı ve Gereksiz Kodların Temizlenmesi
Temiz ve okunabilir kod yazmanın temellerinden birisi kod tekrarından kaçınmaktır. Aynı işleri yapan kodları tekrar tekrar yazmak yerine, fonksiyonlar haline getirmeye çalışmak daha iyi olacaktır.
Ayrıca artık kullanılmayan ölü kodları da mümkün olduğunca çabuk ve düzenli bir şekilde temizlemek gerek çünkü bir süre sonra o kodların ne işe yaradığını kimse hatırlamayacak ve gereksiz kalabalık oluşturmaktan başka işe yaramayacaklar.
Yorumlar