Mevcut Bir Uygulama Koduna Nasıl Adapte Olunur?

yazar:

kategori:

Mevcut bir yazılım projesine dahil oldunuz ve sizden kısa zamanda koda adapte olmanız ve yeni gereksinimleri implemente etmeniz bekleniyor. Nasıl en kısa zamanda, kendinizi evinizde hissedecek şekilde sisteme adapte olabilirsiniz? Bu ve buna benzer sorular bana ulaşıyor. Bu yazımda bu tür soruların cevabını vermeye çalışacağım.

İki tür programcı vardır:

  • Değişikliği arayan
  • Değişikliği istemeyen

Değişikliği kabul etmeyenlerin bünyeleri yeni projeleri kaldırmakta zorlanabilir, lakin değişikliği arayanlar için yeni projelerin ganimet olduğunu biliyorum. Korkunun ecele faydası yoktur misali yeni projeyi cesur bir şekilde göğüslemeye hazır olmak, değişikliklere adapte olmak için en önemli koşulların başında gelmektedir.

Cesaret programcının ismi ise, resmin genelini görmek soyismidir. Programcı yeni bir projede gidişatı anlayabilmek için genel resmi görmeye çaba sarfetmelidir. Genel resmi görmenin faydaları şu şekilde sıralanabilir:

  • Genel resmi görmek insanı rahatlatır, çünkü resmin neresinde olduğunu bilmek insana güven verir.
  • Genel resmi görmek çözüm üretme sürecini hızlandırır, çünkü insan nasıl ilerlemesi gerektiğini kestirebilir.
  • Genel resmi görmek detayları anlamayı kolaylaştırır.

Bir uygulamada genel resim ile tabir ettiğim şey nedir?

Genel resim:

  • Müsterinin ne istediğidir.
  • Mimaridir.
  • Testlerdir.
  • Kod değildir.

En son nokta ile başlamak istiyorum. Genel resim kod değildir dedim. Buradaki yazımda aktarmaya çalıştım. Başkalarının yazdığı kodu okuyarak, olup, bitenleri kavramak çok güçtür. Bu yüzden salt kod analizi ile genel resmi görmeye çalışmak, açma ipi olmayan paraşüt ile uçaktan atlamak gibidir. Bakarsın açılır ihtimalinin olmaması gibi, bakarsın olup, bitenleri kavrarım ihtimalinin olması da çok düşüktür.

Genel resmi görme kabiliyetine erişebilmek için müşterinin ne istediğini bilmek gerekir. Müşterinin vizyonunu tanımadan ve hangi gereksinimlere sahip olduğunu bilmeden genel resme bakılsa bile, anlaşılması çok zordur.

Yazılım projelerinde genel resim iki bölümden oluşur:

  • Müşterinin vizyonu
  • Projenin teknik yapısı

Teknik yapı öncelikle uygulamann sahip olduğu mimaridir. Her uygulamanın bir mimariye sahip olduğu söylenemez. Çoğu zaman ilk müşteri gereksinimlerine göre oluşturulan mimari, zaman içinde yeni gereksinimler ile adapte edilmediği için, uygulamanın altında ezilir ve varlığını gösteremez. Bu genel resmi görmek için mimariyle ilgilenmenin faydalı olmayacağı anlamına gelmektedir.

Testler teknik yapının bir parçasıdır. Bircok projede testler varlıklarıyla değil, yokluklarıyla göze batalar. Testlerin olmaması, herhangi bir teknik yapının varlığına engel olmamakla birlikte, teknik yapının kendi ifade gücünü azaltır. Genel resmi görememekteki en büyük zorluğun eksik olan testlerden kaynaklandığını düşünüyorum. Yazımın ilerleyen bölümlerinde bu konuya açıklık getirmeye çalışacağım.

Bir uygulamanın nasıl yapılandırıldığı (build), sürümlendiği (release) ve yüklendiği de (deployment) teknik yapının bir parçasıdır ve genel resmi görmek için anlaşılması gereken unsurlardandır.

Projenin teknik yapısına ekibi, projenin yönetiliş tarzını ve yazılım geliştirme sürecini de dahil edebiliriz.

Yazılımcı olarak yeni bir uygulamaya adaptasyon için genel resmi görmenin önemini vurgulamaya çalıştım. Genel resmi görmeye çalışmak yine de soyut bir kavram. Bu soyutluğu teknik yapıdan bahsederek, somutlaştırmaya çalıştım. Konuyu daha da somutlaştırmak adına projeye adapte olmak için atılması gereken adımlardan bahsetmek istiyorum.

Bir uygulamanın nasıl çalıştığını anlamanın en kolay yolu, uygulamanın kullanıcılar tarafından nasıl kullanıldığını görmekten geçmektedir. Kullanıcı uygulamayı bir kara kutu olarak görür. Kullanıcı uygulama ile interaksiyona girer ve girdiği bilgiler (input) doğrultusunda, uygulamadan belli davranış biçimleri (output) bekler. Ama ne yazık ki bir kullanıcının yanına oturarak, uygulamanın nasıl kullanıldığını görmek, yeni yazılımcıyı projeye hazırlamak için yeterli değildir. Bunun başlıca sebebi uygulamanın kullanıcı için bir kara kutu gibi çalışması ve yazılımcının kullanıcı interaksiyonlarının kodsal karşılığını görememesidir. Buradan uygulamanın nasıl kullanıldığını gösteren kod birimlerine ihtiyacımız olduğu sonucunu çıkarabiliriz. Aşağıda böyle bir kod birimini görmektesiniz:

[sourcecode language=”java”]
@Test
public void verifyThatCustomerCanBeFound() {
HomePage home = new HomePage(driver);
SearchResultPage searchResult = home.searchFor("özcan acar");

CustomerPage page = searchResult.clickOnTopSearchResultLink();

String expected = "Özcan Acar HomePage";
String actual = page.getHeadLine();
assertTrue(actual.contains(expected));
}

[/sourcecode]

Bu web bazlı bir uygulamayı test etmek için Selenium ile yazılmış bir onay/kabul (acceptance) testi. Onay/kabul testleri uygulamayı en üst seviyede ve çalışır haldeyken test eden entegrasyon testleridir. Testde görüldüğü gibi müşteri arama sayfasına gidilerek, aranan müşteri ismi giriliyor ve gelen bilgiler kontrol ediliyor. Aynı işlemi kullanıcı da muhtemelen yapıyor olacaktır, lakin kullanıcı işlem esnasında HomePage, SearchResultPage ve CustomerPage gibi sınıfları görmez. Yazılımcı için testlerin avantajı burada başlamaktadır.

Testler genel olarak bir uygulamanın nasıl kullanıldığını gösterir niteliktedir. Testler uygulama için kullanıcı (client) konumundadır. Testlere bakarak, uygulamanın nasıl çalıştığını, uygulamanın giriş ve çıkış noktalarını keşfedebiliriz. Bu sebepten dolayı yeni bir projeye dahil olan yazılımcılar için testler uygulamanın kullanma rehberi olma özelliğini taşırlar. Testler incelendiği ve çalıştırıldığı zaman, uygulamanın nasıl çalıştığı hakkında çok kısa bir zamanda fikir sahibi olmak mümkündür.

Testler aracılığı ile uygulamayı çalıştırdıktan sonra durdurmak (debugging) ve adım, adım takip de etmek mümkündür. Bunu yapabilmek de uygulamayı anlama adına atılabilecek en önemli adımlardandır. Bunu nasıl çalıştığını bilmediğimiz ya da çalıştıramadığımız kod birimlerini sadece okuyarak anlama yöntemiyle kıyasladığımızda, testlerin uygulama bünyesindeki mevcut davranış biçimlerini dokümente etmeleri yanı sıra, uygulamayı çalışır hale getirmek için de kullanılabilecek araçların başında geldiğini söyleyebiliriz.

Değişik türde testler hazırlamak mümkündür. Kullanıcı interaksiyonlarını simüle etmek için onay/kabul, uygulamayı entegre ederek, çalıştıran entegrasyon ve işletme mantığını test eden birim (unit) testleri oluşturulabilir.

En iyi testler uygulamanın dış dünyaya sunduğu arayüzlere karşı yazılmış testlerdir. Bu arayüzlere API (Application Programming Interface) ismi verilir. APIyi uygulamanın giriş kapısı olarak düşünebiliriz. APIyi hedef alan testler, uygulamanın nasıl çalıştığına dair ipuçları verirler. Aşağıdaki örnekte uygulamanın işletme katmanının APIsine ait IJobConfigurationService sınıfı için bir entegrasyon testi yer almaktadır.

[sourcecode language=”java”]
@Test
public void when_property_file_is_found_then_a_valid_jobconfiguration_instance_is_returned() throws Exception {

// Given
IJobConfigurationService service = new FileBasedJobConfigurationServiceImpl();

// When
final JobConfiguration configuration = this.service.getConfiguration("dummy");

// Then
assertThat(configuration.getConfig().getString("ARTIFACT_ID"), is(equalTo("test")));

}
[/sourcecode]

Bu örnekte işletme katmanı APIsinin bir parçası olan IJobConfigurationService sınıfının getConfiguration() isimli metodunun nasıl kullanıldığını görmekteyiz. Bu test bize IJobConfigurationService sınıfının nasıl kullanılması gerektiğini apaçık göstermektedir. Bu testi çalıştırarak, neler olup, bittiğini gözlemleyebiliriz. Yaptığımız gözlemler uygulamanın hangi boyutta işlem yaptığını ve hangi parçalardan oluştuğunu anlamamızı yani genel resmi görmemizi kolaylaştıracaktır.

Haklı olarak her projede test olmayabiliyor diyebilirsiniz. Bu konuda size hak veriyorum. Ne yazık ki teknolojik gelişmelerin en hızlı yaşandığı çagda olmamıza rağmen, yazılım projeleri halihazırda iptidai yöntemlerle götürülmeye çalışılmaktadır. Bunların başında da testlerin eksikliği gelmektedir.

Testler yoksa, uygulamayı anlamak için yeni testlerin yazılması geçerli bir seçenek olabilir. Sadece bu şekilde uygulamanın nasıl çalıştığını deneme, yanılma yöntemiyle anlayabiliriz. Testler doğaları itibari ile belli arayüzleri kullanma eğilimi gösterirler. Yeni testler yazarak, bu arayüzleri keşfedebilir ve uygulamanın APIsi hakkında fikir sahibi olabiliriz. Mevcut kod için sonradan test yazmak zahmetli bir iş olabilir, ama oluşan yeni testlerin uygulamanın nasıl çalışdığına dair ipuçları vereceği gerçeğini unutmamak lazım.

Uygulamayı anlamanın diğer bir yöntemi, uygulamayı çalışır hale getirerek, oluşan log kayıtlarını incelemek ve yeni log kayıtları oluşturmaktır. Bu debugging yöntemiyle kombine edildiğinde, uygulamanın nasıl işlediği ve hangi parçalardan oluştuğu konusunda fikir sahibi olmayı kolaylaştıracaktır.

Yeni bir projeye adapte olmak için teknik beceriler yanı sıra sosyal becerilerin de rol oynadığı bir gerçek. Buraya kadar bahsetmiş olduğum yöntemler teknik anlamda bireyin kendi başına uygulayabileceği yöntemlerdir. Bunun yanı sıra proje hakkında bilginin ekip içinde çalışan bireylerde de olduğunu unutmamak gerekir. Ekip bireyleri ile sıkı bir iletişim, uygulamanın nasıl çalıştığını anlamayı kolaylaştıracaktır. Ekip bünyesindeki bilgiyi bir sünger gibi çekebilmek için, ekip çalışanları ile diyalog içinde olmak ve ekibin bir parçası haline gelmek önemli bir adımdır.

Günümüzde birçok projede Scrum, XP (Extreme Programming) ve FDD (Feature Driven Development) gibi çevik süreçler kullanılmaktadır. Bu tarz yönetilen bir projeye dahil olmadan önce, çevik süreçlerin işleyisi hakkında ön bilgiye sahip olmak gereklidir. Bu yüzden projeye hazırlıklı olarak dahil olmak, projeye teknik hakimiyetin kolaylaşmasını sağlayacaktır.


EOF (End Of Fun)
Özcan Acar