Daha iyi yazılımcı olmak için kod okumak

Daha iyi yazılımcı olmak için kod okumak

Yazılan tüm kitapların kaliteli kod yazmak ile alakalı olduğu bir zamanda insanların kaliteli bir yazılım mühendisi olmayı bu mesleğin sadece kod yazma kısmı ile ilişkilendirmesi normal. Ama yıllarca çalıştığımız kariyerimize bir baktığımızda acaba hangisini daha çok yapıyoruz: Kod yazmak veya kod okumak. Ben kendi kariyerimde yazdığım kodun yüzlerce katı kadar kod okumuşumdur. Peki, okuduğumuz kodlar içinde başkalarının kodu mu yoksa kendi kodumuz mu daha çoktur? Kurumsal projelerde çalışıyorsanız, büyük bir ihtimal, sizin kodunuzun miktarı, projenin geneliyle karşılaştırıldığında, devede kulak ya da kıl kadar kalacak. Peki kod okumanın, özellikle de başkalarının kodunu okumanın, kendi kodunuzu okuma ve yazmadan çok daha fazla zaman aldığı bir meslekte, kaliteli yazılım mühendisi olmayı sadece kod yazmak ile ilişkilendirmek biraz eksik olmuyor mu?

Geçenlerde Finlandiyalı bir yazılımcıya, Linux ile alakalı ne gibi tips ve tricks paylaşmak istersin diye sorduğumda, bana verdiği cevaplar arasında kaynak kod okumaktan çekinmemek gerektiği vardı. Aslında uzun zamandır ben de benzer şekilde düşünüyor, hatta yeri geldiğinde her uygulamayı debug edecek cesareti göstermeye çalışıyordum. Başka birisinden daha benzer fikirleri duymaktan dolayı bu konu hakkında daha detaylı düşünmek ve düşüncelerimi paylaşmaya karar verdim.

Kaynak kod okumak zor bir iş aslında. Hiç bilmediğiniz kısımları okumaya çalışmak ve buralardan çıkarımlar yaparak sistemi anlamak insanın kafasını yorabilen bir uğraş. Özellikle de milyonlarca satır kod arasından aradığınız kısımları bulmak ve kim ve ne zaman yazıldığı bile unutulmuş olabilecek kodları okumak, çokları için çokta zevkli bir zaman geçirme şekli değil. Kaliteli kod yazma yöntemleri ile accidental complexity değerlerini düşürmek bu acıyı bir nebze azaltsa da, maalesef her kod kaçınılmaz olan essential complexity ile birlikte gelir. Bu aslında korkulacak bir durum değil, yazılımcıları değerli kılan önemli bir faktör sadece.

Kaynak kod okuyabilmek her mühendise ciddi kazanımlar sunabilir. Programcıların analitik zekasını geliştirmenin yanı sıra, dökümantasyonların hızlı bir şekilde geri kalabileceği bir durumda, en doğru bilgiyi kaynak kodun kendisi verir. Aynı zamanda, hızlı bir şekilde kaynak kod okuyabilmek, bir mühendisi dahil olduğu her projenin vazgeçilmez bir parçası kılar. Kaynak kodlar kullanmak istediğiniz bir API’nın nasıl kullanabileceğine en doğru cevabı veren yerlerde olabilir. Kimsenin aşina olmadığı ve dökümantasyon hususunda çok gelişmiş olmayan bir automation kütüphanesinde, en büyük yardımcım kaynak kodun kendisiydi. Github reposu üzerinde hızlı bir arama yaparak, kullandığım sihirli methodların aslında benden ne beklediğini, kaynak kod içinde nasıl kullanıldıklarını, ve kullanırsam nasıl çalışacağına dair sorularımın cevaplarını o projenin olabilecek en doğru bilgi kaynağı olan kaynak kodlarından alıyordum.

Yukarıda, kaynak kod okumanın yazılımcıların analitik zekasını geliştireceğine dair bir ifadem vardı. Bunu biraz daha açalım. Programlama dilleri normal cümlelerden daha farklıdır. Matematikseldir. Fonksiyonlar vardır, değer atamaları vardır, hesaplamalar vardır. Dolayısıyla bir programın ne yaptığını anlamak için normal cümlelerin özne, yüklem, nesne, zaman, şartlar, vs. gibi parçaları kod içinde daha farklı ifade edilir. Ufak bir alıştırma ile demek istediğimi anlatayım.

Aşağıda herkesin rahatlıkla anlayabileceği bir cümle var:

Bugün eve giderken, otobüsü kaçırdığım için, yağmurun altında ıslanmak zorunda kaldım.

Haydi bakalım,kafamdan uydurduğum yukarıda ki kodu okuyarak, anlatmak istediğini anlamaya çalışalım. Bu koddan anlaşılır davranışlar çıkarmak istiyorsanız, her bir adımı doğru anlamanız ve bu adımları zihninizde birleştirmeniz, ve ortaya çıkan sonuçtan da bir anlam çıkarmanız lazım. Bu anlam size sistemin nasıl çalışacağını söylecek olan şeydir. Bu arada syntax C# gibi duruyor ama ortaya biraz karışık oldu.

Mülakat yaptığımız insanlara, daha önce görmediği kodları nasıl öğrendiğini ve çalıştığı proje içerisinde karşısına çıkan bir hataya nasıl yaklaştığını sorarız. Çünkü bu yetenekler, kaliteli kod yazabilme kabiliyetinin yanında hayati öneme sahip faktörlerdir. Yaklaşım tarzı kişiden kişiye fark edebilir. Mesela, debugger kullanarak kodu debug edip, adım adım çalışmasını izleyebilirsiniz — ki bu bence kolay ve mantıklı bir yöntem. IDE’ler kod arasında gezinmek için faydalı araçlar sunarlar çoğu zaman. Mesela sınıf hierarşini görmeyi sağlayan, hızlıca sınıflar ve semboller arasında dolaşmaya yardımcı olan, ve bir method ya da değişken nerede tanımlanmış sorusunun cevabını kolayca bulduran onlarca farklı özellikler ile geliyorlar. Ama bu yeterli mi?

Kullanılan bu tür araçlar sadece kolaylık sunarlar. Ama, kod okuma yeteneklerini geliştirmemiş yazılımcılar için bu kolaylıkların umdukları kadar bir faydası olmayacaktır. Sonuçta kodu bulduğunuzda okuyacak olan yine sizsiniz. IDE, size kodun ne yaptığını söylemeyecek. Peki bu durumda nasıl kendimi geliştirebilirim, ipuçlar var mı diye sorarsanız: İlk tavsiyem, diğer tüm yazılarımda söylediğim gibi, bolca pratik yapmak.

Eski zamanlarda yazılmış kitaplara özel bir düşkünlüğüm vardır. Ama günümüz yazarlarına göre, eski yazarlar çok daha edebi ve ağır cümleler kurabiliyorlar. Aynı zamanda bu cümlelere anlatılan konunun da ağırlığı binince, kitaplar anlaşılmayacak hale geliyordu. Ne zaman bu tür kitapları zorla okumaya başladım, o zaman kitaplar manalarını açmaya, karmaşık gelen cümleler daha kolay anlaşılmaya ve kitaplar daha bir zevkli hale gelmeye başladı. Hatta öyleki, bir zaman sonra beynim müptela olmuş gibi kendisini bu şekilde zorlayacak kitaplar okumak istiyordu. Burada kendim ile alakalı gözlemlediğim iki tane değişim vardı: Okumak suretiyle kitapların anlattığını konulara karşı olan hakimiyetim geliştiği için, bilgi eksikliğinden kaynaklanan anlaşılma sorunları kaybolmaya başlıyordu. Diğeri ise yazarın cümle kurma tarzını daha iyi anlamaya başladım.

Kaynak kod okumakta böyledir aslında. Kullanılan diller farklı olsa bile, temelde hepsi bilgisayar dilini konuşur. Bizde elmadır, onlarda apple, diğerlerinde başka bir şey. Kaynak kodu okurken bu düşünceyi kafadan çıkarmamak lazım. Sonuçta hepsi değişkenlere veri atar, varsa fonskiyonlar çağırır, network üzerinden data stream yapar, vs. Ama bunları bir amaç uğruna yapar. Mesela, kullanıcının login olmasını sağlamak için kullanıcıdan aldığı bilgileri network API’ları üzerinden config dosyalarında sakladıkları endpointlere stream ederler. Onun için bilsayarların genel çalışma prensiplerini bilmek okunacak kaynak kodu anlamada çok yardımcı olacak.

Kod okurken bana yardımcı olan şeylerden bir tanesi de, daha implementasyon detaylarını görmeden, hızlıca bazı varsayımlar ve beklentiler içinde bulunmak olur. Mesela, getNetworkCredentials() diye bir method gördüğümde, bir inputtan ya da bir config doyasından vs. bazı bilgiler alınacak demek ki diye hızlıca aklımdan geçirir ve kendimi okuyacağım koda zihnen hazır ederim. Merak içinde bekleyen beynim ise, kodları ayrı bir iştah ile incelemeye ve umduğu şeyler doğru mu, gerçekte nasıl çalışıyor gibisinden başlar öğrenmeye. Bu aslında zihnimi mindless kod okumak halinden kurtarıp, okuduğum koddan bir beklenti oluşturmasından dolayı daha bir farkındalık haletine sokuyor. Kitap okurken, yazarla kitabı üzerinden mücadele etmek ve dediklerini ispatlamasını beklemek gibi, kod okurken de okuduğunuz koddan beklentilerinizin olması zihininiz canlı tutacaktır. Hatta yeri gelince, yazılan koda kızmanın ve siz nasıl yazardınız eleştirisini bile yapmanızın çok faydasını göreceksiniz. Ama tabi bu eleştireleriniz şimdilik sizde kalsın.

Genelde public API kısımları okuduğunuz kaynak kod hakkında daha genel bir resim hızlı bir şekilde gösteren taraflardır. Mesela bir sınıfı anlamaya çalışıyorsanız, sınıfın ismi ve public ettiği methodlara bakabilirsiniz. Aksi halde sınıfın encapsulate ettiği bir sürü privatemethod vs. kafanızı karıştırabilir ve kodu anlamanızı zorlaştırabilir. Eğer bir sınıfın member’larını (method, property, vs.) gibi gösteren ve bunlar üzerinde public kriteri üzerinden filtreleme yapabilen IDE ya da pluginler kullanırsanız, işinizi daha da kolaylaştırmış olursunuz. Doğru verilmiş method ve sınıf isimleri, çok şey anlatırlar. Hatta komut satırında grepkullanarak bile bunu halledebilirsiniz.

Eğer bir klasör içinde ki tüm .cs dosyalarının içinde ki publicmethodları görmek isterseniz, aşağıda ki komutu:

grep — include=”*.cs” public .

Ya da sadece bir dosya içinde ki publicmethodları, property’leri, vs. görmek isterseniz de aşağıda ki komutu kullanabilirsiniz:

grep public UserSessionStateDataAccess.cs

Yukarıda ki komutun çıktısı aşağıdakine benzer olacak:

Bazen kodlar çok karmaşık geldiğinde, projenin local kopyasını alır ve kodları okurken başlarım refactor etmeye. Uzun methodları anlaşılır method isimleri ile birlikte küçük methodlara böler ve büyük resmi bu yeni abstraction (soyutlama) içinde görmeye çalışırım. Uzunca yazılmış if-conditionları bir değişkene atar ve neyin check edilmek istendiğini bu değişken isminde saklarım. Amacım bu kodu bir insanın anlayacağı doğal bir dile ne kadar çok getirebilirsem, o kadar daha anlaşılır olacağıdır. Tabi refactor etmek uzun bir iş olabilir.

Kısacası, zamanla kendi öğrenme biçiminize göre kendi yöntemlerini geliştiriyor olacaksınız. Herkesin anlama ve öğrenme biçimi kendine has farklılılar gösterebilir. Ama hepsinin gelişmesine temel teşkil edecek ortak davranış ise pratik yapmak ve günlük kod yazdığınız gibi belki de kendinize düzenli olarak kaynak kod okuma alışkanlığı kazandırmanızdır. Github pratik yapabileceğiniz milyarlarca satır kaynak kod ile dolu. Ya da bırakın GitHub’ı, kendi projenizde bile daha önce dokunmadığınız kısımlar varsa, onları okumak ile başlayın işe. Okurken, anlamanızı zorlayan nedenleri iyi inceleyin. Zaman ve pratiğin kainatta olgunlaştırmadığı hemen hemen hiç bir şey yok gibidir.

Son olarak, okuduğunuz kodun ne için kullanıldığını bilmek kodu daha rahat anlamanıza yardımcı olabilir. Ama bazen bu bilgiye sahip olmayacaksınız. Bu durumda bile okuduğunuz kodun ne için kullanılıyor olabilir sorusuna cevap verebiliyor olmanız önemli. Çünkü bu fikirler, kodun metadatası olacak kısımlardır ve size kodu nasıl improve edebileceğiniz fikirlerini verir.

Aklıma gelen şimdilik bazı fikirleri yazmak istedim. İleride bu makaleyi güncelleyebilirim. O zamana dek, kalın sağlıcakla…