Clean Code
Clean Code
Clean Code
Temiz Kod
Akın Kaldıroğlu
Selsoft Yazılım Danışmanlık Eğitim ve Ticaret Ltd. Şti.
Hakkımda
• Balıkesir, Ayvalıklıyım.
• 1990 İTÜ mezunuyum.
• Sonrasında 1993 – 2001 yılları arasında
ABD’de master eğitimi aldım ve çalıştım.
• Yazılıma C/C++ ile başladım ve çıktığından bu
yana Java’yı kullanıyorum.
• İlk Java sertifikalı developerlardanım.
• 2001-2008 arasında Türkiye’de yazılım
mimarı, yazılım müdürü, GMY vb.
pozisyonlarda çalıştım. 2
Hakkımda
• Java Teknolojileri
3
Eğitmen Hakkında
Hakkımda
• [Link] adresinde bir günlüğüm var.
• Erişim noktalarım:
• Twitter: @kaldiroglu
• LinkedIn: [Link]/in/akinkaldiroglu/
4
Temiz Kod Nedir?
Clean Code - Temiz Kod Nedir?
• Clean Code ya da Temiz Kod (iyi, kaliteli, yalın kod) nedir?
• Nasıl tanımlarsınız?
• Siz kişisel olarak kod yazarken temiz olması adına nelere dikkat
ediyorsunuz?
6
Clean Code Nedir? - I
• Bjarne Stroustrup: Şık ve etkin (elegant and efficient)
Dave Thomas
8
Uncle Bob
• Clean Code kavramı Robert Cecil
Martin (uncle Bob) tarafından öne
çıkarılmıştır.
• [Link] adresinde
Clean Code eğitim videolarını
yayınlamaktadır.
9
Bence “Temiz Kod” - I
• Kodlama (programlama) aslen karmaşık ve zordur ve aslolan
geliştirmek değil değiştirmektir (bakım), dolayısıyla değişebilen kod
geliştirmek daha da zordur.
10
Bence “Temiz Kod” - II
• Clean code, teknolojiden, sektörden bağımsız olarak, anlaşılır,
yalın, kaliteli koddur.
11
Temiz Kod - Teknik Borç - I
12
Temiz Kod - Teknik Borç - II
• Yazılımda üretim hızını etkileyen pek
çok faktör vardır:
• İş ve teknik mimari,
13
Temiz Kod ve Karmaşıklık
• Temiz olmayan kod karmaşıktır (complex), temiz kod karmaşık değildir.
14
15
Temiz Kod Çerçevesi
Temiz Kod Çerçevesi - I
17
Temiz Kod Çerçevesi - II
• Basit (Simple)
• Odaklı (Focused)
• Doğru (Correct)
• Tam (Complete)
18
Temiz Kod Çerçevesi - III
19
20
Basitlik
Basitlik - I
• Çoğu zaman dilde basit (simple) kelimesini, bayağı, gelişigüzel anlamında
kullanırız.
• Bu “galat-ı meşhur”dur.
23
Basitlik Nihai Karmaşıklıktır
24
Basitlik Nasıl Elde Edilir? - I
• Basit, bir seferde elde edilen bir durum değildir.
• Basitleştirmek, bir şeye tümüyle, her yönüyle hakim olup, asıl ile
teferruatı ayırmaktır, gelişigüzel çıkarma, indirgeme değildir.
25
Basitlik Nasıl Elde Edilir? - II
26
Basitlik Nasıl Elde Edilir? - III
27
Basitlik Nasıl Elde Edilir? - IV
• Einstein’e atfedilen
ya da
Bir yazılım tasarımı geliştirmenin iki yolu vardır. Birisi onu o kadar
basit yapmaktır ki hiç bir hata olmadığı açık olsun. Diğeri onu o
kadar karmaşık yapmaktır ki açıkta görünen hiç bir hata olmasın.
31
Basit Kod Nasıldır? I
[Link]([Link]() ?
([Link]([Link]()) ?
[Link]() : [Link]()):
([Link]([Link]())) ?
[Link](): [Link]());
32
Basit Kod Nasıldır? II
#// Burada CardInfo’nun Idsi atanır. Id olarak eğer musteri TC vatandasi ise
#// ve ya WS’den ya da fromdan gelen tckn atanır. Eğer müşteri TC vatandaşı
#// değilse Id olarak customerNo alınır.
#// Burada da yine ya WS’den ya da formdan gelen customer no atanır.
String idNo = null;
boolean isTcCitizen = [Link]();
String tcknFromForm = [Link]();
String tcknFromWS = [Link]();
boolean nullOrEmptyTcknFromWS = [Link](tcknFromWS);
String custNoFromWS = [Link]();
Bu çok daha boolean nullOrEmptyCustNoFromWS = [Link](custNoFromWS);
basittir. if(isTcCitizen){
if(nullOrEmptyTcknFromWS)
idNo = tcknFromForm;
else
idNo = tcknFromWS;
}
else{
if(nullOrEmptyCustNoFromWS)
idNo = tcknFromForm;
else
idNo = custNoFromWS
} 33
[Link](idNo);
[Link]([Link]() ?
([Link]([Link]()) ?
[Link]() : [Link]()):
([Link]([Link]())) ?
[Link](): [Link]());
#// Burada CardInfo’nun Idsi atanır. Id olarak eğer musteri TC vatandasi ise
#// ve ya WS’den ya da fromdan gelen tckn atanır. Eğer müşteri TC vatandaşı
#// değilse Id olarak customerNo alınır.
#// Burada da yine ya WS’den ya da formdan gelen customer no atanır.
String idNo = null;
boolean isTcCitizen = [Link]();
String tcknFromForm = [Link]();
String tcknFromWS = [Link]();
boolean nullOrEmptyTcknFromWS = [Link](tcknFromWS);
String custNoFromWS = [Link]();
boolean nullOrEmptyCustNoFromWS = [Link](custNoFromWS);
if(isTcCitizen){
if(nullOrEmptyTcknFromWS)
idNo = tcknFromForm;
else
idNo = tcknFromWS;
}
else{
if(nullOrEmptyCustNoFromWS)
idNo = tcknFromForm;
else
idNo = custNoFromWS
}
[Link](idNo);
34
Anlaşılır Kod - I
• Anlaşılır kodun iki şartı vardır:
• Anlaşılır kod standard bir şekilde yazılmıştır, mümkün olan her yerde
aynı yaklaşımı, aynı çözümü, şekli, aynı ismi vs. kullanır.
• Anlaşılır kod odaklıdır, bir yerde sadece ve sadece bir şeyi yapar ama
tam yapar.
35
Anlaşılır Kod - II
36
Dilimiz ve Dünyamız
• L. Wittgenstein Tractatus Logico-Philosophicus (5.6
nolu not) isimli kitabında şöyle der:
37
İsimlendirme Zordur
Phil Karlton
38
İsimlendirme - I
• Anlaşılır isimlendirmenin en temel engeli kısaltmadır.
• “executeUser“ ne demek?
41
İsimlendirme - III
• Ne yaptığınızı bilmiyorsanız iyi isim veremezsiniz!
public class GenericUtil{…}
class XMLParsingUtil{…}
42
İsimlendirme - IV
ParaDate
TransactionDate
43
Odaklılık
Temiz Kod Çerçevesi
45
Anlaşılır Kod - İçerik Şartları - I
46
Anlamak İçin Kod
• Martin Fowler, Refactoring isimli kitabında şöyle der:
Any fool can write code that a computer can understand. Good
programmers write code that humans can understand.
47
Anlaşılır Kod - İçerik Şartları - II
• Anlaşılır kodun en temel içerik özelliği, odaklı olmasıdır.
• Odaklı kod, bir yerde birden fazla şeyi bir araya getirmez.
• Kodlama, anlama, anlatma, test, değişim vs. için odaklı kod şarttır. 48
Odaklılık İlkesi
• Odaklı kodun iki özelliği vardır:
• Tek hedefli
• Tekrarsız
• Tek hedeflilik, bir seferde sadece bir şeyi hedeflemek, onu yapmak,
halletmek demektir.
• Yapılan işi sadece ve sadece bir yerde ve bir kere yapmak, tekrarsız
kodun gereğidir.
49
Odaklı Kod
50
Odaklılık
• Odaklılık bir hedeftir ve farklı terimlerle ifade edilir.
Separation of concerns
Single-responsibility principle
High-cohesion
Low-coupling
51
Temel Prensipler - I
Techniques - Patterns
Principles
52
Temel Prensipler - II
• SOLID
• GRASP
53
SOLID Prensipleri
• SOLID prensipleri şunlardır:
• Open-Closed Principle
54
GRASP
• GRASP, “General Responsibility Assignment
Software Patterns”ın kısaltmasıdır.
55
GRASP
• GRASP patternları şunlardır:
• Controller
56
Odaklı ve Tekrarsız Kod İçin Budama
I have only made this letter longer because I have not had the
time to make it shorter.
58
Don’t Repeat Yourself - I
Her bilgi parçasının sistemde, tek, açık, güvenilir bir ifadesi olmak
zorundadır.
• Davranış, bilgi, kısıt, vs. ne olursa olsun sadece bir yerde olsun.
59
Don’t Repeat Yourself - II
• DRY prensibini sadece tasarım ile gerçekleştirmek imkansızdır.
60
Uygulama
Uygulama
• login() metodunu SRP’ye uygun olarak nasıl gerçekleştirilebileceğini
düşünün.
62
public void login(String tckn, String password) throws NoSuchCustomerException,
CustomerLockedException, CustomerAlreadyLoggedException, WrongCustomerCredentialsException,
MaxNumberOfFailedLoggingAttemptExceededException, ImproperCustomerCredentialsException,
NoProperPasswordException {
• login validateTckn(tckn);
validatePassword(password);
Customer customer = [Link](tckn);
metodu if ([Link]().equals(password) & ![Link]() & ![Link]()) {
[Link](true);
prosedürel [Link]([Link]() + " " + [Link]() + " logs in.");
[Link](customer);
birlikteliğe currentCustomer = customer;
} else if ([Link]()) {
throw new CustomerAlreadyLoggedException("Customer is already logged in. Please first log out.");
sahiptir. } else if ([Link]()) {
throw new CustomerLockedException("Customer is locked. Please consult your admin.");
} else if (![Link]().equals(password)) {
loginAttemptCount#++;
• Birden int limit = [Link]([Link]("[Link]")
if (loginAttemptCount #== limit)) {
yapıyor. }
else
throw new WrongCustomerCredentialsException("TCKN/password is wrong.");
}
}
63
public void login(String tckn, String password) throws NoSuchCustomerException,
CustomerLockedException, CustomerAlreadyLoggedException,
WrongCustomerCredentialsException,
MaxNumberOfFailedLoggingAttemptExceededException {
Customer customer = [Link](tckn);
1
if ([Link]().equals(password) &
![Link]() & ![Link]()) {
#// Database is updated when a customer logs in.
[Link](true);
if ([Link](customer))
currentCustomer = customer;
2
loginAttemptCount = 0;
}
else if ([Link]()) {
throw new CustomerAlreadyLoggedException("Customer is already logged in.
Please first log out."); 3
}
else if ([Link]()) {
throw new CustomerLockedException("Customer is locked.
Please consult your admin.");
4
}
else if (![Link]().equals(password)) {
badLoginAttemptCount#++;
if (badLoginAttemptCount #== [Link]([Link](
"[Link]"))) {
[Link](true); 5
[Link](customer);
throw new MaxNumberOfFailedLoggingAttemptExceededException("Max number of
login attempt reached: "
+ badLoginAttemptCount);
}
throw new WrongCustomerCredentialsException("TCKN/password is wrong.");
} 64
}
public void checkIfCustomerAlreadyLoggedIn(Customer customer) throws CustomerAlreadyLoggedException {
if ([Link]()) {
throw new CustomerAlreadyLoggedException("Customer is already logged in.
Please first log out."); 3
}
}
}
throw new CustomerLockedException("Customer is locked. Please consult your admin."); 4
}
}
}
yapan
public void checkLoginAttempCount(Customer customer) throws
MaxNumberOfFailedLoggingAttemptExceededException{
metotlar
if (loginAttemptCount #== [Link]([Link](
lockCustomer(customer);
"[Link]"))) { 5
}
}
• Bir kodun kendi başına doğruluğu ancak birim testiyle (unit test)
sınanabilir.
• Bir kodun çevresindeki diğer kod parçalarıyla birlikte doğru çalıştığı ise
ancak entegrasyon testiyle sağlanabilir.
68
Doğru Kod - II
69
Tamlık
Tam Kod - I
• Temiz kod tamdır (complete).
71
Tam Yazılım - II
• Sadece ilk maddeye, olması gerekene odaklanmak kodunuzu tam
yapmaz.
72
Savunmacı Programlama - I
• Savunmacı programlama (defensive programming) ismini
savunmacı sürüşten (defensive driving) alır.
• Hatta programcı, ileride kendisi için bile kodunu savunmacı bir şekilde
yazmalıdır.
74
Önleme ve Yönetme
• Savunmacı programlamanın tedbirleri iki türlü olabilir:
Selsoft
[Link]