Month: February 2014

Doğum günümde Alınacaklar Listesi

Böyle bir listeyi en çok istediğim şeyleri yazmak için oluşturdum. Biri bunları almazsa kendim de almayacağım. Bunlara sahip olmamı istemiyorsanız almamanız yeterli. 😦

  • ilginç renkli pilot kalemler
    beautiful_1x
  • Macbook Pro
    macbook
  • 7 Mart ’14
    Benimle çektirdiğiniz bir fotoğrafı doğum günümde -çerçevelettirmeseniz de olur- hediye olarak vermeniz benim için çok anlamlı olur. Çok sevinirim.
    Polaroid-camera
  • IPod Touch-5     (01.01.2015) (Doğum günüm yarın)
    new-ipod-touch-32-go-blue-generation-5
Advertisements

SOA Nedir?

Yazılım dünyasında birçok şeyi bildiğimi zannediyorum. Bilmediğim diğer şeylerin ise aslında bana çok da uzak olmadıklarını SOA ile gördüm… CV’lerde, iş ilanlarında hep birşeylerin kısaltması yazılır. Ben bunların isimlerini (kısmen) bilmiyorum. Ama yaptıkları iş; evet onları biliyorum. Bunlardan biri SOA.
Serkan Yazıcıoğlu kaynaklı bir tanım buldum, sizlerle paylaşıyorum… Sizin de bu tanımı bildiğinizi, kullanıdığınızı, sadece adının ne olduğunu bilmediğinizi varsayıyorum değerli yazılımcı rakiplerim =)
SOA (Service Oriented Architecture) birbirlerinden farklı servislerin daha karmaşık yapılar oluşturabilmesi için bir harmoni içerisinde beraber çalışabilmesi yaklaşımıdır. Dolayısıyla servis tabanlı mimari yaklaşımı ile tasarlanmış bir sistemin alt sistemi ise doğal olarak servisin ta kendisidir. Servisler ise birbirleri ile iletişime geçebilen yapılardır.

Detaylar:

Klasik mimari bize katmanların birbirleri ile konuşmasını ve üst katmanın alt katmanı çağırmasını söylemektedir. Katmanlı mimari dediğimiz bu yapının oluşturulabilmesi için belirli işleri yapan katmanların bölünmesi ve düzgün bir hiyerarşi ile birbirleri ile konuşabilmeleri şarttır. SOA ise en basit haliyle bu katmanların servis olarak oluşturulmasıdır. Tekrar basit mantık ile devam edecek olursak normal şartlarda oluşturduğumuz data katmanını bir servis haline getirdiğimiz taktirde aslında bir servis yapısına adım atmış oluruz. Bu sayede data katmanımız sadece tek bir uygulamaya değil içeriden ve dışarıdan birden fazla uygulamaya hizmet verebilir hale gelir. Anlıyacağınız üzere SOA bir framework veya kütüphane gibi elle tutulabilir bir altyapı değil, mimari bir yaklaşımdır.

SOA’nın S’si

İlk başta “servis tabanlı mimari” yaklaşımının tanımına bakıldığında servis kelimesinin web servisler (XML Web Services, WCF vs.) ile bağdaştırılması çok olası olmakla birlikte hatalı bir düşüncedir. Tabi ki özellikle WCF teknolojisi SOA yaklaşımı için çok uygun bir altyapı olsa da sadece IIS üzerinde host edilmediğini düşünmemiz gerekir. Örnek vermek gerekirse bir WCF servisini Windows servisi üzerinde host edebildiğinde ve tcp üzerinden connection kurulduğunda makinenin hiçbir internet veya intranet bağlantısı olmayabilir. Sadece windows servislerinin kullanılması da farklı bir yaklaşımdır. Bus servis olarak tasarladığınız bir windows servisi veritabanındaki kayıtları devamlı kontrol ederek işlem yapabilir. Veya hiç windows veya WCF servislerine girmeden direk MSMQ altyapısı da bu yaklaşım için kullanılabilicek bir diğer teknolojidir. Saydığım teknolojiler tabi ki hep MS ürünleri, bir de işin MS olmayan kısmı var ama buranın üzerinde şimdilik çok fazla odaklanmayalım.

Neden SOA?

Tekrar Kullanılabilirlik

Sebeplerden ilkine ve belki de en önemlisine aslında az önce değinmiş olduk. SOA’nın temelinde birden fazla uygulamaya veya kullanıcıya (client) ulaşabilme ihtiyacı bulunmaktadır. Yani tanımlama yapmak gerekirse amaç tekrar kullanılabilirliktir. Biraz işin pratiğine bakalım. Örnek olmak gerekirse bir adet ASP.NET web sitesi geliştirildi fakat müşteriden bir de IOS uygulaması talebi geldi. Bu isteğin ardından IOS için web servisler yazılır ve bundan sonra yapılacak tüm güncellemeler iki taraf için de ayrı ayrı yapılır. Sonuç olarak tekrar kullanılabilirliği göz ardı etmiş, geliştirme maliyetini ve hata çıkma ihtimalini de ikiye katlamış olduk. Bu gibi sıkıntılara yol açmamak için baştan servis mimarisine uygun bir tasarım işlerimizi çok kolaylaştıracaktır.

SOA1

Benzer bir durumda sizin kontrolünüzde geliştirilmeyen (3rd Party) uygulamaların sisteminize entegre olma isteğidir. Bu gibi durumlarda önceden yazılmış servisler işimizi kolaylaştıracaktır.

SOA2

Heterojen Sistemleri Bağlayabilme

Günümüz yazılım dünyasında ortak bir altyapının oluşması mümkün değildir. Sistemlerin teknolojisinin farklı olabileceği gibi aynı teknolojide farklı versiyonda sistemler ile de karşılabiliriz.

Bağlılığı Azaltma (Loose Coupling)

Servisler birbirlerine sınıflar ile değil şema ve kontratlar ile bağlıdırlar. Dolayısıyla da bağlılık azdır. Bir servisin yerine aynı şemaya uyan başka bir servis çok daha rahatlıkla getirilebilir. Örnek vermek gerekirse bir Java servisininin yerine .NET servisi konulabilir veya aynı şemada ama farklı bir iş akışında başka bir servis ile değişiklik yapılabilir.

Ayrıca bağlılığı azaltmak sistemde oluşabilecek darboğazları da azaltır. Örnek vermek gerekirse E-mail gönderme servisindeki bir hatadan dolayı iletişim sayfası yavaşlamaz.

Basitleştirme ve Gizleme (Facade)

Karmaşık yapıların ve karmaşık servislerin daha basit bir arayüz üzerinden sunulması için bu tarz bir mimari kullanılabilir. Bu tarz bir yaklaşım daha çok farklı yazılımcılara servis açtığınızda teknik karışıklıktan ve iş akışlarından uzak tutmak için tercih edilir. Arka taraftaki sistemlerin ve kullanılan teknolojilerin neler olduğu gibi kapsamlı bir bilgilendirmeden ziyade sadece servis hakkında bilgilendirme tüketici (consumer) için yeterli olacaktır. Burada tüketiciden kastım servisi kullanan diğer sistem, servis veya uygulamadır.

Bazı durumlarda tüketcinin rolüne, yetkisine vs. göre farklı verilerin gösterilmesi gerekebilir. Bu gibi durumlarda servis üzerinde filtrelenmiş bir veri iletimi ideal güvenliği sağlayacaktır. Bkz: DTO

Soyutlama

Her servis kendi işinden sorumludur. Şifreleri üretmesini istediğiniz servisiniz sadece şifreleri üretirken login işlemini yapan servis sadece kullanıcı adı ve password bilgilerini kontrol eder. Her bir parça birbirinden ayrı ayrı tasarlandığı için uygulama daha basit parçalara bölünmüş olur. Bu da kodun okunabilirliği arttırırken, bakım süresini kısaltır.

SOA Yaklaşımı Nerelerde Kullanılmalı

SOA yaklaşımı daha çok heterojen, birden fazla sistemin (işletim sistemi gibi), tüketicinin (consumer), uygulamanın (client) yer aldığı yapılarda tercih edilmelidir. Aksi taktirde fazladan bir esneklik sağlamanın karşılığı fazladan bir maliyet olarak karşımıza çıkacaktır. Basit, tek client üzerinden çalışan uygulamalarda klasik katmanlı mimari tercih edilmeye devam edilebilir.
Teşekkür ederim.

Api Oluşturmak

Öncelikle api nedir bunu bir anlayalım.
Api, Application Programming Interface kelimelerinin baş harflerinden oluşan bir kısaltmadır. Uygulama Programlama Arayüzü anlamına gelen Api, herhangi bir uygulamanın belli işlevlerini diğer uygulamalarında kullanabilmesi için oluşturulmuş bi modüldür. Google translate api, twitter api, instagram api, facebook gibi örnekleri vardır.

Soru: Ben nasıl yapacağım?
Cevap: Şimdi şöyle bir problemim vardı, kendi yöntemlerimle çözdüm. Sonra baktım ki ben burada api yazmışım ve kullanıyorum! Biraz daha açıklıyorum;

Android uygulamamda kullanıcı metin kutusuna bir yazı yazıyor, butona tıkladığında o metin birkaç ‘karakter replace’ işleminden geçtikten sonra (burada encode işlemi yapıldı) JSON ile http://www.siteadi.com/get_data.php sayfasına POST ediyorum. Ardından sunucuya gelen metin tekrar ‘replace’ ediliyor (burada decode işlemi yapıldı). Bu metin birkaç ‘php işleminden’ geçiyor, veritabanına kaydedilip POST cevabı olarak farklı bir metin veya değişken olarak ve de SUCCESS değişkeni ile android uygulamama geri dönüyor. Ben gelen metni farklı amaçlara hizmet etsin diye kullanıyorum ve işlem tamamlanmış oluyor.

Yukarıdaki senaryoda android tarafında sadece bir link gördüm. Bu linke metin post edip cevabını aldım. İçeride neler dönüyor neler bitiyor {android tarafında} hiç bir şey görmedim. Bu sunucu üzerindeki yapı API oluyormuş. Eğer bu linklin sonuna http://www.siteadi.com/get_data.php?API_KEY=DRstH36RPrdp1qrkahc3t yazsaydım ve o keyi sunucu üzerinde kontrol etseydim public olarak değil de bir kullanıcıya yönelik işlem yaptırmış olurdum. Ve o key sayesinde kullanıcıyı kısıtlamış, izlemiş ve loglamış olurdum…

Not: Durumlar henüz olgunlaşmadığı için site adını, yapılan işlemlerin detaylarını, metin gönderip alma olayının sebebini – ne işe yarayacağını şimdilik yazamıyorum. İnanın ki süper birşey oluyor….
Yakın zamanda herşeyi resimlerle ve dil seçenekleriyle açıklayacağım.

Şunu da inceleyin, ben hemen geliyorum. https://developers.google.com/google-apps/app-apis

JSON Nedir Nasıl Kullanılır?

Native olarak yazılmış mobil uygulamadan web sunucum üzerine veri göndereceğim. Bunu ister mail atarım. İster veriyi işler, geri getiririm. İster veritabanına yazarım… Peki bunu nasıl yapacağım? JSON ile!
JSON kelime anlamı olarak JavaScript Object Notation manasına gelmektedir.Yapı olarak XML e çok benzeyen JSON tipinin ana amacı veri alış verişi yaparken daha küçük boyutlarda veri alıp göndermektir. Ayrıca kullanımı da çok kolaydır. Sadece 3-5 elemanlı örneklerde bir performans göremesenizde 1000-2000 elemanlı örneklerde performans oldukça farkedecektir. JSON sadece mobil uygulamada değil; xml’in kullanılabileceği her yerde kullanılır. (jquery, c#, php ve diğer dillerle diğer ortamlarda kullanabilirsiniz.)

Not: Burada bir json uygulama örneği bulunmaktadır. Veri yazma, okuma anlatılmıştır. Detaylıca incelemek isterseniz tıklayın.

Push Notification Nedir

Android, IOS veya Blackberry cihazlara yazdığımız uygulamalarda bildirim çubuğuna bildirim bırakmamızı sağlayan yapıdır. Arkaplan servisi (background service) kullanılarak yapılır. Uygulama kapalı olduğunda bile, uygulamanın içeriğine dair kullanıcı bilgilendirmesi yapmak için kullanılır. Örneğin mail geldiğinde telefon titrer, bildirim ışığı yanar ve bildirim çubuğunda 1 yeni posta yazar. Bu, push notification servisi sayesinde yapılır.

Google dökümantasyonda şöyle yazmış: “Google Cloud Messaging for Android (GCM) is a service that helps developers send data from servers to their Android applications on Android devices”.
… diyor ki; “Google Bulut Mesajlaşma servisi, uygulama geliştiricilere sunucudan android cihaz üzerindeki uygulamalarına veri gönderimi yapmayı sağlar.”
Bu servis ile -anlık olarak- yeni veri kullanılabilir olduğunda, sunucudan mobil uygulamanıza istek gönderilir. Böylelikle telefon üzerinde sürekli veri giriş çıkışı kontrolü yapılmaz. Pil, ram, işlemci tasarrufu sağlanır.

Buradan resmi dökümantasyona erişebilir, buradan da geliştirici örneğini inceleyebilirsiniz.

Mobil Uygulama Geliştirme Yöntemleri

Mobil uygulama geliştirirken izlemeniz gereken 3 farklı yol vardır. Geliştireceğiniz uygulamaya göre gereklilikleri de göz önünde bulundurarak bu yolu kendiniz belirlemelisiniz. Bu yollar;

  1. Mobil Site Development
  2. Hybrid Application Development
  3. Native Application Development

1. Mobil Site Development

Mobil cihazınızın kütüphanelerine, sistem ayarlarına, background processlerine ve diğer telefon ile ilgili bir şeye ihtiyaç duymuyorsanız mobil site geliştirerek uygulamanızı yayınlayabilirsiniz. Bunun artısı kolay olması, css ile (css trick) tüm boyutlara tasarımların kolayca uyarlanmasıdır. Eksisi ise sadece sunucu tabanlı çalışıyor olmanız, telefonun hiçbirşeyine erişemiyor olmanızdır.

2. Hybrid Application Development

Bu yöntemde örneğin iphone’a yazdığınız bir mobil program olmalı. İçine web intent koyup uygulama arayüzünü web üzerinden tasarlamalısınız. Aynı zamanda telefon kaynaklarına, background process’lerine erişebilirsiniz. Facebook’un uygulması bir hybrid uygulamadır. Web intent ile tasarlanmış olup aynı zamanda push notification özelliği de kullanılabilmektedir.

3. Native Application Development (Gerçek Uygulama Geliştirme)

Bir şirket için uygulama geliştirdiniz. İçerikleri internetten JSON ile çekip listview veya tableviewgrup’da listelediniz. push notification kullandınız. Android manifest dosyasında internet, telefon kaynakları, sd kart erişimi, telefon bilgisi izinlerine erişip kapsamlı bir uygulama yazdınız. İşte bu native (gerçek) uygulamadır. Telefon üzerindeki C kütüphanelerini ve diğer bahsettiğim kaynakları kullanabilirsiniz.

Mvc Nedir?

Mvc, Model view controller kelimelerinin baş harflerinden oluşan, 1979 yılında Trygve Reenskaug tarafından tanımlandıktan sonra yazılım alanında kullanılmaya başlayan, yazılım mühendisliği’nde kullanılan bir “mimari desenidir (Architectural pattern).” Kullanıcıya yüklü miktarda verinin sunulduğu karmaşık uygulamalarda veri ve gösterimin soyutlanması esasına dayanır. Böylece veriler (model) ve kullanıcı arayüzü (view) birbirini etkilemeden düzenlenebilir. Model view controller(Mvc), bunu controller adı verilen ara bileşenle, veri gösterimi ve kullanıcı etkileşiminden, veri erişimi ve iş mantığını çıkarma suretiyle çözmektedirmvc

Mvc kavramları nelerdir?

1- Model: Veritabanı ile bağlantı işlemleri burada yapılıyor.

2- View: Sitenin tasarımı controllerdan alınan verilerle view sayfalarında yapılıyor.

3- Controller: Bir nevi model ile view arasında köprü görevi görüyor.

Mvc mimarisinin faydaları nelerdir?

1- Kodların daha düzenli, anlaşılır ve sistematik olması,

2- Projenin geliştirilebilirliğini eski yapılara göre çok daha hızlı kılması,

3- Kodlar olması gerektiği yerde, kod karmaşasını önleyeceği için performans arttıracaktır,

4- web projesi şeklinde kullanılabilmektedir.

5- url Routing ile seo dostu Url’ler yaratmak daha kolaylaşmıştır.

6- MVC’nin Ajax kütüphanesi (System.Web.Mvc.Ajax) sayesinde json kullanımı çok kolay hale gelmiştir.

7- Ekip olarak çalışılan projelerde görev paylaşımını ve kodların okunabilirliğini arttırarak takım çalışmasına olanak sağlar.

8- Hata ayıklamayı ve kodu test etmeyi kolaylaştırır.

9- /controllerName/functionName şeklinde sayfalara ulaşma imkanı sunar.
Kaynak: http://mvc.nedir.com/#ixzz2sjV3XzYV

Back End & Front End Developer

Back-End Developer

Back-End Developer; Bir web sitesinin arka planında görünmeyen kodlama ve veritabanı mimarisini inşa eden kişidir. Örnek vermek gerekirse; Bir e-ticaret sisteminin arka planında çalışan veritabanı ve hesaplama işlemlerini yazan kişilerdir.

Bir de back end için şunlar söylenebilir;
Web sistemlerinde arayüz dışında kalan (html, css, javascript, resimler vb.) kısma verilen ad. bir nevi altyapı, işin arka tarafında dönenler denilebilir.

Front-End Developer

Back-End developer’ın tam zıttıdır. Bir web sitesinde bulunan tüm görsel içerikleri front-end developerlar yapar. Tasarımcılardan aldıkları site tasarımlarını html css’e döker ve arayüz programlamasını hazırlarlar.

Behaviour Driven Development

Tarihçe: Bu makale ilk olarak 2006’nın Mart ayında Better Software‘de yayımlandı. Ardından Japonca‘yaYukei WachiKorece‘ye HongJoo Leeİtalyanca‘ya Arialdo MartiniFransızca‘ya Philippe Poumaroux ve de en son İspanyolca‘ya Oscar Zárate tarafından çevrildi.

Bir problemim vardı. Değişik koşullarda gerçekleşen çeşitli projelerde Test-driven development (TDD) gibi çevik yöntemler uygular ve öğretirken hep aynı karışıklık ve yanlış anlamalarla karşılaşıyordum. Programcılar nereden başlayacaklarını, neyi test edip, neyi etmeyeceklerini, bir seferde ne kadar test yazacaklarını, testlerini nasıl adlandıracaklarını ve bir testin başarısız olma nedenini nasıl anlayacaklarını bilmek istiyorlardı.

TDD’de derinleştikçe, kendi deneyimimin giderek artan bir ustalaşma yerine daha çok deneme yanılmalardan oluşan bir yolculuk olduğunu farkettim. Birçok kez “Evet, anlıyorum” yerine “Keşke biri bana bunu daha önce söyleseydi!” dediğimi hatırlıyorum. Sonuçta TDD’nin tuzaklarından kaçınarak, doğrudan iyi taraflarını öne çıkartacak bir şekilde sunmanın mümkün olduğuna karar verdim.

Cevabım Behaviour-driven development (BDD) oldu. Bu yöntem oturmuş çevik uygulamalarından gelişti ve çevik yazılım süreçlerine yeni olan takımlar için daha erişilebilir ve etkin olması amacıyla tasarlandı. Zamanla BDD, çevik analiz ve otomatik kabul testlerinden oluşan daha geniş bir kitleye hitap eder hale dönüştü.

Test metodlarının isimleri cümle şeklinde olmalı

İlk “İşte bu!” anı, çalışma arkadaşım Chris Stevenson’ın yazdığı, yanıltıcı derecede basit agiledox uygulamasını bana gösterdiğinde oldu. Bu yardımcı program bir JUnit test sınıfını alıp metodlarını düz cümleler haline getirmekteydi. Yani şuna benzeyen bir test senaryosu:

public class CustomerLookupTest extends TestCase {
    testFindsCustomerById() {
        ...
    }
    testFailsForDuplicateCustomers() {
        ...
    }
    ...
}

şöyle bir şekile dönüşmekte:

CustomerLookup
- finds customer by id
- fails for duplicate customers
- ...

“test” kelimesi hem sınıftan hem de metod isimlerinden çıkartılıp, camel-case isimlerin düz metine çevrilmesiyle oluşuyordu. Tüm yaptığı bu, fakat sonuçları şaşırtıcı.

Geliştiriciler, bu uygulamanın, en azından bir kısım dokumantasyonu kendileri için yapabileceğini keşfedince, testlerine gerçek cümlelerden oluşan metod isimleri vermeye başladılar. Daha da iyisi, metod isimlerini iş diliyle yazdıklarında, üretilen dokumanlar kullanıcılara, analistlere ve testçilere de anlam ifade etmeye başladı.

Basit bir cümle şablonu, test metodlarının spesifik olmasını sağlar

Ardından test metod isimlerinin “should” ile başlaması konvansiyonunu geliştirdim. Bu cümle şablonu -“Bu nesne bir şey yapmalı”- sadece o sınıf için test tanımlayabileceğinizi belirtmektedir. Ve bu dağılmanızı engeller. Eğer bu şablona uymayan bir metod ismi yazdığınızı farkederseniz, bu aslında size, davranışın başka bir yere ait olduğunu söyler.

Örnek olarak, ekrandan gelen inputu doğrulayan bir sınıf yazıyordum. Çoğu alan basit kullanıcı detayları -isim, soyad, vs., içeriyordu. Fakat hem doğum tarihi hem de yaş için alanlar da vardı. ClientDetailsValidatorTestsınıfını testShouldFailForMissingSurname ve testShouldFailForMissingTitle gibi metodlarla yazmaya başladım.

Ardından yaşı hesaplama kısmına geldim ve karışık iş kuralları karşıma çıktı: Hem yaş hem de doğum tarihi girilmişse ama değerler birbirini tutmuyorsa ne olacak? Doğum tarihi bugünse? Sadece doğum tarihi varsa yaşı nasıl hesaplayacağım? Bu davranışları açıklayan gittikçe çapraşık test metod isimleri yazdım. Sonuçta bu davranışı başka bir yere aktarmaya karar verdim. Bu beni yeni bir AgeCalculator sınıfı yaratmaya yönlendirdi. Ve de ona ait AgeCalculatorTest sınıfını. Tüm yaş hesaplama davranışı Calculator sınıfına geçti, dolayısıyla Validator’ın Calculator ile doğru etkileşime geçtiğini görmek için tek bir test yetti.

Eğer bir sınıf birden çok iş yapıyorsa, bunu genellikle başka sınıflar yaratıp, bazı işlerini onlara devretmek için bir işaret olarak alırım. Yeni servisi ne yaptığını anlatan bir isimle interface olarak tanımlar ve bu servisi sınıfa constructor vasıtasıyla geçerim:

public class ClientDetailsValidator {

    private final AgeCalculator ageCalc;

    public ClientDetailsValidator(AgeCalculator ageCalc) {
        this.ageCalc = ageCalc;
    }
}

Bu şekilde nesleri birbirine bağlama tarzı dependency injection olarak bilinir ve özellikle mock’larla çalışırken faydalıdır.

Açıklayıcı bir test ismi o test başarısız olduğunda yardımcı olur

Bir süre sonra, eğer kodu değiştirdiğim zaman test başarısız oluyorsa, testin ismine bakıp, o kodun amaçlanan davranışını anlayabildiğimi farkettim. Genelde 3 durumdan biri gerçekleşmiştir:

  • Bir bug yaratmışımdır. Çözüm: Bug’ı düzelt.
  • Amaçlanan davranış hala geçerli fakat başka bir yere taşınmıştır. Çözüm: Testi taşı, veya değiştir.
  • Davranış artık geçersizdir, sistemin gereksinimleri değişmiştir. Çözüm: Testi sil.

Son madde çevik projelerde bilginiz arttıkça sıklıkla karşınıza çıkar. Maalesef yeni TDD’ciler, kodlarının kalitesini düşüreceği korkusuyla testleri silmekten çekinirler.

Should (-meli/malı) kelimesinin püf noktası, daha resmi olan will veya shall (-ecek) ile karşılaştırıldığında ortaya çıkmaktadır. Should dolaylı olarak size testin ilk nedenini sorgulamanıza izin verir: “Olmalı mı? Gerçekten mi?” Bu soru, eğer test başarısız olduysa, yerleştirdiğiniz bir bug’dan dolayı mı, yoksa sistem hakkındaki varsayımlarınızın artık geçerli olmadığı için mi olduğunu anlamanızı sağlar.

“Behaviour” (davranış) “test”e göre daha kullanışlı bir kelimedir

Artık test kelimesini kaldırmak için bir aracım -agiledox- ve de test metod isimleri için bir şablonum vardı. Bu sayede insanların TDD hakkında yanılgılarının dönüp dolaşıp “test” kelimesine takıldığını anladım.

Tabii ki bu, test yapmanın TDD’nin özü olmadığı anlamına gelmiyor. Sonuçta çıkan metodlar sistemin doğru çalıştığını garanti etmek için etkin bir yoldur. Yine de, eğer bu metodlar sisteminizin davranışını açıklayıcı bir şekilde tanımlanmıyorsa, sizi sahte bir güvenlik duygusuyla teskin ediyorlardır.

TDD ile çalışırken “test” kelimesi yerine “behaviour”ı (davranış) kullanmaya başladım ve sadece daha iyi oturduğunu değil aynı zamanda koçluk sırasında ortaya çıkan birçok sorunu da sihirli bir şekilde çözdüğünü gördüm. Artık bazı sorulara cevabım vardı. Teste ne isim vermeli? Kolay, ilgilendiğin bir sonraki davranışı anlatan bir cümle olmalı. Nereye kadar test etmeli? Tek bir cümlede davranışı anlatabildiğiniz kadar. Test neden başarısız oldu? yukarıdaki prosedürü izleyin: ya bir bug yerleştirdiniz, ya davranış taşındı, ya da test artık geçerli değildir.

Testlerle düşünmekten davranışlarla (behaviour) düşünmeye geçmenin etkileri o kadar derindi ki TDD’ye BDD, behaviour-driven development demeye başladım.

JBehave test yerine davranışa önem veriyor

2003’ün sonuna doğru paramı, daha doğrusu zamanımı, konuştuğum doğrultuda yatırmaya karar verdim. JUnit yerine geçmesi için, teste yapılan göndermeleri kaldırıp yerine davranışları doğrulama üzerine kurulu bir jargonu olan JBehave’i yazmaya başladım. Bunu, katı bir şekilde davranış odaklı prensiplerime sadık kalırsam, bu framework’ün nasıl gelişeceğini görmek için yaptım. Aynı zamanda, test odaklı jargon olmadan, TDD’yi ve BDD’yi öğretmek için etkin bir yöntem olacağını da düşündüm.

Farz edelim bir CustomerLookup sınıfı için davranışı tanımlamak istiyorum. O zaman CustomerLookupBehaviouradı altında bir davranış sınıfı yazarım. Bu sınıf “should” ile başlayan metodlar barındırır. Behaviour runner, davranış sınıfından bir nesne üretir ve her metodunu, aynı JUnit’in yaptığı gibi sırayla çağırır. İlerledikçe sonuçları döker ve sonunda bir özet basar.

İlk hedefim JBehave’ı kendini denetler hale getirmekti. Sadece kendini çalıştırabilmesi için gerekli davranışları ekledim. Tüm JUnit testlerini JBehave’e taşımayı ve JUnit gibi anında geri bildirim almayı sağlamıştım.

Bir sonraki en önemli davranışı belirle

Ardından “business value” konseptini keşfettim. Elbette, her zaman bir amaç için yazdığımın bilincindeydim. Fakat gerçekte o an yazdığım kodun “işe” olan yansımasını hiç düşünmemiştim. Bir başka çalışma arkadaşım, Chris Matts, beni behaviour-driven development’ı “business value” bağlamında düşünmeye itti.

Amaç JBehave’in kendi kendini denetleyen bir yapıda olmasını sağlamaktı. Bu kapsamda Sistemin şu anda yapmadığı bir sonraki en önemli şey nedir? sorusunu sormanın hedeften sapmamak için faydalı bir yol olduğunu keşfettim.

Bu soru, henüz gerçekleştirmediğiniz özelliklerin değerini belirlemenizi ve onları önceliklendirmenizi gerektirir. Aynı zamanda behaviour metodunuzun ismini bulmanıza yardım eder: Sistem X’i yapmıyor (X anlamlı bir davranış olsun), ve X önemli, demek ki sistem X’i yapmalı. Öyleyse bir sonraki davranışınız basitçe:

public void shouldDoX() {
    // ...
}

Artık diğer bir TDD sorusuna da cevabım vardı: Nereden başlamalı?

Gereksinimler de davranışlardır

Bu noktaya geldiğimde, TDD’nin nasıl çalıştığını anlamamı, daha da önemlisi anlatmamı sağlayacak bir framework’üm vardı. Aynı zamanda bu yaklaşım daha evvel karşılaştığım tuzaklardan da koruyordu.

2004 yılının sonuna doğru, Matts’e yeni keşfimi, davranış bazlı jargonumu anlatırken, bana “Bu aynı analiz gibi.” dedi. Bu fikri hazmetmek için biraz durduk, ardından tüm bu davranış odaklı düşünme şeklini gereksinimleri tanımlama adımına uygulamaya karar verdik. Eğer analistler, testçiler, geliştiriciler ve de çalıştığımız alandaki kullanıcılar için tutarlı bir jargon oluşturabilirsek, bu teknik ve iş dünyası arasındaki çoğu anlaşmazlığı ve karışıklığı da ortadan kaldırmaya yarayacaktı.

BDD analiz için “hazır bir dil” sağlar

O sıralarda, Eric Evans liste başı kitabı Domain-Driven Design’ı yayımladı. Kitabında bir sistemi, o sistemin alanını baz alan hali hazırdaki bir dili kullanarak modellemeyi tarif ediyordu. Böylelikle “iş dili” direk olarak koda yansıyordu.

Chris ve ben bizzat analiz süreci için bir dil yaratmaya çalışıyorduk. İyi bir başlangıç noktası yakalamıştık. Şirketçe ortak kullanımda olan hali hazırda şu sekilde bir şablon vardı:

Bir [X] olarak
[Y]’yi istiyorum
böylece [Z]

burada Y herhangi bir özellik, Z bu özelliğin faydası veya değeri, X ise Y’den faydalanacak bir kullanıcı veya bir rol yerine geçmektedir. Bu yaklaşımın gücü, sizi, özelliği daha tanımlarken, onun değerini de belirlemeye itmesidir. Eğer bir özelliğin arkasında gerçek bir değer (business value) yoksa çoğu zaman diyalog şöyle gerçekleşir: “… [herhangi bir özelliği] istiyorum, böylece [sadece istiyorum].” Bu şablon bu gibi egzantirik gereksinimleri kapsam dışı bırakmayı daha kolay kılmaktadır.

Bu noktadan yola çıkarak, Matts ile birlikte zaten her çevik testçinin bildiğini yeniden keşfettik: Bir hikayenin davranışı basitçe onun kabul kriterleridir – eğer sistem tüm kabul kriterlerini karşılarsa, o zaman doğru davranıyordur, tersiyse, doğru davranmıyordur. Dolayısıyla bir hikayenin kabul kriterlerini yakalayan bir şablon oluşturduk.

Bu şablonun analistlere suni veya sınırlayıcı hissettirmeyecek kadar esnek ama bir hikayeyi parçalarına ayırabilecek ve onları otomatikleştirecek kadar yapısal olması gerekmekteydi. Dolayısıyla kabul kriterlerinisenaryolar olarak tanımlamaya başladık. Şu şekli aldı:

Given (Tanımlanan): İlk şartlar,
when (Ne zaman): bir olay olunca,
then (Sonuç): sonuçları doğrula.

Örneklendirmek için, klasik ATM örneğini verelim. Hikaye kartlarından biri şöyle olabilir:

+Başlık: Müşteri para çeker+
Bir müşteri olarak,
ATM’den para çekmek istiyorum,
böylece bankada sıra beklememe gerek kalmaz.

O zaman bu hikayeyi tamamladığımızı ne zaman bilebiliriz? Göz önüne alınması gereken birkaç senaryo var: Hesapta bakiye mevcuttur. Hesap eksi bakiyededir, ama eksi bakiye limitinin altındadır. Hesap eksi bakiyededir ve eksi bakiye limitini de aşmıştır. Tabii ki başka senaryolar da olacaktır, mesela hesapta bakiye mevcuttur ama çekilecek para hesabı eksi bakiyeye düşürecektir veya ATM’de para kalmamıştır.

Burada given-when-then şablonunu kullanarak, ilk iki senaryo şu şekilde oluşturabiliriz:

+Senaryo 1: Hesapta bakiye var+
Given Bakiyesi olan bir hesap
And kart geçerli
And ATM’de nakit
When müşteri para çekmek istediği zaman
Then paranın hesaptan düğtüğüne emin ol
And paranın verildiğine emin ol
And kartın iade edildiğine emin ol

Tanımlanan ve sonuçların bağlanması için kullanılan “and”‘e (ve) dikkat edin.

+Senaryo 2: Hesap bakiyesi ekside ve eksi limit aşılmış+
Given Hesap eksi bakiyede
And kart geçerli
When müşteri para çekmek istediği zaman
Then red mesajının gösterildiğine emin ol
And paranın verilmediğine emin ol
And kartın iade edildiğine emin ol

İki senaryo da aynı olay üzerine kurulu, hatta aynı girdileri (given) ve sonuçları da (then) paylaşıyorlar. Burada girdileri, olayları ve sonuçları tekrar kullanabileceğimizin altını çizelim.

Kabul kriterlerinin çalıştırılabilir olması lazım

Senaryoların parçaları, girdiler, olaylar ve sonuçlar, kodda direk olarak temsil edilebilecek kadar ayrıntılı olmalı. JBehave bize senaryo parçalarını Java sınıflarında adresleyebilmemizi sağlayan bir nesne modeli vermektedir.

Her given’ı temsil eden bir sınıfı şu şekilde yazabilirsiniz:

public class AccountIsInCredit implements Given {
    public void setup(World world) {
        ...
    }
}
public class CardIsValid implements Given {
    public void setup(World world) {
        ...
    }
}

Bir olay (when) için:

public class CustomerRequestsCash implements Event {
    public void occurIn(World world) {
        ...
    }
}

Benzer sınıflar çıktılar (then) için de yapılır. JBehave tüm bunları birbirine bağlar ve çalıştırır. Nesnelerinizi saklayıp, given’ları geçirebileceği bir “dünya” yaratır. Ardından JBehave “olaya”, o “dünyada” “gerçekleşmesini” söyler. Bu da senaryonun davranışını işletir. En sonunda da kontrolü, tanımladığımız “sonuç” nesnelerine geçirir.

Elimizde her bir parçayı temsil eden bir sınıf olması, bu parçaları başka senaryolarda tekrardan kullanmamıza olanak verir. İlk başta bu parçalar mock’lar kullanılarak gerçekleştirilir. Mesela bakiyesi olan bir hesabı veya geçerli bir kartı temsil etmek için. Böylece davranışı tanımlarken bir başlangıç noktası oluşmuş olur. Uygulamayı kodladıkça, tanımlananlar (given) ve sonuçlar (then) gerçek sınıfları kullanacak şekilde değiştirilir. Böylelikle sonunda gerçek sınıflardan oluşan uçtan uca fonksiyonel testleriniz olmuş olur.

JBehave’in bugünü ve yarını

Kısa bir aradan sonra JBehave tekrar aktif geliştirmeye dönmüş durumda. Çekirdeği oldukça tam ve sağlam bir halde. Bir sonraki adım IntelliJ IDEA ve Eclipse gibi popüler IDE’ler ile entegrasyon.

Dave Astels aktif olarak BDD’nin reklamını yapıyor. Blogu ve yayımlanmış makaleleri birçok hareket çekti. BDD’nin Ruby dilinde gerçekleştirilmiş hali olan rspec bunlardan biri. Ben de JBehave’in Ruby versiyonu olan rbehave üzerinde çalışmaya başladım.

Bazı çalışma arkadaşlarım çeşitli projelerde BDD tekniklerini kullandılar ve bunları oldukça başarılı buldular. JBehave’in hikaye çalıştırıcısı (Behaviour runner) yani kabul kriterlerini onaylayan kısmı, aktif olarak geliştirilmekte.

Vizyonumuz analistlerin ve testçilerin düz metin editöründe hikayeleri yazabileceği ve bunlardan davranış sınıflarının yaratılabileceği bir editor yaratmak. Ve hepsi iş alanının dilinde olacak şekilde. BDD birçok kişinin yardımıyla gelişti ve hepsine minnettarım.

— Dan Northhttp://dannorth.net/introducing-bdd
DAN NORTH’un yazısıdır