Showing posts with label uml. Show all posts
Showing posts with label uml. Show all posts
Anti Pattern'lar aynı Design Pattern'lar gibi zamanla kalıplaşmış yapılardır. Design Pattern'larından farkı bir problemin nasıl olması gerektiğini değil nasıl olmaması gerektiğini anlatmasıdır. Bu yönüyle Design Pattern'larının zıttıdır diyebiliriz. Bazı Anti Pattern örnekleri;
- Magic Pushbutton : Frontend elemanların kodları arasına iş mantığını sağlayan kodların yazılması ile oluşur.
- Functional Decompozition : Birbirinden alakasız statik fonksiyonları tek bir sınıfa toplanması ile oluşan bir anti pattern'dır.
- Database as IPC : Farklı uygulamalar arasındaki iletişimin bir veritabanı üzerinden yapılması ile oluşur.
- Swiss Army Knife : Kullanılmayan, gereksiz kod parçalarının bulunduğu yazılımlarda görünür.
- Busy Waiting : Zaman alan işlemleri aynı thread üzerinde yaparak uygulamanın yanıt vermemesi durumunu oluşturan kodlara denir.
- Soft Coding : İş mantığını konfigürasyon dosyası gibi dosyalarda kodlanmasına denir.
- Lasagna Coding : Gereğinden fazla katmandan oluşan kodlara denir.
- Spagetti Coding : Soyutlama gibi tasarım prensipleri uygulamadan yazılmış karmaşık kodlara denir.
- God Object : Birden fazla amacı olan çok fazla kod bulunan sınıflara denir.
- Error Hiding : Uygulamada oluşan hataları handle eden ve bu hataları loglamayarak üstünü kapatmaya çalışan yazılımlarda görünür.
- Copy Paste Programing : Hız kazandırdığı düşüncesiyle yapılan ancak daha sonradan çok fazla soruna yol açabilecek bir tekniktir.
Design Pattern yani dizayn paternleri programlamada sürekli karşılaşılan problemlere en iyi çözümü sağlayan kalıplaşmış yöntemlerdir denilebilir. Bu yüzden programlama dilinden bağımsız yapılardır. Ben yazılarımda dizayn paternlarını anlatırken Java dilini kullanıyor olacağım ancak bu yapılar tüm nesneye yönelik programlarda kullanılabilir.
Dizayn paternlarının amacı programcının sürekli karşılaşılan problemler için çözüm aramamasını sağlamak ve daha önceden yapılan ve yanlış olduğu görülen yöntemler denememesini sağlamaktır. Bu yapılar zamanla kalıplaşmıştır ve en doğru çözüm olduğu konusunda hemfikir olunmuştur.
Dizayn paternları kendi içinde mantıksal olarak ayrılır. Aşağıdan bu paternlar ile ilgili yazdığım yazılara ulaşabilirsiniz.
Creational Pattern'lar (Nesne Yaratılışına Ait Patern'lar)
Structural Pattern'lar (Yapısal Patern'lar)
Behavioral Pattern'lar (Davranışsal Patern'lar)
- Chain Of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
Yazılım sistemlerinde değişiklik kaçınılmaz bir durumdur. Yazılan kod her zaman değişmek zorunda kalır. Bu yüzden yazdığımız kodu kolay değişebilir şekilde yazmalıyız. Aksi takdirde yazdığımız kod çok kısa bir zaman sonra çöp olacaktır. Bu problemi çözümü nesne yönelimli programlamada polimorfizm'dir. Polimorfizm ile sistemimizde bir değişiklik yapmak zorunda kaldığımızda mevcut kodları değiştirmeden sadece yeni kodlar ekleyerek problemlerimizi çözebiliriz. Bu işlemin amacı daha önceden yazılmış kodun bağımlılıklarından kurtulmaktır. Çünkü bir kodu değiştirmek her ne kadar kolay gözüküyor olursa olsun o kodun sistemimizde bağımlı olduğu yerleri düşündüğümüzde yani etkilediği diğer kod parçalarını düşündüğümüzde işin içinden çıkılamaz bir durum oluşur. Bu yüzden polimorfizm kullanarak sistemlerimizi tasarlamalıyız.
Polimorfizm kısaca, yazılımda uyumluluğu yani geçmişte yazılan kodların, gelecekte yazılacak olan kodları desteklemesini sağlayan bir nesne yönelimli programlama tekniğidir.
Polimorfizm iki şekilde gerçekleştirilebilir.
- Soyut sınıf ve saf sanal fonksiyonlar kullanılarak.
- Interface yani arayüzler kullanılarak.
Aşağıdaki iki örnekte de sisteme yeni bir şekil eklendiği zaman Ciz sınıfında veya sistemin herhangi bir yerinde bir kod değişikliği yapmamıza gerek olmaz.
public class Ciz{
public void sekilCiz(Sekil sekil){
sekil.sekilCiz();
}
}
public class Sekil {
public void sekilCiz(){
}
}
public class Kare extens Sekil {
public void sekilCiz(){
}
}
public class Daire extens Sekil {
public void sekilCiz() {
}
}
Interface Örneği
public class Ciz{
public void sekilCiz(Sekil sekil){
sekil.sekilCiz();
}
}
public interface Sekil {
public void sekilCiz();
}
public class Kare implements Sekil {
public void sekilCiz(){
}
}
public class Daire implements Sekil {
public void sekilCiz() {
}
}
Bir yazılım birden fazla şekilde yazılabilir ancak her çalışan kod gerçekten bir yazılım sayılmaz. Örneğin inşaat mühendisleri bir binayı tasarlarken sadece binayı yapmayı düşünmezler. Tüm olası durumlarda o binanın ayakta durması için gerekli olan şeyleri düşünüp ona göre binayı inşa etmek zorundadırlar. Yazılım mühendislerininde böyle bir zorunluluğu vardır çünkü her ne kadar kod çalışıyor olsa bile iyi tasarlanmamış bir kodun ömrü çok kısa olacaktır. Bu yüzden yazılımı yazmadan önce o yazımı iyi tasarlamak gerekir. Aksi halde işin içinden çıkamayacak problemlerle karşılaşılır ve kod bir çöpe dönüşür. Bazı yazılım prensipleri;
- Yazılımda olacak paydaşları doğru bir şekilde çıkararak bunları yazılıma aktarmamız gerekir. Gerçek dünya nesneleri olarak düşünerek bunların yazılımdaki karşılıkları olan sınıfları çıkarmalıyız. Bunu yaparken her bir paydayı ayırmalıyız. Örneğin müşteri, satıcı olan ve hatta bu tiplerin alt türlerinin de bulunduğu bir yazılımda tüm bu paydaşlar için tek bir sınıf yaparsak daha sonraki herhangi bir değişiklikte işin içinden çıkılamaz bir karmaşıklık oluşur. Bunun için buraki tüm paydaşları amacına göre tek tek ayırarak sistemi tasarlamamız gerekir.
- Bir sınıfı tasarladığımızda o sınıfın üyeleri yani özellik ve fonksiyonları mantıksal açıdan birbirlerine yakın olmalı ve benzer bir amaç için var olmalıdırlar. Yani aynı sınıfta birbirinden amaç olarak uzak olan iki üye olmamalıdır. Böyle bir durum var ise muhtemelen yanlış bir tasarım yapıyoruz demektir.
- Bir sınıfı tasarladığımızda o sınıfın tek bir amacı olmalıdır. Birden fazla amaca hizmet eden sınıflar kötü tasarımı gösterirler. Yazılımda bir değişiklik olacağı zaman muhtemelen bir amaca yönelik olur. Eğer sınıflarımızı doğru bir şekilde tanımlarsak herhangi bir ihtiyaçta çok az kod değişimi yaparak belki de hiç kod değiştirmeden sadece biraz kod ekleyerek problemi çözebiliriz.
- Tasarladığımız sınıflar genellikle birbirleri ile etkileşim içerisinde olurlar. Bu kaçınılmaz bir durumdur ancak bu bağımlılıklar kodda bir değişiklik yapmak istediğimizde karşılaştığımız en büyük problemdir. Bu yüzden sınıfların arasında mümkün olduğunca az bağımlılık yaratmalıyız ve yarattığımız bağımlılıkların seviyesini mümkün olduğunca düşürmeliyiz. Bu seviyeyi düşürmenin en güzel yolu da polimorfizm'dir.
- Tasarladığımız sınıflarda yeniden kullanılabilirliği düşünmeliyiz. Örneğin bir sınıfa eklediğimiz özellikler başka sınıflarda da kullanılabilecek genel özellikler ise bu özellikleri tekrar tekrar yazmak yerine yeniden kullanılabilirliği sağlayarak genelleştirmeli ve tüm sınıflarımızda kullanmalıyız. Böylelikle genel yapıda bir değişiklik yapmak istediğimizde tüm sınıflarda değişiklik yapmak yerine tek bir noktada değişiklik yapabiliriz.
- Tasarladığımız sistemlerde değişimin olmaması imkansızdır. Yazılım sistemlerinde değişim kaçınılmaz bir durumdur. Bu yüzden sistemimizi buna göre tasarlamak zorunda olmalıyız. Sistemimizi buna göre tasarlarken dikkat etmemiz gereken nokta bir değişiklikte kod değişikliği yapmak yerine sisteme yeni kodlar eklemek olmalıdır. Çünkü sınıflar arasındaki bağımlılıktan dolayı yapılacak bir kod değişiminin etkisi çok büyük olacaktır. Bu yüzden kod değişimi yerine kod eklemesi yapmalıyız ve sistemimizi buna göre tasarlamalıyız. Bunu yapmanın en kolay yolu polimorfizm'dir.
Örnek
Aşağıdaki örnekte kötü bir tasarım örneğini görüyoruz. Bu sisteme yeni bir şekil eklediğimizde Ciz sınıfı içerisindeki metodu değiştirerek if bloğu içerisine bir koşul daha yazmamız gerekecektir. (EnumDegeri ile mantıksal olarak bir enum varmış gibi düşünülmüştür. Burada EnumDeğeri yerine mantıksal bir parametre veya buna benzer bir yapı olabilir önemli olan bu tür kullanımın yanlışlığının gösterilmesi olduğu için enum koda eklenmemiştir.)
public class Ciz{
public void sekilCiz(EnumDegeri){
if(EnumDegeri == Kare) {
Kare kare = new Kare();
kare.kareCiz();
} else if(EnumDegeri == Daire) {
Daire daire = new Daire();
daire.daireCiz();
}
}
}
public class Sekil {
public void sekilCiz(){
}
}
public class Kare extens Sekil {
public void kareCiz(){
}
}
public class Daire extens Sekil {
public void daireCiz() {
}
}
Bu problemi çözerek daha iyi bir tasarım yapmak için sistemimizi yeni bir şekil eklendiğinde hiç bir kod değişikliği yapılması gerektirmeyecek şekilde tasarlamamız gerekmektedir. Bu tasarım polimorfizm ile gerçekleştirilir. Bu şekilde sistemimize yeni bir şekil eklendiği zaman Ciz sınıfı içerisinde hiç bir değişiklik yapmaya gerek kalmadan sistemimiz çalışacaktır.
public class Ciz{
public void sekilCiz(Sekil sekil){
sekil.sekilCiz();
}
}
public class Sekil {
public void sekilCiz(){
}
}
public class Kare extens Sekil {
public void sekilCiz(){
}
}
public class Daire extens Sekil {
public void sekilCiz() {
}
}
Bir yazılım sistemi çok farklı şekillerde yazılabilir. Bu noktada farklı yaratan yazılımın kalitesidir. Yazılımın kalitesi çoğu zaman performans ile ölçülsede bu tek başına yeterli değildir. Çünkü yazılımlar bir kere yazılan kod parçaları değildir. Yazılımlar sürekli değişir ve yazılımların bu değişimlere ayak uydurması gerekir. Eğer bir yazılım değişim karşısında problem yaratıyorsa o yazılım performansı ne kadar iyi olursa olsun o yazılım kaliteli bir yazılım değildir. Aşağıdaki maddeler kaliteli olmayan bir yazılım başlıca nedenleridir ve bu nedenler kötü yapılmış bir tasarım sonucu ortaya çıkmaktadır.
- Bir yazılımın sisteminin değişime karşı gösterdiği direnç ne kadar yüksekse o yazılım sisteminin kalitesi o kadar kötüdür. Yani değişen ihtiyaçlar doğrultusunda bir yazılımda değişiklik yapılması ihtiyacı olduğunda karşılaşılan problemler ne kadar çoksa o yazılım tasarımı da o kadar kötüdür. Bu yüzden iyi bir yazılım tasarlanırken esneklik çok önemlidir.
- Yazılımın modüleritesi yani yeniden kullanılabilirliği ne kadar düşükse yazılım tasarımı da o kadar kötüdür. Yazılım parçaları modüler şekilde tasarlanmalı ve başka sistemlerde de kullanılabilmelidir. Bu şekilde yazılımın parçaları daha kolay değiştirilebilir ve anlaşılabilir.
- Yazılım sisteminde değişiklik yapılması gerektiğinde bu değişiklikler yazılımın tasarımını değiştirmeye zorluyorsa o yazılımın tasarımı kötü bir tasarımdır.
Bir sistemi tasarlarken direkt olarak sınıfları tasarlamaya geçmek içinden çıkılamayan bir karmaşıklığa yol açar. Zaten bir sistem yazılırken tüm sınıflar aynı yere yazılmaz. Bu sınıflar mantıksal olarak paketlere ayrılır ayrıca mantıksal parçalar birbirlerinden soyutlanarak yazılım sistemi tasarlanır. Bu amaca yönelik geliştirilmiş diyagramlardan biri de paket diyagramlarıdır. Bu diyagramlar ile mantıksal parçalar ve onların altındaki alt parçalar ile sistemin parçaları arasındaki etkileşim ortaya konmaya çalışılır.
Paket Diyagramları Nasıl Çizilir?
- Her paket sol üst köşesinde küçük bir dikdörtgen olan bir dikdörtgen şeklinde çizilir.
- Palet adları bu dikdörtgenler içerisine yazılır.
- Paketler arasındaki bağımlılıklar kesikli ok ile bağımlı olan paketten bağlı olunun pakete doğru gösterilir.
- Paketler mantıksal olarak daha üst paketler içerisinde yer alabilir.
Communication diyagramları, Sequence diyagramları gibi sistemin dinamik yapısını ortaya koymaya yarar. Sistemdeki nesnelerin arasındaki iletişimi ortaya koyar. Ancak Sequence diyagramlarından ayrıldığı temel nokta Communication diyagramlarında bir zaman çizelgesi olmamasıdır.
Communication Diyagramlar Nasıl Çizilir?
- Çoğu UML diyagramında standart haline gelmiş olduğu gibi Communication diyagramlarda da nesneler dikdörtgen şeklinde çizilir.
- Nesneler arasındaki iletişim yani yazılımsal anlamda metot çağırımları çağıran metottan çağırılan metoda doğru bir ok ile gösterilir. Bu ok üzerine metot bilgisi eklenir.
- Bu diyagramda zaman çizelgesi olmadığından, dinamik yapıyı takip edebilmek için nesneler arasındaki iletişimlere numaralar verilir. Genel akıştan ayrılarak alt bir akış oluşuyorsa o zaman o akışın başladığı numara alt dallarına ayrılır. Örneğin 2 numaraları etkileşimde o nesne kendi içerisinde farklı işlemler yapacak ise bu işlemler 2.1, 2.2 gibi numaralandırılır.
Class diyagramlar sistemin statik yapısını ortaya koymaya yarar. Class diyagramlarda sınıflar ve nesneler arasındaki bağlantı ve sistemin yapısı ortaya konur. Sequence diyagramlarda ise sınıfların ve nesnelerin dinamik çalışma yapısı ortaya konmaya çalışılır. Sınıflar ve nesnelerin zaman çizelgesindeki etkileşimleri tasarlanır.
Sequence Diyagramlar Nasıl Çizilir?
- Sınıf ve nesne gösterimleri class diyagramlarda olduğu gibi dikdörtgen şeklinde çizilir.
- Sistemdeki her olay ayrı bir diyagram olarak çizilir ve bu olay içerisindeki kullanılan tüm sınıflar yatay bir düzlemde çizilir.
- Zaman çizelgesi dikey olarak kesikli bir çizgi olarak çizilir.
- Nesnelerin sistemde aktif olduğu yani kullanıldığı zamanları göstermek için ilgili sınıfın zaman çizgisi üzerine dikdörtgen çizilir.
- Nesneler arasındaki etkileşim yani yazılım anlamında metot çağırımları, çağıran metottan çağırılan metoda doğru çizilen bir ok ile gösterilir.
- Nesnelerin yaratılması veya yok edilmesi stereotype'lar ile gösterilir.
- Metotların dönüş değerleri çağırılan metottan çağıran metoda doğru kesikli bir ok ile gösterilir. Bu gösterim opsiyoneldir.
- Sekron metot çağırımları içi dolu bir ok ile gösterilirken, asenkron metot çağırımları normal bir ok ile gösterilir.
Bu diyagramlar sistemin farklı zamanlardaki durumunu ortaya koymak için tasarlanırlar. Örneğin kullandığımız ATM'lerin sisteminin durumu bizim yaptığımız işlemlere değişir. Sürekli aynı durumda olmayan bir sistemdir ve sistemin bu durumlarını tasarlamak için durum diyagramları kullanılır.
Durum Diyagramları Nasıl Çizilir? (State Diagram Nasıl Çizilir?)
- Sistemin başlangıç durumu içi dolu yuvarlak şeklinde çizilir.
- Sistemin sonlanma durumu içi boş yuvarlağın içinde daha küçük içi dolu bir yuvarlak olacak şekilde çizilir.
- Sistemin durumları kenarları yuvarlatılmış dikdörtgenler şeklinde çizilir.
- Tetikleyici olaylar sistemin durumları arasına düz bir çizgi şeklinde çizilir. Bu olaylar ile sistemin durumu değişir. Olaylar ile ilgili açıklayıcı bilgi veya kodlamadaki metot karşılıkları çizgi üzerine yazılabilir.
- Karar ifadeleri baklava şeklinde dikdörtgen olarak çizilir.
Nesne yönelimli programlamada nesnelerin bağımlılıkları olmaktadır. Bu bağımlılıklar birden fazla nedenden dolayı olabilir. Örneğin bir nesne diğer bir nesnenin bir metodunu kullanıyor olabilir. Metodunun kullanıldığı sınıfta bir değişiklik yapıldığında metodu kullanan sınıfta bu değişiklikten etkilenecektir. Bu gibi durumlarda dependency vardır denir. Bu ilişkinin olmasının nedeni değişebildiği için ilişkinin gösteriminde stereotype'lar kullanılır.
Dependency ilişkinin çiziminde iki sınıf arasına bir kesikli çizgi çekilir ve bağımlı olunan yapının olduğu tarafa bir ok çizilir. Çizginin ortasına ilişki nedenine uygun stereotype yazılır.
Nesne yönelimli programlamada kodlarda değişiklik yapılabilmesini kolaylaştıran, çoklu kalıtımı sağlayan ve bir çok faydası bulunan interface yapısı kullanılır. Interface yapısında oluşturulan interface'leri sınıflar implement ederler. Bu ilişki türüne Realization denir.
Interface ile class arasına kesikli bir çizgi çizilerek bu çizginin interface tarafına içi boş bir ok çizilir.
Nesne yönelimli programlamanın temel unsurlarından biri kalıtım(inheritance)'dır. Kalıtım yolu ile bir sınıfa ait özellikler bir başka sınıfa sadece küçük bir belirtim ile dahil edilir. Kalıtım yolu ile iki sınıf arasında kurulan ilişkiye Generalization denir.
Generalization ilişkinin çiziminde iki sınıf arasına bir düz çizgi çekilir ve kalıtım yapılan sınıfın olduğu tarafa içi boş bir ok çizilir.
Kodlama açısından Association ilişki ile aynı olan bu ilişki türü mantıksal olarak Association ilişkiden ayrılır. Bu ilişki türünde Association ilişkide olduğu gibi bir sınıf içerisinde başka bir sınıfın referansı tutulur. Ancak bu ilişkide referansı tutan sınıf ile referans edilen sınıf arasında bir parça bütün ilişkisi vardır.
Bu iki ilişki türünde parçalar bütünü oluşturur. Yani referansı tutan sınıf bir bütündür ve referansı tuttuğu sınıflar onun parçalarını oluşturur. Aggregation ilişki ile Composition ilişki arasındaki fark ise Composition ilişkide parçalar oluşturdukları bütüne özeldir. Yani parça dahil olduğu bütünden ayrılıp bir başka bütüne dahil edilemez. Aggregation ilişkide ise parçalar bütünü oluşturur ancak o bütüne özel değildir bir başka bütün ile de kullanılabilir. Bir ilişkide parça bütün ilişki varsa ve Aggregation mı yoksa Composition ilişki mi kurulacak karar verilemiyorsa aşağıdaki üç soru sorularak cevap verilir.
- Bütün nesne yok edildiğinde parça da yok ediliyorsa
- Parça bir yere taşındığında bütün de onunla taşınması gerekiyorsa
- Parça kolaylıkla başka bir bütüne dahil edilemiyorsa
bu ilişki Composition ilişkidir denir. Aksi halde Aggregation ilişkidir denir.
Aggregation ilişki çizimde bütünü oluşturan kısmın bulunduğu tarafa içi boş baklava şeklinde bir dikdörtgen çizilir.
Composition ilişki çizimde bütünü oluşturan kısmın bulunduğu tarafa içi dolu baklava şeklinde bir dikdörtgen çizilir.
Yukarıdaki örnekte Player sınıfı Organ sınıfının referansını tutar. Burada bir Composition ilişki vardır çünkü parça olmadan bütünün olması söz konusu değildir. Team sınıfı ise Player sınıfının referansını tutar. Burada bir Aggregation ilişki vardır çünkü oyuncu olmadan da bir takım var olabilir ve bir oyuncu kolaylıkla başka bir takıma dahil edilebilir.
Nesneler arasında var olabilecek en temel ilişki türüdür. Bir nesnenin içerisinde bir başka nesnenin referansını tutması ile oluşur. Örneğin;
public class Insan{
private Araba araba;
}
public Class Araba{
}
Bu örnekte Insan adındaki sınıf içerisinde Araba adındaki sınıfın referansını tutmaktadır. Bu ilişki tek taraflı olmak zorunda değildir yani Insan sınıfı Araba sınıfının referansını tutarken Araba sınıfı da Insan sınıfının bir referansını tutabilir.
Navigability
UML diyaramlarda bu ilişki iki nesne veya sınıf arasında düz bir çizgi ve referansı tutan nesneden çıkan bir ok şeklinde belirtilir. İlişki iki yönlü ise ok ile belirtim yapılmaz.
Eğer iki nesne veya sınıf arasında çoka çok ilişki varsa veritabanlarında yapıldığı gibi araya ekstra bir yapı konulur. Nesneye yönelimli programlamada bu bir sınıf olur.
Örneğin yukarıdaki örnekte müşteri birden fazla kitapçıdan alışveriş yapabilir ve bir kitapçının da birden fazla müşterisi olabilir. Bu durumda araya ekstra bir sınıf koyarak örneğin sipariş sınıfını koyarak bu ilişki tanımlanır.
Bu diyagramlar sistemin static yapısınız ortaya koymak amacıyla tasarlanırlar. Bu diyaramlar ile sınıflar, sınıfların yapısı ve arasındaki ilişki tasarlanır. Bu diyagramları çizerken standart haline gelmiş şekil ve semboller kullanılır.
Sınıf ve Nesne Diyagramları Nasıl Çizilir?
- Sınıflar dikdörtgen şeklinde çizilir.
- Sınıfların çizildiği dikdörtgenler dikey olarak 3 parçaya ayrılır. İlk parçaya sınıfın ismi yazılır. İkinci parçaya sınıfın özellikleri yani değişkenler yazılır. Üçüncü parçaya sınıfın yaptığı işlemler yani metotlar yazılır.
- Yazılan özellikler için erişim belirleyici + özellik ismi + :özellik tipi şeklinde belirtim yapılır.
- Yazılan metotlar için erişim belirleyici + metot ismi + (metot parametreleri) + dönüş tipi şeklinde belirtim yapılır.
- Erişim belirleyiciler için semboller kullanılır. Bu semboller public için +, private için -, protected için # şeklindedir.
- Nesneler tek parça dikdörtgen şeklinde çizilir ve içerisine nesne bilgisi yazılır.
- Yazılacak nesne bilgisi nesne adı + sınıf adı şeklinde belirtilir.
İlişkiler
UML diyaramlarda iki nesne veya sınıf arasında bir ilişki belirtilirken, bu iki çizim arasına bir çizgi çizilir. Ayrıca daha sonra ilişki türüne göre bu çizgi üzerine eklemeler yapılır. İlişki türleri ilerleyen yazılarda anlatılacaktır.
Nesne veya sınıflar arasında bir ilişki belirtirken bu ilişkiye bir isim verilir. Bu ilişkiyi açıklayan anlamlı bir isim verilmelidir. Bu ilişkiyi belirten düz çizginin tam ortasına yazılır.
Nesne veya sınıflar arasında bir ilişki belirtirken bu ilişkiye bir isim verilir. Bu ilişkiyi açıklayan anlamlı bir isim verilmelidir. Bu ilişkiyi belirten düz çizginin tam ortasına yazılır.
Multiplicity
İlişkide bulunan nesnelerin sayısını belirtmek için kullanılır. Örneğin yukarıdaki örnekte Kitap sınıfı içerisinde bir üye barındırabilir veya hiç barındırmayabilir. Yani bir kitabı bir üye ödünç almış olabilir veya o kitabı hiç bir üye ödünç almamış olabilir. Bu örnekte bir kitabı birden fazla üyenin ödünç alamayacağı gösterilmiştir.
Abstraction yani soyutlama nesne yönelimli programlamanın ve yazılım mühendisliğinin en önemli konularından biridir. Soyutlama yapılmadan yazılmış bir kodda değişiklik yapmak çok zordur. Soyutlama ile bir sistemin karmaşıklığı o sistemi kullanan paydaşlardan gizlenir. Kod yazarken de soyutlama ile yazdığımız her parça kendi işini yapmalı ve karmaşıklığını kendi içinde çözmelidir. O parçayı kullanan diğer parçaların işin nasıl yapılmadığı ile ilgili bir bilgisi olmamalıdır. Örnek verecek olursak kullandığımız telefonlarda bir soyutlama yapılmıştır. Biz arama yaptığımızda veya mesaj gönderdiğimizde bunu telefonun nasıl yaptığını bilmeyiz. Telefonumuza bir güncelleme geldiğinde veya başka bir telefon kullandığımızda herhangi bir zorluk çekmeyiz çünkü sistemin tüm detaylı bizden soyutlanmıştır.
Use Case yani kullanım senaryosu diyagramları sistemin operasyonlarını ortaya koymaya yarar. Genellikle modellemenin ilk aşamasında oluşturulur. Bu yüzden sistemin detayını değil genel bir yapısını oluşturur. Bu modellemede detaylı bir dil kullanılmaz basitçe bir olayın nasıl olacağını anlatılır. Örneğin "müşteri bilgileri veritabanına kaydedilir" use case diyagramlarda bir aksiyondur. Burada bu bilgilerin nasıl kaydedileceği, hangi teknolojinin kullanılacağı gibi herhangi bir detayın önemi yoktur. Sadece operasyon ile ilgili genel bir bilgi verilir.
Use case diyagramlar çizilirken sistemin aktörleri ve operasyonlar belirlenir. Sistemin aktörleri sistem ile ilişkili olan ve sistemin dışında olan her şeydir. Örneğin sistemi kullanan müşteri veya sistem yöneticisi bir aktördür. Aynı zamanda sistem örneğin bir ödeme sistemine bağlıysa bu da bir aktördür. Operasyonlar ise aktörlerin sistem üzerinde gerçekleştirdikleri aktivitelerdir.
Use Case Diyagramlarının Çizimi
- Aktörler basit bir çubuk adam şeklinde belirtilir.
- Operasyonlar elips şeklinde belirtilir.
- Aktörlerin hangi operasyonları yapabilecekleri, aktörler ile operasyonlar arasına düz bir çizgi çizilerek belirtilir. Buna association denir.
- Elemanlar arasındaki bağımlılıklar kesikli çizgi ile gösterilir. Örneğin bir use case operasyonunun içerisinde bir başka use case operasyonunu kullanması durumunda bir bağımlılık oluşur.
Use Case Anlatımları
- Varsayım : Anlatımı basitleştirmek için bir operasyon olmadan önce zaten rutin olarak yapılacak işlemlerin kısaca belirtildiği kısımdır. Örneğin müşterinin giriş yapıp yapmadığının kontrolü.
- Ön Koşul : Operasyonun başlaması için gerekli şartların belirtildiği kısımdır. Örneğin para çekme işleminde limit dahilinde bir tutarın girilmesi gerektiği gibi.
- Başlatma : Operasyonu başlatan eylemdir. Örneğin kullanıcının butona basması gibi.
- İşlem : Sistem içerisinde yapılan işlemler. Örneğin girilen tutar, bakiyeden düşürülür. Daha sonra yeni bakiye veritabanına kaydedilir gibi.
- Sonlanma : Belirtilen senaryoda başarılı veya başarısız durumların oluştuğu kısımdır. Bakiyenin yetersiz olması, veritabanına erişilememesi veya atm'den müşteriye paranın teslim edilmesi gibi durumlar senaryonun sonlanma koşulları olabilir.
- Sonlanma Koşulu : Operasyonun başarılı tamamlanma koşuludur. Örneğin para çekme işlemi sonucunda yeni bakiyenin doğru bir şekilde hesaplanması gibi.
- Alternatif Akışlar : Ana senaryo dışında oluşabilecek yan senaryoların belirtildiği kısımdır. Örneğin atm'de para kalmaması durumu veya veritabanından bakiyenin okunamaması durumu gibi.
UML diagramlarını çizmek için pek çok farlı araç mevcuttur. UML diagramı çizmek için geliştirilmiş araçlar olduğu gibi mevcut ide'ler üzerine geliştirilmiş plugin'ler de mevcuttur. UML diagramı için kullanabileceğiniz bazı araçlar;
UML (Unified Modelling Language) bir modelleme dilidir. İş sistemlerinin modellemesi için kullanılır. Yazılım alanında da sıklıkla kullanılmaktadır. 1990'lı yıllarda yazılım dillerinden bağımsız bir modelleme diline duyulan ihtiyaçtan dolayı geliştirilmiştir. İsminde bulunan birleştirilmiş sözcüğü, birden fazla geliştiricinin geliştirdiği modelleme dillerinin bir standart oluşturmak için birleştirilmesinden dolayı eklenmiştir. UML modelleme sistemlerine bir standart getirir.
UML Kullanmanın Faydaları
- Proje başlangıcında modelleme bir zaman kaybı gibi görünsede ilerleyen süreçlerde çıkabilecek hataları azalttığı ve geliştirme süresini kısalttığı için proje süresinde ciddi bir iyileştirme sağlar.
- Projedeki gereksinimlerin ve risklerin proje başlangıcında ortaya çıkmasını sağlayarak daha sonradan başarısız olacak bir projenin geliştirmesine başlamadan bu durumun görünmesini sağlar.
- Projenin kalitesini arttırır.
UML Modelleri
UML modelleri üç ana kategoriye ayrılır.
- Dinamik, Davranışsal Modelleme (Sistemin davranışını modelleme)
- Statik, Yapısal Modelleme (Sistemin yapısını modelleme)
- İşlevsel Modelleme (Sistemin aktörler ile birlikte nasıl etkileşim kuracağını modelleme)
Dinamik, Davranışsal Modelleme
- Sequence (Etkileşim) Diyagramları
- Communication (İletişim) Diyagramları
- State (Durum) Diyagramları
- Activity (Faaliyet) Diyagramları
- Timing (Zamanlama) Diyagramları
Statik, Yapısal Modelleme
- Class (Sınıf) Diyagramları
- Object (Nesne) Diyagramları
- Deployment (Dağıtım) Diyagramları
- Composite Structure (Bileşke Yapı) Diyagramları
- Component (Bileşen) Diyagramları
İşlevsel Modelleme
- Use Case Diyagramları























