Yazılım geliştirme süreçlerinde sürekli karşılaşılan kronikleşmiş ve her yazılımcının başına gelen belli başlı sorunlar bulunmaktadır. Yazılım dili veya kullanılan teknoloji ne olursa olsun belli sorunlar ve uygulanması gereken algoritma yapıları her yazılım geliştirme süreci için aynı olabilir. Bu gibi durumlara karşı Design Pattern’ler geliştirilmiştir. Nesneye Yönelik Progamlama mimarisi içerisinde kullanılan bu pattern’ler ile kronikleşmiş sorunlara standart çözümler sunmaktadır. Ancak bu kalıpların dışına çıkılamaz ve sadece bu kalıplar kullanılacak diye bir kural yoktur. Her yazılımcı kendi tasarım kalıplarını oluşturabilir ve bunu diğer yazılımcılar ile paylaşarak ortak bir pattern ortaya koyabilir.
Bu yazıda, ABAP programlama dili içerisinde OOP mimarisiyle Singleton Design Pattern konusundan bahsedip küçük bir örnekle nasıl kullanılabileceğine dair değineceğim.
Singleton design pattern, bir yazılım geliştirme sürecinde belirli işlemleri tekrarlamak yerine OOP mimarisi ile yeniden kullanılabilir objeler ortaya koymak için kullanılmaktadır. Örneğin veritabanı üzerinden bir select işlemi ile tablo oluşturuyorsunuz. Bu tabloyu farklı yerlerde kullanmak istediğinizde oluşturduğunuz obje global bir nesne olduğundan dolayı ilk aldığınız instance değerini her şekilde aynı olmasını sunmaktadır. Tekrar tekrar veritabanı üzerinden select işlemi yapmanıza gerek kalmadan. İlk aldığınız tablo üzerindeki değerler korunarak istediğiniz işlemi yapmaya devam edebilirsiniz. Bunun en büyük avantajı aslında performansa yansımasıdır.
Singleton design pattern’ini ABAP ile nasıl kullanacağımıza dair örneğimize geçecek olursak…
Senaryomuz şu şekilde, ZDEMO_TABLE isminde bir tablomuz bulunmakta ve bu tabloda MATNR, WERKS, COST alanları bulunmakta. Yazacağımız programda WERKS değeri 1000 olanlar için COST değerini 5 ile çarpılmasını ve tablonun elemanlarının bu şekilde döndürülmesini istiyoruz. Ancak bu tabloyu bir kere aldıktan sonra ilerleyen kodlamalarda tekrar kullanmak istiyoruz. Bunun için Singleton design pattern metodunu düzenleyerek başlıyoruz.
ZCL_SINGLETON_DEMO isminde bir sınıf oluşturuyorum ve bu sınıf içerisinde kendi instance’ını alacak bir class-method tanımlıyoruz. Bu sınıfın implemantasyon kısmında eğer objemiz boşsa kendisini türetecek bir obje yaratarak return value olarak sunuyoruz. Metodlarımızda ise WERKS değerini programdan gelecek olan WERKS değerinin SET edildiği ve bu werks değerine göre zdemo_table işlemi için gerekli select işlemini belirleyerek return edeceğimiz tabloyu oluşturuyoruz. Get metodu ile bu tablonun ve içeriğindeki değerlerin WERKS’e göre set edilmiş halini döndürüyoruz.
CLASS ZCL_SINGLETON_DEMO DEFINITION PUBLIC CREATE PRIVATE . PUBLIC SECTION. CLASS-METHODS: GET_CLASS_INSTANCE RETURNING VALUE(RETURN_OBJECT) TYPE REF TO ZCL_SINGLETON_DEMO. METHODS: SET_V_WERKS IMPORTING IV_WERKS TYPE WERKS_D. METHODS: GET_V_WERKS RETURNING VALUE(RV_WERKS) TYPE ZDEMO_TY_TABLE. PRIVATE SECTION. CLASS-DATA: LOCAL_CLASS_OBJECT TYPE REF TO ZCL_SINGLETON_DEMO. DATA: V_WERKS TYPE WERKS_D. DATA : IT_DEMO_TABLE TYPE ZDEMO_TY_TABLE. ENDCLASS. CLASS ZCL_SINGLETON_DEMO IMPLEMENTATION. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Instance Private Method ZCL_SINGLETON_DEMO->GET_CLASS_INSTANCE * +-------------------------------------------------------------------------------------------------+ * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD GET_CLASS_INSTANCE. IF LOCAL_CLASS_OBJECT IS INITIAL. CREATE OBJECT LOCAL_CLASS_OBJECT. ENDIF. RETURN_OBJECT = LOCAL_CLASS_OBJECT. ENDMETHOD. "get_apps_instance * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_SINGLETON_DEMO->GET_V_WERKS * +-------------------------------------------------------------------------------------------------+ * | [<-()] RV_WERKS TYPE ZDEMO_TY_TABLE * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD GET_V_WERKS. RV_WERKS = ME->IT_DEMO_TABLE. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_SINGLETON_DEMO->SET_V_WERKS * +-------------------------------------------------------------------------------------------------+ * | [--->] IV_WERKS TYPE WERKS_D * +--------------------------------------------------------------------------------------</SIGNATURE> METHOD SET_V_WERKS. DATA : LT_DEMO_TABLE TYPE ZDEMO_TY_TABLE. SELECT * INTO CORRESPONDING FIELDS OF TABLE LT_DEMO_TABLE FROM ZDEMO_TABLE. FIELD-SYMBOLS : <WA_DEMO> TYPE ZDEMO_TABLE. LOOP AT LT_DEMO_TABLE ASSIGNING <WA_DEMO>. IF IV_WERKS EQ '1000'. <WA_DEMO>-COST = <WA_DEMO>-COST * 5. ELSEIF IV_WERKS EQ '1001'. <WA_DEMO>-COST = <WA_DEMO>-COST * 3. ELSEIF IV_WERKS EQ '2000'. <WA_DEMO>-COST = <WA_DEMO>-COST * 2. ENDIF. ENDLOOP. ME->IT_DEMO_TABLE = LT_DEMO_TABLE. ENDMETHOD. ENDCLASS.
Artık SET ettiğimiz werks değerine göre bize ZDEMO_TABLE tablosunu döndürecek olan Singleton Design Pattern’i hazır. Bu yapıyı program içerisinde kullanacağımız kısım ise aşağıdaki gibidir.
Aşağıda gröüldüğü üzere ilk olarak oluşturduğumuz sınıfa ait bir instance alıyoruz. Bu instance içerisinde yer alan SET_V_WERKS metoduna istediğimiz WERKS değerini belirliyoruz. Sonrasında bu WERKS değerine göre oluşturulan tablo GET_V_WERKS ile bize sunuluyor. Singleton konusu bu aşamadan sonraya devreye giriyor. Aynı sınıftan bir başka instance aldığımızda SET işlemini hiç devreye sokmadan direkt olarak sadece GET işlemini yaptığımızda aynı tablonun ilk instance içerisindeki WERKS değerine ait verilerden oluşan tablonun tekrar sunulduğunu göreceksiniz.
Bunun için select işlemini 2 kere yapmadık böylelikle tek seferde elimizde tuttuğumuz global objeyi istediğimiz şekilde set ederek get ile kullanabilmekteyiz.
REPORT Z_SINGLETON_DEMO. START-OF-SELECTION. DATA: LO_SINGLETON_CLASS TYPE REF TO ZCL_SINGLETON_DEMO. DATA: LV_RESULT TYPE ZDEMO_TY_TABLE. LO_SINGLETON_CLASS = ZCL_SINGLETON_DEMO=>GET_CLASS_INSTANCE( ). LO_APPLICATION->SET_V_WERKS( '1000' ). LV_RESULT = LO_APPLICATION->GET_V_WERKS( ). CLEAR LV_RESULT. DATA: LO_SINGLETON_CLASS_2 TYPE REF TO ZCL_SINGLETON_DEMO. LO_SINGLETON_CLASS_2 = ZCL_SINGLETON_DEMO=>GET_CLASS_INSTANCE( ). LV_RESULT = LO_2ND_APPS->GET_V_WERKS( ). CLEAR LV_RESULT.