Design Pattern Serisi 3: Pipeline

Temiz ve yalın kod yazmak yazılım dünyasında olmazsa olmaz şeylerin başında geliyor. Bunu sağlamak için bir çok yol var bizde bunlardan birine değineceğiz.

Bu yaklaşım birden fazla yerde kullanılıyor, örneğin ASP.NET Core üzerinde http istekleri bir pipeline (veri hattı) ile işlenmekte ve bu işlenme sırasında aralara iyi bir şekilde müdahale edilebilmektedir. Ayrıca, ML.NET’de bu yaklaşım üzerine kurulmuştur. Benim şahsi kanaatim, bu yapıyı birden fazla şekilde hayata geçirebilirsiniz, o yüzden doğaçlama yapmaktan çekinmeyin. Fazla sözü uzatmadan örneğimize geçelim.

Benim yapacağım örnekte yapı 3 farklı bölümden oluşmaktadır. Bunlardan ilki işlerin türeyeceği interface, işlerin daha kolay anlaşılmasını ve unit test yazarken bize kolaylık sağlayacak IPipeObject.

İçerisinde bulunan şeylere gelirsek, yapılacak işi Invoke methodu yapacak.Next ve NextPipe ise bir sonraki işe geçmemizde yardımcı olacak. Burada dikkat edilmesi gereken nokta Next ve Invoke methodlarının bir state objesi almış olduğu, bu obje sayesinde iki iş (pipe) arasında veri taşınmaktadır.

Bir diğeri ise, bu interface sınıfının bir parçasının implement’e edilmiş halinin bulunduğu PipeObject .

Bu sınıfta ise, bir sonra ki işi çağırmamızı sağlayacak olan Next methodunun uygulanışını yapıyoruz. Yukarıda dediğim gibi bu işi birden fazla şekilde yapabiliriz, örneğin Next methodunu kaldırıp, NextPipe üzerindende gidilip bir sonraki iş çağrılabilir.

Son ana sınıfımız ise, iş hattımızı başlatacak ve gerekli bilgileri barındıracak sınıf Pipeline.

Sınıf veri hattının başlangıç ve bitiş noktasını tutmakta, bunlar bizim bir sonraki işi, eklenen işe bağlarken yardımcı olacak. Append method’u eğer veri hattında hiç bir iş yoksa, veri hattının başlangıcını belirlemekte. Ve eğer, ikinci iş ve sonraki işler ekleniyorsa, kuyruk şeklinde işleri birbirine bağlamaktadır. _pipeEnd değişkeni sürekli en son eklenen işi işaret etmektedir. Bu şekilde eklenen tüm işler birbirine bağlanmaktadır. Start methodu ile birlikte de iş hattımızı bir değer ile başlatabilmekteyiz.

Ana hatlar tamamlandıysa, şimdi örnek bir veri hattı oluşturabiliriz. Örneğimiz girilen cümleyi belirli işlemlerden geçirerek ekrana yazdırmak olacak. Bunun için aşağıdaki grafiği inceleyebiliriz.

Örnek Pipeline 1

Aşamalar,

  • Küçük harflere çevir Lower

Lafı uzatmamak için bu işlerin hepsini tek gist’te göstereceğim,Invoke methodlarına bakarsak her yapılan iş çok basit ve temiz bir şekilde yapıldığını görebiliriz. Ayrıca,Next methodu ile birlikte veriyi bir sonraki veri hattına gönderiyoruz. Şimdi kodu çalıştırıp sonuçları görebiliriz.

Sonuç

Tests

Bu kadar gelmişken unit test yazmadan olmaz. Hemen xUnit üzerinden tüm sınıflarımız için testlerimizi yazıyoruz. Burada sadece önemli testleri göstereceğim.

Pipeline sınıfındaki Append methodu doğru çalışmasını kontrol etmemiz için yukarıdaki test’i yazıyoruz. Önceden de belirttiğim gibi interface bize unit test yazarken yardımcı olacak demiştim, 4 adet IPipeObject mock’luyoruz. Ve her birini Append ederek NextPipe değişkenlerinin birbirlerine ardışık olarak atanıp atanmadıklarını kontrol ediyorum. Buna ilaveten veri hattının başlangıç ve bitiş noktasını da kontrol ediyorum.

Asıl amacımız olan veri hattındaki işlerin testlerini test etmemiz mühim. Veri hattına giren ve çıkan veriyi kolayca kontrol edebilmekteyiz.

Yukarıda tanımlamış olduğumuz PipeObject lerin her birinin testini aşağıda görebilirsiniz.

Sonuç

Bu yapı ile birlikte daha temiz ve düzenli kod yazabilmenin bir yolunu göstermiş olduk. Yukarıdaki kodların proje haline aşağıdan erişebilirsiniz.

Referanslar

ITU. CE. LCWaikiki www.alimozdemir.com

ITU. CE. LCWaikiki www.alimozdemir.com