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.

Hiç yorum yok: