"http://www.w3.org/TR/html4/loose.dtd">

XPO ile O\R MAPPING -3

   Merhabalar, bu makale serimizde Object Relational Mapping kavramından ve DevExpress ürün ailesine ait XPO ile temel veritabanı işlemlerimizi nasıl yapabileceğimizden bahsedeceğiz.

İlişkiler:

Veritabanı uygulamalarımızda her zaman tek tabloyla çalışmadığımız için XPO’da da birden fazla tabloyla çalışmamızı ve aralarında ilişkiler kurmamızı sağlayan yapılar var. XPO’da tablolar arası ilişki kurmak istediğimizde bunu bu tablolara ait sınıflarımızı oluştururken Association anahtar sözcüğüyle oluşturuyoruz. Ancak bire bir ilişkiler de Association sözcüğünü kullanmak yerine ilişki içinde bulunan her iki sınıfta da diğer sınıf türünden bir nesne oluşturmamız yeterli oluyor.

Bu ilişkilerde cascading ise Association deyiminin içine yazacağımız Aggregated sözcüğü ile sağlıyoruz. Eğer Aggregated yazmassak silme ve güncelleme işlemlerini yapıyor. Yazdığımız takdirde ise diğer tablolarla ilişki içinde olduğu için bu işlemlere izin vermiyor.

 

[ Aggregated , Association ( "FK_Address_Person" , typeof ( Address ))]

 

Aggregated: Cascading’i sağlıyor.

FK_Address_Person: İlişkimizin ismi.

Address: Diğer sınıfın ismi. Bir nevi ilişki kurulacak tablo da denilebilir.

 

Bire bir ilişkiyi sınıfımızda gösterme:

İlişkideki ilk sınıfımız:

 

public class Ev : XPObject

{

public Ev() {

}

public Ev( Session session) :

base (session) {

}

 

 

[ Aggregated , Association ( "FK" , typeof ( Insan ))]

Insan owner = null ;

public Insan Owner

{

get { return owner; }

set

{

if (owner == value )

return ;

Insan prevOwner = owner;

owner = value ;

 

if (prevOwner != null && prevOwner.House == this )

prevOwner.House = null ;

 

if (owner != null )

owner.House = this ;

}

}

}

Diğer sınıf:

public class Insan : XPObject

{

 

public Insan() {

}

public Insan( Session session) :

base (session) {

}

 

 

[ Aggregated , Association ( "FK" , typeof ( Ev ))]

Ev house = null ;

public Ev House

{

get { return house; }

set

{

if (house == value )

return ;

 

Ev prevHouse = house;

house = value ;

 

if (prevHouse != null && prevHouse.Owner == this )

prevHouse.Owner = null ;

 

if (house != null )

house.Owner = this ;

}

}

}

1 e Çok ilişki:

public class Person : XPBaseObject

{

private int fId;

[ Key ( true )]

public int ID

{

get { return fId; }

set

{

if ( value == ID) return ;

fId = value ;

}

}

 

public Person()

{

Name = "" ;

}

public string Name;

[ Aggregated , Association ( "FK_Address_Person" , typeof ( Address ))]

public XPCollection Addresses

{

get { return GetCollection( "Addresses" ); }

}

}

Diğer Sınıf:

public class Address : XPBaseObject

{

private int fId;

[ Key ( true )]

public int AID

{

get { return fId; }

set

{

if ( value == AID) return ;

fId = value ;

}

}

 

 

public Address()

{

AddressInfo = "" ;

}

public Address( string addr)

{

AddressInfo = addr;

}

[ Association ( "FK_Address_Person" )]

public Person ID;

public string AddressInfo;

}

Bire çok ilişkinin bire bir ilişkiden farkı Association kullanmamız. Association sözcüğünün hemen altında da diğer sınıfa ait nesnemiz var. 1 çok ilişkide bir diğer ayırt edici özellikte Çok olan kısımda bir XPCollection kullanmamız böylece bir tablodaki bir veri için diğer tablodan birden fazla veri getirebiliyoruz.

Çoka Çok İlişki:

Çok çok ilişkide aynı bire çok ilişki gibidir. Tek farkı bu sefer iki sınıfta da Association’ın iki ucuda XPCollection’dır. Bireçok ve çokaçok ilişkilerdeki bu XPCollection’lar diğer sınıf türündedir.

 

Transaction:

XPO’da transaction’ı sessionlar aracılığıyla yapıyoruz. Bu işlemi yaparken 3 metod kullanıyoruz. Bunlardan ilki transaction’ı başlatmamızı sağlayan BeginTransaction, bundan sonra ekleme silme güncelleme işlemlerimizi yaptıktan sonra CommitTransaction metodu ile tamamlıyoruz. Eğer bir problem olursa bunu yakalayıp RollbackTransaction metodu ile yaptığımız değişiklikleri geri alıyoruz.

 

using (Session session = new Session()) {

session.BeginTransaction();

try {

// ekleme silme güncelleme işlemleri

session.CommitTransaction();

}

catch {

session.RollbackTransaction();

throw;

}

}

Validation:

XPO ile validation işlemlerinde öncelikle Exception sınıfından türeyen bir sınıf oluşturuyoruz. Bu sınıfımızda da constructor metodumuzda vereceğimiz uyarıyı belirtiyoruz.

Daha sonra XPO ile bize sağlanan OnDeleted, OnDeleting, OnLoaded, OnLoading, OnSaved, OnSaving metodlarından birini tekrar yazarak kontrolü ne zaman yapacağımızı, hangi kontrolü yapacağımızı ve oluşturacağımız exception’ı belirliyoruz.

public class RequiredPropertyValueMissing: Exception

{

public RequiredPropertyValueMissing(XPObject theObject, string propertyName):

base(String.Format("The {0} property of the {1} object with id {2} must have a

value", propertyName, theObject.GetType().Name, theObject.Oid))

{

}

}

 

public class Company : Person {

public string Name = "";

protected override void OnSaving() {

if (Name == "")

throw new RequiredPropertyValueMissing(this, "Name");

}

}

 

        Bu makale serimizde O/R Mapping kavramından ve bunun XPO ile nasıl yapılabilceğinden bahsetmeye çalıştım. Konuyla ilgili veya diğer her türlü sorunuz için mail adresimden bana ulaşabilirsiniz. Bir başka makalede buluşmak üzere.

 

Her türlü sorunuzu metkor@gmail.com dan iletebilirsiniz.

Referans: www.devexpress.com/XPO


"http://www.w3.org/TR/html4/loose.dtd">

XPO ile O\R MAPPING -2

   Merhabalar, bu makale serimizde Object Relational Mapping kavramından ve DevExpress ürün ailesine ait XPO ile temel veritabanı işlemlerimizi nasıl yapabileceğimizden bahsedeceğiz.

  Bu makalemizde temel ekleme, çıkarma, güncelleme, veri getirme ve kümeleme işlemlerinden bahsedeceğiz.

 

Ekleme Çıkarma Güncelleme Getirme:

Bu işlemleri yapmadan önce elimizde bulunan veritabanına göre sınıfımız oluşturalım.

class proje : XPBaseObject

{

public proje () {}

public proje ( Session session) : base (session) {}

public proje ( Session session, string projectName, string owner): base (session)

{

this .projeAdi = padi;

this .projeSahibi = psahibi;

}

private int pId;

private string projeAdi;

private string projeSahibi;

 

[ Key ( true )]

public int ID

{

get { return pId; }

set

{

if ( value == ID) return ;

pId = value ;

}

}

public string ProjectName

{

get { return projeAdi; }

set

{

string oldValue = padi;

if (oldValue == value )

return ;

projeAdi = value ;

OnChanged( "ProjectName" , oldValue, value );

}

}

public string Owner

{

get { return projeSahibi; }

set

{

string oldValue = psahibi;

if (oldValue == value )

return ;

projeSahibi = value ;

OnChanged( "Owner" , oldValue, value );

}

}

}

Sınıfımızda gördüğümüz [Key(true)] sözcüğüyle OID kullanmayacağımızı söylüyoruz ve veritabanındaki PK yı belirlemek için bu alanın tanımladığımız yerin hemen üstüne yazıyoruz.

Key gibi kullanılan bir diğer yapımız ise [Indexed] bu söcükle veritabanımızda index olarak kullanılan alanları belirtiyoruz.

[ Indexed ( "Ad;Dtarih" , Unique = true )]

public string Soyad = string .Empty;

public string Ad = string .Empty;

public DateTime Dtarih;

Bu kullanımda Indexed sözcüğü hemen Soyad ın üstünde belirtildiği ve Ad-Dtarih ‘te Indexed sözcüğü içnde belirtildiği için bu üç alanın index olarak kullanıldığını anlayabiliriz. Sadece Soyad ın index olmasını isteseydik Ad ve Dtarih alanlarını Indexed sözcüğü içine yazmayacaktık.

Ekleme:

XpoDefault .ConnectionString = "Data Source=******;Initial Catalog=******;UID=mehmet;password=12345" ;

using ( UnitOfWork uow = new UnitOfWork ())

{

insan p = new insan (uow);

p.ProjectName = “Deneme”;

p.Owner = “Metko”;

uow.CommitChanges();

 

}

Silme:

XpoDefault .ConnectionString = "Data Source=******;Initial Catalog=******;UID=mehmet;password=12345" ;

XPCollection kaynak = new XPCollection ( typeof ( insan ));

using ( UnitOfWork uow = new UnitOfWork ())

{

insan p = kaynak[2] as insan ;

p.Delete();

uow.CommitChanges();

}

Burada gördüğümüz XpCollection yapısı verdiğimiz sınıf isminde yani tablodaki verileri getirip tutuyor. Daha sonra verdimiz index numarasıyla istediğimiz veriyi alabiliyoruz. Burada çektiğimiz verilerdeki 2 index nolu nesne siliniyor.

Güncelleme:

XpoDefault .ConnectionString = "Data Source=******;Initial Catalog=******;UID=mehmet;password=12345" ;

XPCollection kaynak = new XPCollection ( typeof ( insan ));

using ( UnitOfWork uow = new UnitOfWork ())

{

insan p = kaynak[2] as insan ;

p.ProjectName = “Deneme2”;

p.Owner = “ABH”;

uow.CommitChanges();

}

 

Burada da çektiğimiz verinin alanlarına direk istediğimiz verileri girip CommitChanges metodunu çağırdığımızda verileri güncellemiş oluyoruz.

Verileri getirme:

Verileri XPCollection nesnesinde tuttuğumuz belirtmiştik. XPCollection nesnesinin bir diğer özelliği ise DataSource olarak gösterilebilmesidir. Bu özelliği sayesinde verileri kolayca çekebiliriz.

XpoDefault .ConnectionString = "Data Source=******;Initial Catalog=******;UID=mehmet;password=12345" ;

XPCollection kaynak = new XPCollection ( typeof ( insan ));

gridControl1.DataSource = kaynak;

 

Arama ve Kümeleme İşlemleri:

XPO ile arama ve kümeleme işlemlerini CriteriaOperator nesnesiyle yapabiliriz. Bu işlemi ya verileri çekerken XPCollection nesnesiyle yada daha sonradan Filter metoduyla yapabiliriz. Birkaç örnek vermek gerekirse:

CriteriaOperatorun özelliği değiştirilerek max,min,sum,avg,count vs işlemleri de yapılbiliyor.

——XPCollection kaynak = new XPCollection(typeof(muhasebe),

——CriteriaOperator.Parse("HesaplarSınıfı.Sum(HesapAlanı) < 100"));

—- XPCollection kaynak1 = new XPCollection ( typeof ( muhasebe ), CriteriaOperator .Parse( "ID==’" + int .Parse(textBox1.Text)+ "’" ));

—– XPCollection kaynak = new XPCollection ( typeof ( insan ));

——CriteriaOperator filter = new BinaryOperator ( "Owner" , textBox1.Text, BinaryOperatorType .Equal);

 

Son makalemizde XPO’da ilişkilerden , transaction ve validation kavramlarından bahsedeceğiz.

Her türlü sorunuzu metkor@gmail.com dan iletebilirsiniz.

Referans: www.devexpress.com/XPO


"http://www.w3.org/TR/html4/loose.dtd">

XPO ile O\R MAPPING -1

   Merhabalar, bu makale serimizde Object Relational Mapping kavramından ve DevExpress ürün ailesine ait XPO ile temel veritabanı işlemlerimizi nasıl yapabileceğimizden bahsedeceğiz

  Object Relational Mapping : O\R Mapping kısaca nesne tabanlı programlama dilleri ile ilişkisel veritabanları arasında ilişkilendirme yapmamızı sağlayan bir programlama tekniğidir. Yani veritabanı üzerinde yapacağımız işlemler için hiçbir Sql kodu yazmamız gerekmez. Veritabanı üzerindeki alanlara programımızda oluşturduğumuz sınıflar aracılığıyla ulaşıyoruz ve ekleme silme vb işlemleri sınıflar üzerinden yapıyoruz. Böylece veritabanı bağımsız uygulamalar yapabiliyoruz. Bu işlemi yapmamamız sağlayan çeşitli çözümler var açık kaynak kodlu Nhibernate, .Net 3.0 ile gelen LINQ, DevExpress Xpo bunlardan bir kaçı.

 

  XPO:

  Açılımı eXpress Persistent Objects olan XPO Developer Express’e ait O\R Mapping çözümüdür. XPO veritabanı katmanını uygulama geliştiriciden soyutlar ve onun sadece nesne tabanlı olarak çalışmasını sağlar. Uygulamamızı geliştirirken DevExpress.XPO namespace’imizi uygulamamızda belirtmemiz gerekiyor.

  Sınıf oluşturma:

  Sınıfımızı normal bir sınıf oluşturur gibi oluşturuyoruz. Tek farkı oluşturduğumuz sınıfın XPObject’den türetilmiş olması. Örneğin

class insan : XPObject

{

public string adi;

public string soyadi;

public int yasi;

public string cinsiyet;

}

 

   Veritabanımızda olsa bile XPO not null alan tanımlamaya izin vermez. Bunları programatik olarak yakalamamız gerekir.

    Temel Veritabanı işlemleri:

   Temel veritabanı işlemlerine geçmeden önce veritabanı bağlantısı hakkında belirtmemiz gereken bir şey var. XPO eğer veritabanı yönetim sistemi hakkında birşey belirtmezsek varsayılan olarak Access’i kabul ediyor ve Access veritabanı oluşturuyor. Eğer farklı bir veritabanı yönetim sistemi belirtmek istiyorsak XpoDefault.ConnectionString deyimiyle veritabanı bilgilerimiz belirtmemiz gerekiyor. Örneğin

XpoDefault .ConnectionString = "Data Source=******;Initial Catalog=******;UID=mehmet;password=12345" ;

   Veritabanı üzerinde işlemler yapabilmemiz için Session veya Unit of Work oluşturmamız gerekiyor. Ancak session oluşturmazsak uygulama tarafından DefaultSession kullanılıyor. En basit şekliyle bir ekleme işlemini şu şekilde gerçekleştiririz.

XpoDefault .ConnectionString = "Data Source=******;Initial Catalog=******;UID=mehmet;password=12345" ;

insan contact = new insan ();

contact.adi = “Ali”;

contact.soyadi = “Veli”;

contact.yasi = 23;

contact.cinsiyet = “Erkek”;

contact.Save();

    Session:

    Session’ları veritabanı işlemleri sırasında verileri tutan bir yapı olarak düşünebiliriz. Session’lar veritabanı işlemleri sırasında veritabanı bağlantı bilgilerinin bulunduğu Data Access Layer’ları kullanır. Sessionlar varsayılan olarak kullanılabileceği gibi kendi sessionlarımızı da oluşturabiliriz.

Session mySession = new Session();

    Şeklinde session’ımızı oluşturabiliriz. Kendi oluşturduğumuz session’ı kullanabilmek için Constructor metodumuza session’ımızı iletmeliyiz. Daha sonra veritabanına bağlanabilmek için bu sessiona ait ConnectionString yada Connection özellikleri belirmemiz gerekiyor.

    Session’a bağlanmak için Connect, bağlantıyı kesmek için Disconnect metodlarını kullanıyoruz. Ama Connect metodunu kullanmaz isek XPO otomatik olarak bağlanır. Bu durumda Connect metodu hiçbir şey yapmaz.

class insan : XPObject

{

public string adi;

public string soyadi;

public int yasi;

public string cinsiyet;

public Customer(Session session) : base(session) {}

}

 

     Unit Of Work :

     Unit of work’ler de session’larla aynı işi yaparlar. Aralarındaki tek fark Session’larda her değişiklik için Save metodu çağrılırken Unit of work lerde yapılan değişiklerin tutularak tek bir CommitChanges metoduyla tüm değişiklerin kaydedilebilmesidir. Ancak bunun için sınıfımız içinde OnChanged metodu kullanılmalıdır.

class insan : XPObject {

public insan(Session session) : base(session) { }

public insan(Session session, string name) : base(session) {

this.name = name;

}

private string ad;

public string Ad {

get { return ad; }

set {

string eski = Ad;

if(eski == value)

return;

ad = value;

OnChanged("Ad", eski, value);

}

}

 

     Veritabanında yapacağımız işlemlerde eğer tablomuz yok ise XPO verdiğimiz bilgilere ve sınıfımıza göre bir tane oluşturuyor ve tek olan bir primary key OID atıyor. Eğer var olan bir tablo üzerinde işlemler yapmak istiyorsak sınıfımız veritabanımıza göre yazmamız yeterli. Eğer var olan bir Key kullanacaksak ve OID yi kullanmak istemiyorsak sınıfımızı XPObject’ten değil XPBaseObject’ten türetmelisiniz.

     İlk makalemizde O/R Mapping’den, XPO’dan ve temel sınıf işlemlerinden bahsettik. Diğer makalemizde biraz daha veritabanı işlemlerine girmeye başlayacağız. Her türlü sorunuzu metkor@gmail.com dan iletebilirsiniz.



Dependency Injection –
Bağımlılık İletimi

 

Merhaba
arkadaşlar, gecikmeli de olsa, güncelliğini yitirmemiş bir
konu olan Dependency Injection hakkındaki serinin ikinci
makalesini yayınlıyorum.

 


Dependency Injection ve Inversion of Control

Kurumsal
Mimari Desenler, her ne kadar farklı alanları adreseler de
[1] , bu desenlerden birisi vardır ki hemen her kurumsal
uygulamada karşımıza çıkar. Basitçe, bir nesnenin bağımlı
olduğu (kabaca, UML de referansı olan) nesnelerin dinamik
olarak çalışma zamanında yapılandırılabilmesine imkan
sağlayan bu desenin adı Dependency Injection desenidir.
Inversion of Control (IoC – Kontrolün geri çevrimi)  olarak
adlandırılan bu dinamik yapılandırılabilen bağımlılık
problemi, özellikle kurumsal uygulamaların yaygınlaşmasıyla
birlikte çok sık uygulanan bir çözüm  (ki aksi takdirde
desen olması mümkün olmazdı) haline gelmiştir.

 

Özellikle
günümüzde Servis olarak Yazılım (SaaS) olarak adlandırılan
prensip ile birlikte popülerliğinin zirvesinde olan
Bileşen-temelli geliştirme (CBD-Component Based Development)
yaklaşımının özünü oluşturan tekrar kullanılabilirlik için
tasarımların genelgeçer olmasının ötesinde, çalışma
zamanında nesnelerin dinamik yapılandırılabilmesi de
gereklidir.

 


Hello
World!…


Internet’te Dependency Injection veya Inversion of Control
şeklinde bir arama yaptığınızda Martin Fowler’in bu konuyu
anlattığı temel makaleye ulaşırsınız. Bu makalede kullandığı
filmleri listelemeye yarayan MovieLister örneği, bir çok DI
ve IoC projesi için Hello World!… niteliğindeki örnektir.
Bu nedenle, ben de bu temel örneği kullanarak bu kavramı
sizlere aktarmaya çalışacağım.

 

Temel
olarak örneğimiz şöyle: Verinin hangi kaynaktan
geldiğininden tamamen bağımsız olmak üzere bir MovieLister
bileşeni yaratmak istiyoruz.

 


public

class MovieLister


      { …


 


public

Movie [] MoviesDirectedBy (string
director)


        {


            IList
allMovies = _movieFinder.FindAll ();


            IList
movies = new
ArrayList ();


            foreach
(Movie m in
allMovies)


            {


                if
(director.Equals (m.Director))


                {


                    movies.Add (m);


                }


            }


            return
(Movie []) ArrayList.Adapter
(movies).ToArray (typeof
(Movie)); …        }

 

Yukarıdaki
örnek koddan da göreceğiniz gibi finder nesnesi
verikaynağına üzerinde çalışmaktadır. İşte, DI problemi
filmleri listeleyen MovieLister sınıfı ile finder
nesnelesinin nasıl ilişkilendirileceği problemidir.

 

Bu noktada
şunu söyleyebiliriz “Madem finder nesnesinin belirli bir
metodunu ve onun döndürdüğü türü biliyoruz, o zaman finder
sınıfının bu nesnesini bir arayüze taşıyalım ve onu
gerçekleyen sınıfları türeterek MovieLister sınıfında
kullanalım”

 


private

IMovieFinder _movieFinder;


public

MovieLister ()


{


      _movieFinder = new SimpleMovieFinder(“myMovies.txt”);


}

 

Yukarıda
bu arayüzü, ve bunu gerçekleyen bir sınıf nesnesinin
MovieLister içinde nasıl yaratılıp kullanılabileceğini
görebilirsiniz. Evet, belirli bir arayüzü gerçekleyen bunun
gibi onlarca sınıf yaratabilir ve onları yukarıdaki gibi
kullanabiliriz. Ama unutmayalım, daha tasarım zamanındayız;
çalışma zamanında yukarıdaki nesneler statik olarak
ilişkilendirileceklerdir. Bu anda UML diagramına bakacak
olursak MoveLister sınıfının MovieFinder arayüzüne ve bunu
gerçekleyen sınıfa bağımlı olduğunu görebiliriz. Çalışma
zamanında, bu bağımlılık statik hale gelecektir. O halde
soruyu soralım: MovieLister sınıfını, sadece MovieFinder
arayüzüne bağımlı bırakıp, onu gerçekleyen sınıfla dinamik
olarak nasıl ilişkilendirebiliriz. DI problemini teknik
olarak böyle ifade edebiliriz.

 


Figure 1

 

 


Inversion
of Control – Kontrolün Ters Çevrimi

Yukarıdaki
kodun çalışma zamanındaki davranışını düşünecek olursanız,
bağımlılık ilişkisinde kontrolün MovieLister sınıfında
olduğunu görürsünüz. Yani bu kod ilgili arayüzü gerçekleyen
sınıfın nesnesini yaratarak kullanmaktadır. Bu kontrolün
MovieFinder arayüzü ve onu gerçekleyen sınıfa aktarılması
durumuna Inversion of Control – Kontrolün Ters Çevrimi
diyoruz.

 


İyi,
Kötü,Çirkin…

DI
probleminin üç çözüm yolu mevcuttur. Birincisi Constructor
injection (type 3), ikincisi Setter injection (type 2) ve
üçüncüsü Interface injection (type 1). Bu çözüm yollar
çeşitli platformlarda gerçeklenmiştir. Bu platoformlardan en
meşhurları pico container (Constructor injection), Spring (Setter
injection) ve Avalon (Interface injection) dur. Bu üç
projeyi de internette ücretsiz olarak bulabilirsiniz. Hemen
belirtmek istiyorum, her üç projenin de .NET türevi
bulunmaktadır.

 


1)
Constructor Injection

Bu DI
çözüm yolunda MovieLister sınıfının constructor metodunu
aşağıdaki gibi düzenleyip, pico container’in
yapılandırmasında kullanılacak MovieFinder gerçeklemesini
belirterek kullanılır.

 


public

MovieLister (IMovieFinder movieFinder)


            {


                  _movieFinder = movieFinder;


            }

 


2)Setter
Injection

Spring.NET
tarafından kullanılan bu yöntemde, MovieLister sınıfının
bağımlılık kurduğu MovieFinder nesnesi set metodu
aracılığıyla dışarıdan iletilir. Spring container, xml
aşağıdaki gibi bir yapılandırma ayarıyla çalışma zamanında
bu set metoduna hangi MovieFinder gerçeklemesinin
verileceğini belirler.

 


public

IMovieFinder MovieFinder


        {


            set


            {


                _movieFinder =
value;


            }


        }


 



 


      <
object


id
="MyMovieLister"
type="Spring.Examples.MovieFinder.MovieLister,
MovieFinder
">


            <
property


name
="movieFinder"
ref="AnotherMovieFinder"
/>


      </
object>


      <
object


id
="MyMovieFinder"
type="Spring.Examples.MovieFinder.SimpleMovieFinder,
MovieFinder
" />


      <
object


id
="AnotherMovieFinder"
type="Spring.Examples.MovieFinder.ColonDelimitedMovieFinder,
MovieFinder
">


            <
constructor-arg


index
="0"
value="movies.txt"
/>


      </
object>

 


3)
Interface Injection

Avalon
tarafından kullanılan bu yöntemde iletim işlemi arayüzler
tarafından gerçekleştirilmektedir. MovieLister sınıfı bu
arayüzü gerçeklemektedir. Avalon framework’ü bu arayüzler
üzerinden, yapılandırma dosyasına gore ilgili sınıfların
nesnelerini yaratıp çalışma zamanında MovieLister’in
kullanımına sunmaktadır. Bir başka deyişle, Spring.NET
container’i tarafından kullanılan set metodlarının yerini
veya pico container tarafından kullanılan constructor
metoduna parameter iletiminin yerini arayuzler almaktadır.

 



interface

InjectMovieFinder


    {


        void
injectFinder(IMovieFinder
movieFinder);


    }


 


Sonuç

Sonuç
olarak, DI veya IoC kullanarak, gerçekten tekrar
kullanılabilir bileşenler yaratılabilir. Çalışma zamanı
davranışının dinamik olarak gerçekleştirilmesi sayesinde,
ilgili container framework’lerin yardımıyla, plugin
mimarileri oluşturabilirsiniz. Gerçekte de bir çok projedeki
plugin mimarileri bu ve benzer yapılarla oluşturulmaktadır.

 

Bir başka
makalede görüşmek üzere,

Ekrem AKSOY



Kurumsal Uygulama Nedir?


Kurumlar, soyutlandığında iş süreçleri üzerine
kuruludur. Küçük patron şirketlerinden uluslararası
holdinglere kadar her kurum iş akışları, iş mantığı,
girdileri ve çıktıları ile süreçlerden oluşur. Bu
geniş yelpazenin iki ucu arasındaki tek fark
süreçlerin tanımlı olmasıdır.


Her koşulda, kurum süreçlerini otomatikleştirmek ve
karar almaya destek verecek sistemleri geliştirmek
zor bir tasarım problemidir. Süreçlerin tanımlı
olması, problemin zor olmasını engellemez; ve
kurumsal uygulamalar geliştirmekten bahsediyorsak,
genelde her problem zordur.


Kurumsal uygulamalar, iş süreçlerinin otomasyonunu
gerçekleştirmek için geliştirilen ve genelde büyük
miktarda ve karmaşık ilişkileri olan verinin
görüntülenmesini, işlenmesini ve saklanmasını
sağlayan yazılım uygulamalarıdır [1,Fowler]. Bu
sistemlerin diğer bir adı da Bilgi Sistemleri’dir.
Yazılım geliştirme süreçleri doğal olarak bu tür
uygulamaları geliştirmeyi de sağlamaktadır. Ancak,
kurumsal uygulama geliştirmek ile televizyon
içindeki donanımı kontrol edecek gömülü yazılımı
geliştirmek arasında çok büyük farklar vardır. Her
iki durumda aynı yazılım geliştirme yaklaşımını
kullanmak, bu nedenle, çok büyük problemler
yaratabilir.


Literatürde, Kurumsal Uygulama’nın ne olduğu net
olarak tanımlı değildir. Ancak, genel olarak bir
kurumsal uygulama şu özellikleri içerir:

·  


Çok miktarda veri

·  


Karmaşık veri ilişkileri

·  


Eş-zamanlı erişim

·  


Çok kullanıcılı arayüzler

·  


Dağıtık altyapı

·  


Farklı sistemlerle entegrasyon

·  


Belirli bir iş alanı (Business Domain) bilgisi


B2C siteler, Rezervasyon sistemleri, Müşteri
İlişkileri Yönetimi (CRM) sistemleri, Kurumsal
Kaynak Planlama (ERP) sistemleri, Hastane Yönetim
Bilgi Sistemleri (HYBS) , Üniversite Öğrenci İşleri
Bilgi Sistemleri (ÖİBS), kurumsal uygulamalardan
birkaçıdır.



 



Kurumsal Uygulama Geliştirme


            Yazılım geliştirme, ve özellikle
kurumsal uygulama geliştirme, pek çok açıdan inşaat
yapmak ile aynıdır. Ancak, bir yazılım mühendisi
kadar sofistike eğitime sahip olmayan inşaat
işçileri, kalfalar, ustalar tarafından yapılan (ve
elbette, mimar ve inşaat mühendisi tarafından
tasarlanmış) yapı projelerinin gerçeklenmesinde pek
problem yaşanmazken (Biten İnşaat / Tüm İnşaatlar
oranı çok yüksektir), yazılım mühendisleri ve
programcılar tarafından yürütülen projelerin
başarısızlık oranı çok yüksektir. Kurumsal Uygulama
Geliştirme problemi için öncelikle buradaki
çelişkiyi anlamamız gerekmektedir.


            Yapılar inşaa etmek insanoğlunun
binlerce yıldır tekrarladığı bir iştir. İnsan,
yerleşik düzenin temelini oluşturan barınak
yapımından günümüzün gökdelenlerine kadar herşeyi
inşaa etmiş ve bunun tecrübesini nesilden nesile
aktarmıştır. Neticede, günümüzde insanoğlu binlerce
yıllık bir tecrübeyi kullanarak daha büyük ve daha
gelişmiş yapılar inşaa etmektedir. Burada sizlerin
de farkedeceği anahtar kavramlar tecrübe aktarımı ve
bunun çalışma-zamanındaki karşılığı tekrarlamadır.
Kısa bir not olarak, hepimizin bildiği ve kullandığı
Design Patterns (Tasarım Desenleri) kavramının
mimari bir kavram olduğunu belirtmekte fayda var [2,Alexander].


            Buradan hareketle günümüzün yazılım
geliştirme kavramına bakacak olursak ilk başta
binlerce yıllık bir bilgi birikiminin olmaması
nedeniyle sıkıntıların yaşandığı sonucu
düşünülebilir. Ancak, bu asıl problemin
yanılsamasıdır. Yazılım Geliştirme her iterasyonda
 (her projede) sıfırdan başlandığı için problemler
yaşamaktadır. Tekrarlama ve tecrübe aktarma
kavramlarını içermeyen bir yazılım geliştirme
sürecinin başarısız olması ihtimali yüksektir.


            Pragmatik olarak tecrübe aktarma ve
tekrarlama kavramlarını tasarım desenleri (design
patterns) ve bunun çalışma-zamanı karşılığı tekrar
kullanılabilirlik (re-usability) ve ile
gösterebiliriz. Tasarım probleminin çözümüne yönelik
tasarım desenlerini kullanmak ve bu tasarımları
içeren kod bileşenlerini tekrar kullanmak kurumsal
uygulama geliştirme projesinin başarıya ulaşması
için gerekli pratiklerdir.


           


            Kurumsal Mimari Desenler


            Tasarım Desenleri (Design Patterns),
Gang of Four (GoF) olarak bilinen, Eric Gamma,
Richard Helm, Ralph Johnson ve John Vlissides
tarafından yazılan “Design Patterns: Elements of
Reusable Object-Oriented Software” kitabıyla Yazılım
Mühendisliği literatüründe yerini aldı. Elbette,
Gamma’nın ve diğer bazı yazılım mühendislerinin konu
üzerinde 80’li yılların sonundan beri çalıştığını
biliyoruz ancak GoF Design Patterns kitabı
yayınlandığında tüm yazılım geliştiricilerin
dikkatini bu konuya ve kavrama çekti. Bugün tasarım
desenleri çok yaygın olarak tanımlanmakta ve
kullanılmaktadır. Farklı problem türleri için
zamanla tekrar eden çözümlerin “keşfedilmesi”yle
çeşitli desenler ortaya çıkmıştır. Kısacası,
desenler aslında yıllardır kullanılan çözümlerdir ve
birisinin fikri yada tasarımı değildir.


            Desenlerin keşfedildiği bilgisini
aklımızın bir kenarında tutarak Kurumsal Mimari
Desenler’in ne olduğunu inceleyelim. Kurumsal Mimari
Desenler, kurumsal uygulama geliştirirken
karşılaşılan özel tasarım problemlerini çözmekte
kullanılan çözümlerdir. Farklı kurumsal uygulama
platformlarında kullanılan özel çözümler de
mevcuttur (ör. Sadece J2EE tasarım desenleri).


            Bir desen, belirli bir tip problemi
çözmekte kullanılır. Bu nedenle, desenin hangi
durumlarda kullanılacağını bilmek ve özel olarak
karşılaşılan problemde nasıl kullanılacağını bulmak
önemlidir. Ancak desenler, problemi çözmek için
olduğu gibi yutulan sihirli haplar değildir. Her
desenin ilgili problem için özelleştirilmesi her
zaman olmasa da çoğu zaman gereklidir.


           



            Kurumsal Uygulama Geliştirme Problemleri


            Desenleri incelemeye başlamadan önce
kurumsal uygulama geliştirme problemlerinden
bahsetmek istiyorum. Tabi “problem” kelimesinin
sıkıntı veren durum anlamında değil, ilgili durumu
oluşturan bileşen olarak kullandığımı da
belirtmeliyim. Kurumsal uygulama geliştirme
problemlerini aşağıdaki şekilde sıralayabiliriz:


  1. İş Alanı Modelleme

  2. Veri/İş Modeli Uyumu

  3. Web sunumu

  4. Çok-katmanlı yapı

  5. Çok-kullanıcı için multi-threading

  6. Transaction problemleri


 


            Kurumsal uygulamaların iş süreçleriyle
doğrudan ilintili olduğunu belirtmiştim. Bu nedenle,
iş mantığının (yada daha doğru olacak şekilde,
ilgili iş alanının) belirlenmesi çözülmesi gereken
bir problemdir. İş alanı bilgisi veya iş mantığının
bileşenlerinin belirlenmesi, bunların yapısal ve
davranışsal ilişkilerinin çözümlenmesi, ilgili iş
modelinin oluşturulması ve temel mimari yapının bu
model üzerinde belirlenmesi bu problemin çözüm
adımlarıdır. Günümüzde iş-alanı (domain)
modellenmesinde Model-güdümlü Mimari (Model-driven
Architecture, MDA) ve Alan-güdümlü Analiz (Domain-driven
Analysis, DDA) kullanılmaktadır.


Kurumsal uygulamalar ile ilgili diğer bir problem,
veri modeli ile iş mantığının eşleştirilmesidir.
Günümüzdeki persistance mekanizmaları (Hibernate,
TopLink vb. ) bu probleme doğrusal bir şekilde çözse
de, bu problemin farklı durumlarda tercih
edilebilecek birden fazla çözümü bulunmaktadır.
Ayrıca dağıtık ve heterojen veri kaynaklarının
erişimi ve model eşleştirilmesi de yine ele alınması
gereken problemlerdendir.


            Internet’in yaygınlaşmasıyla günümüzün
kurumsal uygulamalarının büyük bir çoğunluğu Web
sunumuna sahiptir. Ancak Web’in HTTP ve HTML tabanlı
olması (Mobil uygulamalardaki durum da hemen
aynıdır) dinamik web uygulamalarına özgü problemleri
de ilgi alanımıza sokmuştur. Bütün dinamik Web
platformları  aynı yaklaşımla çalışır.
Model-View-Controller (MVC) olarak adlandırılmış bu
yaklaşım (aynı isimli desen de mevcuttur) ASP, PHP,
JSP veya daha farklı bir dinamik Web platformunun,
dinamik olarak üretilen verinin (Model) durağan HTML
gösterimine (View) çevrilmesini (Controller
tarafından) sağlar. Burada Model’in iş mantığı ile
etkileşimi, Model bilgisinin Controller tarafından
View’e çevrimi ve View’in Model’deki bileşenleri
temsil etme biçimi bir çözülmesi gereken bir çok
problemi içerir.


            Kurumsal uygulamaların yapısal
tasarımında çok katmanlı yapı kullanılmaktadır. Çok
katmanlı yapıya duyulan gereksinim bu makalenin
kapsamı dışındadır.  Ancak, mimari olarak
katmanların belirlenmesi yine çözülmesi gereken bir
problemdir. Sunum katmanının kapsamı, İş mantığının
katmanlar arasındaki etkileşimi ve veri katmanına
erişim bu aşamadaki problemlerimizdir. Kimi
uygulamalarda sunum katmanı sadece verinin
gösterimini içermekte, kimi uygulamalarda da iş
mantığının belirli kısımlarını içermektedir. Benzer
şekilde bazı uygulamalar sunum katmanının veri
katmanına doğrudan erişimini içerirken (genelde bu
çok sık görülür) bazı uygulamalar veri katmanını iş
mantığı içerisinde gizlemektedir. Burada
hatırlanması gereken temel prensip uzamsal olarak
bağımlılıkların yukarıdan aşağıya doğru olmasını
sağlamaktır.    


            Kurumsal uygulamaların genelde (doğrusu
hemen her zaman) çok kullanıcılı sistemler olduğunu
düşünecek olursak, çok kullanıcının aynı kaynak(lar)
üzerinde yaptıkları işlemlerin sistemin kararlılık
sınırları içerisinde kalmasını ama aynı anda birden
fazla kullanıcıya hizmet edebilmesini sağlamak çok
zor bir problemdir. Problemin en zor yanı çok
kullanıcıya hizmet vermek için multi-thread uygulama
geliştirmekte yatar. Bu tür uygulamaların çalışma
zamanı davranışlarını test etmek çok zordur. Ayrıca,
çalışma zamanındaki performansları çok hassastır;
tasarımındaki ufak değişiklikler performanslarını
çok fazla etkiler. Bu nedenle, multi-thread
uygulamaları tasarlarken kullanılacak kaynaklar,
işlem zamanları, iyi/kötü senaryolar, stress
testleri dikkatlice planlanmalı ve dikkatlice
uygulanmalıdır.


            Multi-threading ile birlikte transaction
kullanımı da kurumsal uygulama tasarımındaki
problemlerdendir. Transaction denince ACID tabirini
de hemen hatırlarız. İşte kurumsal uygulama
geliştirirken sıkça kullanacağımız tranasction’lar
için ACID özelliklerini sağlayacak çözümler
geliştirmek gereklidir. ACID özelliklerine kısaca
değinecek olursak:


  1. Atomicity: Transaction içindeki her bir eylemin
    başarıyla tamamlanması gereklidir. Herhangi bir
    adımda yaşanacak hata bütün transaction’ın
    başarısız olmasına ve tüm işlemlerin geri
    alınmasına (roll-back) neden olur.

  2. Consistency: Sistemin transaction süresince
    tutarlı durumda bulunması gereklidir.

  3. Isolation: Her bir transaction işleminin sonucu,
    başarıyla tamamlanana kadar diğer
    transaction’ları etkilememeli ve onlar
    tarafından görülmemelidir.

  4. Durability: Transaction işleminin sonucu kalıcı
    olmalıdır.


            Kurumsal Mimari Desenler, işte bu
sıraladığım problemler için uygulanan çözümlerdir.
Yukarıda sıralanan problemlerin herbiri için tek tek
veya belirli kombinasyonları için uygulanacak
çözümler mevcuttur. Ancak daha önce de belirtmiş
olduğum gibi, bu çözümleri olduğu gibi uygulamaya
çalışmak problemi çözmek yerine yeni “sıkıntı”lar da
yaratabilir. Bu nedenle iyi bir tasarım için, ilgili
durumu iyi anlamak ve desenlerin nasıl
kullanılacağını belirlemek önemlidir.



            Sonuç


            Bu makale, Kurumsal Mimari Desenler
konulu serinin ilk adımıdır. Kurumsal mimari
desenleri anlamak için öncelikle kurumsal uygulama
kavramını ve çözümü gerektiren problemlerin yapısını
anlamak gerekmektedir. Serinin bir sonraki
makalesinde Dependency Injection desenini
işleyeceğiz. Tekrar görüşmek üzere.

 

Ekrem AKSOY

Yazılım testi denildiğinde OOP programcıları olarak aklımıza sadece Unit (birim) testi gelir. Daha doğrusu, sınıfları geliştirir, birim testlerini yapar (XP’ci arkadaşlar tam tersini yaparlar bu arada) keyfimize bakarken, kadrosu test mühendisi olan arkadaşların yoğun bir şekilde çalışmalarına kıs kıs güleriz. Bu yazıda test mühendisi arkadaşların neden bizler kadar rahat olamadıklarını inceleyeceğiz.
Kritik sistemler üzerinde çalışan yazılımların test edilmesi neredeyse bu sistemler için yazılım yazılması kadar eskidir. Ancak, endüstriyel yazılımlar için test metotlarının geliştirilmesi ya da başka bir deyişle, kritik sistemler için kullanılan test metotlarının endüstriyel yazılımlar için uygulanması özellikle 90’ların ikinci yarısından sonra tam anlamıyla başlamıştır. 2000’li yıllara girildiğinde dünyayı kasıp kavuran güvenlik kaygıları ile güvenilir yazılım geliştirmenin önemi net şekilde görülmüştür. Hatta şimdi adını hatırlayamadığım ünlü bir üniversitenin yazılım mühendisliği programının başındaki bir profesör, ortaya çıkan karmaşanın nedenini “bizim hatamız, güvenlikten bihaber yazılımcılar yetiştirmektir” şeklinde özetlemişti.
Peki, yazılım nasıl test edilmelidir? Yaptığımız birim testleri yazılımın güvenilir olmasını sağlamakta mıdır? Sezgisel olarak sorunun cevabı “hayır”dır. Bunu vurgulayan en güzel ve en yaygın örnek Fransızların Ariane V füze faciasıdır. Özet olarak şöyle: Ariane V füzesi, Ariane IV füzesini temel alarak geliştirilmiş, ancak daha fazla yük taşıyabilen daha büyük bir füzedir. Füze fırlatıldıktan belirli bir süre sonra kontrolden çıkar ve infilak eder. Nedeni SRI isimli açı ve hız ölçen bilgisayar sisteminin yazılımının Ariane IV füzesindekinin aynısı olmasıdır. Yazılım daha önce test edilmiş olduğu için bir daha test edilmemiştir. Yani Bileşen seviyesinde SRI yazılımının testleri yapılmış, ancak yeni bir platforma konulduğu için diğer sistemler ile etkileşimi test edilmemiştir. Bu nedenle oluşan bir Operand Error yüzünden SRI kendisini kapatmış ve kaza gerçekleşmiştir. Bu kıssadan çıkartılacak hisse, sistemi oluşturan yazılım bileşenlerinin kendi doğrulamalarının yanı sıra sistemin bütünleştirilmesi de doğrulanmalıdır. İşte test mühendisi arkadaşların özellikle yaptıkları iş budur.
Sistem testinin iki temel amacı vardır. Birincisi, sistemin bütünleştirildiğinde oluşan/ortaya çıkan hataları tespit etmek; ikincisi, sistemin beklenildiği gibi çalıştığından emin olmak. Birinci durum için sisteme hatalı veya sınır dışı girdiler vererek sistemin davranışları gözlenmelidir. İkinci durumda ise yapılacak olan, sistemin her işlevsel isteri için bir test kümesi oluşturmaktır.
Araştırmalar yazılımda ortaya çıkan hataların büyük çoğunluğunun bütünleştirme sürecinde ortaya çıktığını göstermektedir. Yani, yazdığımız kodlar (sınıf veya bileşenler olarak) tek başlarına doğru çalışmakta, ancak bir araya getirdiğimizde, ortaya çıkan sistem veya alt-sistemler hata oluşturabilmektedir.
Sistem testi iki kısımdan oluşabilir. İlk olarak yazılımı geliştiren ekipteki arkadaşlar yazılım bileşenlerini birleştirirken her adımda test yaparlar. Burada hemen şunu vurgulamak istiyorum. Çoğu durumda sistem bileşenleri karmaşık ara yüzler ile etkileşim sağlarlar ve burada oluşan hataları tespit etmek maliyetli olabilir. Dahası, sıkça kullanılan kara-kutu test yöntemi ile oluşan hatanın nedeni çok daha zor anlaşılabilir. Bunun üstesinden gelmenin etkili bir ilacı yoktur, dolayısıyla yapılabilecek olan şeylerden birisi, regresyon testini kullanmak (ki NUnit ile bunu otomatik olarak yapabiliyoruz) diğeri de risk yönetimi ile test kümesini belirlemektir.
Burada aklımıza hemen şu soru gelir: sistemleri nereye kadar test edeceğiz? Microsoft, temel yazılım süreçleri bütçesinin %85’ini test için harcadığını söylüyor. Bu, test sürecinin
ne kadar pahalı bir süreç olduğunu göstermektedir. Öte yandan, yazılım mühendisliğinin babası Dijkstra, “Test etmek sadece hataların var olduğunu gösterir, yok olduklarını değil” diyerek mümkün olduğu kadar çeşitli testlerin yapılması gerektiğini söylemektedir. Bu orantı durumunun optimum noktası nasıl bulunur?

Yukarıda da söylediğim gibi cevap risk yönetiminde yatmaktadır. Test kümesindeki elemanların sayısını azaltmak işi için tanımlı bir en iyi yöntem yoktur. Ancak, uygulanabilecek yöntemlerden birisi risk analiz matrisi kullanmaktadır.

ID
Risk Olasılık Hasar Risk Büyüklüğü Test Kümesi
1 Güç
1
5
5
TK-23
2 Müşteri kayıt Formunda boş veri
3
5
15
TK-34,TK-45
3 Müşteri taksit sayısının 24`ten büyük girilmesi
4
3
12
TK-13
           
 

Yukarıdaki risk analiz matrisinde, risk durumları, oluşma ve hasarlarına göre bir katsayı oluşturmaktadır. Daha sonra her bir risk durumu için geliştirilen test kümeleri kolonu verilmiştir. En yüksek 20 katsayıyı oluşturan risk durumlarının test kümeleri gerçeklenir. Risk durumlarının oluşma olasılıklarını ve vereceği hasarı belirlemek için geliştirme ekibi ve müşteri arasında bir anket düzenlenebilir. Kalanlarının gerçekleşmemesi için de nazar boncuğu asılır.
Bu yazımda test mühendisi arkadaşların sorunlarına değinmeye çalıştım. Dahası, yazılım testinin detaylarına inildikçe bu arkadaşlarımızın omzuna ne kadar yük bindiği daha iyi anlaşılabilir. Yazılımın geliştirme kısmında bulunan arkadaşlara önerim, yazılımlarımızın birim testlerini ve dokümantasyonunu eksiksiz yapmaya çalışalım, çünkü bundan kaynaklanacak hataları test mühendisi arkadaşlar yakalayamayabilir ve hatta yakalasa bile düzeltmek bize çok daha maliyetli olabilir. Tekrar görüşmek üzere…

Ekrem AKSOY

Birçoğumuz projelerimizi, çalışmalarımızı gerçekleştirdikten sonra derleme ve kurulum işlemlerini el ile gerçekleştirmeyi tercih ediyoruz. Bununla birlikte özellikle takım geliştirme ortamında veya büyük yazılım projelerinde böyle bir yaklaşım karmaşaya yol açar. Takım geliştirme ortamında yazılımın derlenmesi, sürüm ve değişim kontrolü, test edilmesi ve kurulumu süreçlerini kontrol edebilmek için bazı araçlara gereksinim vardır. Bunun kadar önemli bir diğer problem de bu görevlerin bütünleşik olarak çalıştırılabilmesi ve otomatik olarak gerçekleştirilebilmesidir. Bu yazımızda, yazılım mühendisliğinin bu önemli süreci için kullanabileceğimiz NAnt kurulum aracını inceleyeceğiz.
NAnt kurulum aracı, Java geliştiricilerin yaygın olarak kullandıkları Ant aracının. NET sürümüdür. .NET ortamındaki bütün diller için kullanılabilir. NAnt ile çeşitli kurulum hedefleri tanımlayıp bu hedefler için görevler belirtebilirsiniz. Uygulamanın son sürümünü http://nant.sourceforge.net/ adresinden indirip kurduktan sonra kullanmaya başlayabiliriz. Yazımızda basit bir .NET konsol uygulaması için kurulum gerçekleştireceğiz.
Örnek uygulama tahmin edebileceğiniz şekilde bir “Hello World” uygulaması. Uygulamanın kodu aşağıdaki gibidir:
public class HelloNant
{
static void Main()
{
System.Console.WriteLine("Hello from Nant!
");
}
}
Bu uygulamanın kurulumunu gerçekleştirmek için yapmamız gereken ilk şey bir kurulum dosyası hazırlamaktır. Bu dosya XML formatında ve .build uzantılı bir dosyadır. Örnek uygulamamız için hazırladığım .build dosyası aşağıdaki gibidir:
<project name="Hello Nant" xmlns="http://nant.sf.net/release/0.85-rc3/nant.xsd" basedir=".">
<target name="build">
<csc target="exe" output="HelloNant.exe">
<sources>
<include name="HelloNant.cs" />
</sources>
</csc>
</target>
</project>
Dosyanın detaylarına geçmeden önce örnek uygulamanın kurulumunun nasıl yapılacağından bahsetmek istiyorum. Kurulumu gerçekleştirmek için Nant kurulum dizinini içerisindeki /bin klasöründeki nant.exe aracını Path ortam değişkenine eklemek gerekmektedir. Daha sonra komut satırından
Nant –buildfile:hello.build
komutu ile kurulumu gerçekleştirebilirsiniz.

 
a
 

.build dosyasına göz atacak olursak, dosyanın bir proje tanımladığını görürüz. Proje elemanın altındaki target yani hedef elemanları farklı kurulum görevlerini gerçekleştirebilmemizi sağlamaktadır. Şöyle ki, makinemizde bugünlerde olduğu gibi .NET 1.1 ve .NET 2.0 ortamları yüklü ise uygulamamızı bu farklı hedeflerden birisini kullanabilecek şekilde kurabiliriz.
Her bir target bir takım task yani görev elemanlarını barındırır. NAnt veya genel olarak Ant kurulum aracının esas gücü de bu görev elemanlarında yatar. Örneğimizde <csc> görevini kullanarak csc derleyicisini çalıştırdık. Bu görevleri kullanarak uygulamanızı test edebilir, derlemeden önce eski derlenmiş dosyaları temizlemek isteyebilir, CVS aracını kullanarak en son sürüme ait kodları derleyebilir ve bunun gibi birçok görevi gerçekleştirebilirsiniz. Bu görevleri örnek üzerinde inceleyelim.
Uygulamalarımız her zaman yukarıdaki örnekte olduğu kadar kolay olmaz. Örneğin uygulamamızı debug edebilmek için debug sembollerini de ekleyerek debug seçeneği ile derlemek isteyebiliriz. Bunun için var olan “build” hedefimize ilave olarak “debug” hedefi ekleyelim.
<project name="Hello Nant" xmlns="http://nant.sf.net/release/0.85-rc3/nant.xsd" basedir=".">
<target name="build">
<csc target="exe" output="HelloNant.exe">
<sources>
<include name="HelloNant.cs" />
</sources>
</csc>
</target>
<target name="debug">
<mkdir dir="debug" failonerror="true" />
<csc debug="true" output="debug/HelloNantDBG.exe" target="exe">
<sources>
<include name="HelloNant.cs" />
</sources>
</csc>
</target>
</project>
Kurulumu debug hedefi için gerçekleştirmek istediğimizde

Nant debug –buildfile:hello.build

Komutunu kullanarak hedefimizi debug olarak belirtebiliriz. Debug hedefinde bu defa <mkdir> görevini de kullandık. Bu görevi dizin yaratma işlemlerinde kullanabiliriz. <mkdir> elemanının failonerror niteliği, hata oluşması durumunda görevin durdurulup durdurulmayacağını belirtir.

 

 
a
 

Derlemeden önce derlenmiş eski dosyaları silmek için <delete> görevini kullanabiliriz. Aşağıda, örneğimiz için “clean” hedefi tanımlanmaktadır.
<target name="clean">
<delete file="debug/HelloNantDBG.exe" />
<delete file="debug/HelloNantDBG.pdb" />
</target>
“clean” hedefini tanımladıktan sonra bu hedefi diğer hedeflerle ilişkilendirebiliriz. Hedefleri birbirine bağımlı kılmak için <target> elemanının depends niteliğini kullanırız. Örneğin, debug hedefini clean görevine bağımlı hale getirelim
<target name="debug" depends="clean">

 
a
 

Son olarak kurulum işlemi esnasında farklı bir uygulama çalıştırmanız gerektiğinde <exec> görevini kullanabilirsiniz. Örneğin:
<target name="run" depends="debug">
<exec program="debug/HelloNantDBG.exe" />
</target>
Daha sonra,
Nant run –buildfile:hello.build
Komutu ile uygulamayı çalıştırabiliriz. Burada dikkatinizi çekmek istediğim yer görevlerin birbirine bağımlılıkları. Yani biz run hedefini belirterek kurulum yapmak istediğimizde NAnt önce clean hedefini gerçekleştirecek, sonra debug hedefini gerçekleştirecek ondan sonra run hedefini gerçekleştirecektir. Birbirine bağımlı olmayan hedefleri gerçekleştirmek istediğinizde

 
a
 

Nant build run –buildfile:hello.build
Komutu gibi hedefleri listeleyerek kurulumu gerçekleştirebilirsiniz.

 
a
 

Yazılım projelerinde en sık ihmal edilen ama en büyük sıkıntılara yol açan kurulum işlemini otomatik olarak gerçekleştirmek iyi bir yazılım mühendisliği pratiğidir. Bir sonraki yazımda NAnt aracını NUnit test framework ile kullanarak kurulum ve test otomasyonunun nasıl gerçekleştirilebileceğinizi göstermeye çalışacağım. Sorularınız için e-mail gönderebilirsiniz. Tekrar görüşmek üzere…

Ekrem AKSOY

© 2010 bilyaz.com , Programlama Makaleleri, Yazılım Makaleleri , Örnek Kodlar , Eğitim Videoları , C#,ASP.NET,SQL,PHP Suffusion WordPress theme by Sayontan Sinha