Fluent Interface ile daha okunabilir kodlar


Çoğu yazılım projesinde ortak bir sorundur kod karmaşası.Özellikle kurumsal projeler de içinden çıkılmaz bir hal alabilir ve yazılımcılara çok fazla zaman kaybına yol açıyor.Hangi programla dili ile yazıyor olursanız olun kodlar doğası gereği karmaşıktır.Karmaşık olan bu kodları daha okunaklı ve anlaşılır hale getirmenin yollarından biriside yazılım geliştiriken Fluent Interface prensibinin bilince olarak gerekli sınıflarda uygulamaktır.

Fluent Interface ;

  • Daha keşfedilebilir ve okunaklı kodlar,
  • Kod içerisinde domain bilgiside yer alır (aslında mini-DSL oluşturulmuş olur)
  • Domaine özgü diller oluşturulmaya çalışılır böylece iş analistlerinin de koda bakarak yorum yapabilmesi sağlanmış olur,
  • Kolay bir kullanım sağlar

Başka bir ifade ile kodu kullanan için anlamlı ve akışkan(sıralı ve sırasız) bir arayüz sağlar.Aşağıda geleneksel kodlama ve aynı kodlamanın Fluent Interface kullanılarak yapılmış şekli yer alıyor.En basit ifade ile Fluent interface i aşağıdaki fark anlatıyor.

Capture_13

Fluent Interface iki önemli prensip içerir.

  • Method zinciri (Method chaning)
  • Daha okunaklı API (Domain Spesific Language-DSL- veya API olarak ifade edebiliriz)

Note : ilk bakıldığında method zinciri oluşturmak kod akışını sağlamak için görünüyor olabilir.Fakat Method zinciri ve Fluent Interface birbirinden farklı şeylerdir.Fluent Interface mini-DSL sağlamak için oluşturulan bir method zinciri uygulmasıdır.Bu noktada verdiğimiz isimlendirmelerde önemlidir.

Hangi durumda kullanılabiliriz ?

  • Framework geliştirmesi yapılırken ; bir şirketin yazılım altyapısını oluşturduğunuzu düşünün.Bu altyapıda şirketdeki tüm uygulamaların kullanacağı bir uygulama framework ü geliştireceksiniz.Geliştirdiğini bu uygulama çatısını bir çok yazılım müh. kullnacak ve bu çatı ile yeni uygulamalar üretilecek.Bu durumda Altyapı takımları geliştirdikleri kütüphaneleri bu prensibi dikkate alarak geliştirebilirler
  • Sıklıkla kullanılan sınıf larda
  • 3.party kütüphane kodları ve eski kodları gizlemek istediğimizde Gateway pattern ile birlikte kullanılabilir.

Kullanım biçimleri ;

Test otomasyon uygulamasında kullanılması için tasarlanan nesnelerin üretilemsinde(instance) kullanabiliriz.Bu yüzden nesnenin kendi içerisindeki örneğinin oluşturulması gerekir.Başlangıç methodu Create dir.

Capture

Burada nesnenin özelliklerinin readonly olduğuna dikkat edelim.Set işlemi daha anlamlı isimlendirme ile farklı bir method ile yapılmış.Method zincirinin oluşması içinde methodlara geri dönüş tipi olarak kendisini veriyoruz.şimdi kullanımı görelim.

Capture_12

Diğer bir kullanım şekli ise bir süreci gerçekleştirirken kullanılmasıdır.Örneğin bir test otomasyonu uygulaması yazdınız.Bu test lerin diğer ortam ve platformlarda da çalıştırılma ihtiyacı duyulacaktır.Bunu  için temel fonksiyonelleri (örn: testlerin sistemdeki tüm testlerin tek sınıf aracılığıyla çalıştırılması) sunacak bir kütüphane yazarsınız işte bu kütüphaneyi Fluent Interface kullanarak tasarlayalım.


public class TestProcessorOutput
{
    public string ScreenTestOutputMessage { get; set; }
    public string StoredProcedureTestOutputMessage { get; set; }
    public string RunOutPutFileValidationTestOutputMessage { get; set; }
    public string RunInputFilevalidationTestOutputMessage { get; set; }
}

public interface ITestProcessor
{
    ITestProcessor RunScreenTests();
    ITestProcessor RunStoredProcedureTests();
    ITestProcessor RunOutPutFileValidationTests();
    ITestProcessor RunInputFilevalidationTests();
    TestProcessorOutput TakeResults();
}

public class TestProcessor
        : ITestProcessor
{
    public TestProcessorOutput TestOutput { get; private set; }
    public TestProcessor(TestProcessorOutput testOutput)
    {
        this.TestOutput = testOutput;
    }

    public ITestProcessor RunScreenTests()
    {
        // testleri çalıştırır
        this.TestOutput.ScreenTestOutputMessage = "";
        return this;
    }

    public ITestProcessor RunStoredProcedureTests()
    {
        // testleri çalıştırır
        this.TestOutput.StoredProcedureTestOutputMessage = "";
        return this;
    }

    public ITestProcessor RunOutPutFileValidationTests()
    {
        // testleri çalıştırır
        this.TestOutput.RunOutPutFileValidationTestOutputMessage = "";
        return this;
    }

    public ITestProcessor RunInputFilevalidationTests()
    {
        // testleri çalıştırır
        this.TestOutput.RunInputFilevalidationTestOutputMessage = "";
        return this;
    }

    public TestProcessorOutput TakeResults()
    {
        return this.TestOutput;
    }
}

public static class FluentTestFactory
{
    public static ITestProcessor Init()
    {
        return new TestProcessor(new TestProcessorOutput());
    }
}

// using of it
var testOutputs = FluentTestFactory
                        .Init()
                        .RunInputFilevalidationTests()
                        .RunOutPutFileValidationTests()
                        .RunScreenTests()
                        .RunStoredProcedureTests()
                        .TakeResults();

Örneğimizi sınıf diagram üzerinde de görelim.

Untitled

Fluent Interface prensibi kullanan popüler kütüphaneler ; Moq , Fluent NHibernate , FluentData , Nbuilder , Automapper , StructureMap. Aşağıda benzer kod örneklerini görüyorsunuz.

fleunt_interface_diagram1

fleunt_interface_diagram2

Sonuç olarak ; Fluent Interface daha iyi bir codebase oluşturmaya katkıda bulunmak için kullanılır.Ayrıca daha okunaklı kodu sağlamayı amaçlayan en iyi yoludur.

Yardımcı olabilecek linkler

  • http://www.martinfowler.com/bliki/FluentInterface.html
  • http://russelleast.wordpress.com/tag/fluent-interfaces/
  • http://www.youtube.com/watch?v=lVgz-DeTJhM
  • http://www.youtube.com/watch?v=m63k7UOMweA
  • http://visualstudiomagazine.com/articles/2013/11/01/when-to-build-fluent-interfaces-for-re-use-and-clarity.aspx

Github da konu hakkında kodladığım kod örnekleri yer alıyor , incelemenizi tavsiye ederim.

Bol kodlu günler dilerim 😀

1 comment

Yorum ekleyin

Bir Cevap Yazın