Temiz Kod Nasıl Yazılır? – Basitlik İlkesi – I
Bu yazıda, daha önce paylaşmış olduğum Temiz ve Kaliteli Kod Nasıl Yazılır? başlıklı yazıda bahsettiğim kaliteli kodun ilkelerinden olan basitliği ele alacağım.
Sanılanın aksine bir şeyi basit tutmak zordur, uzun bir şekilde ele almak çok daha kolaydır. Çünkü bir şeyi ilk defa yaparken büyük bir ihtimalle en uzun şekliyle, en zor haliyle yaparız. Ancak o konuda tecrübe sahibi oldukça, anlayışımız, yetkinliğimiz gelişir ve işin aslına odaklanabiliriz. Basitleştirmek, bir şeye tümüyle, her yönüyle hakim olup, asıl ile teferruatı ayırmak, neyin gerekli neyin gereksiz olduğuna karar vermektir, orasını burasını gelişi güzel budamak değildir. İlkini yapan beğenilir, ikincisini yapan indirgemeci olmakla ya da aşırı basitleştirmekle eleştirilir. Einstein’e atfedilen “her şey olabilidiğince basit olmalı, ama daha da basit değil” (everything should be made as simple as possible, but no simpler.) ya da “her şeyi olabildiğince basitleştir, ama daha da basit yapma” (make things as simple as possible, but not simpler.) cümleleri aslında bunu ifade eder.
Bir şey ne zaman mükemmele ulaşır? Mükemmellik nasıl elde edilir? Kamaşıklıkla mı yoksa basitlikle mi? Küçüklükle mi büyüklükle mi? Mükemmellik sonuçta insan taktiridir. İnsan ise basiti daha rahat anlar ve taktir eder, karmaşığı anlamak zordur. Eğer aynı iş, bir basit bir de karmaşık yöntemle yapılabiliyorsa, akl-ı selim olan herkes basit olanı seçer. Mükemmellik tabi olarak algıya bağlıdır ama sanırım Fransız yazar Antoine de Saint-Exupery‘ın şu sözü mükemmel olmanın en temel özelliği olan basitliği çok güzel bir şekilde ifade etmektedir: “Mükemmellik, eklenecek bir şey olmadığında değil, çıkarılacak bir şey olmadığında başarılır.” (Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.) Dolayısıyla küçük her zaman güzeldir. Küçüklük dışında bir güzelleştirme aramaya gerek yoktur.
Basitleştirmek çok sağlıklı ve sağlam bir anlayış, vukufiyet gerektirir. Bu anlayış ve vukufiyeti kazanmak hem zeka hem bilgi ve tecrübe hem de çalışma gerektirir. (Bu anlamda “basit”liği, ele yüze bulaştırmadan, basit bir şekilde anlatmak o kadar zor ki! Hele benim gibi mükemmelliyetçi birisi için. Özellikle yazılım ve programlama gibi aslında zaten anlaşılması ve tarif edilmesi zor olan soyut yapılar için bir çırpıda basit olmayı anlatmak bence çok daha zor bir iş. En azından benim boyumu aşar. Yani bu yazıyla her türlü karizmayı çizdirme riskini göz önüne almış oluyorum. 🙂 Bu yüzden bu yazıyı önce yayınladım sonra geri çektim, üzerine bayağı düşündüm, yaz-boz yaptım ve eskiden bu yana düşündüğüm ama formal bir hale dökemediğim “basit”likle ilgili biraz daha geliştirdiğim anlayışımı paylaşıyorum.)
Basitliği tarif etmek zor hayattaki pek çok şey gibi ama ters örnekleri gördüğümüzde en azından bu basit değil diyebiliriz. Örneğin şu yazıda bahse konu olan ifade kesinlikle basit değil. Bu ifadenin basit olmayıp son derece karmaşık olmasına sebep olan şey bence iki tanedir: İlk ve en temel sebep, bir yerde birden fazla şey yapmak. Yani bir yerde pek çok şeyi halletmeye çalışmak, odaklanmamaktır. Karmaşıklığın en temel sebebi ise budur. Bu bir içerik problemidir ve genelde problemlerin en kötüsü, üstesinden en zor gelinenidir. İkincisi ise, bir cümlede (statement) birden fazla ifade (expression) kullanılmış olmasıdır. Bu tabiki ilk problemin bir sonucu ve şekilsel bir durum. Bütün bunlara bir de Java’daki “?:” operatöründe çok akışkan olmayan yani çok aşina olmayan bir programcı eklenince, anlamak hakikatten çok zor hale geliyor.
Kodun basitliğine gelirsek, basit yazılan kodun temelde iki özelliği vardır: Anlaşılırdır ve kısadır. Anlaşılır olmak için şekil açısından öncelikle kod standartlarına daima uyulmalıdır. Eğer bir sebepten dolayı uyulamazsa bu durumu sebebiyle birlikte belirtilmelidir ki insanlar şaşırıp burada fazladan zaman harcamasınlar. Dolayısıyla anlaşılır kod,
- anlaşılır isimler içeren,
- ferah, mekanı etkin kullanan dolayısıyla rahat okunan,
- tutarlı yani şaşırtmayan, beklendiği gibi, aşina olunan,
- açıklanmış (commented) koddur.
Bunlar anlaşılır kodun şekil şartlarıdır. Bu amaçla paylaştığım isimlendirme ve şekil standartlarına buradan ulaşabilirsiniz.
İçerik açısından ele alındığında anlaşılır kod, okuyananın çok zeki ya da konuya çok hakim olmasına gerek bırakmadan kavranan koddur. Martin Fowler, Refactoring isimli güzel kitabında “Herhangi birisi bilgisayarın anlayacağı kod yazabilir. Fakat iyi programcılar insanların anlayabileceği kod yazarlar.” (Any fool can write code that a computer can understand. Good programmers write code that humans can understand.) der. Dolayısıyla programcı öncelikle kendi anlaması için kod yazmalıdır. Kodunu yazdıktan sonra dönüp bir bakmalı, 3 ay ya da 1 yıl sonra bu kodu anlamak için ne kadar enerji harcayacağını düşünmelidir. Bu anlamda soru “bir kod parçasının kendini ne kadar açık bir şekilde okuyucusuna anlattığı”dır?
Anlaşılır olmak belki bir kaç farklı seviyede ele alınmalıdır. Yani bir kodun anlaşılır olması, sadece o kodun anlaşılır bir şekilde yazılmaya çalışılmasıyla elde edilemeyecek kadar geniş ya da çok faktörlü bir problemdir. Çünkü kod bir son çıktıdır ve kendinden önceki ihtiyaç analizi, mimari ve fonksiyonel tasarım gibi çalışmalar sonucunda üretilebilir. Bu anlamda anlaşılırlık, iş (business) seviyesinden başlamalıdır. Yani basitlik en temelde iş seviyesinde ele alınmalıdır. Yapılacak işin ne kadar kısa, öz, tutarlı olduğu o işin koduna da etkir. Karmaşık bir iş kuralını basit yazmak zordur örneğin. Soru öncelikle “o iş kuralı o kadar karmaşık mı olmalıdır”dır. Ya da “yazılım ile otomatikleştirmeye çalıştığımız süreçlerimiz en basit, en kısa ve en anlaşılır halinde midir” sorularının cevaplanması gereklidir. Bu noktada ünlü felsefeci Adorno’nun “yanlış hayat doğru bir şekilde yaşanamaz” (wrong life cannot be lived rightly) sözü akla geliyor. Karmaşık iş yapış şekillerini basit bir halde koda dökmek zordur diyebiliriz yani. Ülkemizde gelişi güzel, parça parça ya da yazılıma geçirme safhasında akla gelip kurgulanan süreçler gibi problemlerden dolayı zaten iş yapış şekillerimiz sağlıklı değildir, çoğu zaman da onu yapan kişiye bağlıdır. Dolayısıyla süreçleri bölük pörçük, örneğin “ekran” ya da “sayfa” düzeyinde ele alınarak analiz edilmeye çalışılmış bir iş alanın iş kurallarını kodunuzda örneğin nasıl yönetebilirsiniz ki?
İş seviyesinden sonra mimari seviyede basitlikten söz etmeliyiz. Mimarinin ne olduğunu biliyoruz; katmanlar (tiers), bileşenler (components), bunların arayüzleri, aralarındaki ilişkiler, protokoller, “kim kiminle konuşacak”, “hangi bileşen neyi yapacak”, “performans, ölçeklenirlik, güvenirlik, güvenlik vb. kriterleri nasıl sağlayacağız” gibisinden sorular, kullanılacak teknolojiler, donanım mimarisi, sistemin topolojisi vs. hep mimarinin konusu. Mimari bu anlamda sistemin yüksek seviyeli bir taslağıdır.
Mimari bileşenlerin ve aralarındaki ilişkilerin ne kadar basit ve anlaşılır oldukları kesinlikle çok önemlidir. Bu noktalarda alınan kararlar açık bir şekilde ne kadar basit kod yazdığınızı etkiler. Daha doğru ifadeyle mimari kararlar kodunuzun ne kadar basit yazılabileceğini doğrudan etkiler. Kötü oluşturulmuş mimari, karmaşık bir mimari, ya da baştan güzel kurgulanan ama sonra özellikle kontrolsüzlükten ve sisteme giren çıkan yeni programcı vs.nin var olan mimariyi özümsemeden, bilinçsiz ve pragmatik olarak yaklaşmalarından dolayı rayından çıkmış bir mimaride kodunuzu ne kadar basit yazabilirsiniz ki? Java EE’nin ya da Spring’in teklif etmiş olduğu mimariler, mimari şablonlar (architectural patterns) aslında uygulandığı taktirde daha rahat bir yapı kurgulamanızı ve nihayetinde daha basit kod yazmanızı sağlayan yaklaşımlar olarak son derece önemlidirler. Bu anlamda Demeter Kanunu (Demeter Law) sadece sınıflar düzeyinde geçerli değildir, bileşenler ve katmanlar düzeyinde de dikkat edilmesi gereken bir prensiptir. Benzer şekilde daha sonra ele alacağımız “odaklılık” konusu tabi olarak mimari için de geçerlidir.
Daha sonra tasarım seviyesinde basitlik ele alınmalıdır. Sınıf, arayüz, metot vb. yapılar ve aralarındaki ililşkiler, basitlik üzerine kurgulanmadıkça basit kod yazamazsınız. Eğer yazılım geliştirme sürecinizde bir tasarım safhası yoksa o zaman hakikatten basit kod yazmanız çok zor. Çünkü tasarım demek kodunuz hakkında düşünmek demektir. Kodunuzu düşünmeden yazdığınızda çoğu zaman kaliteli ve basit kod yazmaya odaklanamazsınız. Kodu doğru yazmaya, iş mantığını doğru bir şekilde yansıtmaya daha fazla odaklanırsınız. İş, mimari ve tasarım seviyesinde ele alınmayan konuların getirdiği bütün yük üzerinizdedir. (Bu yüke technical debt deniyor.) Bunlar o kadar fazla sayıda faktör olarak ortaya çıkarlar ki zaten zihninizin bu kadar çok şeyi aynı anda halletmesi son derece güçtür. Bu durumda ister istemez kötü kod yazarsınız, basit yazayım derken performansı gözden kaçırırsınız mesela.
Tasarımda yapılacak, sorumlulukları nesnelere atama, nesneler arasındaki ilişkileri düzenleme, değişmesi muhtemel kısımlarla diğer kısımları birbirinden yalıtma, bu amaçlar için tasarım şablonlarını kullanma vb. çalışmalar, kodunuzun kalitesini doğrudan etkiler. Hatta tasarım çalışmaları sonuçta sistemde var olacak her türlü tipin arayüzünü belirlediği için, kod kalitesi büyük oranda tasarımda belirlenir. Bu anlamda bir tasarım çalışması yapmadan kaliteli kod yazmak aslında hayaldir. Ya da kaliteli kod ancak düzgün bir tasarım çalışmasının çıktısı olabilir.
Bu yazıda burada bırakalım. Belli ki basitliği ancak bir kaç yazıda tamamlayabileceğim. Bir sonraki yazıda daha detaylı bir şekilde basit kodun özelliklerinden bahsedelim.
Hoşçakalın…
Toplam görüntülenme sayısı: 9324