Java Günlüğüm
Yazılım, Java, BT, azıcık felsefe, biraz mizah...
  • Udemy Eğitimleri
  • Temiz Kod
  • Tasarım Kalıpları
  • Hakkımda
  • Arşiv
RSS
28 Aralık 2014

Teknik Borç (Technical Debt) ve Yazılım Yöneticileri

Akin Yazılım Kalitesi ve Test

Literatürde “yazılım bozulur” diye dilimize çevirebileceğimiz “software rots” ya da “yazılımın bozulması” anlamında “software rot” gibi tamlamalar vardır. Bu kavram ile genel olarak yazılım kalitesinin zamanla düşmesi kastedilir. Aynı anlama gelen “bit rot”, “code rot”, “software decay” vb. tamlamalar da vardır.

Yazılım fiziksel olarak tabi ki bozulmaz, kokmaz ya da küf tutmaz ama yazılımlar hayatları boyunca kendilerine yapılan eklemeler ve düzenlemelerle ki biz buna bakım (maintenance) diyoruz, genel olarak başlangıçta sahip olduğu kalitesini kaybeder. Her ne kadar yazılımın bozulması kavramı, daha çok performansında düşme bağlamında kullanılsa da bu kavram genel yazılım kalitesinin, yazılıma yapılan her türlü müdahale ile ciddi bir şekilde düşme eğiliminde olduğunu ifade eder.

Yazılımın, eklenen yeniliklerle büyümesi son derece normaldir, yazılımın tabiatındandır. Ama yazılımın büyürken, karmaşıklığının gittikçe artması da bir başka gerçektir. 1 milyon satırlık bir yazılımın kalitesini sağlamak için sarf edeceğiniz enerji, 10 bin satırlık bir yazılımın kalitesini sağlamak sarf edeceğiniz enerjiden 100 kat fazla değildir. Belki ihtiyaç duyulan maliyette üstel olarak büyüme söz konusudur. Dolayısıyla yazılım projelerinin başında bazı şeyleri örneğin dokümantasyon ya da birim testlerini görmezden gelerek ya da yapmayarak ya da mimariye fazla önem vermeyerek işinizi hallettiğinizi düşünebilirsiniz ama bu şekilde yapmadığınız her şey, teknik borç (technical debt) olarak birikir. Yazılım büyüdükçe hem bu borç kendini daha belirgin bir şekilde hissettirir hem de bu borcun ödenmesi zorlaşır. Yazılım projesinin ilk 6 ayında birikmiş 30 adam-günlük bir teknik borcunuz varsa, yani atladığınız-ıskaladığınız kısımları düzeltmek için 30 adam-güne ihtiyacınız varsa, muhtemelen bu miktar projenin 3. yılının sonunda 700 adam-güne çıkmış olacaktır.

Teknik borç ile ilgili Martin Fowler’ın orijinal yazısına ve Türkçe çevirisine bakabilirsiniz. Ward Cunningham’ın bize öğrettiği bu kavram, bir şeyi yapmanın hızlı ve derme-çatma olmasıyla, doğru-düzgün olması arasındaki farkı vurgular. Var olan bir sistemde bir değişikliği doğru-düzgün yapmak, üzerinde düşünülecek bir tasarım, etkilenecek yerleri bulmak için zaman, yeniliğe yer açmak için gerekli iyileştirmeler için adam-güne ihtiyaç duyar. Ama biz yazılımcılar, hızlı ve kirli bir şekilde, derme-çatma yöntemlerle bu değişikliği sisteme yedirmenin yollarını buluruz. Bazen uyarırız bizi yönetenleri, işimizi doğru düzgün yapmak isteriz, derme-çatma yapmanın ileride neye mal olacağını belirtiriz, bazen de ya bilgimiz ya da inancımız olmadığından, en hızlı bir şekilde yapar geçeriz, benden sonrası tufan diye düşünürüz. İlk halde bizim itirazımızı kaale almayan yöneticilerin, ikinci halde de biz yazılımcıların açmazı, yetişmeye çalıştığımız bir tarihin (deadline) olmasıdır.

Teknik borcun doğrusal olarak büyümediğini, katlanarak arttığını söyleyebiliriz. Çünkü oluşturulan her teknik borç, aynen finansal borçla ilgili durumda faizin katlanarak artması gibi birbiri üzerine binerek artar. İlk günlerde gözünüze çok gelmeyen faiz, sıfırlanmadıkça nasıl faizin faizi haline dönüşürse, yapılmayan işler de üst üste binerek çok daha büyük maliyetlere yol açar. Hatta bir müddet sonra teknik kişiler, yazılımı düzeltemeye çalışmanın beyhude olduğunu çünkü baştan yazmanın daha az maliyetli olacağını söylerler. Bu gibi sözlerin yöneticileri çılgına döndürdüğünü ya da teknik kişilerin abartması ya da kaprisi olarak göründüğünü iyi biliyorum. Ama malesef yazılımcılar çoğunlukla haklıdırlar.

Fowler, yukarıda adresini verdiğim yazısında, üretim hızımızı ölçemediğimizden ve nihayetinde teknik borcu, finansal borç gibi algılayamadığımızdan dolayı, yanlış olarak aldığımız ya da almamız gerekirken almadığımız kararların üretim hızımızı nasıl etkilediğini farketmediğimizi ifade ediyor. Ben çoğu yöneticinin yazılımcıların bugları çözmede ve yenilikleri sisteme kazandırmada neden bu kadar yavaş olduklarını devamlı sorguladıklarını ama yazılımcıların işlerini yaparken bu teknik borçla nasıl savaştıklarını anlamaktan kaçındıklarını sıklıkla gözlemliyorum. Alınması gerektiği halde alınmayan ve “çocuklar yolda öğrenir” denen eğitimler, yapılmayan dokümantasyonlar, yazılımcıların kafalarını duvara vura vura öğrendikleri dolayısıyla tekrardan keşfettikleri tekerlekler, yapılması gereken ama akla bile gelmeyen mimari prototip, deneme-yanılma çalışmaları ve testler, tecrübeli yazılımcıya açık ihtiyaç varken, ucuz olsun diye daha genç ve tecrübesiz kişilerle iş yapmaya çalışmak, son derece teknik derinlik isteyen konularda bile uzmanına sormak yerine, bilgisiz ve tecrübesiz ama iyi niyetli kişileri 3-5 günlük eğitime göndererek tüm sorumluluğu onların sırtına bindirmek, müşteriyi yatıştırmak amacıyla bilinçli-bilinçsiz verilen her türlü söz, hepsi teknik borcu oluşturan etkenlerdendir.

Eskiden bu yana yazılım projelerinde teknik borcun %100 giderilemeyeceğini düşünmüşümdür. Özellikle ülkemizde tamamen proje odaklı yazılım işlerinde, yazılımı geliştiren şirketlerin, projeyi sattıkları kurumların maddi ve manevi tahakkümü altında olduklarını iyi biliyorum. Bundan dolayı da, örneğin kapsamın projeyi satın alan firma tarafından sürekli olarak değiştirildiği ve genişletildiği bir ortamda, yazılımı geliştiren firmanın teknik borcu kapatmak için bir şey yapmayacağının, en fazla kullanıcı kabul testlerini geçecek kadar iyileştirme yapmaya imkan vereceğinin çok aşikar olduğunu yaşayarak öğrendim. Ama bu durum böyle davranan yazılım evlerinin, aynı projeyi başka yerlere satma durumunda, teknik borcun kendilerine zorluk çıkarmaya devam edecekleri gerçeğini, yukarıda bahsettiğim tahakkümün oluşturduğu stresten dolayı farketmediklerini, düşünmediklerini hatta düşünmek istemediklerini de çok defa gözlemlemişimdir.

Teknik borç konusunda beni en rahatsız eden şey, teknik borcun kendisinden ziyade bu konuda nasıl davrandığımızdir. Bu ülkede yazılımı yönetenlerin ciddi bir kısmı teknik borç kavramından haberdar değildir. Diğer ciddi bir kısmı da kavramdan haberdar olsa bile mahiyetinden, sonuçlarından, örneğin varlığının bakım sürecini nasıl sıkıntılı hale soktuğunu anlamaktan çok uzaklar. Bundan dolayı yöneticiler, yazılımcıların dillerinin döndüğünce “bunu muhakkak yapmalıyız” cinsinden itirazlarını malesef mükemmeliyetçilik ya da yazılımcı kaprisi olarak göme eğilimindeler.

Örneğin yazılım müdürü olarak çalıştığım bir yazılım evinde patron, benim “bu şekilde olmaz” deyip ayrıntılı olarak açıkladığım bu teknik borç kavramını anlamayıp, benim karşımda, benim altımda çalışan ve benim işe aldığım tecrübeli kişilere danışıp, onlardan gelen “olur ama sonrasında bakımı çok maliyetli olur” şeklinde ifadeyi benim aleyhime kullanıp, “tamam böyle yapıyoruz” diye karar aldığını çok iyi hatırlıyorum. Sonuçta beni işe alırlarken “şöyle kaliteli iş yapalım, böyle kaliteli olsun” diye esip gürleyip, iş bu kaliteyi oluşturacak takımı kurmaya geldiğinde “ama çok pahalı adam alamayız” diye rampa yapıp sonrasında da iş yapış şeklime karşı çıkanlarla çalışmam mümkün olmadığından, hafta sonu yapılan bu toplantıdan sonra ben Pazartesi günü istifa etmiştim. Bu durum, saygısızlık vb. haller yanında çok tipik bir teknik borç aymazlığıdır. Bu şekilde düşünen kişiler, hayatlarında aldıkları en ufak kararların bile bir sonucu ve maliyeti olduğunu bilirler ama nedense yazılım projelerinde böyle bir durumu imkan dahilinde görmezler.

Demeye çalıştığım şey, Fowler’ın yukarıdaki makalesinde vurguladığı şeydir. Aslen önemli olan teknik borcun ne kadar olduğu değildir. Önemli olan bu teknik borcun nasıl yapıldığıdır. “Etimiz, budumuz bu” diyerek, bilinçli olarak altına girilen borçtan dolayı mutsuz olurum belki ama bundan dolayı istifa etmem, savaşırım. Ama kavramlardan bihaber şekilde, cahil cesur olura uyarak, farkında bile olunmadan alınan teknik borca katlanmak zordur, çünkü devamlı kendinizi duvara konuşuyor hissedersiniz. Yöneticileriniz sizden bir şey isterler, siz bunu yapmanın zorluğundan, ciddi zaman alacağından ve bu durumun en büyük sebebinin de var olan sistemin sıkıntılı alt yapısı olduğundan bahsedersiniz ama karşı taraf sizi iyi niyetli olmamakla, iyi çalışmamakla, sonuç odaklı olmamakla vs. suçlar. Bu durumu Fowler, aşağıya Türkçe çevirisinden aldığım bir dörtlü durumla şöyle açıklıyor:

Teknik borç kadranı.

 

Özellikle en sıkıntı çektiğim türden yöneticiler kasten teknik borç oluşturup bunun bedelini yazılımcılara ödetenler yani “kasten ve umursamaz” olanlardır. “Neden yavaş?”, “neden bu kadar uzun sürüyor?” sorularını devamlı sorarlar ama cevabı dinlemezler, anlamaktan kaçınırlar ya da anlamıyor görünürler. Bu ülkedeki yazılım yöneticilerinin ya da yönlendirenlerin ciddi bir kısmı bu tiptedirler. Bu tipten insanlarla çalıştığınızda davulun sırtınızda olduğunu ama tokmağının başkasında olduğunu hızlıca hissedersiniz.

Bu duruma “kasten ve tedbirli” olarak yaklaşanlarla daha rahat çalışılabilir. Çünkü kasten teknik borç oluştursalar da bunun sorumluluğunu üzerlerine alırlar, kimseye bundan dolayı yüklenmezler, hatta “şimdi bu şekilde idare edelim, sonra düzeltiriz” derler. Sonra düzeltilir mi düzeltilmez mi bilinmez ama en azından sorumluluk alan ve ahlaki olarak umursamaz olmayan kişiler, stres seviyenizi yükseltmezler. Yazılımcı olarak siz de “nihayetinde karar sizin, sonuçlarına katlanıyorsanız, eyvallah, öyle yapalım” demeyi seçebilirsiniz. Benim ABD’de çalışırken kısıtlı kaynaklardan dolayı teknik borca girmeyi seçen yöneticilerim genelde bu cinstendi.

Sanırım benim bahsettiğim patronumun da dahil olduğu, ülkemizdeki yazılım yöneticilerinin-yönlendirenlerinin büyük çoğunluğunun en temel sıkıntısı, yukarıdaki kadranda “yanlışlıkla ve umursamaz” çeyreğinde olmalarıdır. Yani “yazılım nedir?”, “yazılım nasıl geliştirilir?”, “yazılımın alt süreçleri nelerdir?”, “yazılım mimarisi nedir?” gibi sorular onların zihinlerinde yoktur. Muhtemelen bu soruların ancak yurt dışındaki kocaman projeler için geçerli olduğunu ama kendi durumları için önemli olmadığını düşünüyorlardır. Bundan dolayı bu yöneticiler farkında olmadan teknik borç oluştururlar ve bunun ne anlama geldiğini ve nasıl riskler oluşturduğunu da bilmezler. Durumun sıkıntısını ise yazılımcılar çeker ve yazılımcılar artık yöneticilerine laf anlatmaya çalışmayı çoktan bırakmışlardır. Bu yüzden bu ortamlarda işten ayrılmalar yüksek orandadır. (Yukarıda bahsettiğim durumu yaşadığım yazılım evi de sonrasında kapısına kilidi vurmak zorunda kaşmıştı.)

Son çeyrekte olanlar iyi niyetli ama bilgi ve tecrübe konusunda “”yanlışlıkla ve umursamaz” olanlarla aynı durumdadırlar. “Yanlışlıkla ve tedbirli” olanlar, iyi niyetleri sayesinde bilmediklerini öğrenirler çünkü düşünürler ve bundan dolayı eksiklik hissetmezler ve çevrelerindeki teknik insanlarla iş birliği yaparlar. Bu tipten olan yazılım yöneticileri, imkan verildiğinde, zamanla daha doğru kararlar alırlar ve iyi ve öngörülü bir yönetici haline gelebilirler.

Bu yazıda teknik borcun oluşması ve doğası ile ilgili noktalara değindik. Teknik borcu nasıl ortadan kaldırabileceğimize ise bir sonraki yazıda kafa yorarız.

Toplam görüntülenme sayısı: 3478

26 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
26 Aralık 2014

Statik Metotlu Sınıf mı Yoksa Singleton mı? – I

Akin Java, Tasarım Kalıpları, Yazılım Modelleme singleton, static, statik metot, tek nesne

Nesne-merkezli dillerde çok tartışılan konulardan birisi de hiç nesne oluşturmaya gerek bırakmadan kod yazmamızı sağlayan statik özellikler ve metotlar mı yoksa sadece bir tane nesne oluştuğundan emin olup, bu tek nesne üzerinde çağıracağımız nesne özellikleri ve metotları mı? Bu probleme kısaca statik-singleton (static vs. singleton) de denir çünkü tasarım kalıplarında, bir sınıftan sadece bir nesne oluşturmaya “singleton” yani “tekil” denir.

Bence statik kullanımı, tabi özellikle statik metot kullanımı, nesne-merkezli dillerin, yanlış kullanıma en fazla konu olanı ya da bir başka deyişle suistimale uğrayan alanı. Malum, loglama vb. utility metotlarını, üzerinde bulunduğu sınıfın nesnesini oluşturmadan hızlıca kullanmak isteriz. Örneğin aşağıda üzerindeki metotları statik olarak tanımlanmış ve bu yüzden de bu metotları kullanmak için nesnesine ihtiyaç duymayacağımız bir Log sınıfı vardır:

public class Log{
	
	public static void logInfo(String infoString){...}
	
	public static void logError(String errorString){...}

        ...
}

Bu sınıfın kullanım örneği de şöyle olabilir:

public class Client{
	public void doThis(){
                ...
                ...
               if(...)
                  Log.logInfo("...");
               else
                  Log.logError("...");
	}
}

Statik metotlara sahip böyle bir sınıfı kullanmanın kolaylığı çok açıktır: Sınıfın kendisini nesne gibi kullanmak. Dahası o tek nesneyi herhangi bir yere geçmenize bile gerek yok, doğrudan sınıfın üzerinden statik alanlara ve metotlara ulaşabilirsiniz.

Eğer yukarıdaki Log sınıfının metotlarını statik yapmak istemezsek ve bu sınıfın sadece bir tane nesnesinin olacağını planlıyorsak bu durumda Log sınıfını singleton olarak şöyle kodlardık:

public class LogSingleton{
	private static LogSingleton logger = new LogSingleton();
	
	private LogSingleton(){...}
	
	public static LogSingleton getInstance(){
		return logger;
	}
	
	public void logInfo(String infoString){...}
	
	public void logError(String errorString){...}
}

Bu durumda da yukarıdaki Client sınıfı şu şekilde değişirdi:

public class Client{
        private LogSingleton logger;

        public Client(){
                logger = LogSingleton.getInstance();
        }

	public void doThis(){
                ...
                ...
               if(...)
                  logger.logInfo("...");
               else
                  logger.logError("...");
	}
}

Şimdi soru şu: Hangi yöntemi kullanmalıyız?

Bazı diller bu ikilemi baştan çözmüşler ve yapılarına statik özellikler almamışlar. Örneğin Scala’da statik metotlu sınıf tanımlamanız mümkün değil, bunun yerine “object” anahtar kelimesiyle nesne tanımlıyorsunuz. Olan biten şey, Scala size doğrudan bir nesnesi olan sınıf tanımlamanızı sağlıyor. Güzel bir çözüm. Java, C#, C++ gibi dillerde ise statik kullanımı söz konusu olduğundan bu tartışma da geçerlidir. Bu durumda sizce hangi kullanımı tercih etmeliyiz ya da siz hangisini tercih ediyorsunuz? Statik metotlar mı yoksa singleton nesne mi?

Toplam görüntülenme sayısı: 3393

15 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
25 Aralık 2014

Önce-Arayüz Yaklaşımı (Interface-first Approach)

Akin Java, Yazılım Modelleme arayüz, inteface

Daha önce “Java Kodunuzun Nesne-Merkezli Olmadığının 10 İşareti” serisinin bu yazısında da bahsetmiştim, ufak olsun büyük olsun, bir program yazacak ya da daha genişi, bir yazılım geliştirecekseniz, işe kodu yazarak değil, tasarlayarak başlamanız gereklidir. Tabi işin analizinin ve detaylı ihtiyaçlarının ortaya konduğunu varsayıyorum.

Önce-arayüz yaklaşımından kastım ise, aslında kodlamaya örneğin Java’da “class” anahtar kelimesi ile sınıf yerine “interface” anahtar kelimesiyle arayüz tanımlayarak başlamak değildir. Bununla kastettiğim, doğrudan koda girişmek yerine biraz geri durup, bilgisayara ya da mesela IDE’ye dokunmadan ihtiyaç üzerine düşünmek ve ona bir tasarım geliştirmektir. Nedir ihtiyaç, ana parçaları nelerdir, bu ihtiyaca nasıl bir çözüm getirilmelidir, çözümdeki temel soyutlamalar neler olmalıdır, aralarındaki ilişkiler nelerdir, kim ne yapmalı, kim neyi bilmeli vb. sorulara cevap vermek için kod yazmaya ihtiyacımız yoktur. Beyaz bir kağıda ya da bir kaç kişiyle çalışıyorsak tahtaya çiziktirerek de bunları yapabiliriz. Yaptığımız bu çiziktirmelerin daha standart ve okunabilir olması için UML’i kullanmayı seçebiliriz ama her iş için UML aracını açıp onu kullanarak bu işleri yapmak eğer işi daha bürokratik hale getiriyorsa bence ona da gerek yok. Dediğim gibi beyaz bir kağıt ya da tahta yeterli.

Problem şu, işe sınıftan başladığınızda yüksek bir ihtimalle IDE’nın başında kod yazıyorsunuzdur. Bu da sizi çok hızlı bir şekilde kodun detaylarına çekecektir. Kodun detayları sonuç olarak “gerçekleştirme” yani “implementation”dır. Gerçekleştirme ise ancak bir tasarım üzerine kurgulanırsa sağlıklı olabilir. “Nasıl arayüzle başlarken kağıt ya da tahta kullanıyorsam, sınıf ile başlayınca da aynı şekilde davranırım, sınıflarla tasarım yaparım” demeyin. İkisi farklı kavramlar ve farklı faaliyetlerin parçası. Arayüz daha çok tasarım faaliyetinin bir parçası, daha az oranda programlamanın parçası. Arayüzler üzerinden düşünmek demek yerine getirilecek olan ihtiyaçla ilgili sorumlulukları belirlemek ve onları uygun soyutlamalarla ifade etmek demektir. Düşünün bir projede arayüzleri kodlamaya ne kadar vakit ayırırsınız, sınıfı kodlamaya ne kadar vakit ayırırsınız. Ezici oranda vaktimizi sınıfları kodlamaya ayırırız, çünkü arayüzlere ayırdığımız vaktin çoğunluğunu arayüzleri kodlamaya değil, onları düzgün bir şekilde ortaya koymaya harcarız. Dolayısıyla probleminizin tasarımına, IDE başında sınıfları kodlayarak girişmek aslında tasarım ve kodlama faaliyetini içi içe geçirmek ve sonrasında da kod detayının ağır basmasından dolayı tamamen koda kayıp tasarımı ıskalamak demektir. Arayüzleri kullanarak tasarıma girişmemiz, yani önce arayüzler üzerine çalışıp sonrasında sınıflara geçmemiz, sağlıklı bir programlama için çok önemlidir.

Tasarım sırasında tabi olarak sınıfları da kullanırız. Çünkü her şeyin arayüzden oluştuğu bir sistemden bahsedemeyiz. Arayüzleri yerine getirecek sınıfların da olması gereklidir ki birileri arayüzde söz verilen sorumlulukları yerine getirsin. Bu yüzden arayüze İngilizce’de “contract” yani “anlaşma” ya da “hand shake” yani “el sıkışma” da denir. Yani sınıflar, arayüzleri yerine getirerek, o arayüzde söz verilen hizmetleri gerçekleştirirler. Ve bu sınıflardan hizmet alacak diğer sınıflar sadece arayüze bağımlı olurlar, arayüzü gerçekleştiren hangi sınıftır bunu bilmez. Hizmet alan sınıfın, aslında sadece arayüzü bilip, gerçekte hangi sınıfın hizmeti sağladığını bilmemesi polymorphism olarak adlandırılır. Programlamamızı tamamen arayüzler üzerinden kurgulamak ise, GoF’un kitabında “program to an interface not an implementation” olarak ifade edilen anlayıştır. Yani daima arayüze bağlı olarak program yazın, arayüzlerin gerçekleştirmeleri olan sınıflara bağımlılık oluşturmayın. Bu prensip Dependency Inversion prensibinin parçası olarak da şöyle “Depend upon abstractions. Do not depend upon concretions.” ya da Robert Martin’in makalesindeki gibi “ABSTRACTIONS SHOULD NOT DEPEND UPON DETAILS. DETAILS SHOULD DEPEND UPON ABSTRACTIONS.” ifade edilir

Tasarım sırasında sınıfların da gündeme gelmesi ile IDE başına oturup ta sınıfları yazmaya başlamak farklı şeylerdir.  Nihayetinde arayüzlerden işe başladığımız için odak noktamız sorumluluklar olacaktır. Bu da arayüzlerde metotların belirlenmesi ve nihayetinde hangi sınıfın hangi arayüzü gerçekleştireceği gibi çalışmaları içerecektir. Beyaz kağıtta bu ana yapıyı kurduktan sonra IDE’ye dönüp, kod detaylarına girişebiliriz. Ama şunu unutmayın: Arayüzleri belirlemek demek sorumluluk öbeklerini yani sorumlulukların arayüzlere nasıl dağıldığını belirlemek, sorumlulukların anlaşma detaylarını (ya da contractual details), yani metotların arayüz bilgilerini (isim, parametreleri ve return tipi), erişim durumlarını, fırlatacağı sıra dışı nesneleri belirlemek demektir. Arayüzlere öncelik vererek tasarıma girişmek, tasarımın konusu olmayan, ancak gerçekleştirmenin konusu olan detayları ele almayı ileriye atmak demektir.

Aşağıdaki örnekte aslen bir sınıf olarak düşünülen Modem’in, arayüz bağlamında düşünüldüğünde, sorumluluklara odaklanarak nasıl iki ayrı arayüz haline geldiğini görebiliriz.

Screen Shot 2014-12-25 at 18.25.39

Yukarıdaki örnekte doğrudan Modem isimli ve dört metoda sahip bir arayüz oluşturmak yerine neden iki farklı arayüz oluşturduğumuzu sorgulayabilirsiniz. İşte bu durum aslında tamamen arayüz odaklı düşünmenin bir sonucudur. Arayüzü önceleyen düşünme sistemi, arayüzleri olabildiğince atomik sorumluluk öbekleri olarak ele alır. Bu prensip de “interface segregation” yani “arayüzlerin ayrılması” olarak ifade edilir. Bu şekilde sadece data alıp-verecek sınıflar Data Channel, sadece bağlantı kuracak sınıflar da Connection arayüzüne bağımlı olurlar.

Bu konuya verilebilecek bir örnek, yukarıda bahsedilen yazıda verildi. Bu örnekte, işin başında arayüz kullanılmadığında sonrasında içine düşülecek sıkıntılı durumlar verilmiştir. Sorumlulukları en başından arayüzlerle ifade etmenin, sonrasında yapıyı ne kadar rahat ettirdiği bu örnekte görülebilir.

Bol arayüzlü günler dilerim.

Toplam görüntülenme sayısı: 1365

11 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
22 Aralık 2014

Bir Algoritma Bağlamında Güzellik ve Performans – II

Akin Bilgisayar Bilimleri, Java monte carlo, performans, pi

Bir önceki yazıya kaldığımız yerden devam edelim.

Tüm bu ölçümler sonuçta JVM’ler üzerinde herhangi bir oynama yapmadan elde edildiler. Algoritmanın performansını arttırmak için yapılacak bir şey var mı diye bakınca aslında algoritmanın kodunda zaten ufak bir-iki iyileştirmenin yapıldığı görülmektedir. Yani algoritmada

double distance = Math.sqrt(Math.pow(x, 2) + Math.pow(y,2));

satırı

double distance = x * x + y * y;

satırı ile değiştirilmişti. Bu ise bizi hem Math.sqrt() ile kare kök almaktan hem de her döngüde iki defa Math.pow() çağrısı yapmaktan kurtardı. Yukarıdaki kodu Math.sqrt() ve Math.pow() metot çağrıları yapacak şekilde değiştirince, n=1000000 için örneğin MacBook Pro’daki 41,70 mili second olan süre yaklaşık 46 miliseconda, n=10000000 için de 415,90 mili seconddan 445 mili seconda çıkıyor. Bu demektir ki biz zaten kodumuzda bu iki metot çağrısını yapmayarak yaklaşık %10luk bir performans artışı kazandık.

Bir başka hızlandırma noktası da rastgele sayı üretimi olabilir. Açıkçası JDK ile gelen yapıların o konudaki en hızlı en optimize kodlar olmadığını tecrübemle biliyorum. Örneğin daha önce de java.util.StringTokenizer‘ı kendim geliştirdiğim çok daha hızlı ve amacım açısından optimize edilmiş bir başka tokenizer ile değiştirmiştim. Aynı şeyi java.lang.Math sınıfındaki random() metodu için de yapabiliriz. Bu durumda ilk akla gelen java.util.Random sınıfı oluyor. Bu sınıfın nextDouble() metodunu kullanınca performansta pek bir değişik olmadı. Sebebi de tam tahmin ettiğim gibi, java.lang.Math sınıfının random() metotu zaten java.util.Random sınıfını kullanıyor 🙂

Apache Commons’daki Math kütüphanesinde de bayağı rastgele veri üreten yapılar var. Dolayısıyla buradaki bir kaç yapıyı denedim ve org.apache.commons.math.random paketindeki MersenneTwister sınıfı mükemmel sonuç verdi. Bu sınıfı kullanmak için koddaki sınıfa

private static BitsStreamGenerator randomData = new MersenneTwister();

satırını ekledim ve

double x = Math.random();
double y = Math.random();

satırlarını

double x = randomData.nextDouble();
double y = randomData.nextDouble();

ile değiştirdim. Macbook Pro üzerindeki şu sonuçlara bakın:

n Süre (ms) Error (%)
10 0,00 16,92
100 0,10 2,91
1.000 0,30 1,34
10.000 1,30 0,4112
100.000 3,60 0,139
1.000.000 19,50 0,047539
10.000.000 188,70 0,013136
100.000.000 1898,00 0,004824
1.000.000.000 19534,90 0,001324

Bu tablodan çıkan sonuç şu, n=10.000 için henüz bir performans ilerlemesi yok ama daha yüksek n sayıları için MersenneTwister sınıfı mükemmel bir performans gösteriyor. Örneğin n=10.000.000 için %57lik, n=100.000.000 için %53lük, n=1.000.000.000 için ise benzer şekilde %52lik bir performans ilerlemesi elde ettik. Burada Apache Commons Math kütüphanesinin hem 2.2 hem de 3.3 sürümlerini kullandığımı ama yukarıdaki sonuçları 2.2 ile aldığımı belirtmeliyim. İlginç bir şekilde 3.3 sürümü, 2.2’ye göre yaklaşık %10 daha yavaş çalıştı. Tabi rastgele sayı üretmek zor iştir, üretilen sayıların rastgele olması açısından olabildiğince bağımsız olması önemlidir. Burada kullandığım MersenneTwister sınıfı için bu konuda daha ayrıntılı bilgi almak isteyenler buraya bakabilirler.

Muhtemelen daha hızlı rastgele sayı üreten yapılar bulunup bu performans daha da arttırılabilir.

Bir sonraki yazıda ise JVM tuning ile neler yapabiliriz buna bakalım.

 

Toplam görüntülenme sayısı: 910

10 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
«< 28 29 30 31 32 >»

Günlüğüme Hoşgeldiniz

Bu günlükte, Yazılım Mühendisliği, Bilgi Teknolojileri, Java, kişisel gelişim ve zaman zaman da diğer konulardaki düşüncelerimi sizlerle paylaşacağım. Umarım beğenir ve hoşça vakit geçirirsiniz.

Her türlü düşüncenizi, yorum olsun, beğeni ya da eleştiri olsun, bana iletmenizi rica ediyorum sizden. Ayrıca bana akin@javaturk.org adresinden ya da Twitter'dan ulaşabilirsiniz. Videolarıma da buradan ulaşabilirsiniz.

Teşekkür ederim.

Akın Kaldıroğlu

Rahat Okumak İçin

A Decrease font size. A Reset font size. A Increase font size.

Sosyal Medya

  • Twitter
  • Facebook
  • LinkedIn
  • Youtube

Son Twitlerim

→ Takip Etmek İçin

Abone Olun

Emalinizi girerek yazılardan haberdar olun.
Loading

Son Yazılarım

  • Udemy Eğitimlerim Üzerine
  • (başlıksız)
  • Clean Code / Temiz Kod Eğitimi Udemy’de
  • Java ile Nesne-Merkezli Programlamaya Giriş Eğitimi Udemy’de
  • Selsoft Video Eğitimleri
  • Spring ile Kurumsal Yazılım Geliştirme
  • Corona Günlerinde Design Patterns
  • Corona Günlerinde Java
  • JDK 10 ve “var” Özelliği
  • Onur Özcan
  • Analist ve İş Bilgisi
  • Farklı Dillerin Bakış Açısıyla Nesne-Merkezli Programlama
  • Java Nedir?
  • Bilgi Teknolojilerinde Yetenek Yönetimi – II: Tanımlar ve Eleştiriler – I
  • Alelade Hikayeler – II: Bir Başka Performans Problemi

Yazı Kategorileri

Yazı Takvimi

Mart 2026
P S Ç P C C P
 1
2345678
9101112131415
16171819202122
23242526272829
3031  
« May    

Yazı Arşivi

Blogroll

  • Binnur Kurt'un Günlüğü
  • Ender'in Java Blogu
  • Erdem Seherler
  • Kızımın Günlüğü
  • Kurumsal Java
  • Levent Karagöl
  • Levent'in Java Blogu
  • Mert Can Akkan’s java tips,options, news…
  • Yaşar Safkan
  • Yasin Saygılı
  • Yazı Dünyası

Yazı Etiketleri

analiz Bilmek C Desen design pattern EJB Eğitim Fortran Hibernate Java Java'ya nasil baslarim Java dersleri Java EE Java Persistence API Java SE Java Sertifika Java Öğren Java öğreniyorum Java öğrenmek JPA Kalıp Kurumsal Java nesne nesne-merkezli No Silver Bullet object object-oriented Oracle Java Certifications pattern performans programlama programlama dilleri programlama nedir sertifika singleton tasarım tasarım deseni tasarım desenleri tasarım şablonu yazılım yazılım geliştirme Yazılım Mühendisliği yazılımın doğası yazılımın zorlukları Şablon

↑

© Java Günlüğüm 2026
Powered by WordPress • Themify WordPress Themes
 

Yorumlar Yükleniyor...