Monday, November 1, 2004

Oracle VARCHAR İndeksleri Üzerinden Erişim Yavaş mıdır?

İnternet'te gezinen bir efsaneye göre, "Oracle VARCHAR, VARCHAR2 kolonları üzerinden yaratılan indeksler üzerinden erişim yavaş olmaktadır", ve "bu tür kolonlar üzerinden indeks yaratılmaktan kaçınılmalıdır".

Kulağa peri masalı gibi gelen bu genelleme hakkında, biz de bir bilene danıştık. Beraber Martha Stewart Omnimedia şirketinde veri ambarı (data warehouse) projesinden çalıştığım Oracle uzmanı arkadaşıma bu soruyu yönelttim. Kendisinden şu cevabı aldım:

Cevap:

Büyük bir ölçüde, bu tam bir peri masalı (myth). Durumun böyle olmadığını değişik ölçülerde tablolar yaratıp üzerlerinde join'ler ve nokta sorgular işleterek çok rahat ispatlayabilirsin. Benim bu peri masalının niye ortada olduğuna dair birkaç teorim bile var.

1) 50,000 satırdan daha az veri içeren küçük tablolarda, direk tarama (direct scan) [1], herhalde daha hızlı sonuç verir. Çünkü donanım seviyesinden düşünürsek, eğer indeks kullanıyorsak, sabit disk kafası önce önce indeksi okuyacak, ondan sonra veri içeren tabloyu okuyacak. Tablo zaten çok küçük ise, erişimi ara "bir diğer işlem" olmadan yapmak, daha hızlı olabilir.

2) Integer ve number üzerinden indekslerin daha hızlı olduğu biliniyor. [2].

3) Bir VARCHAR indeksini yaratmak daha oldukça fazla zaman ve yer tutuyor!!! Bu durum, bahsettiğim peri masalından sorumlu olabilir. Ama mevzubahis olan kolon birçok kere erişiliyorsa, o zaman bu indeksi yaratmak, harcanan zamana ve disk alanına kesinlikle değecektir [3].

Yâni, büyük bir tablo ve üzerinden çok arama yapılan bir VARCHAR kolonu üzerinde indeks koymak, o sorguyu kesinlikle daha hızlandıracaktır. Bunu çok kolay test edebiliriz. 10 milyon satırlık ve üzerinde sadece isim olan bir tablo yarat. Sonra select * from table where isim = 'xxxxxxx' de, ve sorgunun ne kadar hızlı geri geldiğini bir yere not et. Meselâ bu örnekte 5 dakika olsun. Sonra isim kolonu üzerinde bir btree indeksi yarat (bu indeksi yaratmak 10 dakika sürebilir), ve aynı sorguyu tekrar işlet. Sonuç anında geri dönecektir. Evet indeksi yaratmak için 10 dakikayı harcadık, ama 2. ve 3. seferde artık kâra geçiyoruz ve indeksi yaratmak için harcadığımız vaktin bir önemi kalmıyor [3].

Hash Join'ler ve İndeksler

Bir de eğer elinde MEGA donanım/beygir gücü varsa, o zaman indeks kullanmamak daha hızlı olabilir. Bahsettiğim donanım, mikroişlemciler üzerinde Massive Parallel'i destekleyen, ve üzerinden JOIN yapılan tüm kolonların hafızaya önceden yüklemeye izin verebilen türden bir donanımdır. Swap diskler ve asal diskin de dehşet hızlı olması yardım eder. Bu tür bir kuruluşta, parallellik ve hash join'leri kullanmak, varchar kolon üzerinden indeks kullanmaktan daha hızlı olacaktır. Fakat daha küçük donanımlarda eğer bütün hash join hafızada yapılamıyor ve kolonlar çok hızlı okunamıyorsa, varchar olsun olmasın, indeks kullanmaktan başka çaremiz olmayacaktır.

Notlar

[1] İndeks üzerinden değil her satıra teker teker bakılara arama yapılan senaryodur.

[2] Yâni, her nasılsa "integer indekslerinden daha yavaş" betimlemesi, "çok yavaş" betimlemesine dönüşüvermiştir.

[3] Arkadaşım veri ambarcısı olduğu için, bir seferde milyon satıra varan günlük veri transferleri yapmaktadır, ve bu transferler sırasında ara tablolar (staging tables) üzerinde indeksler her seferinde silbaştan yaratılır. Bu indeksleri sürekli yarattığı için, indeks yaratma zamanı da kendisi için önemli bir faktördür. OLTP cenahı için indeks yaratma zamanı önemli olmayabilir, ama arkadaşın VARCHAR indeksi üzerinden "erişim" hakkında söyledikleri her Oracle kullanıcısı için geçerlidir.

Martha Stewart bahsedilen veri ambarını şu anda Oracle 10g üzerinde tutmaktadır.

Türev İşlevi Nasıl Türetilir


Baglanti

Bilişim Kelimelerinin Telâfuzu

Bazi Ingilizce Ingilizce kelimelerin telâfuzu

Pseudo

Google

GNU

Cache

Bash

Perl

Cygwin

Gigabayt

Gauge

Ant

Heuristics

Emacs

SQL

HSQLDB

Tomcat

Struts

Oracle

XML

Transaction

Linux

Attribute

Java

Prioritry

Bayes

Pattern

Ses Dosyalari

Sunday, October 31, 2004

Otomatik Seçim Kutusu Üretmek, Seçmek ve İşlemek


JSP/Struts bazlı projelerde bazı sayfalarda dinamik olarak seçim kutusu (checkbox) üretmek gerekiyor. Veri tabanında kayıtlı olan müşterileri bir ekranda gösterip, seçim kutusu ile seçilen isimleri veri tabanından silmek gibi bir özellik için bu lazım olabilir. Bu seçim kutularına programatik olarak isim1, isim2, vs... gibi tekil no'lar da atanması gerekecektir. Kullanıcı tarafından seçim yapılıp sayfa form olarak servis'e gönderildiğinde, arka planda id'leri tanımak için, şöyle bir kod kullanmak gerekir.


  public void doGet(HttpServletRequest request,
                HttpServletResponse response)
...
...
for (Enumeration e = request.getParameterNames(); e.hasMoreElements() ;) {
  String key = (String)e.nextElement();
  if (key.indexOf("isim") != -1) {
    if (key.length() > 4) {
      String id = key.substring(4, key.length());
      // elde edilen id ile bir islem yap
    }
  }
}
...

Hepsini Seç Özelliği

Bazen müşterileriniz, eğer ekranda çok fazla seçim kutusu olması muhtemel ise, "hepsini seç" gibi tek bir seçim kutusu ile bütün seçim kutularını seçmeyi isteyebilirler. Bunu yapmak için Javascript kullanmamamız gerekiyor. Aşağıdaki Javascript işlevi, parametre olarak gönderdiğiniz herhangi bir isim "ile başlayan" bütün seçim kutularını otomatik olarak seçebiliyor. Bu kodu, lâzım olan JSP sayfalarının başına koyarak, sayfanın istediğiniz yerinden rahatça çağırabilirsiniz.


<script type="text/javascript" language="javascript">
function check_uncheck_all(grpStr, button) {
var form, el, e, f = 0;
var unbuttoned = (button.value.substring(0,2).toLowerCase() == 'un');
while (form = document.forms[f++]) {
e = 0;
while (el = form.elements[e++])
if (el.type == 'checkbox' && el.name.indexOf(grpStr) != -1)
  el.checked = !unbuttoned;
}
button.value = unbuttoned ? button.value.substring(2) : 'un' + button.value;
}
</script>

Çağırmak için...


       <INPUT type=checkbox name=list value="Tumunu Sec"
   onClick="check_uncheck_all('isim',this)">Tumunu Sec

Kaynaklar






Isim 1

Isim 2

Isim 3

Isim 4




onClick="check_uncheck_all('isim',this)">Tumunu Sec

Saturday, October 30, 2004

Log4j İle Log Etmek

Java Programlarımızın hatalarını tamir için, ne yaptığını görmemiz gerekir. Görsel, kullanıcı bazlı, tamamı tek servis içinde işleyen kodları hata ayıklayıcı (debugger) gözetiminde işletmek kolaydır, fakat servis bazlı, dağıtık, birden fazla thread ile çalışan programları ayıklayıcı içinde başlatmak ve hatasını bulmak zordur.

Çözüm olarak koda System.out.println ekleyerek program hakkındaki bilgi üretiriz. Bu çıktıyı bir "dosyaya" yönelterek kalıcı günlük tutabiliriz. Fakat bu basit bir çözümdür, komut satırı seviyesinde dosyaya yöneltemeyi ayrı yazmak gerekmektedir, ve hangi mesajın yazılıp yazılamayacaği hakkında elimize kontrol vermez.

Log4j ile bunların hepsini elde edebiliriz.

Log4J

Log4J, hata ve bilgilendirme mesajlarımızı yaratmamızı sağlayan API'lar içeriyor. Bu arayüzleri mesaj gereken her yerden çâğırebiliriz. Önemli hatalar için error(), bilgilendirme için debug(), ve uyarı mesajları için warn() kullanabiliriz.

Bu çağırımlar kodumuzun içinde kalır. Hangi tür mesajların yazılıp yazılmayacağını log4.properties dosyasından kontrol ediyoruz. Daha da ilginci, bu kontrol sınıf seviyesinde bile yapılabiliyor, yani, istersek "sadece A sınıfından gelen mesajları yaz, B sınıfından gelenleri yazma" gibi bir log4j.properties ayarı bile yapmak mümkün.

Sınif seviyesinde tanım yapmak istemezsek, en üst paket seviyesinde yapılan tanım, onun altındaki sınıflar için de kullanılacaktır. com.test adlı paketin debug() ve daha üst (yani error()) seviyesindeki mesajlarını görebilmek için,

log4j.logger.com.test=debug

tanımı gerekiyor, com.test paket ismi, log4j.logger öneki günlükleme fonksiyonu için kullanılmış.

Root logger, çıkış ortamının ne olduğunu belirliyor. Eğer ekrana basmak istiyorsak,

### günlük mesajlarını ekrana (stdout) yönlendir ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

log4j.rootLogger=warn, stdout

Eğer dosyaya yazman istiyorsak,

### günlük mesajlarını dosyaya (bizimgunluk.log) yönlendir ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=bizimgunluk.log # buraya herhangi bir isim olabilir
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

log4j.rootLogger=warn, file

Eğer tek bir dosya gereğinden fazla büyüyorsa, birden fazla dosyaya yazmak için, aşağıdaki tanımları kullanın. Hattâ sonuç ortamında dönüşümlü (rotating) günlük dosyaları en tercih edilir durumdur.

log4j.appender.R.File=gunluk.log

log4j.rootLogger=debug, stdout, R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=[%d{dd MMM yyyy HH:mm:ss}] SMSGW%8p (%F:%L) - %m%n
#log4j.appender.stdout.layout.ConversionPattern=[%d{dd MMM yyyy HH:mm:ss}] %5p (%F:%L) - %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender

log4j.appender.R.MaxFileSize=5000KB
log4j.appender.R.MaxBackupIndex=25

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=[%d{dd MMM yyyy HH:mm:ss}] %5p - %m%n

Apache Commons

Demo'dan da görebileceğiniz gibi, Log4J ile beraber, bu örnek için Apache Commons Logging adlı bir yardımcı paketi de Log4J ile beraber kullandık. Günlükleme fonksiyonlarını basitleştiren bu yardımcı paketi kullanmanızı tavsiye ediyoruz. Gerekli olan kütüphaneler commons-logging.jar, junit.jar, log4j.jar yerlerine konduktan sonra, günlüğe yazmak isteyen her sınıf önce iki Apache Commons sınıfıni import eder.

...
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class HerhangiBirSinif {
...
}

Bu sınıflar alındıktan sonra, debug mesajları için

    if ( log.isDebugEnabled()) log.debug("Bu bir debug mesajidir");

Uyarılar için

    log.warn ("sadece bir uyari");

Exception atıldıktan ve catch() içinde tutulduktan sonra önemli hata bildirmek için

    ...
} catch (Exception e) {
log.error("Burada ciddi hata cikti", e);
}
..

şeklinde kullanılabilir.


Kaynaklar

* Log4J Sitesi
* Apache Commons Logging
* Demo

Friday, October 29, 2004

Dağılımlar Hakkında

Baglanti

Thursday, October 28, 2004

Projemiz Niye Başarılı Oldu?

Alttaki liste, Hibernate'in ürününün çok popüler olmasında etken olan geliştirme süreci ve yöntemleri açısından doğru yaptığımız şeylerin (fikrimce) bir listesidir.

Hızlı Sürüm Yapmak

Sıkça yaptığımız sürümler (hattâ bazen bir iki gün içinde) projemizi hatasız ve kullanıcarımızı 'ilgili" tutmanın en çabuk yoluydu diyebilirim. Sık sürüm gören kullanıcılar projemizin aktif ve ivmeli olduğuna kanaat getirdiler, ve projeye ilgili kaldılar. Ayrıca bir yazılımda hangi özelliğin (functionality) kullanılan, ihtiyaç duyulan bir özellik olduğunu anlamanın en iyi yolu, işleyen bir yazılımı şöyle bir dışa açmaktır.

Regresyon Testleri

Herhalde artık tüm Java cemaati, otomize edilmiş birim testlerinin önemini biliyor. Çok sayıda ve detaylı bir test havuzu, bizim projemizin kaynak kodlarının idare edilir ve stabil hâlde kalmasında en büyük faktördür, çünkü projemiz inanılmaz büyüklükte dizayn ve özellik listesi değişiklikleri yaşadı. Mentalite öyle olmalıdır ki, eğer bir özellik (feature) için bir test yoksa, o özelliğin çalışır mı çalışmaz mı olduğu hakkında hiçbir fikrimiz olamaz.

'Tek' Bir Şeyi 'İyi' Yapın

Bir şey konusunda en iyi olun. En iyi olamayacağınız şeylerde bırakın öteki projeler iyi olsun.

'Aşırı Dizayn' Hastalığına Kapılmayın

Çok fazla soyutluk ve ürününüze çok fazla esnekliği projenin çok başında tanıştırmak istemek, büyük bir zaman kaybı olacaktır. Bu zamanı çok daha verimli bir şekilde kullanıcıların ihtiyacı olan gerçek problemleri çözmek için kullanmalısınız. İşleyen en basit çözümü kodlayın. Kullanıcıları alakâdar etmeyen problemleri çözmek için uğraşmayın. Kod açısından gerçekleştirimin zarif olup olmadığı HİÇ ÖNEMLİ DEĞİLDİR, en azından projenin en başında bu böyledir. Önemli olan, "kullanışlı özellikleri" "zamanında" kullanıcıya verebilmektir.

Merkezi Vizyon

Bir komite ile karar veriyor olmanız için, devasa bir projede olmanız lazım. Diğer çoğu projelerde, bir iki tane açık fikirli insanın projenin vizyonunu ve yönünü idare etmesi, geliştirmesi yeterlidir. Bu sayede proje tek bir şeyi iyi yapmaya odaklanabilir. Kanımca açık yazılım projelerini çökerten en yaygın sebeplerden biri özellik enflasyonudur (scope creep).

Belgeleme

Belgelenmemiş özellik sözü, telâfuzu imkansız bir şey, anlambilimsel bir imkansızlıktır. Eğer kullanıcılarınız bir özelliğin olduğunu bilmiyorsa, o özellik, yok demektir. Ya belgeleyin, ya da kaynak koddan özelliği atın. Kaynak kodunuzda yer işgal etmekten başka bir şey yapmıyor.

Standartizm Hastalığından Korunun

Doğru hazırlanmış standartlar (meselâ JMS, JDBC) sistemlerarası çalışabilen programlar ve taşınabilir kodlar için fevkalâde yardımcıdır, kötü hazırlanmış standartlar yaratıcılığın ve teknoloji mucitleri için fevkalade bir engeldirler. "XXX standartını destekliyor" gibi bir etiket, hiçbir ürün için bir kullanıcıdan gelen istek/gereksinimin cevabı olamaz, hele ve hele XXXX standartı bir "uzman" komitesi tarafından hazırlanmış ve bu uzmanlardan hiçbiri kendi pişirdiği tatsız yemeği yemek zorunda olmamamış insanlardan oluşuyor ise. En iyi yazılım, deneme, yanılma ve deneyler ile yazılmaktadır. Çoğunluğun standartı olarak bilinen de facto standartlar, kullanıcılar için tepeden indirilmiş, apriori standartlardan daha elverişli ve sağlıklıdır.

10 Dakikada Hazır..İşliyor...Çalışıyor

Müstakbel bir kullanıcının, bir yazılımı indirir indirmez kurmak, ayarlamak ve bazı kuruluş hatalarıyla uğraşmak için harcayacağı zaman, yarım saatten az olmalıdır, bundan fazlası kullanıcıya fazla gelir. Bizim amacımız, yeni kullanıcılarımızın demo'yu "5 dakikada" çalıştırabilmesidir (JDBC bilgilerinin olduğunu farzederek), ve "yarım saatte" kendi Merhaba Dünya programlarını yazabiliyor hâlde olabilmeleridir.

Programcılardan Cevapların Çabuk Gelmesi (Responsiveness)

Kullanıcılar bir problemle karşılaştıkları zaman, ki muhakkak karşılaşacaklardır, ürünü yazmış olan programcıların cevap vermekte hazır ve nazır olmaları gerekir. Kullanıcılar size belgelerinizdeki boşlukları bulmakta yardımcı da olacaklardır (çünkü anlamadıkları bir özelliği kullanamazlar). Kullanıcılar test havuzunuzun kaçırabileceği kendini iyi saklamış hataları bulmanıza da yardımcı olurlar. Sonuçta kullanıcısız bir proje çarçur edilmiş zamandan başka bir şey değildir.

Hatalar hakkındaki komik durum şudur: Aslında hata bulmak kullanıcıları rahatsız etmiyor eğer bu hatalar çabuk tamir edilirse. Çabuk hata onarmak (responsiveness), bir hatanın, bir haftadan önce tamir edilebilmesi demektir. Genel onarma zamanı da (rapor edilmesi ile tamirin CVS'e koyulması arasındaki geçen zaman) 24 saat olursa en idealidir.

Çabuk Güncellenebilen Wiki Sayfaları

..

Gavin King

Projelerde Hata Takip Düzeni

Bilgi işlem projelerinde hata takip için bir sistem kurmanız gereken vakit, stabil bir uygulamanın ortaya çıkmaya başladığı ve sistemi müşterilere göstermeye başladığınız zamana yakın bir arada olmalıdır.

Hatalar, herhangi bir programcının herhangi bir JSP sayfasında/özelliğinde çıkan hatayı tamir etmesi gibi bir istek olabilir; Bu gibi istekler zamanla biriktikçe, hangisinin tamir edilmiş olduğu, test etmeye hazır olduğu gibi konular idare açısından saç yolduracak seviyeye gelebilirler. 20-30 tane bu şekilde hata bile bir hata takip sistemi kurmamızı gerektir.

Bu sistemin ana özellikleri şunlar olmalıdır. Sistem;


* Programcılara ait hataları sadece onlara gösterebilmeli
* Hataların tamir durumunu kaydedebilmeli
* Test edilecek/bitmiş hataların hangileri olduğunu testçilere gösterebilmeli
* Hataların testçiden programcıya, ve tamir edildikten sonra programcıdan testçiye geri olan iş akışını destekleyebilmeli.
* Hataların değişim tarihçesini, herkezin düştüğü notları kayıtlı tutabilmeli ve gösterebilmelidir

Bu ana hatları destekleyecek en iyi uygulama türü, portal şeklinde olan bir hata takip sistemidir. Buna karşılık, Excel tablolarında hata takip yapmak çok külfetli olacaktır, çünkü bu şekilde tablolarda iş akışı, tarihçe tutmak imkansızdır. Tek bir Excel tablosunda birkaç programcının hatalarının en son durumunu kaydedilip birleştirilmesi çok zordur.

Portal bazlı hata takip programı, her programcıya ve testçiye (genelde bir tane olur) bir giriş ismi verecek, testçilerin yarattığı hataları programcılara göndermesini sağlayacaktır.

İş Akışı

İş akışının genel hatları şöyle olur. Testçi, hata portal'ına kendi kullanıcı ismini kullanarak girer projenin uygulamasında gördüğü bir hatayı sisteme ekler. Bu hatayı, bir programcıya atar. Bu programcı, o hatanın çıktığı kodu yazan, ya da o kodu iyi bilen bir başka programcı olabilir.

Bu programcı, günün herhangi bir saatinde portal'e girip hataları listesini kontrol edecektir (ya da hata portal'inden otomatik e-posta almıştır, portal hata atanır atanmaz programcıya e-posta atmak için ayarlanmış olabilir), ve listesindeki kendine atanmış hatayı görür. Herkesin benimPortal listesi, kendine atanan hataları göstermesi için ayarlanmıştır (buna testçi de dahil, çünkü ona da hatalar atanabilir)

Programcı hatanın detayına tıklar, ve tanımı okur. Kendi geliştirme ortamında hatayı tekrar ettirerek (duplicate) kendi de görür, ve tamir etmek için kolları sıvar.

Programcı hatayı tamir edince, yeni kodu kaynak kontrol sistemine ekler. Projenin teknik lideri her gün başında test makinasına zaten sürüm yapıyordur, ya da acil bir sürüm yapılarak (o hata çok önemli ise) test makinasına en son kodlar atılır.

Programcı, portal'den tamir edilmiş hatanın detayına tekrar inerek, bu sefer bir değişiklik yapar. Hatanın statüsünü "Çözüldü" olarak değiştirir, ve hatanın yeni sahibi olarak "testçi" arkadaşını seçer. Hatayı kaydeder. Şimdi programcı kendi benimHataPortal ekranına döndüğünde, tamir etmiş olduğu hatanın kaybolduğunu görecektir. Ne güzel! Yapacak iş azaldı!

Bu hata tabii kaybolmadı. Testçi kimse, benimHataPortal'ına girdiğinde (ya da aynı şekilde e-posta aldığında) portal'a girecek, ve listesindeki hatayı görecektir. Testçilerin hata alması garip olmamalı, testçinin görevi sadece test etmek olduğu için bu hatanın onun listesinde olmasının tek bir anlamı vardır: Hata tamir edilmiştir, ve tekrar test edilmeye hazırdır.

Test makinasında da en son kodlar olduğuna göre, testçi arkadaş bu makinaya bağlanarak hatanın olduğu kısma/bölüme giderek kontrolünü yapar.

Eğer hata gerçekten tamir olduysa, testçi portal'a dönerek o hatanın detayına gelecek, ve "Kapandı" statüsüne getirecektir. Başka yapması gereken bir şey yoktur. Ama eğer hata hâlâ orada ise, o zaman hatanın statüsünü "açık" olarak değiştirmeli, ve sahibi olarak (tamir ettiğini zanneden) programcıyı atamalı, yani, hatayı programcıya geri göndermelidir! Ve bu şekilde iş akışı tekrar başlamış olur.

Eğer hata tamir olmuş ise, kapandı statüsünü alan hata herkezin listesinden kaybolacak, yani tamir edilen hataların arasına karışmış olacaktır.

Ekler


* Dikkat edilmesi gereken bir nokta, bir hatanın tamir olmuş ama, o hatadan bağımsız başka bir hata aynı ekranda/bölümde bulunmasında ortaya çıkar. Bu yeni hatanın eski hata üzerine not düşülmemesi gerekir. Çünkü yeni hata değişik bir hatadır. Ayrı şekilde takip edilmesi gerekecektir.
* Üstte tarif edilen düzende bir nüans farkı şöyle olabilir: Testçi hatayı atar (programcıyı seçerek). Ama programcı, tamirden sonra tesçiye geri atama yapmaz. Sadece hata statüsünü "çözüldü" ye getirir. Bu durumda testçinin görevi, periyodik bir şekilde portal üzerinde statüsü "çözüldü" durumunda olan hataları kontrol etmektir çünkü hatayı geri kendi benimPortal listesinde görmeyecektir.

ITracker

Evet, genel hatları ile tarif ettiğimiz bu iş akışını ITracker programı ile gerçekleştirmeye çalışacağız. ITracker'in nasıl kurulacağını başka bir yazıda işlemiştik.

Programa admin olarak ilk girdiğinizde bu ekranı göreceksiniz. (Eğer bu ekran İngilizce geldiyse, My Preferences altından Turkish seçerek Türkçe ekrana gelebiliriz)


Yukarıdaki ekranda bekleneceği gibi hiçbir proje yok. İlk yapmamız gereken, bir proje yaratmak. İlk önce Sistem Bakımı seçeneğine tıklayın.


Proje Bakımı | Bakım Yap seçeneğinden Proje Listesi ekranına gelin.


Şimdi üst sağda bulunan sayfa ikonuna basarak yeni proje yaratma sayfasına gelebilirsiniz.


Üstteki örnek bilgileri girerek hemen bir proje yaratmamız mümkün. Proje ismi "deneme" olarak seçildi.


Kullanıcılar

Şimdi de kullanıcılar yaratmamız gerekiyor. Bu kullanıcılar, projede görev yapan programcılar, proje müdürü gibi kimseler olacaklar. ITracker'ı kullanan herkese ayrı bir kullanıcı ismi gerekecek, çünkü herkes kendine ait olan sorunlari (hataları) kendi kullanıcısı üzerinden görecek.

Aşağıda ilk kullanıcıyı yaratıyoruz. Kullanıcının ismi ali, ve bu kimse projede sorumlu kişilerden biri. Ali, testçi görevini yürütecek. Ali, uygulamayı test edip çıkan hataları programcılara atamak ile görevli.

Ali'yi eklediğimiz ekrana dikkat ederseniz, Ali'ye birçok hak verdiğimizi görüyoruz. Bunlardan en önemlisi Proje Bakım ve Sorunu Kapat haklarıdır. Proje müdürü (ya da testçisi) olarak Ali, sorunları tamir edildikten sonra tekrar test edip, sorunun çözülüp çözülmeyeceğine karar verebilecek tek kişi olmalıdır. Programcılar sorunları kapatmamalı, Ali'ye test edilmesi için yollamalıdır.


Aynen Ali'yi yarattığımız gibi, Veli'yi de benzer şekilde ekleyebiliriz. Tabii Veli'de testçilere özel haklar olmayacak.

Hata Eklemek

Bu noktada, Ali ve Veli sistemi kullanmaya hazırlar. Ali testçi, Veli programcı. Şimdi, Ali'nin sisteme nasıl sorun eklediğini görelim.

Ali, ilk giriş yaptığında benimITracker ekranını görecek. Buradan, üst kısımdaki Proje Listesi seçeneğinden "deneme" projesini görebilir. Ali, en solda bulunan üçlü ikon gurubundan ortadakini seçerek, yeni bir sorun ekleyecek ve Veli'ye atayacak. Görelim.


Atanma yapıldıktan sonra, görmek için Veli olarak sisteme girebilirsiniz.


İşte listede gördüğünüz gibi bir sorun Veli'ye atanmış.

Not: Eğer Veli, benimITracker'ında çıkan listesini, sadece ona atanmış sorunlara indirmek istiyorsa, bunun ayarını rahatlıkla yapabilir. En üstteki "Tercihlerim" seçeneğinden,


.. "benimITracker Bölümlerimi Sakla" kısmına gidip, orada Atanmış Sorunlar hariç bütün diğer listeleri kapatabilir.

Şimdi gelelim iş akışımızda önemli bir bölüme: Veli, uygulama kodlarını hatasını tamir etmek üzere değiştirdi, kendi geliştirme makinasında test etti ve tamir edildiğine karar kıldı. Şimdi, bu hatanın "tekrar test için Ali'ye geri gönderilmesi gerekiyor.

Hata listesinden bu hatayı değiştirmeyi seçip, aşağıdaki gibi bir giriş yaparsa, hatayı Ali'ye geri göndermiş olacaktır (kırmızı ile işaretli alanlardan)


Bu sayede Ali, kendi benimITracker sayfasından, tamirini istediği hatanın geri gelmiş olduğunu görecek, bu hatayı test ederek eğer tamir olmuşsa Kapat seçeneği ile hatayı kapatacaktır. Kapanmış statüsündeki hatalar kimsenin benimITracker listesinde gözükmezler. Onlar tamir edilmiştir!

Hata Takip Aracı - ITracker

Java projemiz için hata takip programı gerektiğinde, İnternet'te ufak bir arama yaptık. XP projelerini idarede kullandığımız XPlanners tecrübesi, bizi tekrar aynı şekilde Struts ve J2EE tabanlı bir uygulama aramaya itti. J2EE bazlı programların kurulumu oldukça kolay oluyor, ve envai türden işletim sistemi ve veri tabanı ile çalışabiliyorlar.

Bu yüzden ITracker adlı programı denemeye karar verdik.

ITracker


ITracker'ı kurmak için, itracker_xxx.noaxis.bin.zip şeklinde olan dosyayı indirin. Bu zip içinde web tabanlı çalışabilen işlerkodları bulabilirsiniz. Öteki listelenen dosyalar başlangıçta lazım olmayacaktır. Mesela içinde axis kelimesi geçen zip, ITracker'ı bir Web Servisi olarak işletiyor ve öteki programlar ile XML üzerinden iletişim kurmasını sağlıyor! Başlangıçta çok fazla. (İleride kurcalamak isterseniz aklınızda olsun).

Bu yazımızda ITracker'ı, JBoss ve PostgreSQL üzerinde kurmayı tarif edeceğiz.

Kurmak

JBoss ve PostgreSql kurulduktan sonra, aynı makinada birden fazla JBoss servisi işletip işletmeyeceğinize karar verin. Makina kıtlığı çeken projeler genelde hata takip programlarını, proje idare araçlarını ve uygulamalarının test edildiği servisi hep aynı makina üzerine koyabiliyorlar. Eğer projeniz JBoss üzerinde geliştirilen/test edilen bir uygulama ise, ve aynı makinada ITracker ve sizin uygulamanız aynı anda çalışacaksa, iki JBoss arasında port çakışması yaşanacaktır! Evet, aynı JBoss içine birden fazla EAR atabilirsiniz, ama bir uygulamayı iptal ettiğiniz anda, öteki uygulamada duracaktır. En iyisi, iki uygulamayı tamamiyle birbirinden izole edin. Ayrı JBoss'lar.

Aynı makinadaki PostGreSql veri tabanı, herhalde başka uygulamalar tarafından da kullanılıyordur. ITracker için yeni bir veri tabanı yaratırsak, idaresi daha rahat olur. Bu veri tabanının ismi itracker olsun.

createdb itracker

Diğer yazımızda tarif edilen admin kullanıcısı, bu veri tabanı için de geçerli olacak.

Şimdi, ITRACKERDIZINI\sql\postgres\install\create_itracker_core.sql adlı dosyayı,
psql itracker
ile komut satırına girdikten sonra
\i create_itracker_core.sql
kullanarak işletin.

Güzel. Şimdi JBoss dizininize girin, ve ITracker için gerekli olan veri kaynak dosyasını yaratın. itracker-ds.xml adını verebileceğiniz bu dosyayı JBOSSDIZINI/server/default/deploy altına bırakın. İçeriği şöyle olabilir (jndi-name mutlaka ITrackerDS olmalı)





ITrackerDS
jdbc:postgresql://localhost:5432/itracker
org.postgresql.Driver
admin





Şimdi, JBOSSDIZINI/server/default/conf/standardjbosscmp-jdbc.xml dosyasını açın. Default datasource'u değiştirmeniz gerekecek. DefaultDB kelimesi yerine şöyle olsun:

   ...

java:/ITrackerDS
...


En son olarak ITRACKER/docs/itrackerApplication.properties dosyasını JBOSSDIZINI/server/default/conf altına koyarsanız, herşey tamamlanacak. JBoss'u başlattıktan sonra,

http://makinaismi:port/itracker

... adresinden programı kullanmaya başlayabilirsiniz. Program otomatik olarak ilk kullanıcıyı yaratıyor, kullanıcı: admin, şifre: admin ile programa girip projeniz için gerekli bilgileri girmeye başlayabilirsiniz.

ITracker resmi sürümü, blogumuz yardımlarıyla Türkçeleştirilmiştir durumdadır. Kullanıcı olarak sisteme girdikten sonra, "Tercihlerim" (My Preferences) seçeneği altından Türkçe'yi seçerek uygulamanın dilini tamamen değiştirmeniz mümkün.

Kaynaklar


* ITracker
* JBoss
* Mantis Bugtracker adlı Apache/PHP/MySQL bazlı çalışan alternatif bir program.

Java İle Excel Nasıl Okunur?

Bir Excel dosyasını herhangi bir veri tabanına yüklemeniz gerekebilir. Müşteriniz, belki de bazı verileri Excel üzerinden girmekte, ya da Excel dosyaları başka bir veri ortamından sizin ortamınıza aktarma yapmak için bir aracı format olarak kullanılmaktadır. Her iki durum için de, Java dili ile Excel .xls dosyasında istediğiniz hücreye erişmeniz gerekecektir.

Excel çalışma kitapları (workbook) birçok çalışma sayfasından (worksheet) oluşmaktadır. Her sayfa iki boyutlu bir tabloyu içerir. Bu tablolar, hücrelerden oluşmaktadır.

Java Excel API

Yukarıda anlatılan türden bir erişimi sağlamak için Java Excel API biçilmiş kafandır.

Isletmek icin jxl.jar lazim. 

Örnek Kullanım

İlk önce, tek satır kod yazmadan, bir .xls dosyasının içeriğini ekranda göstermeyi örnekleyelim.


java -jar jxl.jar -csv benimexceltablom.xls

İşte bu kadar! Tabii isteğimize uygun değişik bir program yazmak biraz daha uğraş gerektiriyor. Sitemizden indirebileceğiniz dosyada, ExcelTablo.java adlı bir dosya bulacaksınız. Bu dosya, basit bir kullanım kalıbını örneklemektedir. Mesela, çalışma kitabını açmak için gereken kod aşağıdadır.


 String kodlama = "ISO-8859-9";
WorkbookSettings settings = new WorkbookSettings();
settings.setEncoding(kodlama);
Workbook workbook = Workbook.getWorkbook(new File("Book8.xls"));

Daha sonra, bu çalışma kitabından, birinci çalışma sayfasını çıkartalım, ve 1. satır, 1. kolondaki hücreye erişelim.


 Sheet sheet = workbook.getSheet(0);
Cell a1 = sheet.getCell(1,1);
String stringa1 = a1.getContents();
byte tampon[] = stringa1.getBytes(kodlama);

Bu kadar!

Kodlama (encoding)

Özellikle setEncoding komutu ile gösterdiğimiz kodlamanın ne işe yaradığını anlatmamız gerekiyor.

Java Excel API'ın kendi örneklerinde kodlama (encoding) hakkında bir tavsiye bulamayacaksınız. Biz, projemiz dahilinde Türkçe karakterler olan bir Excel tablosunu okumamız gerekince, bu ekleri yapmamız gerektiğini farkettik.

Bulgularımıza göre, doğru karakterleri görebilmek için bir hücreden gelen String nesnesini getBytes(kodlama) ile kullanacağımızı, ya da daha önceden, çalışma kitabı seviyesinde kullandığımız kodlamayı (encoding) JVM'e (Java'ya) bildirmemiz gerekmektedir.

import java.io.*;
import java.util.Date;
import jxl.*;

public class ExcelTablo
{
    public String hucre(int i, int j) throws Exception{
String encoding = "ISO-8859-9";

WorkbookSettings settings = new WorkbookSettings();
settings.setEncoding(encoding);

Workbook workbook = Workbook.getWorkbook(new File("Book8.xls"));
Sheet sheet = workbook.getSheet(0);
Cell a1 = sheet.getCell(i,j);
String stringa1 = a1.getContents();

byte tampon[] = stringa1.getBytes(encoding);

return new String(tampon);
    }
    
    public static void main (String args[] ) throws Exception {
String encoding = "ISO-8859-9";

WorkbookSettings settings = new WorkbookSettings();
settings.setEncoding(encoding);

Workbook workbook = Workbook.getWorkbook(new File("Book8.xls"));
Sheet sheet = workbook.getSheet(0);
Cell a1 = sheet.getCell(0,0);
String stringa1 = a1.getContents();

File f = new File ("out.txt");
FileOutputStream out = new FileOutputStream(f);

byte tampon[] = stringa1.getBytes(encoding);

out.write(tampon);
out.close();
    }
}

Tuesday, October 26, 2004

Emacs

Emacs hic kuşkusuz, bol özellikli, ve esnek bir editor. Emacs,

* LISP'i andıran bir dil ile her şeyini değiştirmenize izin veriyor.
* Gene LISP kullanarak özellik eklemenize izin veriyor (ne isterseniz).
* Her programlama dili icin bir 'kip' (mode) desteği var. Mesela 'sadece' Java yazarken "if kelimesinden sonra otomatik aşağı satıra git" gibi bir tanım Emacs için cok kolay. Bu gibi ayarlar, .emacs config dosyasından rahatça yapılıyor.
* Emacs ve dış dünya bağlantısı rahat. Unix komutlarını Emacs içinden işletmek mümkün. (Esc-x shell)
* Emacs içinden dış kaynak kodları derleme, ve sonuçları tarayıp hatalı olan satırı göstermek çok rahat.

Ekte göstereceğimiz kodlar, benim .emacs config dosyamdan alındı. İlk önce açıklamayı, sonra kodun kendisini sunacağım.

Örnek .emacs

Emacs içinden ANT programı ile derleme yapmak.


(setq compile-command "ant -emacs -find ")

Metin incelerken, Emacs göstergesinden, kaçıncı satırda olduğumuzu görmek:


(setq column-number-mode t)

Sevdiğim renkler..


(set-face-background 'modeline "darkred")
(set-face-foreground 'modeline "white")
(set-face-foreground 'region "lightgrey")
(set-face-background 'region "white")
(set-background-color  "navyblue")
(set-foreground-color "white")
(set-cursor-color "turquoise")

Sevdiğim boyutlar..


(set-frame-width (selected-frame) 83)
(set-frame-height (selected-frame) 49)

Tuşların ne yaptığını tamamen değiştirebilirsiniz. Şahsen ben ok tusları yerine (uzak oldukları için) Control tuşu ile alfabe harflerine beraber basarak ileri-geri gitmeyi tercih ediyorum. 4 yön için, sol = control-J, sağ = control-L, yukarı = control-P ve aşağı = control-N kullandık.


(define-key global-map "\C-m" 'newline-and-indent)
(global-unset-key "\C-f")
(global-unset-key "\C-w")
(global-unset-key "\C-d")
(global-unset-key "\C-l")
(global-unset-key "\C-p")
(global-unset-key "\C-j")
(global-unset-key "\C-k")
(global-unset-key "\C-o")
(global-set-key "\C-o" 'other-window)
(global-set-key "\C-p" 'previous-line)
(global-set-key "\C-k" 'backward-delete-char-untabify)
(global-set-key "\C-n" 'next-line)
(global-set-key "\C-j" 'backward-char)
(global-set-key "\C-f" 'backward-kill-word) ;; geriye git, kelime sil
(global-set-key "\C-w" 'backward-word) ;; geri git, kelime atla
(global-set-key "\C-d" 'forward-word) ;; ileri kelime atla
(global-set-key "\C-l" 'forward-char) ;; ileri git
(global-set-key "\C-p" 'previous-line) ;; onceki satir
(global-set-key "\C-t" 'kill-line) ;; satir sil
(global-set-key "\C-x\c" 'compile) ;; derle
(global-set-key [f9] 'kill-buffer) ;; hafizadaki metni hafizadan cikar
(global-set-key "\C-c\i" 'indent-region) ;; dile gore, secilmis alani duzenle
(global-set-key "\C-c\k" 'kill-region) ;; secilmis alani sil
(global-set-key "\C-c\c" 'copy-region-as-kill) ;; secilmis alani kopyala
(global-set-key "\C-c\u" 'scroll-cursor-to-top)
(global-set-key "\C-x\q" 'query-replace) ;; ara ve degistir
(global-set-key "\C-x\g" 'goto-line) ;; satir no'ya atla

Emacs programlama dili kiplerinden bahsetmiştim. Bu kiplere geçmek için "Esc-x java-mode (enter)" gibi komut işletirseniz Emacs kipe geçecektir. Fakat eğer bu geçişin otomatik olmasını istiyorsanız, aşağıdakini yapabilirsiniz.


(setq auto-mode-alist
 (append '(("\\.C$"   . c++-mode)
("\\.cc$"  . c++-mode)
("\\.cpp$" . c++-mode)
("\\.log$" . hscroll-mode)
("\\.cxx$" . c++-mode)
("\\.hxx$" . c++-mode)
("\\.h$"   . c++-mode)
("\\.hh$"  . c++-mode)
("\\.idl$" . c++-mode)
("\\.c$"   . c-mode)
           ("\\.pl$" . perl-mode)
           ("\\.java$" . java-mode)
           ("\\.jsp$" . java-mode)
           ("\\.inc$" . html-mode)
           ("\\.rb$" . ruby-mode)
           ("\\.?[Ff][Aa][Qq]$" . faq-mode)
           ("\\.txt$" . text-mode))
   auto-mode-alist))

Ayrıca, Emacs kullanırken Control tusunu çok kullanmak gerekiyor. Yeni bilgisayarların çogunda Control tuşu oldukça alttadır. Sürekli Ctrl tuşuna basacağım derken Emacs kullanıcıları el felci geçirmesin diye, çözüm olarak CAPS tuşunu Control tuşuna çevirmek iyi olabilir. CAPS düğmesi yukarıda olduğu için, sol serçe parmağı ile basmak çok rahhattır.

Bu değişimi Windows 2000 üzerinde yapmak için, ekteki dosyayi indirip, üzerine tıklayın. Sorulan soruya evet diye cevap verin. Bilgisayarı kapatıp açtıktan sonra, CAPS düğmeniz Control gibi işliyor olacak.


Entity Bean'lerin Ölümü - Bir Analiz

Evet. Son haberlere göre Entity Bean'ler, EJB 3.0 tarifnamesine dahil edilmedi, ve Entity Bean'ler nihayet diğer kullanışsız teknolojiler ile beraber eski teknoloji mezarlığını boyladı. Bu yazımızın konusu, bir ceset analizi (postmortem analysis) olacak. Okurlarımız olan teknik liderler, programcılara, şahsım ve tanıdığım diğer teknik liderlerin niye Entity Bean teknolojisinden verem görmüş gibi kaçtığını, bunun sebeplerini ve o karara varışımızdaki düşünce çizgisini aktarmaya çalışacağım. "Canım kullanıldı işte, çâlışıyor" demekten özellikle kaçınmamız gerekir, çünkü eğer istatistiklere göre bir proje kodunun bakım zamanında harcanan zaman, projenin tümünün %70'i ise, projede kullanılan teknoloji elimizde öldüğü zaman, ileride bu teknolojiyi bilen insanları bulmakta zorlanırız, ve tabii ki proje esnasında da verimlilik düşüşüne sebebiyet vermiş oluruz. Tüm bu dezavantajlardan korunabilmek için, daha baştan doğru teknolojiyi seçmemiz çok mühimdir.

İlk İntibâlar

Geçmişe dönelim. EJB'ler bilgi işlem sektörüne büyük bir şaşa ile giriş yapmıştı. Şahsımızın bir önceki projesi CORBA üzerine olduğundan dağıtık, nesne bazlı bir teknolojide neler olması gerektiğini aşağı yukarı anlamıştık. Bu tür projelerin hepsinde gereklilikler: Bir nesneyi/servisi bulabilmek, uzaktan erişebilmek, nesnelerin rahat bir şekilde veri tabanına erişebilmesi, ve ölçekleme probleminin bir şekilde adreslenmesi idi. Üç katmanli mimaride iş mantığı nesneleri orta katmanda bulunuyordu. Teknik kitaplarda bu sürekli gördüğüm orta katmanın ne işe yaradığını uzun uzun düşündüğümü hatırlıyorum. O zamanki teknik "abilerimizin" cevabı aşağı yukarı şu idi:

"Eski çift katmanlı mimarilerde, görsel katman veri tabanına direk bağlanır. Ancak o zaman, veri tabanları ancak bir anda eşzamanlı açabildikleri bağlantı sayısı kadar (yâni sınırlı) bir sayıdaki kullanıcıya hizmet verebilirler. Fakat bu kullanıcıların erişim "tekrar kalıplarına" (pattern) bakacak olursak, aynı anda yapılan işlem sayısının daha az olduğunu görülmüştür. O zaman, görsel katman bağlantıları veri tabanına değil, nesnelere yaptırırsak, bu nesneler bir veri tabanı havuzundan ihtiyaçları olduğu zaman bağlantıyı alıp, işlerini görür, ve bağlantıyı havuza tekrar geri verebilirler. Orta katmana erişim hafıdaki nesneler üzerinden olacağından, bu katmanı daha fazla donanım ekleyerek rahatça ihtiyaca göre ölçekleyebiliriz. Böylece daha fazla kullanıcıya aynı anda hizmet verebilmiş oluruz. Ayrıca, üç katmanlı bir mimari, kodlama esnasında pür görsel kodu, pür işlem mantığından ayırmamız için bizi zorlayacağı için, daha temiz bir mimariyi ve kod bazını teşvik edecektir. Koşturma anına dönersek, işlem mantığı için önbellekleme gibi çetrefil işleri orta katmanda daha rahat halledebiliriz, çünkü elimizde daha fazla hafıza olacak, bu yüzden üç katmanlı mimarilerin, modern iş sistemleri için daha uygun olacağı düşünülüyor".

EJB teknolojisine bakarken beklentilerimiz bunlardı. EJB kitaplarını okurken, aklımızdaki ilk soru şöyle oldu: "Uzaktaki nesneye nasıl erişiliyor?". Cevap: Bir Session Bean yazılıyor, Java Naming ile isim kullanarak nesneyi buluyoruz, erişiyoruz, ve işimiz bitiyor.

Peki, Session Bean kodlanırken, neler yapılması gerekiyor? Temel ihtiyaçlarımız, herhangi yazdığımız bir metodun dışarıdan erişilebilir hâle getirilmesi.

Cevap: Bir Home Interface yazılıyor. Sonra bir Remote Interface yazılıyor. İstenilen metot iki değişik class'a konması gerekiyor. ???. Bazı tür mecburi kodlar, her EJB'de oluyor, ama illâki yazılmaları gerekiyor.

"Gereksiz kod gerektiren teknoloji" alarmımız bu noktada çalmaya başladı. Sebebini şöyle açıklayabilirim.

Her bilgi işlem problemine, aslında, bir yeni dil tanımı gibi bakabilirsiniz, EJB de sonuçta bir dildir. Bu dilleri de ölcüp biçerken de kıstasımız şudur: Aynı işi yapan daha kısa dil, her zaman tercih edilmelidir. Kısa dil, kısa kod demektir ve bakılması gereken daha az kod miktarı demektir. %70 sihirli oranını unutmayalım.

Ama tam bu noktada, Session Bean'ler için bu sefer pragmatik mühendis tarafımız duruma dahil oldu, ve şunları sordu: "Piyasada alternatif var mıdır?". Cevap: Yok. O zaman Session Bean'lerin külfeti çekilebilir demektir.

Daha İlerlerken

Kitaplarda ilerlerken açıkçası veriye erişim hakkında bir cevap bulacağımızı beklemiyorduk, çünkü böyle bir soru sormamıştık. Fakat bu konunun üzerine çok büyük bir odakla eğilmiş olunduğunu birdenbire farkettik. EJB'ler sanki tüm bilgi işlem sorunlarını bir kalemde çözmeye tâlip olmuştu. Veriye erişim çözümleri de Entity Bean'ler idi.

Hayretle gördük ki, veriye erişim de Session Bean türü bir nesnenin üzerinden, daha kötüsü aynı şekilde "tekrar gerektiren başka bir dil" ile yapılmaya çalışılmış. Veriye erişim problemi bir tablo kolonu ile nesne özelliğini eşlenmesinden ibarettir, ve dağıtık nesneler problemi ile bir alâkası olmamalıdır. Bir tabloya erişmek için niye Japonya'dan çağrılabilen bir nesne yazmam gerekiyor!? Entity Bean tasarımcılarının büyük bir kafa karışılıklığı yaşadığını hissetmeye başladım. Fakat onları da suçlamamak gerekirdi; Onlardan önce CORBA POS sektörde aynı hatayı yapmıştı, bu tasarımcılar herhalde POS başarısızlığını CORBA'nın IDL dilinin esnek olmamasına bağlamış olmalıydılar. Java ile ikinci bir şans ellerine geçmiş oluyordu.

Fakat bu şansta ellerinden kaçacaktı. EJB 3.0, Remote Interface ve Home Interface garabetlerini ortadan kaldırmakta kalmadı, Entity Bean'leri tamamen kaldırıp attı.

İşaretleri Tanımak

Kariyerimizde önümüzden geçen bir çok teknoloji ile boğuşurken, sürekli tekrar tekrar yapılması gereken işlemleri otomize etmeye bayılmışızdır. ABD'de de sektörün raconu, az zamanda daha çok iş yapmayı gerektirir, ve bir işi daha kısa ve temiz yapan programcı daha iyi görülmektedir. Bu kıstasa sistem admin'leri bile dahildir; Öyle ki bir sistem admin arkadaşım, biri sürekli çalışan ama bir diğeri oyun oynayan iki admin arasından, oyun oynayanın muhakkak daha iyi olacağını bana söylemişti, çünkü oyun oynayan, işini daha kısa bir şekilde (betik yazarak) yapmanın yolunu bulmuştu.

Biz de CORBA ile boğuşurken, hep aynı şekilde yazılan fazladan kodları (bunun ismi İngilizce boilerplate code'dur) , Perl gibi bir dil ile üreterek kısa bir şekilde işimizi görmenin yolunu bulmuştuk. Ama işte tam bu noktada, kendimize şu soruyu sormaya başlardık:

"Eğer daha kısa olan A dilini kullanarak, B kodunu üretiyorsam, bu teknolojiyi yazanlar niye A dili gibi daha kısa bir dili baştan kullanmamışlar?"

Hakkında bu soruyu sorduğumuz teknolojiler herhalde aynı şekilde başkaları tarafından da irdelenmişler ki, bir süre sonra miadı dolan teknolojiler çöpüne atıldılar.

Biz de bu tecrübelere dayanarak, şu kuralı geliştirdik: "Ne zaman ki X teknolojisini ayakta tutmak için kod üretmek gerekiyor, o zaman X teknolojisi yanlış tasarlanmışır ve miadı kısa süre içinde dolacaktır. Arkanıza bakmadan kaçınız."

Örnek

EJB 2.0 Session Bean'lerine bu kuralı uygulayalım: Şu anda EJB yazmak için şunlar yapılmaktadır: XDoclet denen bir "başka" teknoloji ile Bean şablonu yazılmakta, ve o şablondan Remote Interface ve Home Interface "üretilmektedir". Hattâ ve hattâ, bazıları daha da ileri gidip, Lomboz denen bir başka teknoloji (Eclipse eklentisi) üzerinden "tıklama" sureti ile XDoclet şablonu üretmektedirler! Yâni diller A-->B-->C hâline gelmiştir! Fakat temiz olmayan bir C dili, üretilse bile bakın nelere yol açmaktadır: XDoclet, her arayüz değişikliğinde tüm şablonların hepsini üretmektedir, ve üretilen kodlar da, aynı olsa bile, zaman damgası (timestamp) değiştiği için derleme sistemi tarafından "yeni kod" olarak algılanmaktadır. Yâni derleme sistemi tek bir EJB değişse de, herşeyi yeniden derlemektedir! Lomboz'a dönelim: Görsel olarak tıklama yapmak güzel, fakat arayüz tanımladıktan ve XDoclet üretildikten sonra arayüzde düzeltme yapmanız imkansızdır! Bunun sebebi: Lomboz yeni bir teknolojidir. XDoclet'te yenidir. E bu niye? EJB'den yanan insanların kod üreten teknolojilere yönelmesi için biraz zaman geçmesi gerekmiştir, bu da doğaldır. Fakat bu işin baştan yanlış olduğunun göstergesidir. Session Bean'lerdeki gibi alternatifiniz yoksa, EJB'leri buyrun kullanın. Fakat ya Entity Bean'ler?

Alternatif son 3 senedir mevcuttur. Toplink ve JDO doğru olarak veri erişimini eşleme problemi olarak çözmüşlerdir. JDO'dan bir çıta yukarıda da Hibernate vardır.

Peki Entity Bean'leri Seçenler, Niye Seçti?

Bunun sebebi şöyle gibi gözüküyor: Entity Bean'ler J2EE paketine dahildi, ve bu yüzden "J2EE bilmek", Entity Bean'leri bilmek gibi bir intiba ortaya çıkmıştır. Bir diğer sebep te, Entity Bean'ler J2EE'ye dahil olduğu icin geleceği daha sağlam bir teknoloji gibi görüldüğüdür. Fakat Sun gibi şirketler bile hata yapabilirler, bu yüzden paketten çıkan herşeyi didik didik tartmamız gerekmektedir. Ayrıca, çok tepki gören teknolojileri, Entity Bean örneğinde olduğu gibi, şirketler tedavülden kaldırabilmektedirler. Bunları da gözönüne almamız gerekmektedir.

Saturday, October 23, 2004

NT Üzerinde Cygwin İle Cron

Cron, zamanlı (planlı) süreç işletabilen faydalı bir Unix aracıdır. crontab -e ile değiştirilen planı cron süreci alıp, gerekli programları gereken zamanda işletir.

Fakat, eğer bir talihsizlik sonucu Windows ortamı üzerinde iş yapmak zorunda kaldı iseniz, Unix araçlarını (cron) dahil Cygwin sayesinde kullanabilirsiniz. Cygwin üzerinde ls, diff, find gibi tanıdık bütün komutları bulacaksınız.

Bir tek komut, cron, problem çıkartacak. Cron'un kontrol kısmı, Unix üzerinde arka plan süreci (deamon) olarak çalışıyor, işletim sistemi bunu başlarken otomatik olarak başlatıyor. Fakat cygwin Windows sistemine sonradan eklendiği için, aynı etkiyi yaratmak için, cron programını Windows "servisi" olarak kurmamız gerekecek.

cygrunsrv -I cron -p /usr/sbin/cron -a -D

Yukarıdaki komutu kullanarak, cron'u servis haline getirebilirsiniz.

Eğer cygrunsrv yok ise, cygwin kuruluş programı "Admin" dizini altından kurun.


Cron, NT servisi olarak kurulduktan sonra diğer servisler gibi Services altında gözükecektir.


Crontab içeriği...
$ crontab -e
* * * * * echo "test 123" >> c:/temp/a.out
> ~
> ~
> :wq (vi altinda kaydet ve kapat demektir)

CVS ile Yazılım Geliştirme Metodu

CVS en cok kullanılan Kaynak Kod İdare programlarından birisidir. "Açık Yazılım" (Open Source) projeleri sürekli CVS kullanırlar.


* CVS, kilitsiz sistem denen yöntem ile calışır. Kaynak deposundan alınan bütün kayıtlar her programcı her an değiştirebilir. Bazı Kaynak Kod İdare programları buna izin vermez. Açık Kod projeleri dünyanın her tarafına yayılı olduğundan, kilitsiz çalışma stili onlara daha uygun gelmektedir
* CVS çok hafif bir programdır, CVS'i barındıran servis makinasının çok güçlü olması gerekmez.

Kitleme usulü çalışan KKI sistemlerinde, kayıtlar once kitlenir, başka kimse erişemez, sadece tek bir kişi değişim yapıp kayıdı depoya geri verir.

Dallı/Budaklı Kod Ağacı metodu kullanan KKİ sistemleri, ana kod ağacından, bir dal yaratıp onun üzerinde çalışmaya imkan verir, ve gerektiğinde bu daldan ana koda 'birleğtirme (merge)' yapılabilir. Çakışmaların (aynı kodda ayrı değişiklikler yapmış iki değişik kişi alâkalı) mutlaka çözülmesi gerekir. CVS dallanmaya izin verir. Fakat bizim tavsiyemiz, CVS ile dallanma kullanılmaması.

Proje tecrübemizde karşımıza bir çok KKİ sistemi çıktı. PVCS (kitlemeli), ClearCase (dallama/budaklama sistemi çok rahattır) adlı programları kullandık. Bunların içinden ClearCase, bazı işleri rahat yapmanızı sağlasa da, genelde bütün düzeninizi zorlastıracaktır, ve kurması, idaresi müthiş zor bir programdır. PVCS'in durumu rezalet ötesidir, o yüzden kategoriye alınmasına bile gerek yok.

CVS kullanmaya karar verdiyseniz, isabet ettiniz. Aynı şirkette ve projede 40 kadar programcının CVS'i başarı ile kullandığını duyduk. CVS kullanırken dikkat etmeniz gereken husus şudur:

Bütün programcılar, ana depoya kendileri 'birleştirme' yaptıkları için, bazen bütün kaynak kodunuzda hatalar artabilir. Yani, birbirinden habersiz yapılan değişiklikler, ana kod ağacını hasta bir hale getirebilir. Bazı gördüğümüz KKİ düzenlerinde, tek bir kişi bütün programcı dallarından ana ağaca birleştirmeyi yapıyordu. (CVS'te herkes kendi yapar). Bu kişi her değişime bakabildiği için (ve görevi üzere), birbirine uymayan değişiklikleri iptal edebiliyor. Fakat bizce bu tek kişilik görev çok zor, ve bir insana çok yükleniyor.

Onun yerine, kontrolü herkese geri veriyoruz. Fakat, ana ağacın durumunu surekli kontrol etmemiz gerekiyor. Bunun çok basit bir yolu var. Otomatik bir şekilde, her saatte bir, bütün kaynak kodunu derleyip, testlerden geçirirsiniz. Eger yanlışlar bulunursa, otomatik olarak bu yanlışlar e-posta ile herkese gönderilir.

Önce yeni bir Unix kullanıcısı yaratın. Adı 'canavar' olsun mesela. Canavar her saatte bir, Unix cron kontrolünde uyanır. Uyanınca ilk yapacağı şey cvs co komutunu işletmek olacak. Böylece depodan en yeni kaynak kodlar alınır.

Bundan sonra canavar, ant, make ile bütün kaynak kodu derleyecek. Sonra JUnit testlerini işletecek. Bütün bunları bir "takip dosyasında" (log file) görünmesi lâzım. İş bittikten sonra bir grep komutu ile 'Syntax error', TEST FAILED gibi cümleler aranır. Bulunursa, e-posta, takip kayıdının tamamı eklenerek postalanır. Suçlu programcılar bulunup falakaya yatırılır. (Şaka Şaka..)

Aşağıdaki betik (script) bizim son projemizde kullandığımız bir betiktire. Projenizin derleme komutu değişik olabilir, onu rahatça değiştirebilirsiniz. Unutmayın, derlemeden sonra testleri mutlaka işletin. Sonuçların aynı takip dosyasında olmasına özen gösterin.

#!/usr/local/bin/perl

chdir ($ENV{'HOME'});

$cvs_command = "cvs co sizinprojeniz > /tmp/co_out.txt 2<&1"; system($cvs_command); $lines_1 = 0; $lines_2 = 0; $lines_1 = system("grep \'^U \' /tmp/co_out.txt"); $lines_2 = system("grep \'^A \' /tmp/co_out.txt"); exit if ($lines_1 != 0 && $lines_2 != 0); $curr_date = `date '+%m/%d/%y-%M'`; chomp($curr_date); $curr_date =~ s/\//\-/g; $log_name = $ENV{'HOME'} . "/logs/build_log_" . $curr_date; system("derle.sh > $log_name 2<&1"); $cmd = "grep \'BUILD_FAILED\' $log_name"; #print $cmd . "\n"; $lines = system("grep \'BUILD FAILED\' $log_name"); send_mail ("***Hata Bulundu***", $log_name) if ($lines == 0); send_mail ("Basari!", $log_name) if ($lines != 0); exit; sub send_mail { $note = shift; $log = shift; @lines = `cat $log`; open (MESSAGE, "| /usr/lib/sendmail -t"); print MESSAGE "To: ali\@falan.com,veli\@falan.com\n"; print MESSAGE "From: Canavar\n"; print MESSAGE "Subject: Derleme-Testler: $note\n"; print MESSAGE "\n"; print MESSAGE "\n"; print MESSAGE "Takip dosyasi $log notu var $note\n"; print MESSAGE "\n"; print MESSAGE "@lines" . "\n"; print MESSAGE "\n"; close (MESSAGE); }

Ve aşağıdaki satırları cron için girin.
0 10,11,12,13,14,15,16,17,18,19,20,21,22 * * 1-5 /falan/filan/derle.pl > /dev/null 2<&1