Monday, July 8, 2013

Java 8 ile Sayısal Loto Oynamak

Sayısal Loto için 1-49 arasında biri birinden farklı altı sayı çeken ve ekrana sıralı olarak yazdıran programı Java programlama dilinde farklı yaklaşımlarla yazmaya çalışalım.
İlk olarak çözümü Java dizilerini kullanarak oluşturalım:
package com.example.lottery;

import java.util.Arrays;
import java.util.Random;

public class LotteryArrays {
 private static final int SIZE = 6;
 private static final int MIN_VALUE = 1;
 private static final int MAX_VALUE = 49;
 private static Random random= new Random();

 public static void main(String[] args) {
  int[] numbers = new int[SIZE];
  Arrays.fill(numbers, MIN_VALUE + MAX_VALUE);
  for (int i = 0; i < SIZE; ++i) {
   int candidate = 0;
   do {
    candidate = random.nextInt(MAX_VALUE) + 1;
   } while (Arrays.binarySearch(numbers, candidate) > 0);
   numbers[i] = candidate;
   Arrays.parallelSort(numbers);
  }
  System.out.println(Arrays.toString(numbers));
 }
}
Çözümde Arrays sınıfının binarySearch() ve parallelSort() metodlarını kullanmış olmak işimizi epey kolaylaştırdı. 

Şimdi de aynı problemi Java'daki Collections API'yi kullanarak çözelim. Eğer Set ve TreeSet sınıflarını kullanmayı akıl edersek çözüme hızlı bir şekilde ulaşabiliriz:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.example.console;

import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class LotteryCollections {
    private static final int SIZE = 6;
    private static Random random;
    public static void main(String[] args) {
        random = new Random();
        Set<Byte> numbers= new TreeSet<>();
        while (numbers.size()<SIZE){
           numbers.add((byte) (random.nextInt(49) + 1));
        }
        System.out.println(numbers);
    }
}

Son olarak aynı problemi Java 8 ile birlikte gelen Lambda ifadeleri ve Map/Reduce çatısını kullanarak çözelim:
package com.example.lottery;

import java.util.Random;

/**
 *
 * @author Binnur Kurt (binnur.kurt@gmail.com)
 */
public class LotteryLambda {
    public static void main(String[] args) {
         new Random()
             .ints(1,50)
             .parallel()              
             .distinct()
             .limit(6)
             .sorted()
             .sequential()                
             .forEach(System.out::println);                             
    }
}
Koda bakınca Java 8'in soyutlama gücünün arttığını hissetmişsinizdir. Çünkü artık lambda ifadeleri yazabiliyoruz, fonksiyonel programlama yapabiliyoruz. Fonksiyona parametre  olarak fonksiyon geçebiliyoruz. Fonksiyonel programlama ile bildirimsel programlamaya (=declarative programming) geçiş yapıyoruz. Buna karşın yukarıdaki ilk iki örnekte ise buyruksal programlama (=imperative programming) uygulaması var. Nesneye dayalı programlama ile hem bildirimsel hem de buyruksal programlama yapılabilir. Java 8 ile birlikte Java'da fonksiyonel programlama yapabiliyor olsak da Java saf bir fonksiyonel programlama dili değildir.

Wednesday, July 3, 2013

Java 7'de Sınıf Yükleyici Yazmak

Java 7, programlama dili seviyesinde, geliştiricinin daha verimli kod yazabilmesini sağlayan  basit bir kaç yenilik getirdi: 
  • Otomatik Kaynak Yönetimi 
  • catch içinde | sembolü ile ayırarak birden fazla hata sınıfı tanımlayabiliyoruz
  • switch parametresi olarak tam sayı tipler (byte, short, int, long), char, enum tipler dışında [nihayet] String sınıfını kullanabiliyoruz
Java sanal makinası (JSM) seviyesinde uzun bir süreden sonra yeni bir bytecode komutu geldi: invokedynamic. Henüz Java 7'de derlendiğinde invokedynamic kodu ürettirecek herhangi bir Java ifadesi bulunmuyor. Java 8'de ise fonksiyonel programlama ve arayüz metot eklentileri (=Method Extensions) içeren kodlar derlendiklerinde invokedynamic kodu içerebilecek. JSM seviyesinde, Java 7 ile gelen yeniliklerin bir kısmı, çok çekirdekli sistemlerde başarımı iyileştirmeyi amaçlıyor. Örneğin, sınıf yükleyicileri artık paralel çalışabiliyorlar. Java'da kendi sınıf yükleyicimizi yazabiliriz. Bunun için ClassLoader sınıfından yeni bir sınıf türetmemiz gerekiyor. Java 7'de yükleyicinin paralel çalışmaya uygun olduğunu belirtmek üzere registerAsParallelCapable() metodunu çağırıyoruz. Aşağıdaki örnekte class dosyalarını veritabanında arayan bir sınıf yükleyicisi yer alıyor:    
1:  public class JdbcClassLoader extends ClassLoader {  
2:    
3:    public JdbcClassLoader() {  
4:      boolean isOk = registerAsParallelCapable();  
5:      if (isOk) {  
6:        System.err.println("JdbcClassLoader is registered as parallel capable!");  
7:      } else {  
8:        System.err.println("JdbcClassLoader can not be registered as parallel capable!");  
9:      }  
10:    }  
11:    
12:    @Override  
13:    protected Class<?> findClass(String name) throws ClassNotFoundException {  
14:      Class cls;  
15:      EntityManagerFactory emf= Persistence.createEntityManagerFactory("classdbPU");  
16:      EntityManager em= emf.createEntityManager();  
17:      ClassEntity ce= em.createNamedQuery("ClassEntity.findByClassname", ClassEntity.class)  
18:          .setParameter("classname", name)  
19:          .getSingleResult();  
20:      byte[] bytes= ce.getClassBytes();  
21:      cls= defineClass(name, bytes, 0, bytes.length);  
22:      em.close();  
23:      emf.close();  
24:      return cls;  
25:    }  
26:  }  
27:    
Bunun için MySQL veritabanında önce bir veritabanı ve tablo yaratıyoruz:
mysql> create database classdb;
Query OK, 1 row affected (0.05 sec)
mysql> create table classes (
    -> id int(11) not null auto_increment,
    -> classname varchar(256) not null unique,
    -> class longblob not null,
    -> primary key(id)) engine=innodb;
Query OK, 0 rows affected (0.11 sec)
Aşağıdaki Circle sınıfını derleyip, class dosyasını yukarıdaki classes tablosuna ekliyoruz. Bu veriye test kodunu yazarken ihtiyacımız olacak.
1:  public class Circle {  
2:    private double x,y;  
3:    private double radius;  
4:    
5:    public Circle() {  
6:      radius= 1.0;  
7:    }  
8:    
9:    public Circle(double x, double y, double radius) {  
10:      this.x = x;  
11:      this.y = y;  
12:      this.radius = radius;  
13:    }  
14:    
15:    public double getX() {  
16:      return x;  
17:    }  
18:    
19:    public double getY() {  
20:      return y;  
21:    }  
22:    
23:    public double getRadius() {  
24:      return radius;  
25:    }  
26:    public double area(){  
27:      return Math.PI*radius*radius;  
28:    }    
29:  }  
Circle.class dosyasını ise aşağıdaki şekilde classes tablosuna atıyoruz: 
mysql> insert into classes values(NULL,'com.example.shapes.Circle','');
Query OK, 1 row affected (0.08 sec)

mysql> update classes set class=load_file('c:/temp/Circle.class');
Query OK, 1 row affected (0.11 sec)
Rows matched: 1  Changed: 1  Warnings: 0
Veritabanına erişim için JPA 2 kullanacağız. Bunun için projeye önce persistence unit ve daha sonra ise Entity sınıfını ekliyoruz:
1:  package com.example.entity;  
2:    
3:  import java.io.Serializable;  
4:  import javax.persistence.Basic;  
5:  import javax.persistence.Column;  
6:  import javax.persistence.Entity;  
7:  import javax.persistence.GeneratedValue;  
8:  import javax.persistence.GenerationType;  
9:  import javax.persistence.Id;  
10:  import javax.persistence.Lob;  
11:  import javax.persistence.NamedQueries;  
12:  import javax.persistence.NamedQuery;  
13:  import javax.persistence.Table;  
14:    
15:  /**  
16:   *  
17:   * @author Binnur Kurt  
18:   */  
19:  @Entity  
20:  @Table(name = "classes", catalog = "classdb", schema = "")  
21:  @NamedQueries({  
22:    @NamedQuery(name = "ClassEntity.findAll", query = "SELECT c FROM ClassEntity c"),  
23:    @NamedQuery(name = "ClassEntity.findById", query = "SELECT c FROM ClassEntity c WHERE c.id = :id"),  
24:    @NamedQuery(name = "ClassEntity.findByClassname", query = "SELECT c FROM ClassEntity c WHERE c.classname = :classname")})  
25:  public class ClassEntity implements Serializable {  
26:    private static final long serialVersionUID = 1L;  
27:    @Id  
28:    @GeneratedValue(strategy = GenerationType.IDENTITY)  
29:    @Basic(optional = false)  
30:    @Column(name = "id")  
31:    private Integer id;  
32:    @Basic(optional = false)  
33:    @Column(name = "classname")  
34:    private String classname;  
35:    @Basic(optional = false)  
36:    @Lob  
37:    @Column(name = "class")  
38:    private byte[] classBytes;  
39:    
40:    public ClassEntity() {  
41:    }  
42:    
43:    public ClassEntity(Integer id) {  
44:      this.id = id;  
45:    }  
46:    
47:    public ClassEntity(Integer id, String classname, byte[] classBytes) {  
48:      this.id = id;  
49:      this.classname = classname;  
50:      this.classBytes = classBytes;  
51:    }  
52:    
53:    public Integer getId() {  
54:      return id;  
55:    }  
56:    
57:    public void setId(Integer id) {  
58:      this.id = id;  
59:    }  
60:    
61:    public String getClassname() {  
62:      return classname;  
63:    }  
64:    
65:    public void setClassname(String classname) {  
66:      this.classname = classname;  
67:    }  
68:    
69:    public byte[] getClassBytes() {  
70:      return classBytes;  
71:    }  
72:    
73:    public void setClassBytes(byte[] classBytes) {  
74:      this.classBytes = classBytes;  
75:    }  
76:    
77:    @Override  
78:    public int hashCode() {  
79:      int hash = 0;  
80:      hash += (id != null ? id.hashCode() : 0);  
81:      return hash;  
82:    }  
83:    
84:    @Override  
85:    public boolean equals(Object object) {  
86:      // TODO: Warning - this method won't work in the case the id fields are not set  
87:      if (!(object instanceof ClassEntity)) {  
88:        return false;  
89:      }  
90:      ClassEntity other = (ClassEntity) object;  
91:      if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {  
92:        return false;  
93:      }  
94:      return true;  
95:    }  
96:    
97:    @Override  
98:    public String toString() {  
99:      return "com.example.entity.ClassEntity[ id=" + id + " ]";  
100:    }    
101:  }  
Test kodunda ise Java 7 ile gelen Reflection API'ye göre daha yüksek başarımlı olarak çalışan MethodHandle sınıfını kullanacağız:
1:  package org.godel.test;  
2:    
3:  import java.lang.invoke.MethodHandle;  
4:  import java.lang.invoke.MethodHandles;  
5:  import java.lang.invoke.MethodType;  
6:  import org.godel.loader.JdbcClassLoader;  
7:    
8:  /**  
9:   *  
10:   * @author Binnur Kurt  
11:   */  
12:  public class TestJdbcLoader {  
13:    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, Throwable {  
14:      JdbcClassLoader jcl= new JdbcClassLoader();  
15:      Class cls= jcl.loadClass("com.example.shapes.Circle");  
16:      MethodHandles.Lookup lk= MethodHandles.lookup();  
17:      MethodType mt= MethodType.methodType(double.class);   
18:      MethodHandle mh= lk.findVirtual(cls, "area", mt);  
19:      MethodType mtCons= MethodType.methodType(void.class,double.class,double.class,double.class);  
20:      MethodHandle mhCons= lk.findConstructor(cls, mtCons);  
21:      Object circle= mhCons.invoke(1.0,1.0,100.0);  
22:      double area= (double) mh.invoke(circle);  
23:      System.err.println("Area: "+area);  
24:      System.err.println(cls.getName());  
25:    }  
26:  }  
27:    
Uygulama çalıştırıldığında aşağıdaki gibi bir ekran görüntüsü oluşmaktadır: 
JdbcClassLoader is registered as parallel capable!
Area: 31415.926535897932
com.example.shapes.Circle

Friday, June 28, 2013

Modelleme

Yazılım bir dizi etkinliğin gerçekleştirildiği bir sürecin sonucu olarak ortaya çıkar. Basitçe bu etkinlikleri, müşteriden isteklerin alınması, isteklerin çözümlenmesi, sistemin çözümlenmesi, mimari tasarım, yazılımın tasarımı, kodlama ya da gerçekleme, test etme, kurulum ve teslim etme ve bakım olarak sıralayabiliriz. İlk etkinlik müşteriden isteklerin alınmasıdır. Müşteri çoğu zaman tam olarak neyi istediğini bilmez ya da bilemez. Gerçeklemesini istediği sistemle ilgili olarak kafasında genel bir fikir vardır. Bu bir eksiklik olarak görülmemelidir. Yazılım geliştirme sürecinin doğal bir özelliğidir. İsteklerin alınması aşamasının temel amacı da müşteriye aklındaki sistemi tanımlamasına yardımcı olmaktır. İsteklerin çözümlenmesi aşamasında yazılımın gereksinimleri tanımlanır. Yazılımla ilgili olarak basitçe iki tür gereksinimden söz edebiliriz: İşlevsel gereksinimler ve işlevsel olmayan gereksinimler. İşlevsel gereksinimler, yazılımın, kullanan için bir amacı yerine getiren, ona fayda sağlayan yeteneklerini tanımlar. Örneğin, para çekme makinası için para çekme, para yatırma, bakiye sorma, fatura ödeme, havale yapma birer işlevsel gereksinimdir. İşlevsel olmayan gereksinimler ise genellikle yazılımın hizmet kalitesine yönelik tanımlamalar içerir. Örneğin, para çekme makinası örneği için banka müşterisinin banka kartını sisteme tanıttıktan sonra para çekme seçimini yapıp, tutarın onaylamasının ardından, sistemin en geç 10 saniye içinde paragözüne seçilen tutar kadar banknotu bırakması isteniyorsa, bu bir işlevsel olmayan bir gereksinimdir. Gereksinimler dışında iş kuralları ve kısıtlar da bu aşamada not edilir. Örneğin, banka müşterisinin para çekme makinasından günlük olarak en fazla 2,500 TL para çekebileceği tanımlanmış ise bu bir iş kuralı olarak not edilir. Örneğin, yine para çekme makinasının en fazla 2GB bellekli ve Linux işletim sistemli bir platform üzerinde çalışabilmesi istenmişse, bu bir kısıt olarak not edilir. Sistem çözümleme aşamasında sistemin nasıl çalıştığı anlaşılır, tasarım aşamasında ise problem çözülmeye çalışılır. Gerçekleme aşamasında ise çözüm, seçilen bir programlama dilinde kodlanır. Kodlanan çözüm test edilerek sınanır ve müşteriye teslim edilir.
Bu etkinlikleri bir sürecin parçası haline getirmek ve yönetebilmek gerekir. Bu söylemesi kolay ancak gerçeklemesi güç bir söylemdir. Güçlük büyük ölçüde etkinlikleri bir disiplin haline getirebilmekte yatıyor. Profesyonel ile amatörü biri birinden ayıran özelliklerden biri de profesyonelin elindeki işi bir düzen içinde yapmasıdır. Örneğin tıp doktorluğu, inşaat mühendisliği, makina mühendisliği profesyonellik gerektiren mesleklerdir. Yazılım mühendisliğinin de böyle olması beklenir. Yazılım mühendisliğinde süreç yönetim modellerinin amaçlarından biri de bu disiplinleri tanımlamak ve geliştirme ekibindeki her bir rol için ne zaman neyi hangi sırada yapacağını tanımlamaktır. Son yıllarda çevik süreçler olarak adlandırılan öz yinelemeli, artımsal, müşteri odaklı süreç yönetim modelleri öne çıkmıştır. Scrum ve eXtreme Programming (XP) çevik süreç yönetim modellerine örnek olarak verilebilir. Scrum'da belirli bir disiplin yoktur. Bunu daha çok çalışanların deneyimine bırakmaktadır. Bu aynı zamanda Scrum'a getirilen en önemli eleştirilerden biridir. XP modelinde ise bu pratikler tanımlanmıştır. İkili programlama, test güdümlü programlama bu pratiklerden bazılarıdır. 2-4 haftalık dönemlerle yazılım yaşam döngüsü tekrarlanır ve her yineleme sonunda çalışan uygulama müşteri ile paylaşılır ve geri besleme alınır. Her yineleme sonunda uygulama yeni bir işlev kazanır ve bir önceki yinelemenin hataları düzeltilir. Yinelemeler ilerledikçe hem ekip hem de müşteri gerçeklenen yazılım hakkında daha fazla deneyime ve isterler konusunda daha net bir görüşe sahip olacaktır. Bu ise bir taraftan ekibin özgüvenini arttırırken diğer taraftan müşterinin projenin başarıyla tamamlanacağına olan inancını arttıracaktır.
Yazılım geliştirmek zor iştir. Kaliteli yazılım geliştirmek ise daha da zordur. Yazılım projelerin önemli bir kısmı başarısızlıkla sonuçlanmaktadır. Başlangıçta belirlenen bütçe, insan kaynağı ve süre ile ilgili hedeflerin çoğu tutturulamamaktadır. Burada temel güçlük yazılım sistemlerinin karmaşıklığı yanında yazılımın soyut bir kavram olmasından kaynaklanmaktadır. Bilişim sistemleri yazılım ve donanım sistemlerinden oluşur. Donanım para verip satın aldığımızda dokunabileceğimiz, beş duyu organımızla hissedebileceğimiz bir varlıktır. Yazılım ise çalışabilmek için donanıma ve diğer yazılımlara ihtiyaç duyar. Yazılımın ürettiği sonucu ancak bir donanım aracılığı ile algılayabiliriz. Para çekme makinası örneğinde, kartımızı tanıtıp para çekme işleminin adımlarını başarı ile tamamladığımızda, parayı paragözünden alırız ve o an yazılımın para çekme işlevine dokunmuş oluruz. Soyut düşünme konusunda çok başarılı olduğumuz söylenemez. Bu yüzden yazılımı görselleştirmek üzere çeşitli şekiller çizmeyi tercih ediyoruz. Unified Modeling Language (UML), Business Process Modeling Notation (BPMN), System Modeling Language (SysML) gibi standart varlığı ortak bir gösterim dili oluşturması açısından önemlidir. Yazılım yaşam döngüsünde tüm etkinliklerin bir çıktısının olması istenir. Bu çıktı bazen yazılan bir kod bazen çizilen bir UML diyagramı bazen de paydaşlara gönderilen bir e-posta olabilir. Çevik süreç yönetim modellerinde ise UML diyagramı çizilmesine soğuk bakılır. Gerçekten karmaşık bir durumu anlamayı ya da açıklamayı kolaylaştıracağı düşünülüyorsa UML diyagramı çizilebilir. Çevik süreçlerde en iyi modelin çalışan kod olduğu düşünülür.
UML modelin nasıl çizileceğini tanımlar, ancak bir problem verildiğinde problemin bilgisayardaki modelinin nasıl üretileceğini söylemez, yol göstermez. Bir kurumda iki tür sistemden söz etmek mümkündür: Bilişim Teknolojileri Sistemi (BTS) ve İş Süreçleri Sistemi (İSS). İş süreçleri firmaya para kazandıran faaliyetler olarak düşünüle bilinir. BTS'nin amacı İSS'den aldığı verileri işleyip bilgiye dönüştürmek ve karar verme sürecinde kullanılmak üzere İSS'ye aktarmaktır. Genellikle BTS'yi modellemek için UML, İSS'yi modellemek için BPMN kullanılmaktadır. İstenirse UML standardındaki etkinlik (=Activity) diyagramını kullanarak da iş süreçleri modellenebilir. UML bir programlama dili değildir. Ancak istenirse bilgisayar destekli yazılım mühendisliği araçları kullanılarak iskelet kod üretebilinir. UML çalıştırıla bilinir bir model değildir. BPMN 2 ise çalıştırılabilir bir model sunar. Oracla SOA and BPM Suite 11g ürünü kullanılarak web tabanlı bir arayüz üzerinden BPMN'de modelleme yapmak mümkündür. Oracle SOA Suite üzerinde yer alan BPMN motoru bu modeli çalıştırır.
UML profil tanımlanarak genişletilebilir bir modelleme dilidir. Bu profillerden en bilineni SysML profilidir. UML temel olarak yazılım sistemlerinin modellenmesi için tasarlanmıştır. SysML UML'i her türlü sisteme uygulanabilmesini sağlar. SysML UML'de yer alan 14 diyagramın 7'sini kullanır. SysML’de bu diyagramlara ek olarak yeni iki diyagram tanımlanmıştır: ister diyagramı ve parametrik diyagramı.
Hem UML hem de SysML Object Management Group (OMG) tarafından yönetilen standartlardır. OMG kar amacı gütmeyen bir organizasyondur ve yayınladığı standartlar ticari kullanıma açıktır. UML’in güncel sürümü 2.4.2 ve SysML’in güncel sürümü 1.3’dür. UML 2'de diyagramlar, elemanlar ve ilişkiler yine UML elemanları ve sınıf diyagramı kullanılarak tanımlanmıştır. Bu yapı Meta-Model Facility (MOF) olarak adlandırılmaktadır. Profiller de yine MOF kullanılarak tanımlanır. Örneğin SysML profilinin MOF ile tanımlanmış bir meta modeli vardır.
Problemi anlamak, çözmek, çözümü belgelemek için modelleme yapıyoruz. Modelin problemin çözümü için yeterli düzeyde detayı içeriyor olması gerekir. Eğer model eksik ise problemin doğru çözümünü elde edemeyiz, model gereğinden fazla detay içeriyor ise fazladan mühendislik yaptığımız için vakit kaybederiz, bütçeyi gereksiz yere arttırmış ve insan kaynağını verimsiz bir şekilde kullanmış oluruz.
Bir yazılım projesinde tek bir model bulunmaz. Çok sayıda model vardır. Yukarıda gördüğümüz BTS'nin ve İSS'nin ayrı ayrı modelleri vardır. BTS için yine birden fazla model oluştururuz. Yazılım yaşam döngüsünün her bir evresi için bir model yaratırız. Örneğin müşteriden isterlerin alınması evresinin sonunda ister modeli oluşur. Her bir evre sonunda oluşan model izleyen evreler için girdi olarak kullanılır. Örneğin ister modeli çözümleme evresi için girdi olarak kullanılır ve evrenin sonunda analiz modeline evrilir. Analiz modeli tasarım evresinde tasarım modeline, mimari tasarım evresinin sonunda ise mimari modele dönüşür. Mimari modeller yüksek seviyeli modellerdir ve bileşenlerin biri birilerine nasıl bağlanacağını modeller. Sıklıkla kullandığımız mimari modellere istemci-sunucu mimarisini, n-katmanlı mimarisini, Model-View-Controller (MVC) mimarisini, Servis Odaklı Mimariyi (SOM) örnek olarak verebiliriz. Mimari modeller genellikle bize bir şablon verirler. İşlevsel isterler tasarım modelini işlevsel olmayan isterler ise mimari modeli şekillendirir. Çözüm modelini ise tasarım modelini mimari modelin sağladığı bu şablona uygulayarak elde ederiz.
Süreç yönetim modeli ise bir başka modeldir. Yazılım yaşam döngüsünün nasıl yönetileceğini, hangi rolün hangi etkinliklerde yer alacağını, ne zaman neyi yapacağını modeller. Eğer yinelemeli bir süreç yönetim modeli kullanılıyor ise her bir model her yinelemede yeni bir sürüme sahip olacaktır. Dolayısı ile her model yinelemeler boyunca değişebilir ve yeni bir sürüme sahip olabilir.
Bir problem verildiğinde modeli nasıl elde edileceğine ilişkin genel geçer bir yöntem bulunmamaktadır. Genellikle nesneye dayalı bir yaklaşım kullanılarak çözümleme ve tasarım yapılmaktadır. Nesneye dayalı programlamada üç temel yapı bulunmaktadır. Her nesneye dayalı programlama dili bu üç yapıyı destekler:
  1. Paketleme (=Encapsulation)
Nesneye dayalı programlamada, modelleme sınıflar (=Class) aracılığı ile sağlanır. Sınıf veri ve sadece o veri üzerinde işlem yapan metotların bir araya getirilmesi ile oluşturulur. Sınıfın iki tür üyesi bulunur: öznitelikler ve metotlar. Öznitelikler bazen veri, bazen durum olarak da adlandırılır ve sınıfın durağan davranışını modeller. Örneğin çemberi modellemek üzere bir sınıf yazmamız gerekse merkez koordinatları (x,y) ve yarıçap radius bu sınıfın öznitelikleri olacaktır. Bu sınıf Java programlama dilinde kodlanırsa kod aşağıdaki gibi olacaktır:
public class Circle {
     private double x,y ;
     private double radius;
}
Bu model doğru mudur? Doğru, yanlış ya da eksik olduğunu ancak tanımlandığı bağlama bakarak karar verebiliriz. Eğer bu sınıf geometri hesaplamalarında kullanılacak ise doğrudur. Ancak bir çizim programında kullanılmak üzere modellenmiş ise eksiktir. Buna kalınlık, çizim stili, renk gibi öznitelikler eklemek gerekir:
public class Circle {
     private double x,y ;
     private double radius;
     private Color color;
     private int thickness;
     private int style;
}
Bir çizim problemi için yukarıda sınıf daha doğru bir modelleme sağlayacaktır. Metodlar ise sınıfın dinamik davranışı modeller. Örneğin çember sınıfı için area() fonksiyonu çemberin alan hesabını tanımlar:
public class Circle {
     private double x,y ;
     private double radius;
     public double area(){
        return Math.PI * radius * radius;
     }
}
Ancak yukarıda olduğu gibi eğer bir çizim yazılımı için modelleme yapılacak ise draw() metodu daha doğru bir modelleme sunar. Nesneye dayalı programlamanın soyutlama gücü yüksektir. Problemin tanımlandığı fiziksel dünya ile sınıfları kullanarak bilgisayarda kurduğumuz modeli biri birine yaklaştırır. Böylelikle geliştiricinin zihinsel modeli ile gerçeklik arasındaki algılama ya da kavrama uzaklığı azalacaktır. Bu ise problemin daha rahat anlaşılmasını, tasarlanmasını, kodlanmasını ve test edilmesini sağlar.
Sınıflar problemin çözümü için yeterli değildir. Sınıf, inşat mühendislerinin binayı inşa etmeden önce yaptıkları taslak plan çizimleri gibidir. Taslak planda oturamazsınız, yaşayamazsınız. Mutlaka o taslak plana uygun bir şekilde binanın inşa edilmesi gerekir. Sınıflar da aynen taslak planlar gibidir. Problemi çözebilmek için sınıflardan nesneler yaratmak ve bu nesnelerin metotlarını belirli bir sırada ve uygun parametreler ile çağırmak gerekir. Nesneler yaşayan varlıklardır. Sınıflar ise aynı türden nesneler için bir şablon tanımlar. Aynı sınıftan nesnelerin aynı özellikleri vardır, ancak durumları, bu özelliklerin aldıkları değerler farklı olabilir. Aşağıdaki örnekte unitCircle ve anotherCircle nesnelerinin her ikisi de Circle tipindendir, aynı özelliklere sahiptir, ancak durumları farklıdır. unitCircle nesnesi birim çemberdir, diğer nesne anotherCircle ise merkezi (1.0,-1.0) noktasında olan 2.0 yarıçaplı bir çemberdir:
            {
        Circle unitCircle= new Circle(0.0,0.0,1.0);
        Circle anotherCircle= new Circle(1.0,-1.0,2.0);
     }
Nesneye dayalı bir yaklaşımla tasarlanmış bir yazılımın çalışma zamanında resmini çekebilsek karşımıza bir nesne dokusu (ağı) çıkacaktır. Bu dokudaki nesnelerin durumunun bozulmasını istemeyiz. Nesneler bozulduğunda bakım aşamasında hata ayıklama etkinliği ile önce hatanın yerini bulmalı ve düzeltmeliyiz. Keşke hiç bozulmayan nesnelerimiz olabilse. Paketleme bozulmayan sınıflar tasarlamak için tek başına yeterli değildir. Bunun için veri gizleme ilkesini de uygulamak gerekir. Veri gizleme ilkesine göre, sınıfın verilerine doğrudan erişime kapatılmalı ve kontrollü erişim için ise dışarıya açık metotlar eklenmelidir. Bu metotlar nesneyi hatalı bir duruma gitmesine izin vermeyecek şekilde tasarlanmalıdır. Bu ilkeyi Circle sınıfına uygulanacak olursa aşağıdaki gibi çözüm elde edilir:
package com.example.domain;

public class Circle { // Immutable Class

    private double x, y;
    private double radius=1.0;

    public Circle(double x,double y,double radius) {
        this.x = x;
        this.y = y;
        if (radius > 0) {
            this.radius = radius;
        }
    }

    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

    public double getRadius() {
        return radius;
    }

    public double area() {
        return Math.PI * radius * radius;
    }
}
Bu sınıftan yaratılacak hiçbir çember nesnesi geçersiz duruma gitmeyecektir. Ne yapılırsa yapılsın negatif yarıçaplı bir çember elde etmek mümkün olamaz.
Paketleme ve veri gizleme ilkesinin beraber kullanımının bir faydası da Kapalı Kutu (Black-Box) tasarıma olanak vermesidir. Sınıfın dışarıya açık metotlarının imzası (metodun adı, aldığı parametreler ve tipleri) değiştirilmeden sınıfın dışarıya kapalı mimarisi ya da yapısı değiştirildiğinde, bu sınıftan hizmet alan diğer sınıflarda bir değişiklik yapmak gerekmez. Metotların imzalarında değişiklik yapmadan metodun içini değiştirmeye yazılım mühendisliğinde yeniden yapılandırma (=Refactoring) olarak adlandırıyoruz. Bir sınıfı ya da metodu daha hızlı ve kararlı çalışması, daha güvenilir sonuç vermesi, daha az bellekle çalışması, çok-çekirdekli sistemlerde daha verimli çalışması ya da daha güvenli olması gibi nedenlerle yeniden yapılandırabiliriz.
Paketleme ve veri gizleme ilkesinin diğer bir faydası da hatayı bulmayı kolaylaştırmasıdır. Bir nesne hatalı bir duruma gittiğinde hatayı tüm kodda aramamız gerekmez. Kodun daha küçük bir bölgesinde arama yapmamız yeterli olacaktır. Örneğin aramayı hatalı nesnenin sınıfı içindeki metotlara, kalıtım ilişkisi olan sınıflara ya da bu sınıfın arkadaş sınıflarına indirgeyebiliriz. Java’da aynı paketteki sınıflar biri birlerinin arkadaşları olarak adlandırılır. Arkadaş sınıflar biri birlerinin default tanımlı üyelerine erişebilirler. Java’da bir üye tanıtılırken public, protected ve private erişim denetim sözcüklerinden herhangi biri kullanılmamışsa default erişime sahip olur.
  1. Kalıtım (=Inheritance)
Her yeni projeye başladığımızda kendi kısıtları ile başlarız. Temel proje kısıtları olarak proje süresini, bütçesi ve insan kaynağını sıralayabiliriz. Üç yıllık bir proje başarı ile tamamlanmış olsun. Yeni bir projeye başlanıldığında, bu yeni projenin kendi kısıtları ile karşılaşılır. Bu kısıtları ortadan kaldırmak mümkün değildir, ancak kısıtlar hafifletilebilir. Eğer daha önceki projelerde yazdığımız sınıfları yeni projelerde de kullanabilirsek aynı yazılımı daha kısa sürede ya da daha az bütçe ile ya da daha az insan kaynağı ile tamamlayabiliriz. İşte nesneye dayalı programlamadaki kalıtım mekanizması daha önceki projelerde kodladığımız, test ettiğimiz sınıfları bazı değişiklikler yaparak yeni projelerde de kullanabilmemize olanak sağlar. Dolayısı ile bir problemi çözerken tasarladığımız sınıfları sadece elimizdeki problemi çözmek için değil ileride başka projelerde de kullanabilir miyim sorusunu sorarak tasarlamalıyız. Yazılım mühendisliği açısından buna tekrar kullanılabilirlik (=Reusability) diyoruz.
  1. Çok Şekillilik (=Polymorphism)
Nesneye dayalı programlamanın en önemli ayağı çok şekilliliktir. Yazılım mühendisliği açısından çok şekillilik çeviklik sağlar. Üç yıllık bir proje başarı ile tamamlanmış olsun. Yazılımın diğer mühendisliklerin ürünlerinden farklı olduğu birkaç nokta vardır. Bu noktalardan biri teslim ettiğimiz yazılım üzerinde müşterinin her zaman değişiklik isteğinde bulunabilmesidir. Örneğin inşaat mühendisliğinde bir köprü inşası tamamlanıp teslim edildikten sonra köprünün konumunu 10 kilometre kuzey doğuya taşımak, gidiş-dönüş yönünde birer şerit eklemek gibi istekler kabul edilemez. Aynı durum yazılım için çok geçerli değildir. Önemli olan bu değişiklik isteğine ne kadar sürede cevap verebildiğimiz, ne kadar çevik olabildiğimizdir. Eğer basit ya da karmaşık bir değişiklik isteğine bir yılda cevap veriyorsak tasarımda bir problem var demektir. Muhtemelen kodun büyük bir kısmında değişikliğe gitmek zorunda kalmışızdır. Çok şekillik, sınıf hiyerarşisine birkaç sınıf eklemek ve değiştirmek istediğimiz davranışı, metodu yeniden tanımlayarak değişiklik isteğine hızlıca karşılık vermemize olanak sağlar.

Wednesday, June 19, 2013

Java EE 7 Yayınlandı

Java EE platformunun yeni sürümü Java EE 7 oylandı ve kabul edildi. Oylamaları aşağıdaki tablodan okuyabilirsiniz:
Referans gerçekleme yine Glassfish 4.0 uygulama sunucusu. Platformu tanımak ve uygulama geliştirmek için NetBeans 7.3.1'i kullanabilirsiniz. Java EE 7'nin şartnamesine (JSR 342) bu sayfadan erişebilirsiniz. Java EE7 ile gelen JSR listesine ve şartname dokümanlarına aşağıdaki bağlantılardan erişebilirsiniz:
Yenilenen JSR listesi:
  1. JSR 342: Java Platform, Enterprise Edition 7
  2. JSR 236: Concurrency Utilities for Java EE 1.0
  3. JSR 338: Java Persistence 2.1
  4. JSR 339: JAX-RS: The Java API for RESTful Web Services 2.0
  5. JSR 340: Java Servlet 3.1
  6. JSR 341: Expression Language 3.0
  7. JSR 343: Java Message Service 2.0
  8. JSR 344: JavaServer Faces 2.2
  9. JSR 345: Enterprise JavaBeans 3.2
  10. JSR 346: Contexts and Dependency Injection for Java EE 1.1
  11. JSR 349: Bean Validation 1.1
Platforma yeni eklenen JSR listesi:
  1. JSR 352: Batch Applications for the Java Platform 1.0
  2. JSR 353: Java API for JSON Processing 1.0
  3. JSR 356: Java API for WebSocket 1.0
Bakımı yapılan JSR listesi:
  1. JSR 109: Web Services for Java EE 1.4 (Maintenance Release 3)
  2. JSR 115: Java Authorization Service Provider Contract for Containers 1.5 (JACC 1.5) (Maintenance Release 3)
  3. JSR 196: Java Authentication Service Provider Interface for Containers 1.1 (JASPIC 1.1) (Maintenance Release 2)
  4. JSR 245: JavaServer Pages 2.3 (Maintenance Release 2)
  5. JSR 250: Common Annotations for the Java Platform 1.2 (Maintenance Release 2)
  6. JSR 318: Interceptors 1.2 (Maintenance Release 2)
  7. JSR 322: Java EE Connector Architecture 1.7 (Maintenance Release)
  8. JSR 907: Java Transaction API 1.2 (Maintenance Release)
  9. JSR 919: JavaMail 1.5 (Maintenance Release 2)

Tuesday, June 18, 2013

C++ Programming Language, Fourth Edition

     Günümüzde C​ ve C++​ programlama di​lleri​, metale yakın olması nedeni ile
  • Unix sistem​lerinin​ programla​n​ma​sında​, 
  • ​Gömülü sistemlerin programlanması​nda​, 
  • ​Gerçek-zamanlı sistemlerin programla​n​ma​sında, 
  • ​Çok çekirdekli sistemlerin programlanmasında​,​
  • Grafik İşlemci Birimlerinin programlanmasında 
ağırlıklı olarak ​kullanılmaktadır.

     C++, 2011 yılında çıkan yeni sürümü ile günümüz modern programlama dillerinde bulunan birçok ileri düzey özelliğe kavuşmuştur. Nihayet paralel programlama için kullandığımız İş Parçacıkları (=Thread) işletim sistemine bağımlı olmaktan kurtuldu ve dilin bir parçası haline geldi. Nesneye dayalı programlama (=Object Oriented Programming) ve Üretken Programlama (=Generic Programming)'dan sonra Fonksiyonel Programlama yeteneğine kavuştuk. Şablonlar değişken sayıda tip parametresi alabiliyor. C++'ın soyutlama gücü hiç bu kadar güçlü olmamıştı. 
C++ programlama dilinin tasarımını Bjarne Stroustrup yapmıştır. Aynı zamanda dilin standartlaştırma kuruluna liderlik etmektedir. Bu konuda yazdığı "C++ Programming Language" kitabı geçen ay dördüncü baskısını yaptı. Kitabın siparişini Amazon'un web sitesinden verebilirsiniz. Bu yeni baskısı 1360 sayfadan oluşuyor. Daha önceki baskıların yıllarına ve sayfa sayılarına bakalım:
  • Birinci baskı, 1985, 326 sayfa
  • İkinci baskı, 1991, 696 sayfa
  • Üçüncü baskı, 1997, 920 sayfa
  • Üçüncü özel baskı, 2000, 1030 sayfa
İlk ve son baskı arasında 28 yıl geçmiş. Sayfa sayısındaki artış ise tam 4 katı.



Tuesday, May 28, 2013

Oracle JDK numaralandırmasında değişikliğe gidiyor

İnsanlık tarihinde sayabilmek önemli bir aşama olmuştur. Sayabilmek soyut düşünebilmeyi gerektirir. Bu nedenle bugün anladığımız anlamda sayabilmek için epey bir süre beklemişiz. Başlangıçta duvarlara ya da kil tabletlere çeşitli sembollerle miktarı betimleyen semboller çizdik, eşleştirme yapmak üzere taş gibi cisimlerden yararlandık. Hindistan milattan 300 yıl önce sayı ifadelerini rakamlamaya başladı ve altıncı yüzyıla doğru basamakları sağdan sola doğru olan, 1 ‘den 9’a kadar rakamlar ortaya çıktı. Bu rakamlar 660 yıllarında Hindistan dışında da tanınmaya başlandı. El-Harezmi (780-850) milattan önce ve sonra yazılan eski Mezopotamya, Mısır, Yunan, Hind ve İslam alimlerinin kitaplarından yararlanarak kitaplar yazmıştır. Bunların içinde en önemlisi El-Kitabü’l-Muhtasar fi Hesabi’l-Cebri ve’l-Mukabele kitabıdır. Bu eserin aslı İngiltere Oxford Bodlyn kütüphanesindedir. Bu eserde sıfır rakamı ve 9 ayrı rakamın aritmetik işlemlerde nasıl kullanılacağı açıkça gösterilmiştir.
Oracle Java SE versiyonlarının güncellemelerini numaralama yaklaşımını değiştirmeye karar verdi. Oracle'ın yeni numaralama şekli ile ilgili açıklamasını aşağıda bulabilirsiniz: 

  • Limited Update releases will be numbered in multiples of 20. 
  • We intend for Critical Patch Updates to continue to use odd numbers. The numbers will be calculated by adding multiples of five to the prior Limited Update and when needed adding one to keep the resulting number odd. 
This is best illustrated with an example: 
The next Limited Update for JDK 7 will be numbered 7u40, and the next 3 CPUs after that will be numbered 7u45, 7u51, and 7u55. The next release will be a Limited Update 7u60, followed by CPUs 7u65, 7u71, and 7u75. This numbering scheme will leave several numbers between releases which will allow us to insert releases – for example security alerts or support releases, should that become necessary - without having to renumber later releases.

Sunday, May 5, 2013

MySQL'de XML ile Çalışmak

MySQL ilişkisel veritabanı yönetim sisteminde XML veriler ile çalışmak mümkündür. İlk olarak sorgu sonuçlarını nasıl XML olarak alabileceğimizi görelim:

$ mysql -uroot -proot world --xml -e "select * from Country where continent='Asia'" 
<?xml version="1.0"?>

<resultset statement="select * from Country where continent='Asia'
" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <row>
        <field name="Code">AFG</field>
        <field name="Name">Afghanistan</field>
        <field name="Continent">Asia</field>
        <field name="Region">Southern and Central Asia</field>
        <field name="SurfaceArea">652090.00</field>
        <field name="IndepYear">1919</field>
        <field name="Population">22720000</field>
        <field name="LifeExpectancy">45.9</field>
        <field name="GNP">5976.00</field>
        <field name="GNPOld" xsi:nil="true" />
        <field name="LocalName">Afganistan/Afqanestan</field>
        <field name="GovernmentForm">Islamic Emirate</field>
        <field name="HeadOfState">Mohammad Omar</field>
        <field name="Capital">1</field>
        <field name="Code2">AF</field>
  </row>
  .
  .
  .
Burada -e ile mysqld sunucusundan select * from Country where continent='Asia' sorgusunu çalıştırmasını, --xml ile sorgu cevabını XML belgesi olarak ekrana dökmesini istiyoruz. İsterseniz sorgu sonucunu --html seçeneğini vererek doğrudan HTML belgesi olarak da alabilirsiniz. 
Burada mysqld sunucusunun döndürdüğü XML'i daha zengin bir içeriğe dönüştürmek üzere aşağıdaki XSL dönüşümünü uygulayabiliriz:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml"/>
    <xsl:template match="/resultset">
        <countries>
            <xsl:for-each select="row">
                <country>
                    <xsl:for-each select="field">
                        <xsl:element name="{@name}" >
                            <xsl:value-of select="."/>
                        </xsl:element>
                    </xsl:for-each>
                </country>
            </xsl:for-each>
        </countries>
    </xsl:template>
</xsl:stylesheet>

Dönüşüm sonunda Asya ülkelerinin listesini yine XML belgesi olarak elde ediyoruz:

<?xml version="1.0" encoding="UTF-8"?>
<countries>        
    <country>
        <Code>AFG</Code>
        <Name>Afghanistan</Name>
        <Continent>Asia</Continent>
        <Region>Southern and Central Asia</Region>
        <SurfaceArea>652090.00</SurfaceArea>
        <IndepYear>1919</IndepYear>
        <Population>22720000</Population>
        <LifeExpectancy>45.9</LifeExpectancy>
        <GNP>5976.00</GNP>
        <GNPOld/>
        <LocalName>Afganistan/Afqanestan</LocalName>
        <GovernmentForm>Islamic Emirate</GovernmentForm>
        <HeadOfState>Mohammad Omar</HeadOfState>
        <Capital>1</Capital>
        <Code2>AF</Code2>
    </country>
.
.
.
XML bir dokümanı herhangi bir tablonun bir sütununda saklayabilirsiniz. Bunun için o sütunu TEXT tiplerinden birini kullanarak tanımlamanız gerekir:
mysql> use test
Database changed
mysql> create table continents (
    -> name varchar(64) not null,
    -> countries MEDIUMTEXT not null ) ;
Query OK, 0 rows affected (0.35 sec)
XML dosyayı bir değişkene okuyabilirsiniz:
mysql> SET @xml = LOAD_FILE("c:\\temp\\asia.xml");
Query OK, 0 rows affected (0.10 sec)
Bundan sonra tabloya eklemek için INSERT INTO cümlesi çalıştırmak yeterli olacaktır:
mysql> insert into continents values ('Asia',@xml);
Query OK, 1 row affected (0.10 sec)
XML dokümanı sakladığınız sütunu sorgularda kullanabilir ve sonucu bir değişkene alabilirsiniz:
mysql> SELECT countries FROM continents where name='Asia' INTO @xml;
Query OK, 1 row affected (0.04 sec)
MySQL XML dokümanlardan üzerinde XPath ifadeleri çalıştırabilmek için ExtractValue isimli bir fonksiyon sağlıyor. Kullanımına ilişkin bir kaç örneği aşağıda bulabilirsiniz: 
  • Asya ülkelerinin sayısını öğrenmek için count(//row) XPath ifadesini kullanabiliriz:
mysql> SELECT ExtractValue(@xml, 'count(//row)');
+------------------------------------+
| ExtractValue(@xml, 'count(//row)') |
+------------------------------------+
| 51                                 |
+------------------------------------+
1 row in set (0.00 sec)
  • Asya ülkelerinin toplam nüfusunu elde etmek için
mysql> SELECT ExtractValue(@xml, "sum(//row/field[@name='Population'])") as 'Tot
al Population';
+------------------+
| Total Population |
+------------------+
| 3705025700       |
+------------------+
1 row in set (0.00 sec)
ExtractValue ve XPath ile birlikte kullanımına ilişkin daha fazla detayı bu bağlantıdan öğrenebilirsiniz.