İçeriğe geç

Pratik Temiz Kod: Adlandırma

8 dk okuma

Bu yazı makine çevirisidir. İngilizce aslını oku

İçindekiler
  1. Kodun hedef kitlesi kim?
  2. Zihinsel bir model olarak programlama
  3. Anlamsız adlar
  4. Yanıltıcı adlar
  5. Daha iyi adlar nasıl verilir?
  6. 1. Belirgin ve Açıklayıcı Olun
  7. 2. Tutarlı Adlandırma Kurallarına Uyun
  8. 3. Gereksiz Kısaltmalardan Kaçının
  9. 4. Alana Özgü Dil Kullanın
  10. 5. Gereksiz Tekrardan Kaçının
  11. 6. Birbirini Tamamlayan İşlemler İçin Zıt Adlar Kullanın
  12. 7. Fonksiyonlar İçin Fiil, Değişkenler/Sınıflar İçin İsim Kullanın
  13. 8. Boolean Adlandırma
  14. 9. Yanıltıcı Adlardan Kaçının
  15. Sonuç

Bilgisayar biliminde yalnızca iki zor şey vardır: önbellek geçersiz kılma ve bir şeyleri adlandırma.

- Phil Karlton

Programları bilgisayarlar için değil, insanlar için yazarız.

Bunun tersini düşünmek yaygın bir yanılgıdır; ya da bu konu üzerinde yeterince kafa yormuyoruz.

Bir kutuya üzerinde 'Name' yazan bir etiket yapıştıran kişi

Kodun hedef kitlesi kim?

Biraz düşünelim.

Kabaca söylemek gerekirse makineler makine kodunu anlar ve en verimli şekilde onunla çalışır. Daha yüksek seviyeli bir dilde kod yazdığımızda kodumuz ya daha düşük seviyeli dillere dönüştürülür ya da bu işe özel bir program tarafından yorumlanır. Her iki durumda da yalın makine kodunun üzerine yeni soyutlama katmanları ekleriz. Bu da dönüştürme veya yorumlama süreçlerinde daha fazla karmaşıklık ve gereksiz kod ya da işlem anlamına gelir. Peki öyleyse neden daha yüksek seviyeli bir dilde kod yazıyoruz?

Cevap basit: Kodu insanlar için yazıyoruz.

Kodumuzun insanlar tarafından anlaşılabilir olmasını istiyoruz.

Altı ay sonra, ne hakkında olduğunu tamamen unuttuğumuzda bile o kodun bakımını yapabilmek istiyoruz.

Başkasından devraldığımız kodu anlamak istiyoruz. Onu doğru biçimde değiştirebilmek, yeni değişiklikleri ve gereksinimleri uygulayabilmek için anlamak zorundayız.

Kısacası kodumuzun okunabilir, anlaşılır ve bakımı kolay olmasını istiyoruz.

Kodun insanlar ve bilgisayarlar tarafından okunmasını gösteren diyagram

Zihinsel bir model olarak programlama

Kodu insanlar için yazdığımızda hemfikirsek, insanlar için daha iyi kodu nasıl yazacağımızı düşünelim.

Programlama yaparken zihnimizde dünyanın zihinsel bir modelini oluştururuz. Bu model gerçek dünyanın kendisi olmak zorunda değildir; daha karmaşık bir problem alanını basitleştirir. Dolayısıyla modelin, üzerinde çalışılacak kadar basit kalırken olabildiğince doğru olmasını isteriz.

Model gerçek dünyayı “modellediği” için zihnimizdeki kavramları koddan gerçek dünyadaki karşılıklarına eşlememiz ya da çevirmemiz gerekir. Bu, ana dilimiz olmayan bir dili konuşmaya benzer.

O yabancı dilde düşünemiyorsanız, kelimeleri ve cümleleri doğal olarak zihninizde çevirirsiniz. Daha fazla iş yaptığınız için yabancı dilde konuşmak size daha çok zaman ve enerjiye mal olur. Ama doğrudan o yabancı dilde düşünmeyi öğrenirseniz zihninizde herhangi bir çeviri olmaz; böylece daha akıcı konuşur ve konuşurken daha az enerji harcarsınız.

Bu benzetmeyi programlamaya uyarlarsak: koddaki kavramları gerçek dünyaya kolayca eşleyebiliyorsak kodu anlamak ve kod üzerinde akıl yürütmek de daha kolay olur.

Kod ile dünya arasındaki eşlemeyi kolaylaştırmak için yapılacak ilk şey nedir? Adlandırma.

Kodumuzdaki şeyleri adlandırırken özensiz davranmayı bırakmalıyız. Bu, temiz kod pratiklerinin ilk ve en önemli adımıdır.

Neden mi? Adlandırma neden temiz bir zihinsel modelin en önemli bileşenidir?

Bir çocuk tahtadaki harfleri işaret ediyor.

Anlamsız adlar

Berbat adlandırılmış bir kodu devraldığınızı düşünün. Değişkenlerin, fonksiyonların ve sınıfların adları yanıltıcı ya da okuması zor. Kaybolmuş hissedersiniz, değil mi? Kodu daha iyi bilen birinin rehberliğine ihtiyaç duyarsınız. Ekibiniz yeni üyelerin uyum sürecine daha fazla adam/saat harcamak zorunda kalır. Öte yandan iyi adlar, kodda gezinirken yanınızda bir rehber olması gibidir.

Bu kodun ne yaptığını anlıyor musunuz?

public class P {
private int a;
private int b;
private List<Integer> l;

    public P(int x, int y) {
        this.a = x;
        this.b = y;
        this.l = new ArrayList<>();
    }

    public void m() {
        for (int i = 0; i < a; i++) {
            int t = f(i);
            if (g(t)) {
                l.add(t);
            }
        }
        s();
    }

    private int f(int n) {
        return n * b;
    }

    private boolean g(int v) {
        return v % 2 == 0;
    }

    private void s() {
        Collections.sort(l);
    }
}

Boş verin. Uğraşmaya değmez. Ama ne demek istediğimi anladınız.

Karışık, okunmaz harflerden oluşan bir tabela.

Yanıltıcı adlar

Kodu hiç anlamamaktan daha kötü bir şey varsa o da kodu yanlış anlamaktır. Kötü adlandırma kodun anlamını yanlış yorumlamanıza yol açabilir; bu da beklenmedik hatalara ve gereksiz hata ayıklama süresine neden olur. İnanın bana, değerli zamanınızı harcamanın en iyi yolu bu değil.

Şu örneğe bakalım:

public class UserManager {
private List<User> deletedUsers;

    public UserManager() {
        this.deletedUsers = new ArrayList<>();
    }

    public void deleteUser(User user) {
        deletedUsers.add(user);
    }

    public void removeInactiveUsers() {
        for (User user : deletedUsers) {
            if (!user.isActive()) {
                user.deactivate();
            }
        }
    }

    public int getActiveUserCount() {
        return deletedUsers.size();
    }
}

Kötü adlandırma yüzünden metotların amacını söylemek zor. Hiçbir anlam ifade etmiyor. Birkaç adlandırma sorunu var:

  • deletedUsers listesi yalnızca silinen kullanıcıları değil, tüm kullanıcıları içeriyor.
  • deleteUser metodu kullanıcıyı silmiyor, listeye ekliyor.
  • removeInactiveUsers kullanıcıları kaldırmıyor, devre dışı bırakıyor.
  • getActiveUserCount yalnızca aktif kullanıcıların değil, tüm kullanıcıların sayısını döndürüyor.

Adlandırmayı düzelttikten sonra şunu elde ederiz:

public class UserManager {
private List<User> allUsers;

    public UserManager() {
        this.allUsers = new ArrayList<>();
    }

    public void addUser(User user) {
        allUsers.add(user);
    }

    public void deactivateInactiveUsers() {
        for (User user : allUsers) {
            if (!user.isActive()) {
                user.deactivate();
            }
        }
    }

    public void removeDeactivatedUsers() {
        allUsers.removeIf(user -> !user.isActive());
    }



    public int getTotalUserCount() {
        return allUsers.size();
    }

    public int getActiveUserCount() {
        return (int) allUsers.stream().filter(User::isActive).count();
    }
}

Daha iyi adlar nasıl verilir?

1. Belirgin ve Açıklayıcı Olun

Genel adlar kullanmak yerine davranışı ya da veriyi tarif eden adlar kullanmalıyız. Bu, yorum satırlarına olan ihtiyacı azaltır. Ayrı bir konu ama gerekmedikçe yorum satırlarından kaçınmalısınız; çünkü kodunuz kendini olabildiğince kendi başına açıklamalı.

Aşağıdaki örnekte girdi verisinin ne olduğu ve process metodunun tam olarak ne yaptığı belli değil. Bu yüzden geliştirici, bağlamı daha iyi açıklamak için bu metoda birkaç yorum satırı eklemek zorunda kalabilir. Bunun yerine metodu ve parametreyi aşağıdaki gibi yeniden adlandırmalı.

// BAD! Don't do this!
void process(List<String> data)

// BETTER!
void calculateAverageUserRatings(List<String> userRatings)

2. Tutarlı Adlandırma Kurallarına Uyun

Bütün modern dillerin yerleşik bir yazım biçemi vardır. Adlandırmada da ona bağlı kalın.

Kötü:

class user_account {
private String UserName;
private String email_address;
private int Age;
}

İyi:

class UserAccount {
private String username;
private String emailAddress;
private int age;
}

3. Gereksiz Kısaltmalardan Kaçının

Kodunuzda yaygın olmayan kısaltmalar kullanmak için neredeyse hiçbir neden yoktur. Bu, kodu daha az anlaşılır hale getirir.

Kötü:

int d; // Days
List<String> lst; // List of items

İyi:

int daysElapsed;
List<String> shoppingItems;

4. Alana Özgü Dil Kullanın

“Form”, “List” gibi kodun teknik ayrıntılarını yansıtan adlar yerine, daha önce konuştuğumuz zihinsel modeli daha iyi yansıtan alan dilini kullanın.

Kötü:

class Form {
String i1;
String i2;
Date i3;
}

İyi:

class PatientRecord {
String patientName;
String diagnosis;
Date admissionDate;
}

5. Gereksiz Tekrardan Kaçının

Adlandırmada gereksiz tekrarlardan kaçının. Bu, “gereksiz kısaltmalardan kaçının” kuralıyla çelişiyormuş gibi gelebilir ama çelişmez. Her şeyin bir dengesi olmalı. Çok kısa da kötüdür, çok uzun da.

Aşağıdaki örnekte “customer” kelimesini alan adlarında tekrar etmemize gerek yok; çünkü bağlamdan zaten anlaşılıyor.

Kötü:

class Customer {
String customerName;
String customerAddress;
int customerAge;
}

İyi:

class Customer {
String name;
String address;
int age;
}

6. Birbirini Tamamlayan İşlemler İçin Zıt Adlar Kullanın

Yalnızca tek tek öğelerin adlarını değil, bütün resmi düşünün. Bu, kodunuzu daha tutarlı kılar.

Örneğin ilk bakışta init/finish çiftinin zıt ya da simetrik işlemler olup olmadığı belli değildir. Ama open/close ya da start/stop çiftlerinin zıt işlemler olduğunu söylemek kolaydır.

Kötü:

file.init();
file.finish();

İyi:

file.open();
file.close();

7. Fonksiyonlar İçin Fiil, Değişkenler/Sınıflar İçin İsim Kullanın

Bu çok temel bir kural ama yine de anmaya değer. En iyisi davranış için fiil, veri/nesneler için isim kullanmaktır. Her kuralda olduğu gibi bunun da builder'lar ya da DSL fonksiyonları gibi bazı istisnaları var; ama o istisnaları şimdilik bir kenara bırakalım.

Kötü:

class calculation {
int number(int x, int y) {
return x + y;
}
}

İyi:

class Calculator {
int add(int firstNumber, int secondNumber) {
return firstNumber + secondNumber;
}
}

8. Boolean Adlandırma

Nihai amaç kodu düz İngilizce gibi daha okunabilir kılmak olduğundan, boolean döndüren metotları “is”, “are” gibi olmak fiilleriyle adlandırın. Böylece kullanıldığı yerde daha akıcı ve doğal okunur.

Kötü:

boolean flag = user.ValidateUserCredentials();

İyi:

boolean isValid = user.areCredentialsValid();

9. Yanıltıcı Adlardan Kaçının

Daha önce konuştuğumuz gibi, yanıltıcı adlar kullanmak en kötüsüdür! Adların doğru kalmasına özellikle dikkat edin; size ya da bir meslektaşınıza yalan söylemelerine izin vermeyin.

Kötü:

List<User> inactiveUsers = getAllUsers();

İyi:

List<User> allUsers = getAllUsers();

Sonuç

Kod yazarken genellikle aceleyle davrandığımız ya da pek önemsemediğimiz için daha iyi, daha açıklayıcı adlar bulmaya yeterince çaba harcamayız. Oysa iyi adlar vermek gerçekten önemlidir.

Programlamada doğru adlandırma; kod kalitesini, okunabilirliği ve bakım kolaylığını önemli ölçüde etkileyen kritik bir beceridir. İyi adlar çeşitli faydalar getirir:

  1. Sizin ve diğer geliştiricilerin bilişsel yükünü azaltır
  2. Yanlış anlama ve hata riskini en aza indirir
  3. Kodunuzu kendi kendini belgeler hale getirir, aşırı yorum satırı ihtiyacını azaltır
  4. Ekip içinde kod incelemelerini ve bilgi aktarımını kolaylaştırır
  5. Sizi her bileşenin amacını net düşünmeye zorlayarak yazılımınızın genel tasarımını iyileştirir

İyi adlandırma süregiden bir süreçtir. Problem alanına dair anlayışınız geliştikçe adları yeniden düzenleyin ve iyileştirin. Bu, uzun vadede daha az hata ayıklama süresi, daha kolay bakım ve daha sorunsuz iş birliği olarak geri döner.

Sonuçta amacınız kodunuzun bir hikâye anlatması olsun. Yeni bir geliştirici kodunuzu okuduğunda, kapsamlı bir dış belgelendirmeye ihtiyaç duymadan amacını ve işlevini anlayabilmeli. Daha iyi adlar vererek yalnızca kod yazmış olmazsınız; gelecekteki okuyuculara (kendiniz dahil) yazılımınızın mantığı ve niyeti boyunca yol gösteren bir anlatı kurarsınız.

Şimdi bir dakikanızı ayırıp mevcut projenize bakın. Kötü adlandırılmış bir değişken, fonksiyon ya da sınıf bulun ve burada konuştuğumuz ilkelerle yeniden adlandırın. Bu küçük adım, daha temiz ve daha okunabilir koda giden yolda ilk adımınızdır.

Unutmayın, daha iyi adlandırma pratikle gelişen bir beceridir. Her seferinde bir ad; devam edin.