anlak.com
Showing posts with label çevik. Show all posts
Showing posts with label çevik. Show all posts

Pragmatik Araştırmacı: Kod Kalitesini Korumak

, Tuesday, 17 September 2013
Geçenlerde aşağıdaki karikatürü gördüm ve o kabus durumla başetmek zorunda kalmadığıma sevindim. Çünkü geçenlerde, yayın, konferans süreci öncesi kod kalitesini korumanın ve ardından araştırmanıza kaldığınız yerden devam etmenin enfes bir yolunu keşfettim.


Önereceğim çözüm güzelliğin güzelliği çektiği bir durum aslında; version control (sürüm denetimi, ör: SVN, Hg, Git) kullanmanın faydası zaten çok. Version control kullanarak bunun da üstesinden gelebiliyoruz. Şöyle ki...

Kodumuzun içine edeceğini düşündüğümüz, konferans öncesi vakit geldiğinde, kodumuzda branch oluşturuyoruz. Çözüm bu kadar basit :) Yaptığımız her türlü değişiklik o branch içerisinde kalıyor ve biz kodumuzu berbat duruma soktuktan sonra hiçbir şey olmamış gibi eski haline geri dönebiliyoruz.

Branch'te çalışırken darboğazlardan birini çözdünüz ve kodunuz daha da hızlandı, fakat şimdi eski temiz kodunuza bu özelliği eklemek istiyorsunuz, açtığınız branch'e tıkılı kalsın istemiyorsunuz. Bunun için de ilgili kodu merge yapabilirsiniz.

Elbette version control kullanırken de bir şeylere dikkat etmek lazım. Örneğin her commiti ne kadar kendi içinde tutarlı ve küçük tutarsanız bahsettiğim merge işleminin idaresi o kadar kolay olur.

Ben genelde araştırma için kodumu mümkün olduğunca modüler yapıyorum; sadece yayın öncesi özelleşmiş sonuç gerektiğinde ve grafik üretimek için bir branch'e alıyorum. Şimdilik kodumu bu şekilde idare etmekten çok memnunum. Umarım bunun gibi yazılım mühendisliği pratikleri araştırma için de yaygın biçimde kullanılır.

Pragmatik Araştırmacı

, Saturday, 20 August 2011
Akademiye geçmeden önce bir süre özel bir şirkette çalışmıştım, orada çevik (agile) metodları benimsemiştik. Farkettim ki piyasadaki durum, öğrenci olarak yapılması gerekenlerle pek fazla örtüşmüyor. Bunun başlıca nedeni öğrenci iken bakımı yapılacak şekilde bir ürün üretmiyorsunuz. Örneğin yaptığınız ödevler tek seferlik; bir kere öyle ya da böyle çalışır birşey elde ettikten sonra sonuçlarınızı elde edip yazdığınız kodları bir daha yüzüne bakmamak üzere rafa kaldırıyorsunuz. Araştırma yaparken durum birazcık daha farklı, yazdığınız kod üzerinde biraz daha uzun süre uğraşıyorsunuz , kodları elinizde biraz daha uzun süre tutuyorsunuz, fakat tecrübe ettiğim kadarıyla sonuç pek fazla değişmiyor, kodlar iş bittikten sonra bir köşeye terk ediliyor. Bu yüzden akademideki kod kalitesi bazı istisnalar (ör. Zemberek) dışında oldukça düşük.

Uzun süren araştırmalar bu duruma pek uymuyor, tez gibi uzun soluklu çalışmalarda mecburen kodunuzun bakımını yapmanız gerekiyor. Kimse yapmıyor o ayrı mesele. Yazdığınız kodu güzel yazmadıkça, bakımını yapmadıkça teknik borç (technical debt) birikiyor. Bu borç kısa vadede ilerlemenizi sağlayan fakat orta vadede size ayakbağı olacak eylemlerinizi açıklayan bir kavram. Bugün az bir emek harcayıp kodunuzu güzelleştirmek, ya da bir şeyi doğru şekilde yapmak yerine günü kurtarırsanız, daha sonra atacağınız adımlar daha da güç olacaktır. Az evvel dediğim gibi akademide yazılan kodlar çok kısa ömürlü olduğu için bu pek sorun olmuyor.

En azından makro ölçekte bu böyle. Son dönemlerde deneyimlerim ödevlerin, projelerin kısa ömürlü olmasına rağmen güzel programlama pratiklerine ihtiyaç duyduğu yönünde. En son arkadaşımı benim 1 günde bitirdiğim yapay sinir ağı ödevi için 3-4 gün harcamasını gördüğüm zaman farkettim bu durumu. İşlerimizi kolaylaştıracak yöntemlerin başında temiz kod yazmak geliyor. Temiz kod yazmanın, kısa süreli projeler olsa dahi, hayatımızı nasıl daha güzel kılacağını bir örnekle tarif etmeye çalışayım.

Diyelim ki $w_{i2}x+w_{i1}$ gibi bir ifadenin sonucunu sigmoide sokacağız, bu işi halletmenin MATLAB'da en düz yolu:
   y = 1 ./ (1 + exp(-x.*w(i, 2) + w(i, 1)));

Benim tercih edeceğim yol:
   y = sigmoid(x.*w(i, 2) + w(i, 1))

   function ret = sigmoid(x)
      ret = 1 ./ (1 + exp(-x));
   end

Sigmoid'i fonksiyon olarak ayrıştırarak
  1. Yeniden kullanılabilirliğini arttırdık. Bu örnekte, yapay sinir ağlarıyla uğraştığımızdan, birden fazla yerde sigmoid'i gönül rahatlığıyla kullanabiliriz. Her defasında yeniden aynı ifadeyi yazmakla uğraşmayız.
    Sigmoid'i yazarken bir yanlışlık yaptıysak dahi, bu yanlışlığı her yerde düzeltmemiz gerekmez. Sadece bir yerde düzeltmemiz yeterli olur. Diğer türlü sigmoid ifadesinin geçtiği her yeri bulmaya çalışırken gözümüzden bir kaç tanesini kaçırmamız çok olası.
    Hatta bunun bir adım ötesi, yavaş yavaş kendi kullanacağınız kod parçacıklarını kütüphaneleştirme yoluna gitmek olur. İleride size avantaj sağlayacaktır. Doğrudan kendi deneyimimi paylaşayım. Bir dönem projesi için çeşitli uzaklık metriklerini ($\chi^2$, Bhattacharaya, Kolomogrov vs.) implement etmiştim. Bir sonraki dönem başka bir dersin hocası verilen ödevde kullanacağımız her farklı uzaklık metriği için bonus puan vereceğini söyledi. Hiç uğraşmadan elimdeki hazır yazılmış 3-5 metriği çaktım geçtim.

  2. İfade daha anlaşılır oldu. Anlaşılır olması tekrar geri dönüp baktığınızda ilgili ifadede ne olup bittiğini çabucak kavramanızı sağlar. Anlaşılır kılarken ayrıca bug oluşumunu da engellersiniz aslında. Verdiğim kötü örnekte aslında bug var, exp() içine alırken, "-" toplamın iki elemanını da negatiflemeliydi, yani ifade y = 1 ./ (1 + exp(-x.*w(i, 2) - w(i, 1))); olmalıydı. Gördüğünüz gibi  böylesi "obscure" durumda hata yapmak daha kolaylaşıyor, hatayı bulması da zorlaşıyor. Sigmoid'i ayrı bir fonksiyon olarak yazdığımız durumda hata çabucak gözümüze çarpardı.

Bazıları önerdiğim yöntemin, fonksiyon çağrıları ve pass-by-value yüzünden daha yavaş olduğunu söyleyecektir, hele ki akademide mikro optimizasyonlar oldukça önemli olabiliyorken. Pragmatik programcılığın altın kurallarından biri de
  1. Profile et

  2. Darboğazı bul

  3. Optimize et
der. Profile etmek, kodunuzdaki ifadelerin hangilerinin koşmasının ne kadar zaman aldığını ölçmektir. Yıllardır yazdığım kodların hiçbirinde (abartmıyorum, 1 tanesinde bile olmadı bu) darboğaz tahmin ettiğim yerde değildi, ve bu tip mikro optimizasyonlar performansa hiç katkıda bulunmadı. Ayrıca, modern diller, hatta hantal MATLAB, bile kodlarınızı sizin için derlediğinizde ya da hemen koşturmadan önce optimize edebiliyor. awesome engineerO yüzden mutlaka ilkin profile edin ve kodunuz en çok zamanı nerede harcıyormuş onu bulun ve orayı hızlandırmaya çalışın.

Son olarak MATLAB'a özel bir tüyo vereyim, yıllardır MATLAB yazan insanların kodlarında bile görüyorum bu kötü uygulamayı. Matris işlemleri yaparken for döngüsü kullanmayın, kodunuzu vektörize edin. Vektörize etmek kodunuzu daha anlaşılır kılar, çünkü matematiksel ifadeleri neredeyse aynı şekilde ifade etmiş olursunuz hem de kodunuz hızlanır. Çünkü MATLABda array elemanlarına erişim oldukça maliyetli. Gerçi son dönemki MATLABdaki değişiklikler (JIT-accelerator), döngüler ve vektörizasyon arasındaki farkı önemsiz kulabiliyor.Yine de benim önerim kodunuzun güzelliği ve aklınızın sağlığı açısından vektörizasyon kullanmanız.