Efektif programlama, bir programın doğru, güvenli, verimli ve kolayca anlaşılabilir bir şekilde yazılmasıdır. Bu, programlama dillerinin ve diğer araçların etkin kullanımını içerir.
Efektif bir yazılım geliştirmek için programlama dillerinden bağımsız bir yaklaşım gereklidir. Ancak, kullanılan programlama diline ilişkin derin bir bilgiye sahip olmak, daha etkili ve verimli bir yazılım geliştirmenize yardımcı olabilir.
Verimli programlama, programın kaynakları mümkün olduğunca az tüketerek en hızlı ve en az maliyetli şekilde çalışmasını sağlamak anlamına gelir.
Efektif programlama, birçok fayda sağlar:
- Performans: Efektif programlama teknikleri kullanarak, programlar daha hızlı ve verimli hale getirilebilir. Bu, programların daha hızlı çalışması ve daha az kaynak tüketmesi anlamına gelir.
- Güvenilirlik: Efektif programlama teknikleri ile yazılan kodlar, daha az hata ve güvenlik açığı içerebilir. Bu, kullanıcıların programları daha güvenli bir şekilde kullanmasını sağlar.
- Bakım kolaylığı: Kodların okunabilirliği, modülerliği ve yeniden kullanılabilirliği gibi efektif programlama teknikleri, programların bakımını kolaylaştırır. Bu, kodun güncellenmesi, yeniden yapılandırılması veya değiştirilmesi gerektiğinde zaman ve maliyet tasarrufu sağlar.
- Test etme kolaylığı: Efektif programlama teknikleri, kodun test edilmesini kolaylaştırır. Bu, yazılımın doğru çalıştığından emin olmak için testlerin yazılması ve kullanılması anlamına gelir.
- Daha az hata: Efektif programlama teknikleri kullanarak, kodun daha az hataya sahip olması sağlanabilir. Bu, programın daha güvenli ve daha az sorunlu bir şekilde çalışmasını sağlar.
Örneğin, hayal edin ki 15K farklı methodunuz var ve bu methodlar her çalışıtırıldığın bir log basmaktadır. Log basmak için bir sınıfınız var ve bu sınıf basit bir methoda sahip.
public static void printLog(String methodName) {
System.out.println("Method Name: " + methodName);
}
Bu method, ilk bakışta basit bir işlem yapıyor gibi görünse de, tüm methodlar tarafından çağrıldığında gereksiz yere hafızada atık (garbage) oluşabilir. Bunun yerine, logların yazdırılmasına karar veren bir mekanizma yazabiliriz. Bunun için bir boolean tanımlayabilir ve aşağıdaki gibi kullanabiliriz:
public static void printLog(String methodName) {
if (isTrace) {
System.out.println("Method Name: " + methodName);
}
}
Ancak bu yöntem de başarısız olacaktır. Çünkü bu metot çağrıldığında bir string tanımlanacak ve kopyası oluşturulacak, bu kopya metoda gönderilecek ve eğer isTrace=false ise log basılmayacak ve gereksiz yere garbage oluşacaktır.
Bunun yerine, bu metodu çağırdığımızda önce isTrace kontrolü yaparak gereksiz string kopyaları oluşturmadan logları bastırabiliriz. Bu şekilde, gereksiz atık (garbage) oluşumunu önleyebiliriz.
if (isTrace) {
printLog("test method name");
}
Bu yöntemle metot çağrılmadan önce logun isTrace kontrolü yapılarak boşa garbage oluşturmanın önüne geçilmiş olur.
Bir diğer husus ise döngülerdir. Tüm programlama dillerinde döngüler kullanılır. Döngülerde yapılan küçük hatalar büyük sorunlara yol açabilir.
Ancak döngülerin içinde tanımlanan değişkenlerin her tekrarda tekrar oluşturulması, gereksiz bellek kullanımına neden olabilir ve programın performansını olumsuz etkileyebilir.
int i = 0;
while (i < 1000000) {
String methodName = "Test service " + i;
printLog(methodName);
i++;
}
Bu nedenle, döngülerdeki değişken tanımlamaları mümkünse döngülerin dışında yapılmalıdır. Böylece, tek bir değişken üzerinden tüm işlemler rahatlıkla ve daha efektif olarak yapılabilir.
String methodName = null;
int i = 0;
while (i < 1000000) {
method = "Test method " + i;
printLog(method);
i++;
}
Bu yöntem, programın bellek kullanımını azaltır ve işlemlerin daha verimli bir şekilde yapılmasını sağlar. Ancak, döngülerin sınırlandırılması ve koşullarının doğru bir şekilde belirlenmesi de programın verimliliği açısından önemlidir. Yani, döngülerdeki işlemleri mümkün olduğunca basitleştirmek ve gereksiz işlemlerden kaçınmak, programın performansını artıracaktır.
Başka bir konu ise, if-else deyimlerinde kontrol sıralamasının dikkatsizce yazılmasıdır. Geliştirme sırasında, kodların sıralamasının önemi büyüktür.
Örneğin, Java sanal makinesi, kontrol koşullarını soldan sağa doğru değerlendirmektedir. Bu nedenle, kontrol koşullarının doğru bir şekilde sıralandığından emin olmak önemlidir.
if(A() && B() && C(D()))
1. ilk olara A metodu çağrılır ve true gelirse
2. İkinci olarak B metodu çağrılır ve true gelirse
3. D metodu çağrılır ve C metoduna D metodunun çıktısı verilir.
Eğer metotlardan herhangi birisi false gerilirse diğer kontrolleri yapmadan çıkar. Bu durumda kontrol koşullarını akıllıca koymamız daha mantıklı ve efektif olacaktır. Örneğin aşağıdaki gibi bir durum bize çok pahalıya mal olacaktır.
if(expensiveMethodCall() && cheapMethodCall() && cheapBoolEval)
Bunun yerine önce boolean kontrolü yapılmalı ve koşullar aşağıdaki gibi sıralanmalıdır.
if(cheapBoolEval && cheapMethodCall() && expensiveMethodCall())
Önemli konulardan birisi ise karşılaştırma işlemleridir. Karşılaştırma işlemleri için “büyük/küçük” operatörleri kullanmak, eşitlik kontrolünden daha hızlıdır. Bu, sayının tüm bitlerinin kontrol edilmesi gereken eşitlik kontrolünden farklı olarak, büyüklük/küçüklük kontrolünde sayının sadece birkaç bitinin kontrol edilmesi gerektiği anlamına gelir. Bu nedenle, Java’da karşılaştırma işlemlerinde büyük/küçük operatörleri tercih edilir.
if(counter==1000000) vs if(counter>1000000)
Son olarak aklıma gelen başka bir örnek ise bir aşağıdaki gibi bir karşılaştırma durumudur. Bu tip karşılaştırmalarda çok fazla dikkat edilmiyor ama aşağıdaki kod örneğindeki gibi bir durumunuz varsa. Burada Country objesinin null gelebileceğini düşünmelisiniz ve bu karşılaştırma ifadesini daha iyi bir şekilde yazmalısınız.
private final static String CODE = "TR";
boolean isCountryCodeTR(final Country country){
if(country.getCode().equalsIgnoreCase(CODE)){
return true;
}
return false;
}
Aşağıdaki kod örneğinde en basit hali ile bunu nasıl yapabileceğiniz görebilirsiniz.
private final static String CODE = "TR";
boolean isCountryCodeTR(final Country country){
if(CODE.equalsIgnoreCase(country.getCode())){
return true;
}
return false;
}
Sonuç olarak, efektif programlama teknikleri kullanarak, programların daha performanslı, güvenilir, bakımı kolay ve daha az hatalı hale getirilebilir. Bu da kullanıcı memnuniyeti ve daha az zaman ve maliyet kaybı anlamına gelir.