Clean Code — BÖLÜM-2 — Sınırları Belirleme Ve İsimlendirme

Buse Yalçın
4 min readMay 4, 2021

--

Bir önceki bölüm ➜ Nedir Bu Clean Code ?

1. Sınırları belirleme

Ölçeği büyük projeler geliştirirken javascript, html, css, C#, sql gibi bir çok teknololojiyi bir arada kullanmamız gerekebilir. Ancak bu teknolojilerin her birinin söz dizimi ve yapısı farklıdır. Bu sebeple kullandığımız teknolojilerin sınırlarını belirlememiz gerekir. Bu da bize daha okunaklı, bakıma ve geliştirmeye açık kod yazma imkanı sunar.

2. İsimlendirme

İyi isim seçmek zaman alır, ancak uzun vadede daha çok zaman kazandırır.

İsimlendirme konusu kulağa çok basit bir konu gibi gelse de yazılım geliştirmenin en önemli noktalarındandır. Anlamsız veya kısaltmalarla verilen isimler bir süre sonra kodun okunurluğunu azaltarak kodu anlayacak kişiye zaman maliyeti olarak dönecektir. Aynı şekilde anlamlı ve doğru verilen isimler yazılımcının işini inanılmaz derecede kolaylaştırabilir.

İlk örneğimizle başlayalım:

int d; //elapsed time in days (gün cinsinden geçen süre)

d burada hiçbir şeyi açıklamıyor, günlerle ya da zaman ile alakalı hiçbir şey uyandırmıyor. Daha anlamlı isimler seçmeliyiz, şunlar gibi:

int elapsedTimeInDays;
int daysSinceCreation;
int daysSinceModification;
int fileAgeInDays;

Peki aşağıdaki kodun amacı nedir? Ne yaptığını açıklamak neden bu kadar zor? Karışık işlemler yok, boşluklar ve girintiler (indentation) de mantıklı. Burada problem kodun basitliği değil, kapalı oluşudur.

public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList)
if (x[0] == 4)
list1.add(x);
return list1;
}
  1. theList ne içeriyor?
  2. theList’in ilk elemanın önemi nedir?
  3. 4 değerinin önemi nedir?
  4. Dönen list1 listesini nasıl kullanmalıyım?

Bu soruların cevapları kodda değil, yazan programcının zihnindedir. Ancak şöyle olsa:

public List<int[]> getFlaggedCells() {
List<int[]> flaggedCells = new ArrayList<int[]>();
for (int[] cell : gameBoard)
if (cell[STATUS_VALUE] == FLAGGED)
flaggedCells.add(cell);
return flaggedCells;
}

Kodun basitliğinin değişmediğini fark edelim. Hala aynı sayıda işlemci ve sabit var. Ama kod daha açık hale geldi. Daha da ileri giderek, int[] dizisi kullanmak yerine, cell’leri içeren bir Cell sınıfı yapabiliriz.
Yaptığımız bu basit değişikliklerle kodda neler olduğunu anlamak daha kolay hale gelmiş olacaktır.

Kötü isim örneklerinden biri de küçük l (Lüleburgaz’ın L’si) ya da büyük O kullanmaktır. Çünkü küçük l bir(1) rakamına benzeyebilirken, büyük O(Osmancık’ın O’su) ise sıfıra(0) benzemektedir.

int a = l;
if (O == l)
a = O1;
else
l = 01;

a1, a2, a3, … gibi isimlendirmeler kesinlikle anlamlı değildir. Bu tür isimler yazarın amacı hakkında en ufak bir ipucu bile vermezler. Burada a1 ve a2 yerine source (kaynak) ve destination (hedef) kullanılması çok daha anlamlıdır:

public static void copyChars(char a1[], char a2[]) {
for (int i = 0; i < a1.length; i++) {
a2[i] = a1[i];
}
}

Aşağıda ki şekilde isimlendirilmiş metotlarımız olsun;

getActiveAccount();
getActiveAccounts();
getActiveAccountInfo();

Geliştiriciler bu metotlardan hangisini çağıracağını nasıl bilebilir? Benzer durum değişkenlerde de karşımıza çıkabilir. Örneğin moneyAmount değişkeni money değişkeninden, customerInfo customer’dan ya da accountData account’tan ayırt edilemez.

Tek harfli isimleri yalnızca kısa metotlarda lokal değişken olarak kullanılmalıdır. Eğer bir değişken ya da sabit bir kod bloğunda birden fazla kullanılacaksa, arama dostu bir isim vermek en iyisidir.

Şu iki kodu karşılaştıralım:

for (int j = 0; j < 34; j++) {
s += (t[j] * 4) / 5;
}
VEint realDaysPerIdealDay = 4;
const int WORK_DAYS_PER_WEEK = 5;
int sum = 0;
for (int j = 0; j < NUMBER_OF_TASKS; j++) {
int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK);
sum += realTaskWeeks;
}

sum çok kullanışlı bir isim değil ancak en azından aranabilir. Benzer şekilde
WORK_DAYS_PER_WEEK sabitinin kullanımlarını bulmak, 5 sayısını bulmaktan kat be kat daha kolaydır.

Sınıf isimleri Customer, WikiPage, Account ya da AddressParser gibi isimlerden/isim tamlamalarından oluşmalıdır. Sınıf isimleri asla bir fiil olmamalıdır.

Metot isimleri postPayment(), deletePage() ya da save() gibi fiillerden/fiil tamlamalarından oluşmalıdır. Erişimci (getters), mutatör (setters) ya da doğrulayıcı (predicate) (true/false dönen; isEmpty() gibi) metotların başlarına, Java standartlarına göre get, set, is eklenmelidir.

String name = employee.getName();
customer.setName("Mike");
if (paycheck.isPosted())

Farklı parametrelere sahip kurucular (constructors) oluşturmak yerine, “static” yapıcı (builder) metotlar kullanılmalıdır.

İlk satırdaki kod örneği, ikincisinden çok daha iyidir:

Complex fulcrumPoint = Complex.FromRealNumber(23.0);
Complex fulcrumPoint = new Complex(23.0);

İki farklı amaç için aynı kelimeyi kullanmaktan ya da aynı amaçlar için farklı kelimeleri kullanmaktan kaçının. Örneğin Controller, Manager ya da Driver kelimelerini aynı kapsamda farklı sınıflar için kullanmak iyi bir kullanım örneği değildir. Birini seçin ve onunla devam edin.

Örneğin birileri sizden önce add metodu yazmış olsun ve bu metot da iki değeri birbirine birleştiriyor (concat) olsun. Bizim de bir listeye değer ekleyen bir metota ihtiyacımız olsun. Bu metoda add mi demeliyiz? Hayır. Bu durumda yeni metodumuza insert ya da append demeliyiz. Yeni bir add metodu yazmak, kelime oyunu yapmaktır.

firstName, lastName, street, houseNumber, city, state ve zipcode isimli değişkenlerimiz olduğunu düşünelim. Birlikte alınca bir adresin detayları olduğunu çok çabuk anlayabiliyoruz. Ancak sadece state değişkenini görürsek, gene de adrese ait olduğunu düşünebilir miyiz?

Önekler (prefix) kullanarak bağlam (context) sağlayabilirsiniz; addrsFirstName, addrLastName, addrState vb. En azından okuyucular bu değişkenlerin daha büyük bir yapının parçası olduğunu anlayabileceklerdir. Elbette daha iyi bir çözüm Address isimli bir sınıf yaratmaktır.

Bu yazımda anlatacaklarım şimdilik bu kadar. Bilgi paylaştıkça çoğalır. Okudukça paylaşmaya devam edeceğim 😊

Yazımı faydalı bulduysanız aşağıda ki alkış butonuna çökmeye ne dersiniz 👏 👼

Bir sonraki bölüm ➜ Clean Code’ da Fonksiyonlar

--

--

Buse Yalçın

Computer Engineer ⚪️ Backend Developer ⚪️ Research freak 💃🏼 GitHub: https://github.com/Buse5 Website: buse5.github.io