2 Nisan 2014 Çarşamba

Android Custom Toast Messages


Android uygulamalarında ki standart toast mesajlarını nasıl özelleştirebileceğinizi gösteren bir örnek hazırladım.

Bu örneğe ve detaylı bilgiye 
Android-Custom-Toast adresinden ulaşabilirsiniz...

iyi çalışmalar...

21 Ekim 2013 Pazartesi

Refactoring:Tip Kodlarını Alt Sınıflarla Değiştirin !

Yazılımın domain katmanı tasarlanırken,gerçek hayattaki nesneleri, sınıflar yardımı modellediğimiz aşikardır.
Yanlış bir tasarım/modelleme yapıldığında,düzeltmesi yeniden yapılandırması güçleşir.

Sistematik düşünüp kod geliştirme işini, bir çok dinozor yazılımcı angarya,zaman kaybı olarak algılar.Halbu ki ileri de daha fazla zaman kaybedeceğinin farkında değildir...


Şimdi aşağıda ki örneği inceleyecek olursak;
Bir firmadaki Personelleri görevlerine göre modelleğimiz bir örnek.
Firmada ki personeller görevlerine göre yazılım geliştirici,satışcı,destekçi,müdür gibi farklı görevleri olan personeller var.

Bu personellerin hepsini bir Person sınıfı ile ifade etmek karışıklığa yol açabilir.
Neden derseniz ?
Çünkü her bir personel tipinin temelde bazı özellikleri aynı olsa da,farklı olan özellikleri de olabileceği için tek bir Personel sınıfı ile ifade etmek yanlış,yetersiz,karmaşık ve gereksiz olacaktır. :)

Her ne kadar PersonType gibi bir enum kullanarak, Person sınıfı ayırt etmeye çalışsak da buda yetersiz kalacaktır.

Karmaşıklığa bir örnek verecek olursak;
Aşağıdaki methodları Person sınıfına eklediğimizi düşünelim.
public void kodGelistir(); -> Yazılımcının işidir. 
public void satisYap();    ->  Satışcının işidir.
Bu methodların implementasyonu başarılı bir şekilde çalışsa da mantıken Person sınıfında olması yanlıştır.Person sınıfını gereksiz yere kalabalık eder....

O sebeble public void kodGelistir(); methodunun Developer sınıfına eklememiz gerekir.
Aynı şekilde public void satisYap();  methodunun da Salesman sınıfına eklememiz gerekir.
Bu şekilde yazılımcı Personel den satış yapmasını,satışcı personelden de kod geliştirmesini beklememiş olursunuz ! ;)

Buraya kadar yaptığımız işleme "Replace Type Code with Subclasses" refactoring prensibi deniliyor...

Person.cs
using System;

public enum PersonType
{
    DEVELOPER = 1,
    SALESMAN = 2,
    MANAGER = 3,
    SUPPORTER = 4
}

public abstract class Person
{
    public int id { get; set; }
    public string firstName { get; set; }
    public string lastName { get; set; }
    public double salary { get; set; }

    public PersonType personType { get; set; }

    public Person(PersonType type)
    {
        this.personType = type;
    }

    public static Type getType()
    {
        return typeof(Person);
    }
}

Developer.cs
using System;

public class Developer : Person
{
    public Developer()
        : base(PersonType.DEVELOPER)
    {
        this.salary = 10.000;
    }

    public static Type getType()
    {
        return typeof(Developer);
    }
}

Manager.cs
using System;

public class Manager : Person
{
    public Manager()
        : base(PersonType.MANAGER)
    {
        this.salary = 1500;
    }

    public static Type getType()
    {
        return typeof(Manager);
    }
}

Salesman.cs
using System;

public class Salesman : Person
{
    public Salesman()
        : base(PersonType.SALESMAN)
    {
        this.salary = 1500;
    }

    public static Type getType()
    {
        return typeof(Salesman);
    }
}

Supporter.cs
using System;

public class Supporter : Person
{
    public Supporter()
        : base(PersonType.SUPPORTER)
    {
        this.salary = 1000;
    }

    public static Type getType()
    {
        return typeof(Supporter);
    }
}

Diğer bir mevzu ise yazılan kodda ki iç içe bloklu yapılardır.Bu örnek olduğu için göze okunabilir gözükse de complex bir sistemde ne demek istediğimi çok iyi anlayacaksınız.

Aşağıdaki PersonFactory sınıfına ait iki adet method bulunmakta bunlar ;
public Person cleanCreate(PersonType personType); // factory method
public Person dirtyCreate(PersonType personType); // factory method

İki method da parametre ile verilen enum tipinden, ilgili tipi create edip döndürüyor.

dirtyCreate methodu içersinde switch(condition) yapısı kullanılarak ilgili enum tipinden,
enuma karşılık gelen sınıftan bir intance oluşturuluyor.

cleanCreate methodu içersinde ise map'leme yöntemi ile,ilgili enum tipinden class tipini bulup activator sınıfı ile tipden bir instance oluşturuluyor.

cleanCreate methodu içersinde herhangi bir condition(if,switch vs) kullanmadan map'leme yöntemi ile nesne oluşturma işine de "Replacing Conditionals With Map" işlemi deniliyor.


PersonFactory.cs
using System;
using System.Collections.Generic;

public class PersonFactory
{
    private static object _lock = new object();

    private static PersonFactory instance;

    private static Dictionary map = new Dictionary();

    private PersonFactory()
    {
        this.initializeMap();
    }


    public static PersonFactory getInstance()
    {
        if (instanceIsNull())
            createInstance();
        return instance;
    }

    private static void createInstance()
    {
        lock (_lock)
        {
            if (instanceIsNull())
                instance = new PersonFactory();
        }
    }

    private static bool instanceIsNull()
    {
        return instance == null;
    }

 // Replace Conditional With Map işlemi.
    private void initializeMap()
    {
        map.Add(PersonType.DEVELOPER, Developer.getType());
        map.Add(PersonType.SALESMAN, Salesman.getType());
        map.Add(PersonType.MANAGER, Manager.getType());
        map.Add(PersonType.SUPPORTER, Supporter.getType());
    }


    // iyi bir factory method yazım şekli...
    public Person cleanCreate(PersonType personType)
    {
        Type type;
        map.TryGetValue(personType, out type);
        object instance = Activator.CreateInstance(type);
        return (Person)instance;
    }

    // kötü bir factory method yazım şekli...
    // aşağıdaki swicth yapısındaki şartlı instance oluşturma işlemi,
    // initializeMap methodu içerinde map'leme yöntemi ile değiştirilmiştir.
    public Person dirtyCreate(PersonType personType)
    {
        Person person = null;
        switch (personType)
        {
            case PersonType.DEVELOPER:
                person = new Developer();
                break;
            case PersonType.SALESMAN:
                person = new Salesman();
                break;
            case PersonType.MANAGER:
                person = new Manager();
                break;
        }
        return person;
    }
}

Test sınıfına bakacak olursak ;
PersonFactoryTest.cs
using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;


[TestClass]
public class PersonFactoryTest
{
    private PersonFactory factory;

    [TestInitialize]
    public void init()
    {
        factory = PersonFactory.getInstance();
    }

    [TestMethod]
    public void createDeveloperTest()
    {
        //Yazılımcıda bir personeldir (!)
        Person person1 = factory.cleanCreate(PersonType.DEVELOPER);
        person1.id = 1;
        person1.firstName = "ismail";
        person1.lastName = "Kocacan";
    }


    [TestMethod]
    public void createManagerTest()
    {
        //Müdür de bir personeldir...
        Person person2 = factory.cleanCreate(PersonType.MANAGER);
        person2.id = 2;
        person2.firstName = "ali veli";
        person2.lastName = "deli";
    }


    [TestMethod]
    public void createSalesmanTest()
    {
        //Satışcıda bir personeldir...
        Person person3 = factory.cleanCreate(PersonType.SALESMAN);
        person3.id = 3;
        person3.firstName = "adı lazım değil";
        person3.lastName = "sanane";
    }



    [TestMethod]
    public void createSupporterTest()
    {
        // Destekçide bir personeldir...
        Person person4 = factory.cleanCreate(PersonType.SUPPORTER);
        person4.id = 4;
        person4.firstName = "kezban1";
        person4.lastName = "kezban1";
    }


    [TestCleanup]
    public void finalize()
    {
        factory = null;
    }
}

iyi çalışmalar

20 Ekim 2013 Pazar

100 MetreKare DoğalGazlı Daire Bedava

Balıkesir de maltepe mahallesi civalarından, eve doğru giderken birkaç direkte bu ilanı gördüm.

15 Eylül 2013 Pazar

Entity Framework CRUD

Entity Framework kullanarak bir Kullanici sınıfı üzerinde CRUD işlemlerini gösteren örnektir.
"Code First" tekniği kullanılarak hazırlanmıştır.

Aşağıdaki adresten depoya erişip inceleyebilirsiniz.
Entity Framework CRUD

Tüm bu orm'lerin temelinde reflection kavramının yattığını bilmeyen,ama entity framework uçar kaçar diyen de bir o kadar adama rast gelmişimdir zaman içinde... ;)
Neyse...

iyi çalışmalar.




2 Eylül 2013 Pazartesi

Rtti Gevşek Unitler :)

Bir projedeki unit'lerin uses bloglarına baktığımızda bir sürü unit ismi görürüz.

Bunların bir çoğu da projeye bizim eklediğimiz unit dosyalarıdır.

Ve hepsi birbirine bağlıdır.Bu bağımlığı en aza indirmenin yollarından birisi de ,reflection kullanmaktır. :)

Aşağıda yazacağım rttiFormActivator methodu ile bir "unitismi.formsınıfadı" vererek formu oluşturmak için kullanabiliriz.

Bu method kullanıma göre özelleştirebilir.

function  rttiFormActivator(typeQualifiedName : string; isModal:Boolean=false) : TValue;
var
 context      : TRttiContext;
 rttTyp       : TRttiType;
 instanceType : TRttiInstanceType;
 instance     : TValue;
begin

 try
   context   := TRttiContext.Create();
   rttTyp    := context.FindType(typeQualifiedName);

   instanceType := rttTyp.AsInstance;
   instance     := instanceType.GetMethod('Create').Invoke(instanceType.MetaclassType,[nil]) ;

   Result := instance;

   case isModal of
      true  :   instanceType.GetMethod('ShowModal').Invoke(instance,[]);
      false :   instanceType.GetMethod('Show').Invoke(instance,[]);
   end;

 except on E: Exception do
   raise Exception.Create(typeQualifiedName+ ' Tipi register edilmemiş !');
 end;

end;
Unit1.pas dosyanın uses bloğuna kullanmak istediğimiz herhangi bir unit içersindeki formun unitini tanımlamadan direk aşağıdaki kullanılabilecektir.
procedure TForm1.btnShowForm2Click(Sender: TObject);
begin
  rttiFormActivator('Unit2.TForm2',true);
end;


procedure TForm1.btnShowForm3Click(Sender: TObject);
begin
  rttiFormActivator('Unit3.TForm3');
end;
unit1.pas'ın uses bloğuna unit2,unit3 eklemeyerek,bu unitlere bağlı olmasını engellemiş ve dinamik bir kullanım elde etmiş olduk. Yanlız şöyle önemli bir durum var. Kullanacağınız sınıflarını register etmediğiniz zaman rtti amca findType methodu ile ilgili verdiğiniz tipi bulamıyor. o yüzden sınıfları bulunduğu unit içinde register ederek,findType methodu ile bulmasını sağlayabiliriz.
initialization
 RegisterClass(TForm2);

finalization
 UnRegisterClass(TForm2);


Kaynak Kod : https://github.com/ismailkocacan/Rtti-Loose-Coupling-Units

iyi çalışmalar.

25 Ağustos 2013 Pazar

Unity Dependency Injection And Inversion Of Control

Uzun zamandır "Dependency Injection and Inversion Of Control" konusunda bir çok kaynak okudum.

Esnek tasarlama,esnek kod geliştirme, sınıfların birbirleri olan bağımlıklarının en aza indirgenmesi vs kulağa hoş geliyordu.Lakin anlatılanlarla gördüğüm örneklerin uyuşmaması sonrasında,olm ismail sen bir örnek proje hazırla,koy bir yere dursun hem millete faydan olsun,hem de lazım oldukça kendinde öğrenirsin dedim kendime... :)

Hangi konuda olursa olsun,bir çok şey ihtiyaç üzerine gelişiyor ve var oluyor.
Bu durum yazılım dünyasında frameworklerde de böyle işte.
Peki bu frameworkler neden çıkmış olabilir acaba ?
Herifin birinin işi,gücü yokmuşta dur şu frameworkü yazayım millette kullansın mı demiş ? Tabi ki hayır...

Dependency Injection(Bağımlıkların Enjekte Edilmesi)

Bakalım Neden Çıkmış :)
Zaman içersinde develer tellal iken,pireler berber iken ,yazılımcıların  çalıştığı projelerde sürekli değişiklik olurmuş.Bu değişiklikleri ne istediği belli olmayan,ama hep ne istediğini bilmeyen müşteriler sebeb olurmuş.Bu değişikler sonucunda projedeki kodlar,çarşafçılarda ki çarşaflardan daha karışık bir hal alır ve yönetimi,bakımı,zorlaşırmış...

Yapılan değişikliker sonrasında,projenin akla bile gelmeyen yerleri etkilenir ve hatalı çalışmasına neden olurmuş.Çünkü yazılımcıların yazdığı sınıflar birbirine gönülden bağlıymış.
Onları birbirinden ayırmak mümkün değilmiş(!)...
Mevcut bir sınıfı alıp,düzeltip elden geçirmeden başka bir projede kullanmak bile mümkün değilmiş...
Çıkış nedenlerinden birisi buydu :)

Inversion Of Control(Kontrolün Tersine Çevrilmesi)

Diğeri ise yazılımda nesne oluşturmak,oluşturulan bu nesnenin takibini yapmak ise yine zor bir iştir.Nerde oluşturdum. Nerde bellekten sildim.Veya bir başka methodun benim oluşturduğum nesneyi silmesi vs...

Hal böyle olunca isyan bayrağını çekip,ulan nesne oluşturmak benim işim mi ?
Sorusunu soruyorsunuz kendize...
Misal ; Lokantaya gidip yiyeceğiniz yemeği kendiniz mi yapıyorsunuz ? Hayır.
Olm şşt bak bakem buraya şipariş vericez diyorsunuz.Ne yemek istediğinizi söylüyorsunuz oda getiriyor.

Yani yiyeceğiniz yemeğin(nesne) çeşidini(tipini),adını söylüyorsunuz o da size yemeği create ettirip getiyor.Yemeğinizi yiyip(nesneyi kullanıp) gidiyorsunuz.Nereye gidiyorsunuz olm önce hesabı ödeyin :)
2. nedeni de budur.

Yani nesne create etme kontrolünün bizden alınarak bu işin framework tarafından yapılması kısmına da inversion of control deniyor.
Yani lokantada yiyeceğimiz yemeğin tipini söyleyip,yiyeceğimiz yemeği istiyoruz.

Şimdi bu kadar hikayeden sonra bağımlıkların enjeksiyonu, kontrolün tersine çevrilmesi işi c# da unity ile nasıl oluyormuş ona bakalım.

Unity için framework için gerekli paketi aşağıdaki gibi kurabilirsiniz.


Gelen pencereden unity yazdıktan sonra ;


Bende kurulu olduğu için install butonu gözükmüyor.
Sizde kurulu değilse "install" butonuna tıklayarak kurabilirsiniz.

indireceğiniz örnekte 3 adet proje bulunmakta.

UnitySample : Domain ile ilgili sınıfların bulunduğu proje

UnitySampleUnitTest : Unit Test Projesi.

UnityWindowsFormApplication : windows form örnek uygulamasıdır.

Stock klasöründe StockCard ve StokCategory sınıfları bulunmakta.Eğer projemizde ki  stok kartlarını,kategorileyecek olursak,böyle bir tasarım yeterlik olacaktır.

Yani burdan şunu anlıyoruz ki ;
Her stok kartının, birde stok kategorisi olacak.
Stok kategorisine ait birden fazla özellik olabileceği için de StockCategory isminde ayrı bir sınıfta topladık.

Yani her StockCard sınıfın içersinde,birde StockCategory tipinde bir nesne olması gerekli değil mi ?

    // stok kategori sınıfı
    public class StockCategory : IStockCategory
    {
        public int id { get; set; }
        public string categoryName { get; set; }
        public DateTime insertionTime { get; set; }
    }
 
   // Stok Kartı sınıfımız
    public class StockCard : IStockCard
    {
        public int id { get; set; }
        public string stockCode { get; set; }
        public string stockName { get; set; }
        public double unitPrice { get; set; }
        public double amount { get; set; }
        public double total { get; set; }
        public DateTime insertionTime { get; set; }


        public StockCategory stockCategory { get; set; }


        public StockCard()
        {

        }
    }
Peki direk olarak StockCard sınıfa StockCategory tipinde bir property eklersek ne olur ? StockCard sınıfı,StockCategory sınıfına gönülden bağlı olur. StockCategory sınıfının ismini değiştirdiğimde,veya projeden sildiğimde derlemez bile... Sınıfın kendini yazmak yerine,O sınıfın implement ettiği interface tipinizi(IStockCategory) yazıyoruz. Böylece StockCategory sınıfını projeden silinse veya ismi değişse bile derlemede problem çıkmayacak. Sırf derlemede problem çıkmasın diye mi böyle yazdık ? Hayır. Neden ?
    public interface IStockCategory
    {
        int id { get; set; }
        string categoryName { get; set; }
        DateTime insertionTime { get; set; }
    }


    // stok kategori sınıfı
    public class StockCategory : IStockCategory
    {
        public int id { get; set; }
        public string categoryName { get; set; }
        public DateTime insertionTime { get; set; }
    }
 
 
 
    public interface IStockCard
    {
        int id { get; set; }
        string stockCode { get; set; }
        string stockName { get; set; }
        double unitPrice { get; set; }
        double amount { get; set; }
        double total { get; set; }
        DateTime insertionTime { get; set; }

        [Dependency("stokCategory")]
        IStockCategory stockCategory { get; set; }
    }


    // Stok Kartı sınıfımız
    public class StockCard : IStockCard
    {
        public int id { get; set; }
        public string stockCode { get; set; }
        public string stockName { get; set; }
        public double unitPrice { get; set; }
        public double amount { get; set; }
        public double total { get; set; }
        public DateTime insertionTime { get; set; }

        public IStockCategory stockCategory { get; set; }


        public StockCard()
        {

        }
    }
Eğer StockCard sınıfına yazacağımız property aşağıdaki gibi yazılmış olursa;
 public IStockCategory stockCategory { get; set; }
IStockCategory sınıfını implement eden her türlü sınıf tipindeki değişken ,stockCategory propertisine atanabilir. alsana esneklik :D Buraya kadar sadece interface'lerle esnek bir tasarım ve modelleme yaptık.

Şimdi geldik zurnanın deliğinin zırt dediği yere !

Bu oluşturduğumuz tiplerleri UnityContainer sınıfının register methodları ile sınıfların meta bilgilerini kayıt ettirip ilgili map'lemeleri en başta bir kere yapıyoruz.

Daha sonra bir nesne lazım olduğu zaman,UnityContainer sınıfından şu tipte bir nesne lazım dedikten sonra istediğimiz nesneyi elde ediyoruz.

ContainerManager sınıfımız aşağıdaki gibi.
using Microsoft.Practices.Unity;

public class ContainerManager
{
    private static UnityContainer container = new UnityContainer();

    public static UnityContainer getContainer()
    {
        return container;
    }
}

Initialization sınıfımız.
using Microsoft.Practices.Unity;
using UnitySample;

public class Initialization
{
    public static void registerObjects()
    {
        UnityContainer container = ContainerManager.getContainer();
        container.RegisterType();

        // StockCard sınıfının,stockCategory property değeri dinamik olarak set ediliyor.
        var injectMember = new InjectionProperty("stockCategory", container.Resolve());
        container.RegisterType(injectMember);
    }
}
Initialization.registerObjects(); ile önce meta bilgileri register edeceğiz. Burada dikkat etmemiz gereken injection olayının(property injection) yapıldığı yerdir.
        // StockCard sınıfının,stockCategory property değeri dinamik olarak set ediliyor.
        var injectMember = new InjectionProperty("stockCategory", container.Resolve());
        container.RegisterType(injectMember);
Görüldüğü üzere dinamik olarak,StockCard sınıfının stockCategory propertiesi set ediliyor. Yani stockCard nesnesini kullanırken ;
  stockCard.stockCategory = new StockCategory();
  stockCard.stockCategory.categoryName = "Beyaz Eşya"; 
yukarıdaki gibi nesne oluşturmanıza gerek kalmayacak.Direk olarak aşağıdaki gibi kullanabileceksiniz.
  stockCard.stockCategory.categoryName = "Beyaz Eşya"; 
Çünkü daha önce containere eklerken,gerekli map'leri yaparak ekledik.Biz yapacağımız işi en başta bir gerek yaptık yani !

Şimdi Artık Herşey Hazır Bir Test Sürüşüne Çıkalım :)

using System;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UnitySample;

namespace UnitySampleUnitTest
{
    [TestClass]
    public class StockCardTest
    {

        UnityContainer um;

        [TestInitialize]
        public void testInitialize()
        {
         // sınıfların meta bilgilerini container'a ekleyen methodu çağırıyoruz.
           Initialization.registerObjects();
           um = ContainerManager.getContainer();
        }
         

        [TestMethod]
        public void stokKartiNesnesiOlustur()
        {
            if (!um.IsRegistered())
                throw new Exception("stok kartı register edilmemiş.");

            // bir tane stok kartı nesnesi oluştuyoruz.
            var stockCard = um.Resolve();
            // veya aşağıdaki şekilde de containerdan objecte erişmek mümkün.
            //var stockCard = this.getDIContainer().Resolve();
            stockCard.stockCode = "ST0001";
            stockCard.stockName = "Buzdolabı";
            stockCard.insertionTime = DateTime.Now;
            stockCard.unitPrice = 2500;
            stockCard.amount = 60;

            stockCard.stockCategory.categoryName = "Beyaz Eşya";
            stockCard.stockCategory.id = 1;
            stockCard.stockCategory.insertionTime = DateTime.Now;
        }
    }
}
Bu tip kütüphanelerin temelinde reflection kavramının yattığını bilmekte fayda var ;)
Bu Kadar !


Proje kaynak kodu  
https://github.com/ismailkocacan/Unity-Dependency-Injection-And-Inversion-Of-Control

Kaynaklar 

http://unity.codeplex.com/
http://msdn.microsoft.com/en-us/library/ff649614.aspx
http://msdn.microsoft.com/en-us/library/vstudio/bb383977.aspx



1 Ağustos 2013 Perşembe

Can't bind to local 8600 for debugger Çözüm

Console ekranın da "Can't bind to local 8600 for debugger" hatası hatası alıyorsanız.
"use ADBHOST" seçeneğini işareleyip ecplipse uyuzunu  yeniden başlatıyorsunuz ve kaldığınız yerden devam ediyorsunuz :)


















İyi çalışmalar.