Temiz kod neden hâlâ önemli: korunmaya değer sekiz ilke
Yapay zeka senin yerine yeniden düzenleyebiliyor; bu temelleri gereksiz kılmıyor, daha kullanışlı yapıyor. Kod tabanını çalışılabilir tutan sekiz pratik.
Yapay zeka ve temiz kodun bugünkü yeri
Yapay zeka artık bu işin her yerinde; kod parçacığı üretmekten bütün fonksiyonlar yazmaya kadar. Bir model senin yerine yeniden düzenleyebiliyorken temiz kod yazmanın hâlâ bir anlamı var mı diye sormak makul.
Ben de bu soruyla bir süre gidip geldim. Yapay zeka yetkin bir asistan, ama zihin okuyucu değil. Optimize edebiliyor, yeniden düzenleyebiliyor, daha net alternatifler önerebiliyor; bunların hepsi sağlam bir yerden başladığında daha iyi çalışıyor. İyi bir aşçıya mükemmel malzeme ve darmadağın bir tarif verirsen, tabak yine yanlış çıkar.
Temiz kod netlikle, sürdürülebilirlikle ve bir projenin nasıl yaşlandığıyla ilgili. Yan etkisi olarak yapay zeka araçlarını da daha etkili kılıyor. Ayakta kalan sekiz ilke şöyle.
1. Anlamlı isimler
Netlik burada başlıyor. Bütün karakterlerin adının "a", "b" ve "c" olduğu bir hikâye düşün. Kod da farklı değil. Değişkenler, fonksiyonlar ve sınıflar, gövdelerinden tek satır okumadan önce ne yaptıklarını ya da neyi temsil ettiklerini söylemeli.
let d; // What is 'd'? Days? Data?
function p(a, b) {
/* ... */
} // What does 'p' do? What are 'a' and 'b'?
Şununla karşılaştır:
let daysSinceLastLogin;
function calculateTotalPrice(quantity, unitPrice) {
/* ... */
}
İyi isimler kodun içinde belge gibi çalışıyor. Okumanın zihinsel yükünü azaltıyor ve hata ayıklamayı hızlandırıyor. Kodunu okuyan bir model de senin faydalandığın netlikten faydalanıyor.
2. Bir fonksiyon tek bir iş yapmalı
Her fonksiyonun değişmek için tek bir sebebi olmalı. Bir fonksiyon fazla iş yaptığında test etmesi zorlaşıyor, takip etmesi zorlaşıyor ve ona dokunduğunda kırılma ihtimali artıyor.
function processOrder(order) {
// Validate order
// Save to database
// Send confirmation email
// Update inventory
}
Bunun yerine böl:
function validateOrder(order) {
/* ... */
}
function saveOrder(order) {
/* ... */
}
function sendConfirmationEmail(order) {
/* ... */
}
function updateInventory(order) {
/* ... */
}
function processOrder(order) {
validateOrder(order);
saveOrder(order);
sendConfirmationEmail(order);
updateInventory(order);
}
Karmaşık bir işi odaklı parçalara ayırmak kodu modüler yapıyor ve sonradan okumayı hatırı sayılır ölçüde kolaylaştırıyor.
3. Kendini tekrar etme
Aynı mantığı ikinci kez yazıyorsan onu bir fonksiyona ya da yeniden kullanılabilir bir bileşene çek. Tekrar, sürdürülebilirliği sessizce yok ediyor: bir hatayı düzeltmen gerektiğinde birkaç yerde düzeltmen gerekiyor ve eninde sonunda birini atlıyorsun.
// In file A
function calculateDiscountA(price) {
if (price > 100) return price * 0.9;
return price;
}
// In file B (same logic)
function calculateDiscountB(amount) {
if (amount > 100) return amount * 0.9;
return amount;
}
Tek bir uygulama yeterli:
function applyStandardDiscount(price) {
if (price > 100) return price * 0.9;
return price;
}
// Now both A and B can use applyStandardDiscount
4. Ne'yi değil neden'i yorumla
İyi kodun yoruma ihtiyacı olmadığını duymuş olabilirsin; kısmen doğru. Anlamlı isimlerle yazılmış açık kod, yorumların çoğunu gereksiz kılıyor.
Kaydetmen gereken şey, bir işin neden o şekilde yapıldığı ya da bir geçici çözümün neden var olduğu. Bu tür bir yorumun değeri yüksek.
// Increment the counter by 1
counter++;
Bu hiçbir şey katmıyor. Bu katıyor:
// This specific regex is used to handle legacy user IDs
// which sometimes contain leading zeros and special characters.
const userIdRegex = /^[0-9a-zA-Z\-_]+$/;
Kodun ne yaptığını açıklamak için bir yoruma ihtiyaç varsa, bu genelde kodun daha net olabileceğinin işareti.
5. Hataları ele al
Ağlar kopuyor, kullanıcılar anlamsız şeyler yazıyor, API'ler beklenmedik cevaplar dönüyor. Bunu yok saymak, öngörülemez davranışa ve neyin ters gittiğini anlayamayan kullanıcılara yol açıyor.
Ne kadar hata yönetiminin yeterli olduğu bağlama bağlı, ama makul bir kural şu: hatayı, ya toparlanabildiğin ya da kullanıcıya veya sisteme işe yarar bir şey söyleyebildiğin yerde ele al.
function getUserData(userId) {
const data = api.fetch(userId); // What if api.fetch fails?
return data.name;
}
Buna daha yakın bir şey:
async function getUserData(userId) {
try {
const response = await api.fetch(userId);
if (!response.ok) {
throw new Error(`Failed to fetch user data: ${response.statusText}`);
}
const data = await response.json();
return data.name;
} catch (error) {
console.error(`Error fetching user ${userId}:`, error);
// Potentially return a default value, or re-throw a custom error
throw new CustomApplicationError("User data unavailable");
}
}
6. Tutarlı kal
Tutarlılık en çok büyük ekiplerde önemli: kod tabanı boyunca aynı isimlendirme kuralları, aynı biçimlendirme, aynı mimari örüntüler ve tasarım tercihleri. Bir yerde camelCase, başka bir yerde snake_case kullanıldığında okumak sebepsiz yere zorlaşıyor.
ESLint ve Prettier gibi araçlar bunun çoğunu otomatik hallediyor.
let firstName;
const user_id = 123;
function getProducts() {
/* ... */
}
const fetchOrders = async () => {
/* ... */
};
Buna karşılık:
let firstName;
const userId = 123;
function getProducts() {
/* ... */
}
async function fetchOrders() {
/* ... */
}
Tutarlı bir kod tabanı, elli kişi yazmış olsa bile tek kişi yazmış gibi okunuyor. Bu da dosyalar arasında gezinmenin yükünü azaltıyor.
7. Test yaz
Test yazmak angarya gibi gelebiliyor. Aynı zamanda nefesini tutmadan yeniden düzenlemeni ve yayına almanı sağlayan şey. Yapay zeka destekli geliştirmede bunun önemi azalmıyor, artıyor: üretilen kodun doğru entegre olup olmadığını ve başka bir yeri bozup bozmadığını testler söylüyor.
Küçük bir değişiklik yaptığını ve uygulamanın alakasız bir kısmının devrildiğini düşün. Testler yoksa bu uzun bir hata ayıklama seansı. Testler varsa kırılan durum sana problemi gösteriyor.
// function to test
function add(a, b) {
return a + b;
}
// test file
describe("add function", () => {
test("should add two positive numbers correctly", () => {
expect(add(1, 2)).toBe(3);
});
test("should handle negative numbers", () => {
expect(add(-1, 5)).toBe(4);
});
test("should return zero when adding opposite numbers", () => {
expect(add(-3, 3)).toBe(0);
});
});
8. Sadelik
Yukarıdakilerin hepsi tek bir şeye iniyor: basit ve okunması kolay kod yazmak. Dolambaçlı kod hata çekiyor ve bakıma direniyor. Gereksinimi karşılayan en basit çözümü hedefle.
function calculateTotal(items) {
let total = 0;
for (let i = 0; i < items.length; i++) {
let item = items[i];
if (item.type === "premium") {
total += item.price * 1.1; // 10% premium fee
} else {
total += item.price;
}
}
return total;
}
Aynı şey, takip etmesi daha kolay hâli:
const calculateItemPrice = (item) => {
if (item.type === "premium") {
return item.price * 1.1;
}
return item.price;
};
function calculateTotal(items) {
return items.reduce((acc, item) => acc + calculateItemPrice(item), 0);
}
Sadelik kodu aptallaştırmak değil. Bir yıl sonra da anlayacağın bir şey yazmak.
Zanaat ortadan kalkmıyor
Yeni araçlar gelmeye devam ediyor ve yapay zeka çok şeyi değiştirdi, ama zaten yaptığın şeyi büyütüyor; onu iyi yapma ihtiyacını ortadan kaldırmıyor.
Temiz kod bir kural kitabından çok bir alışkanlık. Meslektaşlarına, kullanıcılarına ve bu dosyayı on sekiz ay sonra açacak olan sana gösterilen bir nezaket.