Cuma, Aralık 30, 2005

Compile Edilmis Kodlarin Versiyon Yonetimi

Compile edilmiş kodlar konfigürasyon yönetim (veya versiyon kontrol) aracı tarafından yönetilmeli mi, yönetilmemeli mi? Farklı yazılım ekipleri, bu soruya farklı cevap veriyor. Bazı ekipler, compile edilmiş dosyaları da konfigürasyon yönetim aracında saklıyor, bazı ekipler sadece kaynak kodlarını saklıyor.

Ben, sadece kaynak kodlarını konfigürasyon yönetim aracında saklamanın doğru olduğu görüşündeyim. Bu konuyla ilgili, “Pragmatic Version Control with Subversion” kitabından bir alıntıyı aşağıya kopyalıyorum. Aşağıdaki alıntıda otomatik olarak üretilen tüm dosyalar (compiled classlar ve diğerleri) ele alınmış:

What about Generated Artifacts?
If we store all the things needed to build the project,
does that mean we should also be storing all the generated
files? For example, we might run JavaDoc to
generate the API documentation for our source tree.
Should that documentation be stored in the version
control system’s repository?
The simple answer is “no.” If a generated file can
be reconstituted from other files, then storing it is simply
duplication. Why is this duplication bad? It isn’t
because we’re worried about wasting disk space. It’s
because we don’t want things to get out of step. If we
store the source and the documentation, and then
change the source, the documentation is now outdated.
If we forget to update it and check it back
in, we’ve now got misleading documentation in our
repository. So in this case, we’d want to keep a single
source of the information, the source code. The same
rules apply to most generated artifacts.
Pragmatically, some artifacts are difficult to regenerate.
For example, you may have only a single license
for a tool that generates a file needed by all the
developers, or a particular artifact may take hours to
create. In these cases, it makes sense to store the
generated artifacts in the repository. The developer
with the tool’s license can create the file, or a fast
machine somewhere can create the expensive artifact.
These can be checked in, and all other developers
can then work from these generated files.

Yukarıda yazılanların dışında, tek tek compile edilmiş tüm *.class dosyalarını (yani her bir kaynak kodu dosyasına karşılık gelen compile edilmiş bytecode dosyaları*) KY (Konfigürasyon Yönetim Aracı) ile takip etmek, özellikle check-out ve check-in işlemleri sırasında zahmetli olacaktır. Çünkü bir programcı bir kaynak kodu dosyasında (*.java) değişiklik yaptığı vakit, bu kaynak kodundan üretilen tüm compile edilmiş *.class dosyalarını da check-out etmek ve sonra kaydederken yeniden check-in etmek zorunda kalacaktır. Eğer *.class dosyalarını check-in etmeyi unutursa, başka bir programcının aynı *.class dosyasını tekrar “exclusively check-out” etmesi mümkün olmayacaktır. Eğer bir *.java dosyasında çok sayıda anonim dahili sınıflar (anonymous inner class) varsa, bu *.java dosyasına karşılık gelen çok sayıda *.class dosyasının tümünü birden check-out ve check-in etmesi gerekecektir. Ki bütün bu işlemler pratik olarak çok yorucu olacaktır.

Bir çözüm, tüm *.class dosyaları yerine sadece nihai olarak deploy edilen uygulamayı (EAR dosyasını) KY sisteminde yönetmektir. Bu yukarıda anlattığımdan daha az yorucu bir işlem olacaktır. Ancak yine de bu işlemin de faydası, sebep olduğu ek zahmeti karşılamayacaktır. Sebebini açıklayayım: Bir anda, bir dosya KY prensiplerine göre en fazla bir kişi tarafından kilitlenebilir, yani check-out edilebilir. Dolayısıyla, aynı anda iki kişi, kendi kodlarını compile edip EAR dosyasını deploy etmesi mümkün olmayacaktır. Buna bir çözüm şu olabilir, EAR dosyalarının KY sisteminde tutulduğu klasör, programcıların otomatik olarak EAR dosyasını ürettikleri yerden farklı bir klasör yapılır. Bu durumda her programcı kendi EAR dosyasını oluşturup deneyebilir. Çözümden emin olduğu vakit, EAR dosyasını KY sistemine yükler. Ancak bu programcının kendi kaynak kodlarını check-in etmesinden farklı bir işlem olacağından, programcı tarafından yapılması unutulabilir. Daha sonra bu EAR dosyası production ortamına yüklenirse, yanlış uygulama yüklenmiş olur.

Bu konuyla ilgili aslında çok senaryolar üretilebilir. Bu bahsettiğim problemlere farklı çözümler getirilebilir. Ancak bu çözümler de yine başka problemlere sebep olacaktır. Sonuçta en kısa şekilde bu sorunu çözen, yazılım geliştirmede çok kullanılan bir ilkeyi uygulamak olacaktır, diye düşünüyorum: Asla aynı şeyin iki kopyasını oluşturma (Don’t repeat yourself). Bu ilke, DRY diye de kısaltılıyor. Compile edilmiş kodlar, kaynak kodlarından otomatik olarak üretilebildiğinden, aynı modelin iki farklı görünümü gibidir. Dolayısıyla her ikisinin birden KY üzerinde tutulması, bir düplikasyondur (duplication).

Eğer compile edilmiş kodları bir şekilde KY sisteminde yönetmeye çalışırsak, karşılaştığımız problemleri çözmek için, çeşitli hackler uygulamamız gerekecek. Bu tür hackler birike birike proje yönetimini zorlaştıracaktır. Bakım maliyetlerinin yükselmesine sebep olacaktır.

Compile edilmiş uygulamanın ve kaynak kodlarının KY sisteminde tutulmasının getireceği avantajlar ise, aslında düşünüldüğü kadar çok değil. Bunun sağlayacağı birinci avantaj zamandan tasarruf etmektir. Ancak EAR dosyasını sıfırdan üretmek, toplam bir iki dakikalık bir işlem. Bu da pratik olarak bir sorun oluşturmaz.

İkinci bir avantaj, farklı ortamlarda üretilen EAR dosyalarının bozuk olabilme ihtimaline karşı bir tedbir oluşturmak. Ancak aslında biz farklı ortamlarda bile bozuk EAR dosyalarının üretilmesine engel olmak için zaten KY sistemini kullanıyoruz. Eğer bizim KY sistemimiz üzerinde çalışan otomatik bir script tüm kaynakları compile edip, çalışır durumdaki EAR uygulamasını oluşturmuyorsa, o zaman bizim KY sistemimiz zaten temelden kusurlu demektir.

Üçüncü bir avantaj, compile edilmiş uygulamadan kaynak kodlarına ve oradan dizayn ve analiz dokümanlarına kadar dosyaların aralarındaki ilişkileri yönetmek olabilir. Ancak burada da şu nokta gözden kaçıyor. Labelling mekanizmasıyla biz zaten productiona aktarılan uygulamanın hangi kaynak kodlarına ve oradan hangi dizayn ve analiz dosyalarına ilişkili olduğunu takip edebiliyoruz. Dolayısıyla, compile edilmiş kodları eklemek ek bir traceability imkanı sunmuyor. Zaten labelling mekanizması bu traceability problemini çözüyor.

* C, .Net gibi farklı ortamlarda compile edilmiş dosyaların isimleri farklıdır. Ama temel mantık hepsinde aynı. EAR yerine bu ortamlarda DLL, EXE veya farklı bir uygulama dosyası uzantısı bulunabilir.

Yazının Devamı...

Çarşamba, Aralık 28, 2005

Structure and Interpretation of Computer Programs, Video Lectures

Bu sitedeki videolar gerçekten harika... "Structure and Interpretation of Computer Programs" adlı kitabın yazarları olan iki MIT hocasının 1986'da verdiği derslerin tümünün video kayıtlarını bu sayfadan indirebilirsiniz.

Hocalar meşhur LISP programlama dili üzerinden programlamanın teorisini anlatıyorlar. İlk dersi izledim. Çok güzeldi. Hem anlatım şekli çok iyi, hem de içerik çok faydalı. LISP'i uzun zamandır merak ediyordum. Özellikle de Yahoo'nun ortaklarından Paul Graham'ın web sitesindeki makaleleri okumak, bende merak uyandırıyordu. Bir kitaptan da LISP öğrenmek mümkün, ama dünyanın en iyi hocalarından ikisini yemek yiyerek dinlemek, çok daha rahat :)

Dersin başından ilgimi çeken bir noktayı da sizinle paylaşayım. Hoca dersin başında büyük harflerle tahtaya COMPUTER SCIENCE (Bilgisayar Bilimi) yazıyor ve ekliyor: "Bu ders bilgisayar bilimini tanıtıyor. Ancak bizim yaptığımız iş, ne bir bilimdir, ne de bilgisayarlar üzerinedir."

Aslında biraz düşününce, hocaya hak vermemek mümkün değil. Bilgisayar bir araçtır. Bilgisayar, programlamanın aracıdır, yoksa konusu değil. Programlama bir bilim olmaktan ziyade, bir sanat veya mühendisliktir. Çünkü objektif doğrular yoktur.

Yazının Devamı...

Salı, Aralık 27, 2005

Rubyye Sorularim 1

Şu ana değin, hep Ruby'nin parıltılarını anlatıyordum. Bu sefer bir değişiklik yapacağım. Ruby'yle ilgili bir sorumu, hatta pek de hoşuma gitmeyen bir noktayı yazacağım. Nesne odaklı programlamayla ilgili kurallardan biri, değer nesnelerinin (value objects - ancak bu kavramı J2EE Design Patterns'ın value object patternıyla karıştırmayın, o farklı bir şey) bir kere oluşturulduktan sonra değiştirilmemesi (immutable) gerekir. Bunu temin etmek için, Java String, Integer gibi en çok kullanılan değer nesnelerini değiştirilmez kılmıştır.

Ancak gördüğüm kadarıyla Ruby'de böyle bir durum yok. Değer nesnelerini değiştirebiliyorsunuz....

Rubyde:


x = "merhaba"
x.upcase!
puts x


=>

"MERHABA"

Javada:


String x = "merhaba";
String y = x.toUpperCase();
System.out.println("x = " + x);
System.out.println("y = " + y);

=>

x = merhaba
y = MERHABA


Neden böyle yapmışlar acaba?

Yazının Devamı...

ZohoWriter: yeni bir web2.0 uygulaması

Yeni bir web2.0 uygulaması daha çıktı: zohowriter.com

Bu da writely veya writeboard gibi internet üzerinde metin dokümanlarınızı oluşturabileceğiniz, arkadaşlarınızla birlikte üzerinde çalışabileceğiniz ve webde saklayabileceğiniz bir uygulama.

Zohonun diğerlerine göre farklı özellikleri şunlar:

* Yazdığınız metinleri blogunuza yayınlayabiliyorsunuz.
* PDF üretebiliyorsunuz.
* Tüm dosyalarınıza kolay ulaşım sağlayan bir panel var.
* Dosyalarınız üzerinde yapılan değişiklikleri history kısmından inceleyebiliyorsunuz.
* Çok temiz bir kullanıcı arayüzü var, fakat Word'ün sunduğu temel metin düzenleme araçlarının hepsini sunuyor.

Bu arada, bu yazıyı zohoda yazdım. Blogger'la entegre bir şekilde çalışıyor... :) Ancak yayınlarken sorun çıktı. Sanırım blogger'ın yeni koyduğu yayınlamadan önce metin kodu girişi özelliğinden kaynaklanıyor.

Yazının Devamı...

Pazartesi, Aralık 26, 2005

Rubyden Parıltılar 2 - Bloklar

Rubynin (sanırım Groovy, Python, Smalltalk gibi diğer OO dinamik dillerde de mevcut) çarpıcı özelliklerinden biri de bloklar. Aşağıda fibanacci sayılarını hesaplayan ve bunları konsola yazan bir kod parçası var:


def fib_up_to(max)
i1, i2 = 1, 1 # parallel assignment (i1 = 1 and i2 = 1)
while i1 <= max
yield i1
i1, i2 = i2, i1+i2
end
end
fib_up_to(1000) {|f| print f, " " }


Yukarıda blokların kullanımına bir örnek var. {|f| print f, " " } bir blok. fib_up_to metoduna -bir tür parametre olarak- bu blok gönderiliyor. yield ile metodun içinden, blok çağrılıyor.

Yukarıdaki kodun güzelliği farklı iki sorumluluğun çok net ve kolay bir şekilde birbirinden ayrıştırılmış olması (seperation of concerns). Blok, kendisine gönderilen bir nesneyi konsola yazdırmakla ilgileniyor. Metot fibonacci algoritmasıyla ilgileniyor. Her ikisi de birbirinin davranışlarından tümüyle bağımsız (orthogonal). Ancak ikisi birlikte kolaylıkla işbirliği yapabiliyor.

Bu örnek için şunu diyebilirsiniz, konsola bir değer yazdırmak için, bunu blokta yürütmenin ne faydası var? Doğrudan while döngüsünün içine bu satırı yazsak, daha basit ve hızlı olurdu.

Sadece bu örnek için bu iddia doğru. Ancak düşünün ki, fibonacci algoritmasını yeri geldikçe farklı ortamlarda kullanmanız gerekebilir. Bir yerde fibanacci dizisini veritabanına yazdırabilirsiniz, bir yerde bunu bir GUI'ye koyarsınız. Veya bu dizinin elemanlarıyla yeni matematiksel işlemler yapmanız gerekebilir. Bu gibi farklı ihtiyaçlar için, yukarıdaki metodu hiç değiştirmeniz gerekmez. Sadece metodun birlikte çalışacağı bloku yazmanız yeterli. Böylece fibanacci dizisini oluşturma mantığını sadece tek bir yerde yürütürsünüz (Don't Repeat Yourself - DRY).

Yazının Devamı...

Pazar, Aralık 25, 2005

Rubyden Parıltılar 1 :)

Başlık biraz edebi oldu, biliyorum :) Ama internette dikkati çekmek için, böyle teknikleri kullanmaya alışmam lazım :))

Neyse, lafı uzatmadan, sadede geleyim. Programming Ruby kitabını okumaya başladım. Burada gördüğüm, Ruby'ye ait çarpıcı özellikleri yeri geldikçe, bloglamaya çalışacağım. Bunlardan ilki, nil (yani Javadaki null) nesnesi.

nil, Java ve benzeri dillerde, hiçbir şey anlamına gelir. Bir null değere herhangi bir mesaj gönderirseniz, NullPointerException alırsınız. Bu yüzden, java kodunda çoğu zaman if( x != null ) kalıbıyla önce x'in null olmadığı kontrol edilir, ondan sonra x'in bir metodu çağrılır.

Bu if cümleleri kodu kalabalıklaştırdığından dolayı, zaman zaman bunları temizlemek için Null Object Pattern adı verilen bir çözüm kullanılır. Ancak bu patternı kendiniz uygulamanız gerekir.

Ancak Rubyde nil, bir nesnedir. Bu yüzden az da olsa bazı metotları destekler. Bu da zannediyorum, if( x != null ) gibi kontrollere daha az ihtiyaç duymamızı sağlayacaktır. Yani Null Object Pattern dilin içine kısmen de olsa giydirilmiş gibi...

Yazının Devamı...

Türkçe Karakter Problemleri

Java üzerinde geliştirilen yabancı frameworklerde en çok rastladığım problem, "i" harfinden kaynaklanıyor. Yabancılar, java ile geliştirme yaparken, String.toLowerCase ve String.toUpperCase metotlarını direkt kullanıyorlar. Bilmiyorlar ki, bizim dilimizde, bu metotlar kendi dillerindekinden farklı çalışıyor. En son olarak JEdit'in 4.2 versiyonunda ve Jakarta Commons NET kütüphanelerinde bu sorunu fark ettim. Geliştiricilerine sorunu ve çözümü bildirdim...


"i".toUpperCase() metodu, Türkçe bilgisayarlarda, "İ" Stringini üretir. Bu da çoğu zaman uygulamanın beklendiği gibi çalışmamasına sebep olur.

Sorunu düzeltmek için, "i".toUpperCase(Locale.ENGLISH) şeklinde metodu kullanmak gerekir.

Bu tarz problemleri kolay bir şekilde tespit etmek için, şu main metodunu kullanabilirsiniz:


public class Main2 {
public static void main(String[] args) {
Locale.setDefault(new Locale("tr","TR"));
org.gjt.sp.jedit.jEdit.main(args);
}
}


jEdit yerine, hangi kütüphaneyi kullanıyorsunuz, onu koyun. Bir bu şekilde çalıştırın, bir de Locale.setDefault(Locale.ENGLISH); ile çalıştırın. Eğer sorun çıkıyorsa, büyük/küçük harf dönüşümü sırasında sorun oluyor demektir.

Yazının Devamı...

Cumartesi, Aralık 24, 2005

Test Driven Development vs. Test First Development

Geçen hafta bizim projede de Test Driven Developmentla ilgili bir tartışma çıktı. TDD'ye göre önce test sonra kod yazılması kural olmalı mı, olmamalı mı? Önce test yazılmasının avantajları var, şüphesiz. Ancak her zaman bunu yapmak da kolay olmuyor. Özellikle derin dizayn veya algoritma gerektiren problemler için, unit testten başlayarak yazmak, benim kendi deneyimlerime göre, biraz zorlayıcı oluyordu. Biraz önce Dave Thomas'ın (benim herhalde en çok alıntıladığım yazar :)) bir röportajını okuyordum. Bu tartışmayı güzel bir şekilde ele almış:

"I believe in test-first development in that I know it exists and therefore, I have to believe in it. I don't necessarily believe you have to follow it. I very much believe in test-driven development and the two are often confused. People tend to talk about TDD and test-first development in the same breath, but they are different. Test-first development says you can't write a line of code until you've got a failing test and that's all right, that's cool, but the more important thing is to say, "I want the tests to drive the design of my application." "I am going to listen to unit tests and I am going to use those to say if my design is incorrect" because a lot of the benefit of testing is not the actual running tests, it's the way it influences the design of your program. ..." Devamı için: http://www.theserverside.com/talks/videos/DaveThomas/interview.tss?bandwidth=dsl

Yazının Devamı...

Programcılarla Mülakat

del.icio.us'dan yine güzel bir makale buldum: How to Interview a Programmer

Joshua Bloch, Dave Thomas gibi tanınmış mühendisler bir programcıyı işe alırken nelere dikkat ettiklerini anlatıyorlar.

Ben çalıştığım firmalara yeni bir programcı alınırken, kendi yaptığım mülakatlarda, özellikle küçük bir problem çözdürme tekniğini uyguluyorum. Programcıya bir alanı (mesela bir stok) nasıl modelleyeceğini soruyorum. Bazen de bir vaka anlatıp (mesela jetonla çalışan bir turnike), bunun çok basit bir şekilde programını yazmasını istiyorum. Ancak burada da beklediğim programcının çalışan bir turnikeyi programlaması değil, bu sistemin içindeki nesneleri ve çalışma mekanizmasını (state machine) tespit edebilmesi.

Tabi çok kısa bir zamanda ve mülakat gibi heyecanın yüksek olduğu bir vakitte bütün problemin tam olarak çözülmesini beklemiyorum. Genellikle programcıya yardımcı oluyorum, onunla birlikte problemi çözmeye çalışıyorum. Hedefim, sadece programcının düşünme yöntemini ve problem çözme yaklaşımını algılayabilmek.

Yazının Devamı...

Cuma, Aralık 23, 2005

Rails Kitabını Bitirdim

Birkaç haftadır Ruby on Rails kitabını okuyordum. Nihayet biraz önce bitirdim. Gerçi son kısımları biraz atladım, ama olsun ihtiyacım olduğunda tekrar bakarım.

Şimdi sıra Pragmatik Programcıların yazdığı diğer kitaba sıra geldi: Programming Ruby

İster programcılığa yeni başlayın, ister yılların programcısı olun. Ruby ve Rails dünyasına girmenizi şiddetle tavsiye ederim. Hem Ruby ve Railsin çok kaliteli yazılım geliştirme olanaklarından yararlanabilirsiniz, hem de pragmatik programcıların kitaplarındaki ilginç pek çok fikirden.

Yazının Devamı...

SwitchTower

Henüz ilgilenmeye fırsat bulamadım, ancak ilginç bir araca benziyor. SwitchTower sayfasındaki yazıya göre, bir projeyi sunucuya deploy etmenizi sağlayan bir otomasyon aracı. Buraya kadar Ant'ın yaptıklarından bir üstünlüğü yok. Ancak SwitchTower ile, eğer uygulamada bir sorun fark ederseniz, otomatik olarak bir önceki duruma rollback edebilmek de mümkünmüş. Hoş bir özellik. Elle da bunu yapmak çok zor değil, ama her seferinde sunucudaki uygulamayı yedeklemeyi insan ihmal edebiliyor.

Yazının Devamı...

Perşembe, Aralık 22, 2005

Ruby on Rails ile rekabet üstünlüğü

Odie Fernandez blogunda "How ThoughtWorks recently won a $800,000 bid" adlı bir yazı yazmış. Ruby on Rails, Javayla yazılım geliştirmeye göre verimlilik noktasında üstünlük sağlıyor gibi görünüyor. (Tabi .Net ve PHP'ye göre de)

Yazının Devamı...

Bir Sisteme Müdahele Yolları

Donella Meadows'un sistem düşüncesi sahasında çok etkili çalışmaları olmuştur. Bunların arasında en büyük etkiye sahip çalışması, "Beyond the Limits" ve "Limits to Growth" adındaki kitaplarıdır. Bu kitaplar, ekonomik büyümenin uzun vadede hangi çevre etkilerine sebep olacağını ve önlem alınmazsa, büyümenin bir süre sonra kendi kendisini tıkayan bir etkiye sebep olacağını anlatır.

Meadows'un güzel makalelerinden biri de "Places to Intervene in a System" adlı bir yazısıdır. Bu makalede Meadows, bir sistemin akışını değiştirmek için yapılan çeşitli müdahele tiplerinin ne kadar etkili olacağını inceliyor.

Sonuçta, şu noktaya varıyor: En etkili müdahele yöntemi, insanların dünyaya bakışlarını belirleyen fikir yapılarını değiştirmektir.

Ekteki yazı, Meadows'un fikirlerinin bir yazılım projesine uyarlanmasını da içeriyor.

Yazının Devamı...

Beğendiğim Internet Uygulamaları

Web 2.0 diye yeni bir terim çıkardılar. Internet üzerinden çalışan yüksek etkileşimli ve yenilikçi özellikleri olan uygulamalara ve sitelere verilen bir isim.

Bu dalga altında gerçekten çok kullanışlı pek çok site çıktı son zamanlarda. Bunlardan bir tanesi: http://www.rememberthemilk.com/ Web üzerinden yapacağınız işleri planladığınız çok kullanışlı ve kolay bir site.

Tavsiye ederim...

Yazının Devamı...

Yeniden Blog :)

Uzun zamandan beri bloglamaya ara vermiştim. Şimdi tekrar geri dönüyorum. Umarım, bir daha böyle uzun süreli bir ara veriş olmaz. İnsan bir şeyi hedefledi mi, bunu düzenli yapmalı. Aksi taktirde hiç bunu hedeflememek daha iyi. En azından kendisine olan güveni yıpranmaz...

Yeniden beni bloglamaya iten, yine bloglamayla ilgili bir yazı oldu: Why You Should Blog. Güzel bir yazı... Amerikalıların sık sık yaptığı gibi, maddeler halinde bu işi niçin yapmak gerektiğini anlatıyor.

Bir okuyun. Güzel fikirleri var...

Yazının Devamı...