Aralık | 2017 | Peloton4
İlkeler ve Etik Kurallar
Decorator Design Pattern 27 Aralık 2017
Suite on HANA mı? S/4HANA mı? 16 Kasım 2017
Klasik ABAP, Object Oriented ABAP ve Design Patterns 30 Ekim 2017
OData Servisi Oluştururken Yapılan 10 Hata 15 Ekim 2017
PMI PMBOK6 (Body of Knowledge 6) 10 Ekim 2017
Peloton4 Nedir ve Neden Kuruldu? 16 Eylül 2017
Türkiye S/4HANA Anketi Sonuçları 14 Eylül 2017
S4 Hana Muhatap Migrasyon
S4HANA 1709 kullanıma açıldı mı?
Month / Aralık 2017
27 Aralık 2017 27 Aralık 2017 by Dr. Kerem Koseoglu
Bu makalede; sık kullanılan Design Pattern’lardan biri olan Decorator’ı tanıyacağız.
Bu Pattern, size SAP’nin BADI teknolojisi üzerinden tanıdık gelebilir. Şimdiye kadar BADI’lerin içine kod yazmış olabilirsiniz. Bu yazının sonunda, uygulamalarınızı BADI mantığında genişletebilir hale gelmenizi hedefliyoruz.
Bu makalede, aşağıdaki konulara aşina olduğunuz varsayılmaktadır.
Object Oriented ABAP tecrübesi
Interface ve Class kavramları
Decorator Design Pattern; aynı veri üzerinde birden fazla değişiklik yapılması gerektiği durumlarda kullanılır. Bu değişikliklerin tamamını ana programa veya merkezi bir sınıfa kodlamak yerine; dağınık haldeki mikro sınıflara kodlama prensibine dayanır.
Bu sayede; yeni bir kod eklemek gerektiğinde, test edilmiş eski kodlara herhangi bir şekilde dokunmadan yeni bir sınıf yazmak yeterli olmaktadır. Veya mevcut bir işlevi çıkarmak gerektiğinde, o işlevi barındıran sınıfı etkisiz hale getirmek yeterlidir.
Örnek Uygulama: User Exit
Decorator mantığını anlamak ve avantajlarını görmek için, tipik uygulama alanlarından biri olan User Exit örneğini inceleyeceğiz.
Aşağıdaki fonksiyonun bir User Exit olduğunu varsayalım.
!iv_bukrs TYPE bukrs
!iv_waers TYPE waers
!ct_data STRUCTURE ztt_data.
Bu User Exit içerisinde 3 ayrı iş yapılacağını düşünerek, konuyu irdelemeye başlayalım.
Klasik ABAP Uygulaması
Geleneksel ABAP anlayışında, ZXORNEK dosyası içerisinde bu 3 iş alt alta ve ayrı ayrı kodlanacaktır.
*& Include ZXORNEK
" Exit'te yapılacak 1. iş buraya kodlanır
" Exit'te yapılacak 2. iş buraya kodlanır
" Exit'te yapılacak 3. iş buraya kodlanır
Bu yaklaşımın pek çok sakıncası vardır; bunlardan bazılarını dile getirelim.
Bu Include içerisinde kodlar, ister istemez birbirini etkileyecektir. Örneğin üst satırlara yazılmış bir EXIT komutu, alt satırlarda çalışması gereken bir kodun hiç çalışmamasına yol açabilir.
ZXORNEK içerisine 4. bir ek yapıldığında, diğer 3 işe ait senaryoların da tekrar test edilmesi gerekir.
ZXORNEK üzerinde farklı ABAP’çılar paralel çalışamaz.
ZXORNEK altındaki farklı işler farklı Request’lere dahil edilip canlıya ayrı ayrı taşınamaz. Parçalı taşıma gerektiğinde, kodların yıldızlanıp taşınıp tekrar açılması gibi zahmetli ve riskli yaklaşımlar gerekir.
ZXORNEK’e kodlar eklendikçe, bu dosya zaman içerisinde uzun ve anlaşılması zor hale gelir, bakım maliyeti ve hata riski gittikçe artar.
Şimdi aynı uygulamayı Decorator Design Patern ile yapıp, bu dezavantajları ortadan nasıl kaldıracağımızı görelim.
Decorator Adım 1: Interface
Çözümümüzün ilk adımı, bu User Exit için bir Interface oluşturmaktır. SAPGUI üzerinde SE24 işlem koduna giderek veya Eclipse içerisinde New → ABAP Interface menüsünü kullanarak Interface tanımlayabiliriz.
INTERFACE zif_decorator PUBLIC.
!ct_data TYPE ztt_data.
DECORATE yordamındaki parametrelerin, User Exit parametreleri ile örtüştüğüne dikkat edin.
Basit olması açısından, Interface’imiz içerisinde; hata yönetimi gibi ek işlevleri devre dışı bıraktık.
Decorator Adım 2: Uygulama Sınıfları
Bu adımda, 3 farklı işi yapacak 3 bağımsız sınıf yazacağız. SAPGUI üzerinde SE24 işlem koduna giderek veya Eclipse içerisinde New → ABAP Class menüsünü kullanarak sınıf tanımlayabiliriz.
CLASS zcl_decorator01 DEFINITION
CLASS zcl_decorator01 IMPLEMENTATION.
FROM VALUE t_data( yabanci_kur = abap_true )
WHERE waers NE iv_waers.
Sınıf ZIF_DECORATOR Interface’ini uygulayıp, hayali tablomuzdaki YABANCI_KUR alanını doldurmuş olduk.
Interface’i uygulamamız, bu sınıfın ZIF_DECORATOR içerisinde geçen Method’ları barındırdığını sisteme garanti etmemiz anlamına geliyor. Sistemde ZIF_DECORATOR’u kullanacak şekilde yazılmış herhangi bir program, ZCL_DECORATOR01 sınıfının detaylarını bilmeye ihtiyaç duymadan bu sınıftan faydalanabilir. Zira; içerisinde DECORATE diye bir Method oluğu biliniyor.
Nasıl faydalanacağını birazdan göreceğiz.
Yine basit olması açısından, sınıf içerisindeki kodu basit tuttuk. Gerçek dünyada; bu sınıf içerisinde Type’lar, Private Method’lar, hata yönetimi, vb görmeyi beklerdik.
Aynı mantığı takip ederek, User Exit’te yapmamız gereken ikinci işi barındıran ikinci bir sınıf açıyoruz. Normalde bu sınıfların yapacağı işler daha karmaşık olacaktır, ancak örneği basit tutmak adına işleri de basit tutuyoruz.
CLASS zcl_decorator02 DEFINITION
CLASS zcl_decorator02 IMPLEMENTATION.
) eq abap_true.
MESSAGE e300(zfi) WITH iv_bukrs.
Dikkat ederseniz; bu sınıfta CHECK komutunu çekinmeden kullanabiliyoruz. CHECK, olsa olsa ZCL_DECORATOR02’den çıkmamız anlamına gelir. Diğer uygulama sınıflarını etkilemeyecektir.
Şimdi son sınıfımızı da kodlayalım.
CLASS zcl_decorator03 DEFINITION
CLASS zcl_decorator03 IMPLEMENTATION.
DELETE ct_data WHERE xflag EQ abap_false.
CHECK ct_data IS INITIAL.
Bu şekilde, basitleştirilmiş örnek sınıflarımızı tamamlamış oluyoruz. Elimizde bir Interface ve üç Class var.
Decorator Adım 3: User Exit Uygulaması
Bu son adımda; dağınık Lego parçaları gibi hazırladığımız bileşenleri User Exit içerisinde bir araya getireceğiz.
lo_decorator TYPE REF TO zif_decorator,
lo_object TYPE REF TO object.
" ZIF_DECORATOR Interface'ini uygulamış sınıfları tespit et
WHERE refclsname EQ 'ZIF_DECORATOR'
INTO TABLE @data(lt_class).
" Her bir sınıfa ait nesneyi dinamik yaratıp çalıştır
LOOP AT lt_class ASSIGNING FIELD-SYMBOL(<ls_class>).
CREATE OBJECT lo_object TYPE (<ls_class>-clsname).
lo_decorator ?= lo_object.
iv_bukrs = iv_bukrs
iv_waers = iv_waers
ct_data = ct_data
Gördüğünüz gibi; Exit’in yaptığı iş, ZIF_DECORATOR Interface’ini uygulayan sınıfları tespit edip çağırmaktan ibaret. Exit içerisinde fonksiyonel herhangi bir kod yok.
SEOMETAREL tablosundan ZCL_DECORATOR01 & 02 & 03 sınıflarına erişilecektir.
Loop’un ilk adımında, ZCL_DECORATOR01 içindeki DECORATE Method’u çalışacaktır.
Loop’un ikinci adımında, ZCL_DECORATOR02 içindeki DECORATE Method’u çalışacaktır.
Loop’un üçüncü adımında, ZCL_DECORATOR03 içindeki DECORATE Method’u çalışacaktır.
Inteface’i uygulayan sınıfları bulan kodu basit tutarak doğrudan SEOMETAREL tablosuna baktık. Bu basit kod, Abstract Class uygulandığı durumda sınıfları gözden kaçırabilir veya sınıfların sıralı çağırılması gereken durumda yeterli olmayabilir. Bu konudaki alternatif yaklaşımlar, örnek kodlarla birlikte Design Patterns in ABAP Objects adlı kitabımda var.
Bu yaklaşım, klasik ABAP yaklaşımının dezavantajlarını nasıl ortadan kaldırıyor, birer birer inceleyelim.
Kodlar birbirini etkilememektedir. Örneğin; ZCL_DECORATOR02 içerisindeki CHECK komutu, diğer sınıflarda yer alan kodların çalışmasını etkilememiştir.
ZCL_DECORATOR03’te bir değişiklik yaptığımızda, 01 ve 02’yi tekrar test etmemiz gerekmiyor.
3 farklı ABAP’çı, 3 farklı sınıf üzerinde paralel çalışabilir.
ZCL_DECORATOR01 canlıya giderken, ZCL_DECORATOR02 geliştirme sisteminde bekleyebilir.
Bu Exit’e ek yapmak için tek yapmamız gereken şey ZCL_DECORATOR04 diye yeni bir sınıf açmaktır. Kodlar basit ve modüler parçacıklar halinde olduğundan, değişiklik yönetimi kolaylaşmaktadır.
Yardımcı Diğer Pattern’lar
Sınıflar arasında veri paylaşma ihtiyacı ortaya çıkarsa, Decorator’a yardımcı Property Container Design Pattern uygulanabilir. Bu Pattern; her bir User Exit için ayrı bir Interface açma ihtiyacını ortadan kaldırıp, tüm User Exit’leri (SE19 benzeri) tek bir altyapıdan yönetmeyi de mümkün kılabilir.
Decorator sınıfları arasında, birbirine benzer iş yapan sınıfların işlevleri Template Method veya Servant uygulanarak ortaklaştırılabilir.
Sıralı çağırmak gibi basit ihtiyaçların ötesinde sınıfların koordine edilmesi gerekiyorsa, Mediator kullanılabilir.
Bahsetilen bu Pattern’ların tamamı, örnek uygulamalarla birlikte Design Patterns in ABAP Objects adlı kitabımda var.
Bu makalede, Decorator Design Pattern’i örnek User Exit uygulaması üzerinden incelemiş olduk. Design Pattern kullanmanın avantajlarını da kısmen gördük.
İncelediğimiz bu örnek Pattern’in geliştirmelerinizde faydalı olmasını ve diğer Pattern’leri öğrenmek konusunda sizi teşvik etmesini umuyorum.