analiz et, tasarla, hayata geçir



Web Servis ve Facade Birlikteliği

Halihazırda bir çok makale ve yazı web servislerin ne olduğu ve nasıl yazılması gerektiği üzerine durmaktadır. Bu sebepten ötürü yazımızda web servislerin tanımından ziyade, servisleri uygulamalarımıza nasıl implemente etmemiz gerektiği ve servis developmentının nasıl daha kolay yapılacağının üzerinde duracağız. Bu implementasyon sırasında bize facade ve az da olsa singleton tasarım desenleri yardımcı olacaktır. İsterseniz biz facade kalıbının ne olduğunu hatırlamaya çalışarak işe başlayalım;

Facade Tasarım Deseni

Facade deseni alt sistemlerin üst sistemler tarafından implemente olması sırasında yapılacak işlemlerin daha basit bir kullanımla ifade edilerek tekrar yazılmasıdır. Yani alt sistemlerin karmaşıklığı içerisinde kaybolmadan, sadece gerekli parametreleri baz alarak diğer sistemler için ideal bir kullanım ortamı sağlamak bu kalıbın temel işlevidir.

Peki bu pattern web servis tarafında nasıl bir fayda sağlar. Web servisler doğası gereği bizim sistemimize göre tasarlanmamış olup, kendisine has parametreleri alırlar ve geri döndürürler. Dolayısıyla bu arz-talep işlemini kolaylaştırmak ve ileride gerekecek modifikasyonların kolay yapılmasını sağlamak facade kalıbının görevidir. Facade deseninin yazılması sırasında web servislerin kullanımını sağlamak için ise bir ara sınıfa ihtiyacımız olur. Bu sınıf servis ile yapılacak tüm iletişimden sorumlu olup, servisin anladığı veri yapısını yazılımcının yani implemente eden uygulamanın anladığı veri yapısına çevirir. Bu veri yapısı bir sınıf, entity, dataset vs. olabilir.

Geriye bir tek soru geliyor o da bu sınıfın nerede olacağı. Servislerin kullanım amacı birden fazla uygulamaya hizmet vermek olduğundan ileriki bir tarihte bizim de ikinci bir uygulamamız bu servisi kullanmak isteyebilir. Dolayısıyla bu kıstas bize bariz bir şekilde şunu söylemektedir ki, servisler User Interface’e refere edilmez.
Servislerin refere edilmesi için en uygun yer iş katmanıdır.

Örneğimizde TC Kimlik No ile veri alış verişi yapan bir servisin olduğunu düşünelim. Bu servisteki bir metod kimlik no ve tarih alarak bize bu kimlik no ya ait verileri geri göndermektedir.

using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

public class Service : System.Web.Services.WebService
{
    public Service () {

    }

    [WebMethod]
    public string GetUserData(string identityNo, DateTime queryDate)
    {
        //Bu metod tckimlik no kullanarak kullanıcının
        //tüm bilgilerini geri döndürmektedir.
    }
}

Yukarıdaki servis hazır bir şekilde implemente edilmeyi beklemektedir. İş katmanına servis referans olarak eklendikten sonra solution da aşağıdaki gibi bir sonuç ortaya çıkar;

Şimdi bu iş katmanında ServiceManager adında bir sınıf yaratıp içerisinde servisi kullanmaya başlayalım.
Öncelikle static bir değişken içerisinde servisin bir örneğini saklayalım. Böylelikle her sorguda servisi yeniden örneklendirmemize gerek kalmayacak, örneklenmiş servisin kullanımı bu sınıf içerisinde daha kolay olacak ve ileriki tarihlerde servis tarafında yapılacak herhangi bir değişiklik (token gereksinimi vs…) tek bir yerden yapılacak bir değişiklik ile halledilebilecektir.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Business
{
    public static class ServiceManager
    {
        //Singleton Pattern
        private static MyService.Service currentMyService;
        private static MyService.Service CurrentMyService
        {
            get
            {
                if (currentMyService == null)
                {
                    currentMyService = new Business.MyService.Service();
                    //Servis değişiklikleri ileride buraya yazılabilir.
                }

                return currentMyService;
            }
        }
    }
}

Yukarıda hem sınıf hem de property static olarak tanımlanmıştır. Ayrıca servisin dışarıya açık olmayıp sadece bu sınıf içerisinde kullanılabilmesi için private anahtarı ile encapsulate edilmiştir. Bunun sebebi dışarıdaki sınıfların kullanımına servisin değil sadece metodların sunulacak olmasıdır.

Şimdi bu metodları yazmaya başlayalım. Kullandığımız servisin sadece bir adet metodu olduğundan bu sınıfın da yalnız bir adet metodu bulunacaktır. İstenildği taktirde tabiki overload metodlar yazılabilir, bu da facade tasarım deseninin sağladığı yararlardan bir diğeridir.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Business
{
    public static class ServiceManager
    {
        //Singleton Pattern
        private static MyService.Service currentMyService;
        private static MyService.Service CurrentMyService
        {
            get
            {
                if (currentMyService == null)
                {
                    currentMyService = new Business.MyService.Service();
                    //Servis değişiklikleri ileride buraya yazılabilir.
                }

                return currentMyService;
            }
        }

        public void GetPersonelInformation(PersonelEntity personelEntity)
        {
            //Normalde web servis bizden tc kimlik no beklemektedir
            //ve bu veri bizim sistemimizde personel entity sınıfı
            //içerisinde bulunmaktadır. Dolayısıyla bizim metodumuza
            //parametre olarak bu entity nin gönderilmesi yeterlidir.
            //Ayrıca servis bizden ikincil olarakta bir tarih değeri
            //istemektedir. Bu tarih değerini heryerde yazmak yerine
            //sadece buradaki merkezi metod içerisinde yazmak
            //bize yeterli olmaktadır.

            object data = CurrentMyService.GetUserData(personelEntity.Identity, DateTime.Now);

            //data döndükten sonra entity üzerinde istenilen
            //değişiklikler kolaylıkla yapılabilir.
        }
    }
}

Yukarıdaki şekilde tasarlanmış bir servis sınıfı facade patterni ile sadeleştirilmiştir. Artık bizim sistemimiz tarafından tckimlikNo gibi bir değer yerine personel entity sınıfı gönderilmektedir. Böylelikle sevis üzerinden gelen data ile birlikte bu entity sınıfı üzerinde değişiklikler yapılır ve referans değeri ile entity değişeceğinden bu değişiklikler tüm katmanlara (UI – DataAccess) yansır. Daha değişik bir senaryoda servise atılacak sorguların loglanması istenilebilir. Dolayısıyla da hangi personele, hangi kullanıcı tarafından sorgu gönderildiğinin loglanması tek tek tüm metod çağrılarında yazılmak yerine sadece burada yapılacak bir değişiklik ile sağlanmış olur.

Uygulama tarafında artık bize kalan iş katmanını referans olarak almak ve işlemlerimizi ServiceManager sınıfı üzerinden yürütmektir. Tabi ayrıca config ayarlarımızı iş katmanından, uygulama arayüzündeki config dosyasına kopyalamak gerekmektedir.

...


    
        
            
http://localhost:50828/MyWebService/Service.asmx

Buradaki section ve application settings ayarlarının uygulama tarafına kopyalanması gerekir.


	
		
			
				
http://localhost:50828/MyWebService/Service.asmx ...

Referans işlemi de tamamlandıktan sonra solution aşağıdaki gibi bir görünüme sahip olacaktır. Kod tarafında ise gayet basit bir kullanım yeterlidir.

PersonelEntity personel = new PersonelEntity();
personel.Identity = "123456789";

Business.ServiceManager.GetPersonelInformation(personel);

Umarım okuduklarınız faydalı olur ve kullandığınız servislerin implementasyonu sırasında doğacak hataların biraz önüne geçebilirsiniz. Herkese bol servisli projeler…



Yanıtla



SON YAZILARIM

ajax
UserControl, UpdatePanel ve RegisterPostBack Sorunu

ASP.NET AJAX ile gelen sorunlardan biri de UpdatePanel içerisinde bazı durumlarda ajax postback yerine full...

yazılım
Ofis Savaşları

IT'ciler ile satış takımı arasında hep bir anlaşmazlık vardır. Genelde satış takımının...

yazılım
Çevre Faktörü

Yazılım projelerinin en önemli süreci tabi ki geliştirme aşamasıdır. Uygulama yazılır, yazıldıkça...