Clean ABAP: Tam Türkçe Stil Kılavuzu

SAP Clean ABAP rehberinin eksiksiz Türkçe çevirisi — tüm kurallar, gerçek kod örnekleri ve uzman yorumlarıyla.

150+ Kural  |  Gerçek Kod Örnekleri  |  Uzman Yorumları
1

Nasıl Kullanılır

Genel Bakış

Bu kılavuz, Robert C. Martin'in Clean Code kitabının ABAP diline uyarlanmasıdır. Kod kalitesini artırmak isteyen her ABAP geliştiricisi için vazgeçilmez bir kaynaktır. Aşağıda bu kılavuzu nasıl kullanacağınızı, legacy kodu nasıl refactor edeceğinizi ve otomatik kontrolleri nasıl yapacağınızı bulabilirsiniz.

1.1 Clean Code'a Nasıl Başlanır Orijinal Kaynak

Clean Code'a yeni başlıyorsanız, önce Robert C. Martin'in Clean Code kitabını okumanızı tavsiye ederiz. Clean Code Developer girişimi konuya aşamalı ve didaktik bir giriş yapmanıza yardımcı olabilir.

Boolean'lar, Koşullar ve If İfadeleri gibi kolayca anlaşılan ve genel kabul gören konularla başlamanızı öneririz. En fazla faydayı Metodlar bölümünden göreceksiniz; özellikle "Bir şey yap, iyi yap, sadece onu yap" ve "Metodları küçük tut" kuralları kodunuzun genel yapısını büyük ölçüde iyileştirir.

Yorumlar, İsimler ve Biçimlendirme gibi daha tartışmalı konulara sonradan geçin; bu konular neredeyse dini tartışmalara yol açabilir ve yalnızca Clean Code'un olumlu etkilerini zaten görmüş ekipler tarafından ele alınmalıdır.

Uzman Yorumu: Başlangıç için en iyi yol, küçük adımlarla ilerlemektir. Her sprint'te bir ya da iki kural seçin ve ekibinizle birlikte o kurallara odaklanın. Bütün kuralları aynı anda uygulamaya çalışmak bunaltıcı olabilir.

Kaynağa Git

1.2 Legacy Kod Nasıl Refactor Edilir Orijinal Kaynak

Boolean'lar, Koşullar, If İfadeleri ve Metodlar bölümleri, çok fazla kodu değiştirmeden ya da değiştirmek istemediğiniz durumlarda bile yeni koda uygulanabildiği için legacy projelerinde en ödüllendirici olanlardır.

İsimler bölümü, eski ve yeni kod arasında bir uçurum oluşturabileceği için legacy projelerde çok zorlu olabilir. Kodlama öneklerinden kaçınma gibi bazı kurallar, legacy projelerde görmezden gelinmesi daha doğru olabilir.

Refactoring sırasında aynı geliştirme nesnesi içinde farklı geliştirme stillerini karıştırmamaya özen gösterin. Eğer legacy kod yalnızca ön bildirimler içeriyorsa ve inline bildirimlere tam geçiş yapılabilir değilse, iki stili karıştırmak yerine legacy stile bağlı kalmak daha iyi olabilir.

💡 Uzman Yorumu: Legacy kodu refactor ederken "boy haritası" yaklaşımını benimseyin: önce testleri yazın, sonra refactor edin. Bu sayede değişikliklerinizin mevcut davranışı bozmadığından emin olursunuz.

Kaynağa Git

1.3 Otomatik Nasıl Kontrol Edilir Orijinal Kaynak

SAP'nin ABAP Test Cockpit (ATC) bu kılavuzdaki kuralların büyük çoğunluğunu otomatik olarak kontrol edebilir. Clean Code kısıtlamalarını CI/CD pipeline'larınıza entegre etmek için bu araca başvurun. Code Inspector ve ATC araçlarını kullanarak otomatik kalite güvencesi sağlayabilirsiniz.

💡 Uzman Yorumu: ATC kontrollerini CI/CD pipeline'ınıza entegre edin ve her commit öncesinde otomatik kontrol yapın. Bu, kalite sorunlarını üretim ortamına ulaşmadan yakalamanın en etkili yoludur.

Kaynağa Git

1.4 Diğer Kılavuzlarla İlişki Orijinal Kaynak

Bu kılavuz, Robert C. Martin'in Clean Code'unu ABAP'a uyarlamasıdır ve ABAP Programlama Kılavuzu ile uyumludur. Bazı durumlarda bu kılavuz, resmi SAP kılavuzundan farklı öneriler sunabilir; bu durumlarda bu kılavuzda gerekçeler açıklanmaktadır. Ekibinizin tercihine bağlı olarak hangi kılavuzun öncelikli olduğuna karar verebilirsiniz.

💡 Uzman Yorumu: Birden fazla kılavuz kullanıyorsanız, hangisinin öncelikli olduğunu ekip içinde belirleyin ve bu kararı dokümante edin. Tutarsızlık, kılavuzların hiç olmamasından daha kötüdür.

Kaynağa Git

1.5 Nasıl İtiraz Edilir Orijinal Kaynak

Bu kılavuzdaki bazı önerilere katılmayabilirsiniz. Katılmıyorsanız, alternatif bir yaklaşım önerirken gerekçenizi açıklayın. SAP, bu kılavuzun topluluktan gelen önerilerle sürekli geliştiğini belirtmektedir. GitHub üzerinden issue açarak veya pull request göndererek katkıda bulunabilirsiniz.

💡 Uzman Yorumu: Eleştiri, gelişimin anahtarıdır. Bir kuralla aynı fikirde değilseniz, ekibinizle açık bir tartışma yapın. Sonunda takım olarak bir karara varın ve o karara bağlı kalın.

Kaynağa Git

2. İsimlendirmeler

2.1 Açıklayıcı İsimler Kullanın Orijinal Kaynak

İsimler, nesnenin ne olduğunu veya metodun ne yaptığını yansıtmalıdır. İsmin uzunluğundan çekinmeyin; okunabilirlik her şeyden önce gelir.

✓ İYİ KULLANIM
DATA(days_to_delivery) = calculate_delivery_date( order_key ).
METHODS read_customizing_entries
  IMPORTING
    customizing_id TYPE /clean/cust_id.
CLASS /clean/account_balance_calculator DEFINITION.
✗ KÖTÜ KULLANIM
DATA(d) = calc( k ).
METHODS read
  IMPORTING
    id TYPE /dirty/id.
CLASS /dirty/abc DEFINITION.

💡 Uzman Yorumu: "Eğer bir ismi açıklamak için yorum yazmanız gerekiyorsa, isim yeterince açıklayıcı değildir." Geliştirme ortamındaki otomatik tamamlama özelliği uzun isimler yazmanızı kolaylaştırır, bu nedenle kısalıktan yana olmaya gerek yoktur.

Kaynağa Git

2.2 Çözüm ve Problem Alanı Terimlerini Tercih Edin Orijinal Kaynak

Yazılım biliminin yerleşik terminolojisini (çözüm alanı terimleri) ve iş alanının terminolojisini (problem alanı terimleri) kullanın. Kendi icat ettiğiniz terimlerden kaçının.

✓ İYİ KULLANIM
CLASS /clean/iterator DEFINITION.       " çözüm alanı terimi
DATA delivery_note TYPE /clean/deliv.   " problem alanı terimi
✗ KÖTÜ KULLANIM
CLASS /dirty/my_helper DEFINITION.      " ne demek isteniyor?
DATA my_stuff TYPE /dirty/stuff.        " hangi iş kavramına karşılık geliyor?

💡 Uzman Yorumu: Takım olarak hem teknik hem de iş terminolojisini birleştiren bir sözlük oluşturun. Bu, yeni ekip üyelerinin hızla uyum sağlamasına yardımcı olur.

Kaynağa Git

2.3 Çoğul Kullanın Orijinal Kaynak

Koleksiyonları çoğul isimlerle adlandırın. Bu, bir değişkenin bir koleksiyon mu yoksa tek bir öğe mi içerdiğini hemen anlaşılır kılar.

✓ İYİ KULLANIM
DATA orders TYPE STANDARD TABLE OF order_type.
DATA messages TYPE STANDARD TABLE OF message_type.
LOOP AT orders INTO DATA(order).
✗ KÖTÜ KULLANIM
DATA order TYPE STANDARD TABLE OF order_type.  " tekil ama tablo
DATA message_list TYPE STANDARD TABLE OF message_type.  " gereksiz sonek

💡 Uzman Yorumu: Tablo değişkenlerini tekil formda adlandırmak yaygın bir hatadır. Döngü içinde tablo satırı için tekil, tablonun kendisi için çoğul kullanın.

Kaynağa Git

2.4 Telaffuz Edilebilir İsimler Kullanın Orijinal Kaynak

Kod incelemeleri veya tartışmalar sırasında yüksek sesle okuyabileceğiniz isimler kullanın. Telaffuz edilemeyen isimler iletişimi zorlaştırır.

✓ İYİ KULLANIM
DATA class_name TYPE seoclsname.
DATA order_quantity TYPE i.
✗ KÖTÜ KULLANIM
DATA cls_nm TYPE seoclsname.    " "cls nm" diye mi okunuyor?
DATA ord_qty TYPE i.            " kısaltmalar iletişimi zorlaştırır

💡 Uzman Yorumu: Kod incelemesi sırasında ismi yüksek sesle okuyun. Eğer kendinizi harfleri tek tek heceliyorken buluyorsanız, ismi değiştirmeniz gerekiyor demektir.

Kaynağa Git

2.5 snake_case Kullanın Orijinal Kaynak

Değişkenler ve metodlar için alt çizgi ile ayrılmış küçük harf kullanın (snake_case). ABAP büyük/küçük harf duyarsız olduğundan sınıf ve metod adlarında küçük harf tercih edilir.

✓ İYİ KULLANIM
DATA customer_name TYPE string.
METHODS read_customer_data.
CLASS /clean/customer_validator DEFINITION.
✗ KÖTÜ KULLANIM
DATA CustomerName TYPE string.   " CamelCase ABAP'a uygun değil
METHODS ReadCustomerData.        " ABAP geleneklerine aykırı

💡 Uzman Yorumu: ABAP topluluğu snake_case konusunda genel bir uzlaşıya varmıştır. Bu konvansiyona uymak, kodunuzun diğer ABAP geliştiricilerine tanıdık gelmesini sağlar.

Kaynağa Git

2.6 Kısaltmalardan Kaçının Orijinal Kaynak

Kısaltmalar, okuyucunun bunların ne anlama geldiğini bilmesini gerektirir. Tam isimler kullanmayı tercih edin.

✓ İYİ KULLANIM
DATA company_code TYPE bukrs.
DATA business_partner_number TYPE bu_partner.
METHODS calculate_delivery_date.
✗ KÖTÜ KULLANIM
DATA ccode TYPE bukrs.     " "ccode" ne demek? company code mu?
DATA bpnum TYPE bu_partner.
METHODS calc_del_dt.       " kısaltmalar anlamı gizler

💡 Uzman Yorumu: "Kısaltma kullanmak kodunuzu kısa yazmayı kolaylaştırır ama okumayı zorlaştırır." Kod çok daha fazla okunur, bu nedenle okuma kolaylığı yazma kolaylığından önce gelir.

Kaynağa Git

2.7 Her Yerde Aynı Kısaltmayı Kullanın Orijinal Kaynak

Kısaltma kullanmak zorundaysanız, ilgili kavram için her yerde aynı kısaltmayı kullanın. Bu, arama yapılabilirliği artırır ve kodu tahmin edilebilir kılar.

✓ İYİ KULLANIM
" "detection object type" her zaman "dobjt" olarak kısaltılır
DATA dobjt TYPE /clean/detection_object_type.
METHODS get_dobjt RETURNING VALUE(result) TYPE /clean/detection_object_type.
✗ KÖTÜ KULLANIM
" aynı kavram için farklı kısaltmalar
DATA dot TYPE /dirty/detection_object_type.
DATA dotype TYPE /dirty/detection_object_type.
DATA detobjtype TYPE /dirty/detection_object_type.

💡 Uzman Yorumu: Kısaltma sözlüğü oluşturun ve ekiple paylaşın. Bu, tutarsız kısaltmaların önüne geçer ve kodu aranabilir kılar.

Kaynağa Git

2.8 Sınıflar için İsim, Metodlar için Fiil Kullanın Orijinal Kaynak

Sınıflar ve arayüzler isimler veya isim öbekleriyle, metodlar ise fiiller veya fiil öbekleriyle adlandırılmalıdır. Boolean metodları "is_" veya "has_" ile başlatmak akıcı bir okunuş sağlar.

✓ İYİ KULLANIM
" Sınıflar - isimler
CLASS /clean/account DEFINITION.
CLASS /clean/user_preferences DEFINITION.
INTERFACE /clean/customizing_reader.

" Metodlar - fiiller
METHODS withdraw.
METHODS add_message.
METHODS read_entries.

" Boolean metodlar
IF is_empty( table ).
IF has_entries( orders ).
✗ KÖTÜ KULLANIM
CLASS /dirty/do_calculation DEFINITION.    " sınıf ama fiil
METHODS account.                           " metod ama isim

💡 Uzman Yorumu: Bu kural İngilizce dil bilgisini taklit eder: sınıflar "nesne", metodlar ise "eylem"dir. Bu ayrım kodu okurken akış hissini artırır.

Kaynağa Git

2.9 Gürültü Kelimelerden Kaçının Orijinal Kaynak

"data", "info", "object" gibi anlamsız ek sözcükleri atın ya da gerçekten değer katan özel bir isimle değiştirin.

✓ İYİ KULLANIM
account               " account_data yerine
alert                 " alert_object yerine
user_preferences      " user_info yerine
response_time_seconds " response_time_variable yerine
✗ KÖTÜ KULLANIM
account_data     " "data" gereksiz - zaten account bir veridir
alert_object     " "object" gereksiz - zaten nesne yönelimli kodda nesne
user_info        " "info" belirsiz - hangi bilgiler?

💡 Uzman Yorumu: "data", "info", "object", "manager", "handler" gibi sözcükler genellikle hiçbir anlam taşımaz. Bu sözcükleri isimden çıkardığınızda anlam değişmiyorsa, gereksizler demektir.

Kaynağa Git

2.10 Kavram Başına Bir Kelime Seçin Orijinal Kaynak

Bir kavram için bir terim seçin ve her yerde onu kullanın. Eş anlamlıları karıştırmak okuyucuyu aradaki farkı bulmaya çalışırken zaman kaybettirir.

✓ İYİ KULLANIM
METHODS read_this.
METHODS read_that.
METHODS read_those.
✗ KÖTÜ KULLANIM
METHODS read_this.
METHODS retrieve_that.    " read ile retrieve arasındaki fark nedir?
METHODS query_those.      " query neden farklı kullanılıyor?

💡 Uzman Yorumu: Eş anlamlılar okuyucuyu yanıltır. "Retrieve" ve "read" farklı terimler kullanılıyorsa okuyucu aralarında anlamlı bir fark olduğunu varsayar. Bu gereksiz bilişsel yük yaratır.

Kaynağa Git

2.11 Pattern İsimlerini Sadece Gerçekten Kullanıyorsanız Kullanın Orijinal Kaynak

Tasarım deseni isimlerini (Factory, Singleton, Facade, Composite, Decorator, Iterator, Observer, Strategy) yalnızca gerçekten o deseni uyguluyorsanız kullanın.

✓ İYİ KULLANIM
" Gerçekten Factory deseni uygulayan bir sınıf
CLASS /clean/customer_factory DEFINITION.
  CLASS-METHODS create_by_id
    IMPORTING customer_id TYPE kunnr
    RETURNING VALUE(result) TYPE REF TO /clean/customer.
ENDCLASS.
✗ KÖTÜ KULLANIM
" Factory deseni uygulamıyor ama ismi öyle
CLASS /dirty/file_factory DEFINITION.
  " Aslında sadece bir dosya okuyucusu
  METHODS read_file.
ENDCLASS.

💡 Uzman Yorumu: Tasarım deseni isimleri okuyucuya güçlü beklentiler yaratır. Bu beklentileri karşılamayan bir isim, okuyucuyu derinden yanıltır ve kodu anlamayı zorlaştırır.

Kaynağa Git

2.12 Kodlamalardan Kaçının Orijinal Kaynak

Tüm kodlama öneklerini (Macar notasyonu gibi) kaldırmanızı teşvik ediyoruz. Modern IDE'ler tür bilgisini görsel olarak gösterdiğinden bu önekler artık gereksizdir.

✓ İYİ KULLANIM
METHOD add_two_numbers.
  result = a + b.
ENDMETHOD.
✗ KÖTÜ KULLANIM
METHOD add_two_numbers.
  rv_result = iv_a + iv_b.    " iv_ = importing value, rv_ = returning value - gereksiz
ENDMETHOD.

💡 Uzman Yorumu: Macar notasyonu, IDE'lerin tür bilgisi gösteremediği dönemden kalmadır. Modern ABAP geliştirme araçları bu bilgiyi zaten gösteriyor; bu nedenle önekler yalnızca gürültü ekler.

Kaynağa Git

2.13 Yerleşik Fonksiyonları Gölgelemeyin Orijinal Kaynak

Yerleşik ABAP fonksiyonlarıyla aynı isimde metodlar tanımlamayın. Bu durum, metodların yerleşik fonksiyonların önüne geçmesine ve beklenmedik davranışlara yol açar.

✗ KÖTÜ KULLANIM - Yerleşik fonksiyonları gölgeleyen metodlar
METHODS lines RETURNING VALUE(result) TYPE i.        " lines() yerleşik fonksiyon
METHODS line_exists RETURNING VALUE(result) TYPE i.  " line_exists() yerleşik fonksiyon
CLASS-METHODS condense RETURNING VALUE(result) TYPE i.
CLASS-METHODS strlen RETURNING VALUE(result) TYPE i.

💡 Uzman Yorumu: condense(), lines(), line_exists(), strlen() gibi yerleşik fonksiyonlar ABAP'ta çok kullanılır. Bunlarla aynı isimde metodlar tanımlamak ciddi kafa karışıklığına yol açar.

Kaynağa Git

3. Dil

3.1 Legacy'i Göz Önünde Bulundurun Orijinal Kaynak

Daha eski ABAP sürümleri için kod yazıyorsanız, bu kılavuzdaki tavsiyeleri dikkatle uygulayın. Birçok öneri, eski ABAP sürümlerinde desteklenmeyen nispeten yeni sözdizimi ve yapıları kullanmaktadır. Desteklemeniz gereken en eski sürümde takip etmek istediğiniz kuralları doğrulayın.

💡 Uzman Yorumu: Clean Code'u bir bütün olarak reddetmeyin. Kuralların büyük çoğunluğu (isimlendirme, yorumlama gibi) her ABAP sürümünde çalışır. Yalnızca yeni sözdizimi gerektiren kuralları sürüm uyumluluğuna göre filtreleyin.

Kaynağa Git

3.2 Performansı Göz Önünde Bulundurun Orijinal Kaynak

Yüksek performanslı bileşenler yazıyorsanız bu kılavuzdaki tavsiyeleri dikkatle değerlendirin. Clean Code bazı şeyleri daha yavaş yapabilir (daha fazla metod çağrısı) veya daha fazla bellek tüketebilir.

Ancak belirsiz korkulara dayalı erken optimizasyon yapmamanızı şiddetle tavsiye ederiz. Tipik bir uygulamada çalışma süresinin büyük çoğunluğu kodun çok küçük bir bölümünde harcanır. Önce temiz, nesne yönelimli bir şekilde inşa edin, sonra bir performans ölçümü yapın. Yalnızca o zaman seçili kuralları atmak için gerçeğe dayalı bir karar alın.

💡 Uzman Yorumu: ABAP'ta çalışma süresinin büyük kısmı genellikle veritabanı işlemlerine harcanır. Metod çağrı maliyetleri nadiren darboğaz oluşturur. Profiler kullanmadan performans optimizasyonu yapmaya çalışmak kaynak israfıdır.

Kaynağa Git

3.3 Nesne Yönelimini Tercih Edin Orijinal Kaynak

Nesne yönelimli programlar (sınıflar, arayüzler) prosedürel koda (fonksiyonlar, programlar) kıyasla daha iyi segmentlere ayrılır ve daha kolay refactor edilip test edilebilir.

✓ İYİ KULLANIM
FUNCTION check_business_partner [...].
  DATA(validator) = NEW /clean/biz_partner_validator( ).
  result = validator->validate( business_partners ).
ENDFUNCTION.

💡 Uzman Yorumu: RFC veya transaction gibi prosedürel nesneler zorunlu olduğunda bile, gerçek işi yapacak sınıfları çağıran ince bir katman olarak kullanın. Bu, iş mantığını test edilebilir tutmanın en iyi yoludur.

Kaynağa Git

3.4 Fonksiyonel Dil Yapılarını Tercih Edin Orijinal Kaynak

Modern ABAP sözdizimi genellikle daha kısa ve modern programcılara daha doğal gelir.

✓ İYİ KULLANIM
DATA(variable) = 'A'.
DATA(uppercase) = to_upper( lowercase ).
index += 1.
DATA(object) = NEW /clean/my_class( ).
result = VALUE #( FOR row IN input ( row-text ) ).
DATA(line) = value_pairs[ name = 'A' ].
DATA(exists) = xsdbool( line_exists( value_pairs[ name = 'A' ] ) ).
✗ KÖTÜ KULLANIM
MOVE 'A' TO variable.
TRANSLATE lowercase TO UPPER CASE.
ADD 1 TO index.
CREATE OBJECT object TYPE /dirty/my_class.
LOOP AT input INTO DATA(row).
  INSERT row-text INTO TABLE result.
ENDLOOP.
READ TABLE value_pairs INTO DATA(line) WITH KEY name = 'A'.
READ TABLE value_pairs TRANSPORTING NO FIELDS WITH KEY name = 'A'.
DATA(exists) = xsdbool( sy-subrc = 0 ).

💡 Uzman Yorumu: Modern ABAP sözdizimi yalnızca daha kısa değil, aynı zamanda daha az hata yapmaya davetiye çıkarır. Örneğin VALUE # ile inline tanım, yerel değişken unutma riskini ortadan kaldırır.

Kaynağa Git

3.5 Eski Dil Öğelerinden Kaçının Orijinal Kaynak

ABAP sürümünüzü yükselttiğinizde, eski dil öğelerini kontrol edin ve bunları kullanmaktan kaçının. Yeni alternatifler genellikle okunabilirliği artırır ve daha modern programlama paradigmalarıyla çakışan tasarım çatışmalarını azaltır.

✓ İYİ KULLANIM - Modern sözdizimi (@-escaped host değişkenleri)
SELECT *
  FROM spfli
  WHERE carrid = @carrid AND
        connid = @connid
  INTO TABLE @itab.
✗ KÖTÜ KULLANIM - Eski sözdizimi (escape olmayan form)
SELECT *
  FROM spfli
  WHERE carrid = carrid AND
        connid = connid
  INTO TABLE itab.

💡 Uzman Yorumu: Eski sözdizimi, program değişkenleriyle veritabanı sütunlarını ayırt etmeyi zorlaştırır. Modern sözdizimi @-escape karakteriyle bu ayrımı açıkça gösterir.

Kaynağa Git

3.6 Tasarım Desenlerini Akıllıca Kullanın Orijinal Kaynak

Tasarım desenleri uygun olduğunda ve belirgin bir fayda sağladığında kullanın. Sırf kullanmış olmak için her yere tasarım desenleri uygulamayın.

💡 Uzman Yorumu: Tasarım desenleri araçtır, amaç değil. Bir probleminiz olduğunda çözüm olarak desene başvurun, yoksa gereksiz karmaşıklık yaratırsınız. "Her problem için bir tasarım deseni aramak" anti-pattern'ın kendisidir.

Kaynağa Git

4. Sabitler

4.1 Magic Number Yerine Sabit Kullanın Orijinal Kaynak

Anlamsız sayısal değerler veya metinler yerine adlandırılmış sabitler kullanın. Bu, kodun ne anlama geldiğini okuyucuya açıklar.

✓ İYİ KULLANIM
IF abap_type = cl_abap_typedescr=>typekind_date.
  " Tip, tarih tipi mi diye kontrol edilir - anlam açık
ENDIF.
✗ KÖTÜ KULLANIM
IF abap_type = 'D'.    " 'D' ne demek? Neden 'D'?
ENDIF.

💡 Uzman Yorumu: "Magic number" terimi, kodda sihirli gibi görünen anlamsız sayıları tanımlar. Bu sayıları sabit olarak adlandırmak, hem anlamı açıklar hem de tek bir yerde değiştirme imkânı sağlar.

Kaynağa Git

4.2 Sabitler de Açıklayıcı İsme İhtiyaç Duyar Orijinal Kaynak

ABAP'ta her literal'i bir sabit içine sarmak yaygın bir eğilimdir, ancak çoğu zaman isimler yalnızca içerikleri veya tipleri tekrar eder. Sabitin içeriğini değil, anlamını yansıtın.

✓ İYİ KULLANIM
CONSTANTS status_inactive TYPE mmsta VALUE '90'.
CONSTANTS status_cancelled TYPE sww_wistat VALUE 'CANCELLED'.
✗ KÖTÜ KULLANIM
CONSTANTS:
  c_01    TYPE spart VALUE '01',    " c_01 ne anlama geliyor?
  c_mmsta TYPE mmsta VALUE '90'.    " sadece tipi tekrar ediyor

💡 Uzman Yorumu: Sabitler kodu açıklamalıdır, sadece değerini saklamamalıdır. "c_01" veya "c_90" gibi isimler hiçbir anlam katmaz. "status_inactive" ise hem değeri saklar hem de anlamını aktarır.

Kaynağa Git

4.3 ENUM Tercih Edin Orijinal Kaynak

ABAP'ın yerel ENUM yapısını kullanın (7.51 ve üzeri sürümlerde kullanılabilir). Sabit arayüzlerin karışık yapısından kaçının.

✓ İYİ KULLANIM
CLASS /clean/message_severity DEFINITION PUBLIC ABSTRACT FINAL.
  PUBLIC SECTION.
    TYPES: BEGIN OF ENUM type,
             warning,
             error,
           END OF ENUM type.
ENDCLASS.
✗ KÖTÜ KULLANIM
INTERFACE /dirty/common_constants.
  CONSTANTS:
    warning      TYPE symsgty VALUE 'W',
    transitional TYPE i       VALUE 1,
    error        TYPE symsgty VALUE 'E',
    persisted    TYPE i       VALUE 2.  " ilgisiz sabitler karıştırılmış
ENDINTERFACE.

💡 Uzman Yorumu: ENUM kullanmak, tip güvenliği sağlar ve yanlış değer atamalarını derleme zamanında yakalar. Sabit arayüzlerden farklı olarak, ENUM değerleri birbiriyle ilişkili olduğunu açıkça belirtir.

Kaynağa Git

4.4 Sabitleri Gruplandırın Orijinal Kaynak

ENUM kullanamıyorsanız ve sabitleri bir arayüzde toplamanız gerekiyorsa, en azından onları gruplayın. Bu, ilişkiyi daha net ortaya koyar.

✓ İYİ KULLANIM
CONSTANTS:
  BEGIN OF message_severity,
    warning TYPE symsgty VALUE 'W',
    error   TYPE symsgty VALUE 'E',
  END OF message_severity,
  BEGIN OF message_lifespan,
    transitional TYPE i VALUE 1,
    persisted    TYPE i VALUE 2,
  END OF message_lifespan.
✗ KÖTÜ KULLANIM
CONSTANTS:
  warning      TYPE symsgty VALUE 'W',
  transitional TYPE i       VALUE 1,    " ilgisiz sabitler karışık
  error        TYPE symsgty VALUE 'E',
  persisted    TYPE i       VALUE 2.

💡 Uzman Yorumu: Gruplandırma, sabitlerin birbirleriyle ilişkisini görsel olarak ifade eder ve grup üzerinden döngü ile erişim gibi ek özellikler kazandırır.

Kaynağa Git

5. Değişkenler

5.1 Inline Bildirimi Tercih Edin Orijinal Kaynak

Bu kılavuzu takip ederseniz metodlarınız çok kısa olacak (3-5 ifade) ve değişkenleri ilk kullanımlarında inline olarak bildirmek daha doğal görünecektir.

✓ İYİ KULLANIM
METHOD do_something.
  DATA(name) = 'something'.
  DATA(reader) = /clean/reader=>get_instance_for( name ).
  result = reader->read_it( ).
ENDMETHOD.
✗ KÖTÜ KULLANIM
METHOD do_something.
  DATA:
    name   TYPE seoclsname,
    reader TYPE REF TO /dirty/reader.
  name = 'something'.
  reader = /dirty/reader=>get_instance_for( name ).
  result = reader->read_it( ).
ENDMETHOD.

💡 Uzman Yorumu: Inline bildirim, değişkeni kullanım noktasına yakın tutar. Bu, okuyucunun değişkenin ne olduğunu anlamak için yukarı kaydırmasını önler ve kodun anlaşılmasını kolaylaştırır.

Kaynağa Git

5.2 Bildirim Bloğu Dışında Kullanmayın Orijinal Kaynak

Bir ifade bloğunda (IF veya LOOP bloğu gibi) bildirilen bir değişken, bu bloğun dışında da kullanılabilir olsa da bunu yapmayın. Bu durum okuyucuyu yanıltır.

✓ İYİ KULLANIM
DATA value TYPE i.
IF has_entries = abap_true.
  value = 1.
ELSE.
  value = 2.
ENDIF.
✗ KÖTÜ KULLANIM
IF has_entries = abap_true.
  DATA(value) = 1.    " IF bloğunda bildiriliyor
ELSE.
  value = 2.          " ama dışarıda kullanılıyor - kafa karıştırıcı
ENDIF.

💡 Uzman Yorumu: ABAP'ta bir blok içinde DATA() ile bildirilen değişken o blok sona erdikten sonra da var olmaya devam eder. Bu Java veya C# gibi dillerin aksine bir davranıştır ve istemeden kötüye kullanıma yol açabilir.

Kaynağa Git

5.3 Önceden Bildirimleri Zincirlemeyin Orijinal Kaynak

Zincirleme, tanımlanan değişkenlerin mantıksal düzeyde ilişkili olduğunu ima eder. Bu, gereksiz yere reformatlamayı ve refactoring'i karmaşıklaştırır.

✓ İYİ KULLANIM
DATA name TYPE seoclsname.
DATA reader TYPE REF TO reader.
✗ KÖTÜ KULLANIM
DATA:
  name   TYPE seoclsname,
  reader TYPE REF TO reader.    " zincirleme gereksiz karmaşıklık ekler

💡 Uzman Yorumu: DATA: zincirleme sözdizimi refactoring sırasında çok sorun yaratır. Bir satır eklediğinizde veya çıkardığınızda nokta, virgül ve iki nokta üst üstelerle uğraşmak zorunda kalırsınız. Ayrı DATA ifadeleri çok daha temizdir.

Kaynağa Git

5.4 Alan Sembolleri için Dinamik Veri Erişimi Kullanmayın Orijinal Kaynak

ABAP Platform 2021'den itibaren, genel tipli değişkenlere erişmek veya bir değişkenin bileşenlerine dinamik erişim sağlamak için alan sembolü kullanılması gereken yerler neredeyse kalmamıştır.

✓ İYİ KULLANIM
result = dref->*.
✗ KÖTÜ KULLANIM
ASSIGN dref->* TO <fs>.
result = <fs>.    " gereksiz alan sembolü

💡 Uzman Yorumu: Alan sembolleri güçlü ama tehlikeli araçlardır. Modern ABAP sözdizimi genellikle daha güvenli alternatifler sunar. Referans değişkenleri ve doğrudan erişim operatörleri çoğu durumda alan sembollerinin yerini alabilir.

Kaynağa Git

5.5 Döngüler için Doğru Hedef Seçin Orijinal Kaynak

ABAP döngüsü için üç hedef seçeneği vardır: alan sembolü, referans değişkeni veya düz veri nesnesi. Her birinin farklı amaçları vardır.

✓ İYİ KULLANIM
" Veriyi okumak veya değiştirmek için alan sembolü
LOOP AT table ASSIGNING FIELD-SYMBOL(<line>).
  obj->do_something( <line> ).
ENDLOOP.

" Referansa döngü dışında erişmek için referans değişkeni
LOOP AT table REFERENCE INTO DATA(line).
  obj->do_something( line->* ).
ENDLOOP.

💡 Uzman Yorumu: Alan sembolleri (FIELD-SYMBOL) tablo satırını doğrudan değiştirmek için idealdir. Referans değişkenleri ise nesne yönelimli ABAP'ın genel desenine uygundur ve döngü dışında kullanılabilir.

Kaynağa Git

6. Tablolar

6.1 Doğru Tablo Tipini Kullanın Orijinal Kaynak

Tablo tipini kullanım durumuna göre seçin:

  • HASHED tablolar: Tek seferde doldurulan, hiç değiştirilmeyen ve anahtarıyla sık okunan büyük tablolar için kullanın. Hash tabloların belirgin değeri yalnızca büyük veri miktarları ve çok sayıda okuma erişiminde ortaya çıkar.
  • SORTED tablolar: Her zaman sıralı tutulması gereken, parça parça doldurulan veya değiştirilen ve bir veya daha fazla tam veya kısmi anahtarla sık okunan büyük tablolar için kullanın.
  • STANDARD tablolar: İndekslemenin ek yük yarattığı küçük tablolar ve sıra önemsiz "dizi" benzeri tablolar için kullanın.

💡 Uzman Yorumu: Yanlış tablo tipi seçimi önemli performans sorunlarına yol açabilir. Tablonuzun boyutuna ve erişim desenine bağlı olarak doğru seçim yapın. SORTED tablo, binary search otomatik uygular; STANDARD tabloda manuel SORT ve BINARY SEARCH yapmanız gerekir.

Kaynağa Git

6.2 DEFAULT KEY'den Kaçının Orijinal Kaynak

DEFAULT KEY genellikle yalnızca daha yeni fonksiyonel ifadelerin çalışmasını sağlamak için eklenir. Anahtar bileşenlerini açıkça belirtin ya da anahtara gerek yoksa EMPTY KEY kullanın.

✓ İYİ KULLANIM
DATA itab2 TYPE STANDARD TABLE OF row_type WITH NON-UNIQUE KEY comp1 comp2.
DATA itab1 TYPE STANDARD TABLE OF row_type WITH EMPTY KEY.
✗ KÖTÜ KULLANIM
DATA itab TYPE STANDARD TABLE OF row_type WITH DEFAULT KEY.
" DEFAULT KEY sayısal veri tiplerini yoksayar ve beklenmedik sonuçlara yol açar

💡 Uzman Yorumu: DEFAULT KEY ile SORT veya DELETE ADJACENT kullanmak, özellikle sayısal alanlar içerdiğinde tahmin edilemez sonuçlar üretir. Her zaman anahtar bileşenlerini açıkça belirtin.

Kaynağa Git

6.3 INSERT INTO TABLE Tercih Edin Orijinal Kaynak

INSERT INTO TABLE tüm tablo ve anahtar tipleriyle çalışır ve tablo tipini daha kolay değiştirmenizi sağlar. Yalnızca STANDARD tabloyu dizi gibi kullanıyorsanız APPEND TO kullanın.

✓ İYİ KULLANIM
INSERT VALUE #( ... ) INTO TABLE itab.
✗ KÖTÜ KULLANIM
APPEND VALUE #( ... ) TO itab.    " yalnızca STANDARD tablo için uygundur

💡 Uzman Yorumu: INSERT INTO TABLE tabloyu SORTED veya HASHED'e dönüştürdüğünüzde otomatik olarak doğru davranışı sergiler. APPEND TO ise yalnızca STANDARD tablolarda çalışır ve refactoring'i zorlaştırır.

Kaynağa Git

6.4 LINE_EXISTS Tercih Edin Orijinal Kaynak

Bir satırın varlığını kontrol etmek için line_exists() kullanın. Bu, amacı daha açık ve kısa ifade eder.

✓ İYİ KULLANIM
IF line_exists( my_table[ key = 'A' ] ).
✗ KÖTÜ KULLANIM
READ TABLE my_table TRANSPORTING NO FIELDS WITH KEY key = 'A'.
IF sy-subrc = 0.    " sy-subrc kontrolü amacı gizler

LOOP AT my_table REFERENCE INTO DATA(line) WHERE key = 'A'.
  line_exists = abap_true.
  EXIT.
ENDLOOP.            " çok daha fazla kod, aynı amaç

💡 Uzman Yorumu: line_exists() birkaç satırlık kodu tek satıra indirgeyerek kodu çok daha okunabilir kılar. Amacı da açıkça belirtir: "bu satır var mı?"

Kaynağa Git

6.5 READ TABLE Tercih Edin Orijinal Kaynak

Tek bir satıra erişmek için READ TABLE kullanın, LOOP AT değil. READ TABLE amacı daha açık ifade eder ve daha kısadır.

✓ İYİ KULLANIM
READ TABLE my_table REFERENCE INTO DATA(line) WITH KEY key = 'A'.
✗ KÖTÜ KULLANIM
LOOP AT my_table REFERENCE INTO DATA(line) WHERE key = 'A'.
  EXIT.                " tek satır için LOOP gereksiz karmaşıklık
ENDLOOP.

💡 Uzman Yorumu: Modern tablo erişim sözdizimi (my_table[ key = 'A' ]) daha da kısadır. Satırın var olmama ihtimali varsa OPTIONAL anahtar sözcüğünü ya da TRY/CATCH bloğunu kullanın.

Kaynağa Git

6.6 LOOP AT WHERE Tercih Edin Orijinal Kaynak

LOOP AT WHERE kullanmak, döngü içinde iç içe IF kullanmaktan daha açık ve kısadır.

✓ İYİ KULLANIM
LOOP AT my_table REFERENCE INTO DATA(line) WHERE key = 'A'.
  " yalnızca key = 'A' satırları işlenir
ENDLOOP.
✗ KÖTÜ KULLANIM
LOOP AT my_table REFERENCE INTO DATA(line).
  IF line->key = 'A'.           " WHERE koşulu döngüde tekrar yazılmış
    " işlem yap
  ENDIF.
ENDLOOP.

💡 Uzman Yorumu: LOOP AT WHERE sözdizimi hem daha okunabilir hem de bazı durumlarda daha performanslıdır. SORTED tablolarda WHERE koşullu LOOP, binary search kullanarak belirli satırlara doğrudan erişir.

Kaynağa Git

6.7 Gereksiz Tablo Okumalarından Kaçının Orijinal Kaynak

Bir satırın orada olmasını bekliyorsanız, bir kez okuyun ve exception'a tepki verin. Çift okumadan kaçının.

✓ İYİ KULLANIM
TRY.
    DATA(row) = my_table[ key = input ].
  CATCH cx_sy_itab_line_not_found.
    RAISE EXCEPTION NEW /clean/my_data_not_found( ).
ENDTRY.
✗ KÖTÜ KULLANIM
IF NOT line_exists( my_table[ key = input ] ).   " birinci okuma
  RAISE EXCEPTION NEW /clean/my_data_not_found( ).
ENDIF.
DATA(row) = my_table[ key = input ].             " ikinci okuma - gereksiz

💡 Uzman Yorumu: Çift okuma hem performans açısından kötüdür hem de kod karmaşıklığını artırır. TRY/CATCH yaklaşımı hem daha temiz hem de daha verimlidir.

Kaynağa Git

7. Dizgiler

7.1 Backtick ile Literal Tanımlayın Orijinal Kaynak

String literal tanımlamak için tek tırnak yerine backtick (`) kullanın. Tek tırnak gereksiz tip dönüşümüne ve okuyucunun CHAR mı STRING mi kullandığını merak etmesine yol açar.

✓ İYİ KULLANIM
CONSTANTS some_constant TYPE string VALUE `ABC`.
DATA(some_string) = `ABC`.  " --> TYPE string kesin
✗ KÖTÜ KULLANIM
DATA some_string TYPE string.
some_string = 'ABC'.    " tek tırnak: CHAR mı STRING mi? gereksiz dönüşüm
DATA(some_string2) = |ABC|.  " sabit değer için | gereksiz yük ekler

💡 Uzman Yorumu: Backtick her zaman STRING tipini üretir. Tek tırnak ise CHAR üretir ve string değişkenine atandığında implicit dönüşüm gerektirir. Bu küçük fark bazen beklenmedik davranışlara yol açabilir.

Kaynağa Git

7.2 | ile Metin Birleştirin Orijinal Kaynak

Birden fazla parçayı birleştirirken string şablonları (| |) kullanın. Bu, sabit metnin nerede bitip değişkenin nerede başladığını çok daha belirgin kılar.

✓ İYİ KULLANIM
DATA(message) = |Received HTTP code { status_code } with message { text }|.
✗ KÖTÜ KULLANIM
DATA(message) = `Received an unexpected HTTP ` && status_code && ` with message ` && text.
" && ile birleştirme okunması zor, değişkenleri ayırt etmek güç

💡 Uzman Yorumu: String şablonları yalnızca birleştirme için değil, biçimlendirme için de kullanılabilir. { variable ALPHA = IN }, { variable DATE = USER } gibi biçimlendirme seçenekleri ek güç sağlar.

Kaynağa Git

8. Boolean'lar

8.1 Boolean'ları Akıllıca Kullanın Orijinal Kaynak

Boolean'lar doğal bir seçim gibi görünse de, genellikle bir numaralandırma kullanmak daha iyi olur. Boolean'lar, biri veya diğeri dışında durumların ortaya çıkacağı durumlarda kötü bir seçimdir.

✓ İYİ KULLANIM
archiving_status = /clean/archivation_status=>archiving_in_process.
" Enum, ara durumları açıkça temsil edebilir
✗ KÖTÜ KULLANIM
is_archived = abap_true.
" Ya "kısmen arşivlendi" durumu? Boolean bunu ifade edemez

💡 Uzman Yorumu: Boolean'lar genellikle "şu an için yeterli" görünür ama iş gereksinimleri büyüdükçe yetersiz kalır. Baştan enum kullanmak uzun vadede daha iyi bir tasarım sağlar.

Kaynağa Git

8.2 ABAP_BOOL Kullanın Orijinal Kaynak

Boolean değişkenler için abap_bool tipini kullanın. Genel char1 tipinden kaçının; bu tip, Boolean değişkenle karşı karşıya olduğumuzu gizler.

✓ İYİ KULLANIM
DATA has_entries TYPE abap_bool.
✗ KÖTÜ KULLANIM
DATA has_entries TYPE char1.         " Boolean olduğu belli değil
DATA has_entries TYPE boolean.       " üçüncü "undefined" değeri sorun yaratır

💡 Uzman Yorumu: ABAP, evrensel bir Boolean tipiyle gelmez. abap_bool, type pool'da tanımlanmış olan standarttır. DynPro alanları için abap_boolean kullanın.

Kaynağa Git

8.3 ABAP_TRUE ve ABAP_FALSE Kullanın Orijinal Kaynak

Boolean karşılaştırmaları için abap_true ve abap_false sabitlerini kullanın. 'X' ve ' ' (space) gibi karakter eşdeğerlerinden kaçının.

✓ İYİ KULLANIM
has_entries = abap_true.
IF has_entries = abap_false.
  " açık ve anlaşılır
ENDIF.
✗ KÖTÜ KULLANIM
has_entries = 'X'.           " 'X' Boolean olduğunu gizler
IF has_entries = space.      " space: false demek - açık değil
IF has_entries IS NOT INITIAL.  " INITIAL mi false anlamına geliyor?

💡 Uzman Yorumu: abap_true ve abap_false kullanmak, Boolean ifadeyi açıkça ortaya koyar. Okuyucu 'X' yerine abap_true gördüğünde hemen Boolean ile karşı karşıya olduğunu anlar.

Kaynağa Git

8.4 XSDBOOL Kullanın Orijinal Kaynak

Boolean değişkenleri ayarlamak için xsdbool() kullanın. Uzun IF-THEN-ELSE bloklarının yerini alır.

✓ İYİ KULLANIM
DATA(has_entries) = xsdbool( line IS NOT INITIAL ).
DATA(has_entries2) = COND abap_bool( WHEN line IS NOT INITIAL THEN abap_true ).
✗ KÖTÜ KULLANIM
IF line IS INITIAL.
  has_entries = abap_false.
ELSE.
  has_entries = abap_true.    " 5 satır yerine 1 satır yeterli
ENDIF.

💡 Uzman Yorumu: xsdbool() doğrudan char1 üretir, bu nedenle abap_bool tipiyle mükemmel uyum sağlar. boolc() ve boolx() farklı tipler üretir ve implicit tip dönüşümü gerektirir.

Kaynağa Git

9. Koşullar

9.1 Koşulları Pozitif Yapın Orijinal Kaynak

Koşulları mümkün olduğunda pozitif formda yazın. Olumsuz koşullar okuyucunun zihinsel olarak tersine çevirmesini gerektirir.

✓ İYİ KULLANIM
IF has_entries = abap_true.
  " açık ve doğal okuma akışı
ENDIF.
✗ KÖTÜ KULLANIM
IF has_no_entries = abap_false.
  " çifte olumsuzlama - zihinsel çaba gerektirir
ENDIF.

💡 Uzman Yorumu: "Çifte olumsuzlama" anlamayı önemli ölçüde zorlaştırır. "IF NOT has_no_entries" gibi ifadeler bir an için duraksamanıza neden olur. Pozitif koşullar beyin için daha doğaldır.

Kaynağa Git

9.2 IS NOT Tercih Edin Orijinal Kaynak

NOT IS yerine IS NOT tercih edin. Olumsuzlama, koşulun tam ortasına değil, doğal bir yere yerleşmelidir.

✓ İYİ KULLANIM
IF variable IS NOT INITIAL.
IF variable NP 'TODO*'.
IF variable <> 42.
✗ KÖTÜ KULLANIM
IF NOT variable IS INITIAL.    " NOT en sona yerleştirilmeli
IF NOT variable CP 'TODO*'.
IF NOT variable = 42.

💡 Uzman Yorumu: "NOT IS" yerine "IS NOT" kullanmak, olumsuzlamayı daha doğal bir konuma taşır ve koşulu okurken daha az zihinsel çaba gerektirir.

Kaynağa Git

9.3 Yüklemsel Metod Çağrısı Düşünün Orijinal Kaynak

Boolean metodlar için yüklemsel metod çağrısı kullanın. Bu, kodu doğal dile daha yakın kılar.

✓ İYİ KULLANIM
IF condition_is_fulfilled( ).
IF NOT condition_is_fulfilled( ).
✗ KÖTÜ KULLANIM
IF condition_is_fulfilled( ) = abap_true.
IF condition_is_fulfilled( ) = abap_false.    " karşılaştırma gereksiz

💡 Uzman Yorumu: Yüklemsel metod çağrısı (meth()) tam olarak meth() IS NOT INITIAL'ın kısaltmasıdır. Yalnızca başlangıç değeri "false", başlangıç dışı değeri "true" anlamına gelen metodlarda kullanın.

Kaynağa Git

9.4 Karmaşık Koşulları Parçalayın Orijinal Kaynak

Karmaşık koşulları parçalara bölerek ara değişkenlere atayın. Bu, her bölümün ne anlama geldiğini açıklamayı kolaylaştırır.

✓ İYİ KULLANIM
DATA(example_provided) = xsdbool( example_a IS NOT INITIAL OR
                                  example_b IS NOT INITIAL ).

DATA(one_example_fits) = xsdbool( applies( example_a ) = abap_true OR
                                  applies( example_b ) = abap_true OR
                                  fits( example_b ) = abap_true ).

IF example_provided = abap_true AND
   one_example_fits = abap_true.
✗ KÖTÜ KULLANIM
IF ( example_a IS NOT INITIAL OR
     example_b IS NOT INITIAL ) AND
   ( applies( example_a ) = abap_true OR
     applies( example_b ) = abap_true OR
     fits( example_b ) = abap_true ).  " tek IF'te çok fazla mantık

💡 Uzman Yorumu: Karmaşık koşulları adlandırılmış değişkenlere bölmek, her parçanın ne anlama geldiğini belgelemenize olanak tanır. ABAP Development Tools'un hızlı düzeltme özelliğiyle bunu otomatik yapabilirsiniz.

Kaynağa Git

9.5 Karmaşık Koşulları Ayıklayın Orijinal Kaynak

Karmaşık koşulları ayrı metodlara çıkarmak neredeyse her zaman iyi bir fikirdir.

✓ İYİ KULLANIM
IF is_provided( example ).

METHOD is_provided.
  DATA(is_filled) = xsdbool( example IS NOT INITIAL ).
  DATA(is_working) = xsdbool( applies( example ) = abap_true OR
                              fits( example ) = abap_true ).
  result = xsdbool( is_filled = abap_true AND
                    is_working = abap_true ).
ENDMETHOD.

💡 Uzman Yorumu: Karmaşık bir koşulu ayrı bir metodda toplamak, o koşulun mantığını izole eder ve bağımsız olarak test edilmesini sağlar. Ayrıca metodun okunabilirliğini büyük ölçüde artırır.

Kaynağa Git

10. If İfadeleri

10.1 Boş IF Dalları Kullanmayın Orijinal Kaynak

Boş IF dalları kullanmak yerine koşulu ters çevirin. Boş bir IF gövdesi okuyucuyu şaşırtır.

✓ İYİ KULLANIM
IF has_entries = abap_false.
  " do some magic
ENDIF.
✗ KÖTÜ KULLANIM
IF has_entries = abap_true.
  " boş - hiçbir şey yok
ELSE.
  " do some magic    " mantık ELSE'de, IF gövdesi boş - kafa karıştırıcı
ENDIF.

💡 Uzman Yorumu: Boş bir IF gövdesi "neden burada IF var?" sorusunu akla getirir. Koşulu tersine çevirmek ve boş gövdeden kurtulmak kodu çok daha temiz yapar.

Kaynağa Git

10.2 CASE Tercih Edin Orijinal Kaynak

Birden fazla alternatif koşul için ELSE IF yerine CASE kullanın. CASE, birbirini dışlayan alternatifleri kolayca gösterir ve yeni durumları hızla eklemenize izin verir.

✓ İYİ KULLANIM
CASE type.
  WHEN type-some_type.
    " ...
  WHEN type-some_other_type.
    " ...
  WHEN OTHERS.
    RAISE EXCEPTION NEW /clean/unknown_type_failure( ).
ENDCASE.
✗ KÖTÜ KULLANIM
IF type = type-some_type.
  " ...
ELSEIF type = type-some_other_type.
  " ...                                " type değişkeni her seferinde tekrar
ELSE.
  RAISE EXCEPTION NEW /dirty/unknown_type_failure( ).
ENDIF.

💡 Uzman Yorumu: CASE ifadesi bazı durumlarda birden fazla IF/ELSEIF'ten daha hızlı çalışır çünkü farklı bir mikroişlemci komutu kullanabilir. Ayrıca CASE yanlışlıkla IF-ELSEIF iç içe geçirme hatalarını önler.

Kaynağa Git

10.3 İç İçe Geçme Derinliğini Düşük Tutun Orijinal Kaynak

İç içe IF'ler hızla anlaşılmaz hale gelir ve tam kapsam için üstel sayıda test case gerektirir. Alt metodlar oluşturarak veya koşulları birleştirerek iç içe geçmeyi azaltın.

✓ İYİ KULLANIM
IF <this> AND <that>.
  " düz yapı, koşullar birleştirildi
ENDIF.
✗ KÖTÜ KULLANIM
IF <this>.
  IF <that>.
  ENDIF.
ELSE.
  IF <other>.
  ELSE.
    IF <something>.
    ENDIF.
  ENDIF.
ENDIF.   " dört seviye iç içe geçme - anlamak çok zor

💡 Uzman Yorumu: İç içe geçme derinliği 3'ü aştığında kodu anlamak katlanarak zorlaşır. Erken çıkış (RETURN/RAISE) kullanmak ve koşulları alt metodlara çıkarmak derinliği azaltır.

Kaynağa Git

11. Düzenli İfadeler (Regex)

11.1 Daha Basit Metodları Tercih Edin Orijinal Kaynak

Regex yerine daha basit string metodları kullanın. Basit durumlar genellikle regex olmadan daha anlaşılırdır. Regex ayrıca çalışma zamanında derlenmesi gerektiğinden ek bellek ve işlemci zamanı tüketir.

✓ İYİ KULLANIM
IF input IS NOT INITIAL.
WHILE contains( val = input  sub = 'abc' ).
✗ KÖTÜ KULLANIM
IF matches( val = input  regex = '.+' ).    " basit durumlar için regex gereksiz
WHILE contains( val = input  regex = 'abc' ).

💡 Uzman Yorumu: Regex çok güçlüdür ama okunması da çok zordur. "Bazı insanlar bir problemi çözmek için regex kullanmaya karar verirler. Şimdi iki problemi vardır." —Jamie Zawinski

Kaynağa Git

11.2 Temel Kontrolleri Tercih Edin Orijinal Kaynak

Kendi regex'inizi yazmak yerine, SAP'nin sunduğu mevcut kontrol fonksiyonlarını kullanın. DRY (Don't Repeat Yourself) prensibine uyun.

✓ İYİ KULLANIM
CALL FUNCTION 'SEO_CLIF_CHECK_NAME'
  EXPORTING
    cls_name = class_name
  EXCEPTIONS
    ...
✗ KÖTÜ KULLANIM
DATA(is_valid) = matches( val     = class_name
                          pattern = '[A-Z][A-Z0-9_]{0,29}' ).
" SAP zaten bu kontrolü yapıyor, tekrar yazmak DRY ihlalatıdır

💡 Uzman Yorumu: SAP, pek çok doğrulama için standart fonksiyonlar sunar. Bu fonksiyonlar SAP'nin kendi standartlarına göre test edilmiştir. Kendi regex'inizi yazmak hem zaman kaybıdır hem de potansiyel hata kaynağıdır.

Kaynağa Git

11.3 Karmaşık Regex'leri Birleştirin Orijinal Kaynak

Karmaşık regex'leri daha basit parçalardan oluşturarak okuyucuya nasıl kurulduğunu gösterin.

✓ İYİ KULLANIM
CONSTANTS class_name TYPE string VALUE `CL\_.*`.
CONSTANTS interface_name TYPE string VALUE `IF\_.*`.
DATA(object_name) = |{ class_name }\|{ interface_name }|.
" Regex parça parça açıkça oluşturuldu

💡 Uzman Yorumu: Karmaşık bir regex'i tek satırda yazmak zorunda değilsiniz. Parçalara bölerek hem belgeleyin hem de daha okunabilir hale getirin. Regex parçalarını sabit olarak adlandırmak amacı da açıklar.

Kaynağa Git

12. Sınıflar

12.1 Nesneleri Tercih Edin Orijinal Kaynak

Statik sınıflar, nesne yöneliminin sağladığı tüm avantajları başından atar. Özellikle birim testlerinde bağımlılıkları test double'larla değiştirmeyi neredeyse imkânsız kılar.

✓ İYİ KULLANIM
CLASS /clean/string_utils DEFINITION [...].
  CLASS-METHODS trim
   IMPORTING
     string        TYPE string
   RETURNING
     VALUE(result) TYPE string.
ENDCLASS.

METHOD retrieve.
  DATA(trimmed_name) = /clean/string_utils=>trim( name ).
  result = read( trimmed_name ).
ENDMETHOD.

💡 Uzman Yorumu: Sınıf veya metod statik mi olmalı sorusunun cevabı neredeyse her zaman "hayır"dır. Kabul edilebilir istisna: tamamen durumsuz, temel yardımcı metodlar (string_utils gibi). Bunlar ABAP ifadelerine veya yerleşik fonksiyonlara o kadar yakındır ki test double'larla değiştirilmeleri gerekmez.

Kaynağa Git

12.2 Bileşimi Tercih Edin Orijinal Kaynak

Kalıtım hiyerarşileri yerine bileşim kullanın. Temiz kalıtım tasarımı zordur ve Liskov ikame prensibine uymayı gerektirir. Bileşim daha küçük bağımsız nesneler oluşturmanızı ve bunları birleştirmenizi sağlar.

💡 Uzman Yorumu: "Kalıtım yerine bileşimi tercih et" GoF tasarım desenlerinin temel prensibidir. Kalıtım uygun olduğu yerlerde (Composite deseni gibi) kullanın ama her durumda kalıtıma başvurmaktan kaçının.

Kaynağa Git

12.3 Stateful ve Stateless'ı Karıştırmayın Orijinal Kaynak

Aynı sınıfta durumsuz (stateless) ve durumlu (stateful) programlama paradigmalarını karıştırmayın. Her iki paradigma da geçerlidir, ancak karıştırıldığında anlaşılması zor ve hata üretmeye meyilli kod ortaya çıkar.

✓ İYİ KULLANIM - Stateless sınıf
CLASS /clean/xml_converter DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    METHODS convert
      IMPORTING
        file_content  TYPE xstring
      RETURNING
        VALUE(result) TYPE /clean/some_inbound_message.
ENDCLASS.

" Stateful sınıf
CLASS /clean/log DEFINITION PUBLIC CREATE PUBLIC.
  PUBLIC SECTION.
    METHODS add_message IMPORTING message TYPE /clean/message.
  PRIVATE SECTION.
    DATA messages TYPE /clean/message_table.
ENDCLASS.

💡 Uzman Yorumu: Stateless sınıflar test edilmesi en kolay sınıflardır çünkü yan etkileri yoktur. Stateful sınıflar güçlüdür ama daha dikkatli tasarım gerektirir. İkisini karıştırmak her ikisinin dezavantajlarını birleştirir.

Kaynağa Git

12.4 Global'i Varsayılan Kabul Edin Orijinal Kaynak

Varsayılan olarak global sınıflarla çalışın. Yerel sınıfları yalnızca uygun yerlerde kullanın. Yerel sınıflar yeniden kullanımı engeller ve bulunması genellikle zordur.

💡 Uzman Yorumu: Yerel sınıflar include düzeyinde kilitlenme oluşturur; bu nedenle birden fazla geliştirici aynı anda üzerinde çalışamaz. Global sınıflar bu sorunu ortadan kaldırır ve yeniden kullanılabilirliği artırır.

Kaynağa Git

12.5 FINAL Yapın Orijinal Kaynak

Kalıtım için açıkça tasarlanmamış sınıfları FINAL yapın. Bu, yanlışlıkla kalıtımı önler ve tasarım kararlarınızı açıkça ifade eder.

✓ İYİ KULLANIM
CLASS /clean/my_utility DEFINITION PUBLIC FINAL CREATE PUBLIC.
  " Kalıtım için tasarlanmadı, FINAL ile koruma altında
ENDCLASS.

💡 Uzman Yorumu: FINAL olmayan bir sınıf, "bu sınıftan türetebilirsiniz" demektir. Bu, dışarıya açık bir API'nin parçasıdır ve dikkatli tasarım gerektirir. Eğer kalıtım planlamıyorsanız FINAL kullanın.

Kaynağa Git

12.6 Üyeler Varsayılan Olarak PRIVATE Orijinal Kaynak

Öznitelikler, metodlar ve diğer sınıf üyeleri varsayılan olarak PRIVATE olmalıdır. Yalnızca alt sınıfların bunları geçersiz kılmasını istiyorsanız PROTECTED yapın.

💡 Uzman Yorumu: "Bilmesi gereken kadar bilgi" ilkesi (need-to-know basis). Sınıf iç yapısını dışarıya açmak, beklenmedik yeniden tanımlamalar yoluyla ince hatalara yol açabilir ve refactoring'i zorlaştırır.

Kaynağa Git

12.7 Immutable Kullanmayı Düşünün Orijinal Kaynak

Yapılandırıldıktan sonra hiç değişmeyen nesneler için getter metodlar yerine public salt okunur öznitelikler kullanmayı düşünün.

✓ İYİ KULLANIM
CLASS /clean/some_data_container DEFINITION.
  PUBLIC SECTION.
    METHODS constructor
      IMPORTING
        a TYPE i
        b TYPE c
        c TYPE d.
    DATA a TYPE i READ-ONLY.
    DATA b TYPE c READ-ONLY.
    DATA c TYPE d READ-ONLY.
ENDCLASS.
✗ KÖTÜ KULLANIM
CLASS /dirty/some_data_container DEFINITION.
  PUBLIC SECTION.
    METHODS get_a ...
    METHODS get_b ...
    METHODS get_c ...     " salt getter metodlar gereksiz karmaşıklık ekler
  PRIVATE SECTION.
    DATA a TYPE i.
    DATA b TYPE c.
    DATA c TYPE d.
ENDCLASS.

💡 Uzman Yorumu: READ-ONLY öznitelikler, getter metodlara kıyasla çok daha az kod gerektirirken aynı kapsüllemeyi sağlar. Nesne değiştirilebilirse bu yaklaşımı kullanmayın.

Kaynağa Git

12.8 READ-ONLY'yi Tutumlu Kullanın Orijinal Kaynak

READ-ONLY yalnızca PUBLIC SECTION'da kullanılabilir ve beklenenin aksine sınıf içinden, friend sınıflardan ve alt sınıflardan değiştirilebilir. Bu durum diğer dillerdeki beklentilerden farklıdır.

💡 Uzman Yorumu: READ-ONLY diğer dillerdeki "final" veya "readonly" gibi davranmaz. ABAP'ta sınıf içinden hâlâ değiştirilebilir. Bu, yanlış anlaşılmalara yol açabilir; kullanım amacını ekibinizle açıkça paylaşın.

Kaynağa Git

12.9 NEW Tercih Edin Orijinal Kaynak

Nesne oluşturmak için CREATE OBJECT yerine NEW kullanın. Yalnızca dinamik tipler gerektirdiğinde CREATE OBJECT kullanın.

✓ İYİ KULLANIM
DATA object TYPE REF TO /clean/some_number_range.
object = NEW #( '/CLEAN/CXTGEN' )
DATA(object) = NEW /clean/some_number_range( '/CLEAN/CXTGEN' ).
DATA(object) = CAST /clean/number_range( NEW /clean/some_number_range( '/CLEAN/CXTGEN' ) ).
✗ KÖTÜ KULLANIM
DATA object TYPE REF TO /dirty/some_number_range.
CREATE OBJECT object
  EXPORTING
    number_range = '/DIRTY/CXTGEN'.    " çok daha uzun

💡 Uzman Yorumu: NEW sözdizimi daha kısadır ve method chaining ile daha iyi çalışır. CAST ile birleştiğinde özellikle güçlüdür. Dinamik tip gerekmedikçe CREATE OBJECT kullanmaktan kaçının.

Kaynağa Git

12.10 CONSTRUCTOR'ı Public Bırakın Orijinal Kaynak

Global sınıfınız CREATE PRIVATE ise, CONSTRUCTOR'ı PUBLIC SECTION'da bırakın. Bu, doğru derleme ve sözdizimi doğrulaması için gereklidir.

✓ İYİ KULLANIM
CLASS /clean/some_api DEFINITION PUBLIC FINAL CREATE PRIVATE.
  PUBLIC SECTION.
    METHODS constructor.   " CREATE PRIVATE olmasına rağmen public

💡 Uzman Yorumu: Bu, çelişkili görünebilir ama ABAP Help belgelerine göre gereklidir. Yalnızca global sınıflara uygulanır; yerel sınıflarda constructor private olabilir.

Kaynağa Git

12.11 Birden Fazla Statik Oluşturma Metodu Orijinal Kaynak

ABAP function overloading'i desteklemediğinden, isteğe bağlı parametreler yerine birden fazla statik oluşturma metodu kullanın.

✓ İYİ KULLANIM
CLASS-METHODS describe_by_data IMPORTING data TYPE any [...]
CLASS-METHODS describe_by_name IMPORTING name TYPE any [...]
CLASS-METHODS describe_by_object_ref IMPORTING object_ref TYPE REF TO object [...]
CLASS-METHODS describe_by_data_ref IMPORTING data_ref TYPE REF TO data [...]
✗ KÖTÜ KULLANIM
METHODS constructor
  IMPORTING
    data       TYPE any OPTIONAL
    name       TYPE any OPTIONAL
    object_ref TYPE REF TO object OPTIONAL
    data_ref   TYPE REF TO data OPTIONAL.
" Hangi kombinasyon geçerli? Hepsi OPTIONAL - kafa karıştırıcı

💡 Uzman Yorumu: Birden fazla oluşturma metodu, hangi parametrelerin geçerli olduğunu açıkça ifade eder. İsteğe bağlı parametreler çağırana "hangi kombinasyonu kullanayım?" sorusunu bırakır.

Kaynağa Git

12.12 Açıklayıcı Oluşturma İsimleri Orijinal Kaynak

Oluşturma metodları için new_, create_, construct_ gibi sezgisel başlangıçlar kullanın ve bunları açıklayıcı isimlerle birleştirin.

✓ İYİ KULLANIM
CLASS-METHODS new_describe_by_data IMPORTING p_data TYPE any [...]
CLASS-METHODS new_describe_by_name IMPORTING p_name TYPE any [...]
CLASS-METHODS new_describe_by_object_ref IMPORTING p_object_ref TYPE REF TO object [...]
✗ KÖTÜ KULLANIM
CLASS-METHODS create_1 IMPORTING p_data TYPE any [...]
CLASS-METHODS create_2 IMPORTING p_name TYPE any [...]   " numaralar hiçbir anlam taşımaz

💡 Uzman Yorumu: new_from_template, create_as_copy, construct_by_name gibi isimler hem yaratma eylemini hem de yapılandırma detayını iletir. Bu, IDE'nin otomatik tamamlama özelliğiyle de iyi çalışır.

Kaynağa Git

12.13 Singleton Sadece Gerektiğinde Orijinal Kaynak

Singleton desenini yalnızca nesne yönelimli tasarımınız birden fazla örneğin mantıklı olmadığını söylediğinde uygulayın. Alışkanlıktan veya performans kuralından dolayı Singleton kullanmayın.

✓ İYİ KULLANIM
METHOD new.
  IF singleton IS NOT BOUND.
    singleton = NEW /clean/my_class( ).
  ENDIF.
  result = singleton.
ENDMETHOD.

💡 Uzman Yorumu: Singleton, en çok kötüye kullanılan tasarım desenlerinden biridir. Gereksiz çapraz etkiler yaratır ve test etmeyi ciddi ölçüde zorlaştırır. Yalnızca nesne tasarımı "tek örnek olmalı" diyorsa kullanın.

Kaynağa Git

13. Metodlar

13.1 Statik Metodları Instance Üzerinden Çağırmayın Orijinal Kaynak

Statik metodu çağırmak için class=>method sözdizimini kullanın, instance değişkeni değil. Instance üzerinden statik metod çağırmak potansiyel kafa karışıklığına yol açar.

✓ İYİ KULLANIM
cl_my_class=>static_method( ).

METHOD static_method.
  another_static_method( ).    " aynı sınıf içinde niteleyici gerekmez
ENDMETHOD.
✗ KÖTÜ KULLANIM
lo_my_instance->static_method( ).   " instance üzerinden statik çağrı - yanıltıcı

💡 Uzman Yorumu: Instance üzerinden statik metod çağrısı, kodun bakımcısını "bu metod instance durumunu mu kullanıyor?" diye merak ettirir. => sözdizimi metodun statik olduğunu açıkça gösterir.

Kaynağa Git

13.2 Tiplere Instance Üzerinden Erişmeyin Orijinal Kaynak

Sınıf veya arayüzde tanımlanmış veri tipine, sınıf/arayüz üzerinden erişin, instance değil. Instance üzerinden tip erişimi, tipin instance'a özel olduğunu ima eder.

✓ İYİ KULLANIM
INTERFACE lif.
  TYPES blah TYPE lcl=>foo.    " sınıf üzerinden tip erişimi
ENDINTERFACE.
✗ KÖTÜ KULLANIM
INTERFACE lif.
  DATA(ref) = new lcl( ).
  TYPES blah TYPE ref->foo.   " instance üzerinden tip erişimi - yanıltıcı
ENDINTERFACE.

💡 Uzman Yorumu: Tipler sınıfa aittir, instance'a değil. instance->foo yerine ClassName=>foo kullanmak bu gerçeği açıkça ifade eder ve semantik hatayı önler.

Kaynağa Git

13.3 Fonksiyonel Çağrıları Tercih Edin Orijinal Kaynak

CALL METHOD yerine doğrudan metod çağrısı sözdizimini kullanın. Dinamik tipleme zorunlu kıldığında prosedürel stile başvurun.

✓ İYİ KULLANIM
modify->update( node           = /clean/my_bo_c=>node-item
                key            = item->key
                data           = item
                changed_fields = changed_fields ).
✗ KÖTÜ KULLANIM
CALL METHOD modify->update
  EXPORTING
    node           = /dirty/my_bo_c=>node-item
    key            = item->key
    data           = item
    changed_fields = changed_fields.   " gereksiz uzun

💡 Uzman Yorumu: Fonksiyonel çağrı sözdizimi daha kısa ve modern görünür. CALL METHOD ABAP'ın eski dönemlerine aittir; yeni kodda kullanmaktan kaçının.

Kaynağa Git

13.4 RECEIVING'i Atlayın Orijinal Kaynak

Fonksiyonel çağrı sözdiziminde RECEIVING anahtar sözcüğünü atlayın.

✓ İYİ KULLANIM
DATA(sum) = aggregate_values( values ).
✗ KÖTÜ KULLANIM
aggregate_values(
  EXPORTING
    values = values
  RECEIVING
    result = DATA(sum) ).    " RECEIVING gereksiz uzunluk ekler

💡 Uzman Yorumu: DATA(sum) = method() sözdizimi hem RECEIVING'i hem de EXPORTING'i atlar. Bu modern sözdizimini kullandığınızda kod çok daha temiz görünür.

Kaynağa Git

13.5 EXPORTING'i Atlayın Orijinal Kaynak

Fonksiyonel çağrılarda isteğe bağlı EXPORTING anahtar sözcüğünü atlayın.

✓ İYİ KULLANIM
modify->update( node           = /clean/my_bo_c=>node-item
                key            = item->key
                data           = item
                changed_fields = changed_fields ).
✗ KÖTÜ KULLANIM
modify->update(
  EXPORTING                          " EXPORTING gereksiz
    node           = /dirty/my_bo_c=>node-item
    key            = item->key
    data           = item
    changed_fields = changed_fields ).

💡 Uzman Yorumu: Fonksiyonel metod çağrılarında EXPORTING isteğe bağlıdır ve yalnızca gürültü ekler. Kaldırın ve kodunuzu daha temiz yapın.

Kaynağa Git

13.6 Tek Parametreli Çağrılarda Adı Atlayın Orijinal Kaynak

Tek parametreli çağrılarda parametre adını atlayın (metod adı yeterince açıklayıcıysa).

✓ İYİ KULLANIM
DATA(unique_list) = remove_duplicates( list ).
car->drive( speed = 50 ).    " metod adı tek başına açık değilse adı yazın
✗ KÖTÜ KULLANIM
DATA(unique_list) = remove_duplicates( list = list ).  " "list = list" gereksiz tekrar

💡 Uzman Yorumu: "remove_duplicates( list )" anlaşılırdır; "remove_duplicates( list = list )" ise gereksizdir. Ancak metod adı tek başına açık değilse parametre adı netlik katabilir.

Kaynağa Git

13.7 Me'yi Atlayın Orijinal Kaynak

me-> öz referansı sistem tarafından örtük olarak ayarlandığından, instance öznitelik veya metod çağrısı yaparken atlayın. Yalnızca yerel değişken ile instance özniteliği arasında çakışma olduğunda kullanın.

✓ İYİ KULLANIM
DATA(sum) = aggregate_values( values ).
me->logger = logger.    " yalnızca çakışma olduğunda gerekli
✗ KÖTÜ KULLANIM
DATA(sum) = me->aggregate_values( me->values ).    " me-> gereksiz gürültü

💡 Uzman Yorumu: me-> her yere eklemek kodu gürültülü yapar ve gerçekten gerekli olduğu durumu (yerel değişken çakışması) gizler. Yalnızca gerektiğinde kullanın.

Kaynağa Git

13.8 Instance Metodları Tercih Edin Orijinal Kaynak

Metodlar varsayılan olarak instance üyesi olmalıdır. Instance metodları sınıfın "nesne" niteliğini daha iyi yansıtır ve birim testlerinde daha kolay mock'lanabilir.

✓ İYİ KULLANIM
METHODS publish.              " instance metod

CLASS-METHODS create_instance  " statik yalnızca oluşturma için
  RETURNING
    VALUE(result) TYPE REF TO /clean/blog_post.

💡 Uzman Yorumu: Statik metodlar, bağımlılıkları test double ile değiştirmeyi imkânsız kılar. Statik oluşturma metodları bunun kabul edilebilir istisnasıdır.

Kaynağa Git

13.9 Public Metodlar Interface Parçası Olmalı Orijinal Kaynak

Public instance metodlar her zaman bir arayüzün parçası olmalıdır. Bu, bağımlılıkları ayırır ve birim testlerinde mock'lamayı kolaylaştırır.

✓ İYİ KULLANIM
METHOD /clean/blog_post~publish.   " arayüz üzerinden uygulama

💡 Uzman Yorumu: Arayüz olmadan public metod, nesne yöneliminde çok az anlam taşır. Arayüzler, bağımlılık tersine çevirme prensibinin temelidir ve test edilebilirliği sağlar.

Kaynağa Git

13.10 Az IMPORTING Parametresi Orijinal Kaynak

Üç ya da daha az IMPORTING parametresini hedefleyin. Çok fazla giriş parametresi, metodun karmaşıklığını katlanarak artırır ve genellikle çok şey yaptığının göstergesidir.

✓ İYİ KULLANIM
FUNCTION seo_class_copy
  IMPORTING
    clskey      TYPE seoclskey
    new_clskey  TYPE seoclskey
    config      TYPE class_copy_config
  EXPORTING
    ...
✗ KÖTÜ KULLANIM
FUNCTION seo_class_copy
  IMPORTING
    clskey                 TYPE seoclskey
    new_clskey             TYPE seoclskey
    access_permission      TYPE seox_boolean DEFAULT seox_true
    VALUE(save)            TYPE seox_boolean DEFAULT seox_true
    VALUE(suppress_corr)   TYPE seox_boolean DEFAULT seox_false
    VALUE(suppress_dialog) TYPE seox_boolean DEFAULT seox_false
    VALUE(authority_check) TYPE seox_boolean DEFAULT seox_true
    lifecycle_manager      TYPE REF TO if_adt_lifecycle_manager OPTIONAL
    lock_handle            TYPE REF TO if_adt_lock_handle OPTIONAL
  EXPORTING
    ...  " 9 parametre - çok fazla

💡 Uzman Yorumu: Her yeni parametre, metodun test edilmesi gereken kombinasyon sayısını üstel olarak artırır. Fazla parametreler, parametreleri anlamlı yapılarda birleştirerek azaltılabilir.

Kaynağa Git

13.11 Metodları Bölün Orijinal Kaynak

OPTIONAL parametreler eklemek yerine metodları bölün. İsteğe bağlı parametreler çağıranı hangi kombinasyonun geçerli olduğu konusunda şaşırtır.

✓ İYİ KULLANIM
METHODS do_one_thing IMPORTING what_i_need TYPE string.
METHODS do_another_thing IMPORTING something_else TYPE i.
✗ KÖTÜ KULLANIM
METHODS do_one_or_the_other
  IMPORTING
    what_i_need    TYPE string OPTIONAL
    something_else TYPE i OPTIONAL.    " hangi kombinasyon geçerli?

💡 Uzman Yorumu: İsteğe bağlı parametreler çağırana şu soruları bırakır: "Hangisi gerçekten gerekli? Hangi kombinasyonlar geçerli? Hangileri birbirini dışlar?" Ayrı metodlar bu soruları ortadan kaldırır.

Kaynağa Git

13.12 PREFERRED PARAMETER'ı Tutumlu Kullanın Orijinal Kaynak

PREFERRED PARAMETER hangi parametrenin gerçekte sağlandığını görmeyi zorlaştırır. Parametreleri, özellikle isteğe bağlı olanları, en aza indirmek PREFERRED PARAMETER ihtiyacını otomatik olarak azaltır.

💡 Uzman Yorumu: PREFERRED PARAMETER, isteğe bağlı parametrelerle birlikte kullanıldığında hangi parametrenin sağlandığını anlamayı çok zorlaştırır. Genellikle metodların daha küçük ve odaklı yapıya bölünmesiyle bu sorunu tamamen önleyebilirsiniz.

Kaynağa Git

13.13 Tam Olarak Bir Parametre Döndürün Orijinal Kaynak

İyi bir metod tek bir şey yapar ve bu, tam olarak bir çıktı döndürmesiyle yansıtılmalıdır. Çıktılar mantıksal bir bütün oluşturuyorsa yapı veya nesne döndürün.

✓ İYİ KULLANIM
TYPES:
  BEGIN OF check_result,
    result      TYPE result_type,
    failed_keys TYPE /bobf/t_frw_key,
    messages    TYPE /bobf/t_frw_message,
  END OF check_result.

METHODS check_business_partners
  IMPORTING
    business_partners TYPE business_partners
  RETURNING
    VALUE(result)     TYPE check_result.   " yapı olarak döndür
✗ KÖTÜ KULLANIM
METHODS check_business_partners
  IMPORTING
    business_partners TYPE business_partners
  EXPORTING
    result            TYPE result_type
    failed_keys       TYPE /bobf/t_frw_key
    messages          TYPE /bobf/t_frw_message.   " çoklu EXPORTING kafa karıştırıcı

💡 Uzman Yorumu: RETURNING ile tek nesne döndürmek, method chaining'i mümkün kılar ve IS SUPPLIED kontrollerini ortadan kaldırır. Birden fazla EXPORTING parametresi genellikle metodun çok fazla şey yaptığının işaretidir.

Kaynağa Git

13.14 RETURNING Tercih Edin Orijinal Kaynak

EXPORTING yerine RETURNING kullanın. RETURNING çağrıyı daha kısa yapar, method chaining'e izin verir ve aynı giriş/çıkış hatalarını önler.

✓ İYİ KULLANIM
METHODS square
  IMPORTING
    number        TYPE i
  RETURNING
    VALUE(result) TYPE i.

DATA(result) = square( 42 ).
✗ KÖTÜ KULLANIM
METHODS square
  IMPORTING
    number TYPE i
  EXPORTING
    result TYPE i.

square(
  EXPORTING
    number = 42
  IMPORTING
    result = DATA(result) ).   " çok daha uzun ve okuması zor

💡 Uzman Yorumu: RETURNING ile değer ataması (result = square(42)) matematiksel notasyona yakındır ve okunması kolaydır. EXPORTING ile çağrı ise prosedürel bir görünüm sunar ve daha fazla satır kaplar.

Kaynağa Git

13.15 Büyük Tablo Döndürmek Genellikle Sorun Değil Orijinal Kaynak

ABAP dil belgeleri aksini söylese de, büyük bir tabloyu VALUE parametresinde döndürmek nadiren gerçek performans sorunlarına yol açar. Kanıtlanmış bir sorun olmadıkça RETURNING kullanmaya devam edin.

✓ İYİ KULLANIM
METHODS get_large_table
  RETURNING
    VALUE(result) TYPE /clean/some_table_type.

DATA(my_table) = get_large_table( ).

💡 Uzman Yorumu: Kernel optimizasyonu RETURNING performansını büyük ölçüde iyileştirmiştir. Gerçek bir performans ölçümü yapmadan erken optimizasyon yapmayın. Okunabilirliği koruyun.

Kaynağa Git

13.16 Tek Tip Kullanın Orijinal Kaynak

RETURNING, EXPORTING veya CHANGING'den birini kullanın ama kombinasyon yapmayın. Farklı türde çıktı parametreleri, metodun birden fazla şey yaptığının göstergesidir.

✓ İYİ KULLANIM
METHODS copy_class
  IMPORTING
    old_name      TYPE seoclsname
    new_name      TYPE seoclsname
  RETURNING
    VALUE(result) TYPE copy_result
  RAISING
    /clean/class_copy_failure.
✗ KÖTÜ KULLANIM
METHODS copy_class
  ...
  RETURNING
    VALUE(result)      TYPE vseoclass
  EXPORTING
    error_occurred     TYPE abap_bool
  CHANGING
    correction_request TYPE trkorr
    package            TYPE devclass.   " üç farklı çıktı tipi - ne yapıyor bu metod?

💡 Uzman Yorumu: RETURNING, EXPORTING ve CHANGING'i karıştırmak çağıranın kafasını karıştırır. Çağıran ne beklediğini nasıl anlayacak? Tek tip seçin ve ona bağlı kalın.

Kaynağa Git

13.17 CHANGING'i Tutumlu Kullanın Orijinal Kaynak

CHANGING'i yalnızca halihazırda dolu olan yerel bir değişkenin kısmi olarak güncellendiği durumlar için saklayın. Çağıranı yalnızca CHANGING parametrenizi beslemek için gereksiz yerel değişkenler oluşturmaya zorlamayın.

✓ İYİ KULLANIM
METHODS update_references
  IMPORTING
    new_reference TYPE /bobf/conf_key
  CHANGING
    bo_nodes      TYPE root_nodes.

METHOD update_references.
  LOOP AT bo_nodes REFERENCE INTO DATA(bo_node).
    bo_node->reference = new_reference.
  ENDLOOP.
ENDMETHOD.

💡 Uzman Yorumu: CHANGING, önceden dolu bir değişkeni kısmen güncelleme için doğaldır; örneğin bir tablo üzerinde döngü yaparak bazı alanları güncelleme. Boş bir değişkeni doldurmak için CHANGING kullanmayın; bunun için RETURNING daha uygun.

Kaynağa Git

13.18 Boolean Giriş Yerine Metodu Bölün Orijinal Kaynak

Boolean giriş parametreleri genellikle metodun iki şey yaptığının göstergesidir. Metodu bölmek hem kodu basitleştirir hem de farklı niyetleri daha iyi anlatır.

✓ İYİ KULLANIM
update_without_saving( ).
update_and_save( ).
✗ KÖTÜ KULLANIM
METHODS update
  IMPORTING
    do_save TYPE abap_bool.

update( abap_true ).  " 'true' ne demek? senkron mu? simüle mi? commit mi?

💡 Uzman Yorumu: Boolean parametreler çağrıyı anlamsızlaştırır: update( abap_true ) - bu true ne demek? Ayrı metodlar her birinin ne yaptığını adıyla açıklar.

Kaynağa Git

13.19 RESULT Adını Düşünün Orijinal Kaynak

RETURNING parametresini basitçe RESULT olarak adlandırın. Bu, parametre adının metod adını tekrar etmesini önler ve isim çakışmalarını ortadan kaldırır.

✓ İYİ KULLANIM
METHODS get_name
  RETURNING
    VALUE(result) TYPE string.

METHOD get_name.
  result = name.    " me->name çakışması yok
ENDMETHOD.
✗ KÖTÜ KULLANIM
METHODS get_name
  RETURNING
    VALUE(name) TYPE string.

METHOD get_name.
  name = me->name.    " me-> eklemek zorunda kalıyorsunuz
ENDMETHOD.

💡 Uzman Yorumu: RESULT, RETURNING parametresi için evrensel bir standarttır. İsim çakışmalarını önler ve metodun ne döndürdüğünü açıkça ifade eder.

Kaynağa Git

13.20 EXPORTING Parametrelerini Temizleyin Orijinal Kaynak

Referans parametreleri önceden dolu bellek alanlarına işaret eder. CLEAR veya üzerine yazma ile güvenilir veri sağlayın.

✓ İYİ KULLANIM
METHOD square.
  CLEAR result.       " önce temizle
  " ...
ENDMETHOD.

METHOD square.
  result = cl_abap_math=>square( 2 ).   " ya da doğrudan üzerine yaz
ENDMETHOD.

💡 Uzman Yorumu: EXPORTING parametreleri referans yoluyla geçirildiğinden önceki değerleri taşıyabilir. CLEAR yapmadan işlemek, eski verilerin sonuca karışmasına yol açabilir.

Kaynağa Git

13.21 Giriş ve Çıkış Aynı Olabilirse Dikkatli Olun Orijinal Kaynak

Bazı parametreler hem giriş hem çıkış olarak kullanılabilir. Bu durumda erken CLEAR, giriş değerini silip yanlış sonuçlara yol açabilir.

✗ KÖTÜ KULLANIM
METHOD square_dirty.
  CLEAR result.          " erken clear - value'yu siler!
  result = number * number.
ENDMETHOD.

" Çağrı: aynı değişken hem giriş hem çıkış
square_dirty(
  EXPORTING number = value
  IMPORTING result = value ).   " değer silinir, yanlış sonuç

💡 Uzman Yorumu: Bu tür metodları RETURNING kullanacak şekilde yeniden tasarlayın. RETURNING parametreleri her zaman yeni bir bellek alanı kullanır, bu nedenle bu sorun ortaya çıkmaz.

Kaynağa Git

13.22 VALUE Parametrelerini Temizlemeyin Orijinal Kaynak

VALUE parametreleri yeni, ayrı bellek alanları olarak geçirilir; başlangıçta boşturlar. Yeniden temizlemeye gerek yoktur.

✓ İYİ KULLANIM
METHODS square
  RETURNING
    VALUE(result) TYPE i.

METHOD square.
  " result'ı temizlemeye gerek yok - zaten boş
ENDMETHOD.

💡 Uzman Yorumu: RETURNING parametreleri her zaman VALUE parametresidir ve başlangıçta boştur. Gereksiz CLEAR ifadeleri kodu karmaşıklaştırır ve yanlış bir izlenim yaratır.

Kaynağa Git

13.23 Bir Şey Yapın Orijinal Kaynak

Bir metod tek bir şey yapmalı ve bunu olabildiğince iyi yapmalıdır. Bir metodun tek bir şey yaptığını gösteren işaretler: az giriş parametresi, Boolean parametre yok, tam olarak bir çıktı, küçük boyut, tek soyutlama seviyesi.

✓ İYİ KULLANIM
METHOD read_and_parse_version_filters.
  DATA(active_model_version) = read_random_version_under( model_guid ).
  DATA(filter_json) = read_model_version_filters( active_model_version-guid ).
  result = parse_model_version_filters( filter_json ).
ENDMETHOD.    " 3 ifade, tek amaca hizmet ediyor

💡 Uzman Yorumu: "Single Responsibility Principle" metodlar için de geçerlidir. Bir metodu ne yaptığını tek bir cümleyle açıklayabiliyorsanız, muhtemelen doğru yoldasınız. "Ve ayrıca..." eklemek zorunda kalıyorsanız, refactor zamanı.

Kaynağa Git

13.24 Mutlu Yol veya Hata Yönetimi Orijinal Kaynak

Bir metod ya mutlu yolu (başarılı akış) ya da hata işlemeyi takip etmeli, muhtemelen ikisini birden değil. Doğrulama mantığını ayrı bir metoda taşıyın.

✓ İYİ KULLANIM
METHOD append_xs.
  validate( input ).         " hata işleme ayrı metodda
  DATA(remainder) = input.
  WHILE remainder > 0.
    result = result && `X`.
    remainder = remainder - 1.
  ENDWHILE.
ENDMETHOD.

METHOD validate.
  IF input = 0.
    RAISE EXCEPTION /dirty/sorry_cant_do( ).
  ELSEIF input < 0.
    RAISE EXCEPTION cx_sy_illegal_argument( ).
  ENDIF.
ENDMETHOD.

💡 Uzman Yorumu: Mutlu yol kodu ile hata işleme kodunu karıştırmak, her ikisini de anlaşılmaz kılar. Ayrı metodlara bölmek her iki bölümü de daha net yapar.

Kaynağa Git

13.25 Bir Soyutlama Seviyesi Orijinal Kaynak

Metottaki ifadeler, metodun kendisinin bir seviye altında olmalıdır. Tüm ifadeler aynı soyutlama seviyesinde olmalıdır.

✓ İYİ KULLANIM
METHOD create_and_publish.
  post = create_post( user_input ).   " her ikisi de yüksek seviye
  post->publish( ).
ENDMETHOD.
✗ KÖTÜ KULLANIM
METHOD create_and_publish.
  post = NEW blog_post( ).
  DATA(user_name) = trim( to_upper( sy-uname ) ).   " düşük seviye detay
  post->set_author( user_name ).                    " karışık seviyeler
  post->publish( ).                                 " yüksek seviye
ENDMETHOD.

💡 Uzman Yorumu: Karma soyutlama seviyeleri okuyucuyu "bu neden burada?" diye merak ettirir. Yüksek seviye metod, yüksek seviye operasyonları çağırmalı; detaylar alt metodlara taşınmalıdır.

Kaynağa Git

13.26 Metodları Küçük Tutun Orijinal Kaynak

Metodlar 20 ifadeden az olmalı; ideal olarak 3-5 ifade. Büyük metodlar genellikle birden fazla şey yapıyor demektir.

💡 Uzman Yorumu: Yüzlerce satırlık bir metodun DATA bildirim bloğu bile tek başına metodun ne kadar fazla şey yaptığını ortaya koyar. Küçük metodlar daha kolay anlaşılır, test edilir ve bakımı yapılır.

Kaynağa Git

13.27 Hızlı Başarısız Olun Orijinal Kaynak

Doğrulama yapın ve olabildiğince erken başarısız olun. Geç doğrulamalar anlamak zordur ve kaynakları boşa harcamış olabilir.

✓ İYİ KULLANIM
METHOD do_something.
  IF input IS INITIAL.
    RAISE EXCEPTION cx_sy_illegal_argument( ).   " erken doğrulama
  ENDIF.
  DATA(massive_object) = build_expensive_object_from( input ).
  result = massive_object->do_some_fancy_calculation( ).
ENDMETHOD.
✗ KÖTÜ KULLANIM
METHOD do_something.
  DATA(massive_object) = build_expensive_object_from( input ).   " pahalı işlem önce
  IF massive_object IS NOT BOUND.   " geç doğrulama
    RAISE EXCEPTION cx_sy_illegal_argument( ).
  ENDIF.
  result = massive_object->do_some_fancy_calculation( ).
ENDMETHOD.

💡 Uzman Yorumu: Erken doğrulama hem kaynakları korur hem de hata nedeni daha açık olur. Geç doğrulamada "neden burada hata veriyor?" sorusunun cevabı daha belirsizdir.

Kaynağa Git

CHECK vs RETURN Orijinal Kaynak

CHECK veya RETURN kullanıp kullanmayacağınız konusunda toplulukta fikir birliği yoktur. RETURN daha açıkken, CHECK daha kısadır. İkisini de kasıtlı kullanın.

✓ İYİ KULLANIM - RETURN daha açık
METHOD read_customizing.
  IF keys IS INITIAL.
    RETURN.      " ne olduğu açık: metoddan çıkıyoruz
  ENDIF.
  " asıl işlem
ENDMETHOD.

" veya CHECK ile daha kısa
METHOD read_customizing.
  CHECK keys IS NOT INITIAL.   " koşul sağlanmazsa çık
  " asıl işlem
ENDMETHOD.

💡 Uzman Yorumu: CHECK ifadesi daha kısa ama adı ne olduğunu açıklamaz. RETURN ile IF/ENDIF bloğu daha uzun ama daha açıktır. Ekibinizde bir konvansiyona karar verin ve tutarlı kalın.

Kaynağa Git

CHECK'i Diğer Yerlerde Kullanmaktan Kaçının Orijinal Kaynak

CHECK'i metodun başlatma bölümünün dışında kullanmayın. LOOP içinde CHECK farklı davranır (sadece o yinelemeyi sonlandırır) ve bu beklenmedik etkilere yol açabilir.

✗ KÖTÜ KULLANIM
LOOP AT table INTO DATA(row).
  CHECK row-key = 'A'.    " LOOP içinde sadece o yinelemeyi atlar, metoddan çıkmaz!
  process( row ).
ENDLOOP.
✓ İYİ KULLANIM
LOOP AT table INTO DATA(row).
  IF row-key <> 'A'.
    CONTINUE.             " açık: bu yinelemeyi atla
  ENDIF.
  process( row ).
ENDLOOP.

💡 Uzman Yorumu: CHECK'in LOOP içindeki davranışı, metod başında kullanımından farklıdır. Bu davranış farkını bilmeyen okuyucuyu yanıltır. CONTINUE açık ve belirsizlik taşımaz.

Kaynağa Git

14. Hata Yönetimi

Mesajları Bulmayı Kolaylaştırın Orijinal Kaynak

SE91 transaction'ından where-used araması yaparak mesajları kolayca bulabilmek için aşağıdaki deseni kullanın.

✓ İYİ KULLANIM
MESSAGE e001(ad) INTO DATA(message).
MESSAGE e001(ad) INTO DATA(message) ##NEEDED.   " değişken kullanılmıyorsa
✗ KÖTÜ KULLANIM
IF 1 = 2. MESSAGE e001(ad). ENDIF.
" Ulaşılamaz kod içeriyor ve where-used aramasında bulunamaz

💡 Uzman Yorumu: Mesajların where-used aramasında bulunabilmesi, hangi programların hangi mesajları kullandığını anlamak için kritiktir. Erişilemeyen kodda gizli mesajlar bu imkânı ortadan kaldırır.

Kaynağa Git

14.2 Exception Tercih Edin Orijinal Kaynak

Dönüş kodu yerine exception kullanın. Exception'lar metod imzalarını temiz tutar, çağıran hemen tepki vermek zorunda kalmaz ve hata detayları taşıyabilir.

✓ İYİ KULLANIM
METHOD try_this_and_that.
  RAISE EXCEPTION NEW cx_failed( ).
ENDMETHOD.
✗ KÖTÜ KULLANIM
METHOD try_this_and_that.
  error_occurred = abap_true.   " dönüş kodu olarak boolean
ENDMETHOD.
" Çağıran bu bayrağı kontrol etmeyi unutabilir!

💡 Uzman Yorumu: Dönüş kodları sessizce görmezden gelinebilir. Exception'lar ise çağıranı sözdizimsel olarak tepki vermeye (ya da açıkça iletmeye) zorlar. Bu, hataların kaybolmasını önler.

Kaynağa Git

14.3 Başarısızlıkların Gözden Kaçmasına İzin Vermeyin Orijinal Kaynak

Dönüş kodu kullanmak zorundaysanız (eski fonksiyon modülleri gibi), hataların gözden kaçmasına izin vermeyin. Kontrol edin ve exception'a dönüştürün.

✓ İYİ KULLANIM
CALL FUNCTION 'BAPI_GET_CURRENT_DATE'
  IMPORTING
    current_date = current_date
  CHANGING
    response     = response.

IF response-type = 'E'.
  RAISE EXCEPTION NEW /clean/some_error( ).   " dönüş kodunu exception'a çevir
ENDIF.

💡 Uzman Yorumu: Eski BAPI'lar genellikle BAPIRET2 tablosu veya TYPE alanı döndürür. Bu kontrolleri her seferinde unutmak kolaydır. Bir helper metod oluşturun ve BAPI çağrılarını hep orada yapın.

Kaynağa Git

14.4 Exception'lar Hatalar İçindir Orijinal Kaynak

Exception'ları yalnızca beklenmedik hata durumları için kullanın. Normal, geçerli durumlar için normal dönüş parametrelerini kullanın.

✓ İYİ KULLANIM
" Normal durum: Boolean döndür
METHODS entry_exists_in_db
  IMPORTING
    key           TYPE char10
  RETURNING
    VALUE(result) TYPE abap_bool.

" Hata durumu: exception fırlat
METHODS assert_user_input_is_valid
  IMPORTING
    user_input TYPE string
  RAISING
    cx_bad_user_input.
✗ KÖTÜ KULLANIM
METHODS entry_exists_in_db
  IMPORTING
    key TYPE char10
  RAISING
    cx_not_found_exception.   " "bulunamadı" normal bir durumdur, hata değil!

💡 Uzman Yorumu: Exception kullanmak hem performans maliyeti (exception nesnesi oluşturma) hem de semantik bir maliyete yol açar. Okuyucu exception gördüğünde "bir şeyler yanlış gitti" anlar. Normal durumlar için bunu kullanmak yanıltıcıdır.

Kaynağa Git

14.5 Class Tabanlı Exception Kullanın Orijinal Kaynak

Sınıf tabanlı exception kullanın. Eski sınıf dışı exception'lar dönüş kodlarıyla aynı özelliklere sahiptir ve artık kullanılmamalıdır.

✓ İYİ KULLANIM
TRY.
    get_component_types( ).
  CATCH cx_has_deep_components_error.
ENDTRY.
✗ KÖTÜ KULLANIM
get_component_types(
  EXCEPTIONS
    has_deep_components = 1
    OTHERS              = 2 ).   " eski stil - dönüş kodu gibi çalışır

💡 Uzman Yorumu: Eski EXCEPTIONS sözdizimi kullanıldığında sy-subrc'yi kontrol etmek zorundasınız; yoksa hata sessizce kaybolur. TRY/CATCH ile hataları yakalamak ya da iletmek zorunda kalırsınız.

Kaynağa Git

14.6 Kendi Üst Sınıflarınızı Kullanın Orijinal Kaynak

Her exception tipi için soyut üst sınıflar oluşturun; temel sınıfları doğrudan alt sınıflamak yerine. Bu, "tüm uygulamaya özgü exception'ları" yakalamayı sağlar.

✓ İYİ KULLANIM
CLASS cx_fra_static_check DEFINITION ABSTRACT INHERITING FROM cx_static_check.
CLASS cx_fra_no_check DEFINITION ABSTRACT INHERITING FROM cx_no_check.

💡 Uzman Yorumu: ABSTRACT, geliştiricilerin açıklayıcı olmayan bu üst sınıfları doğrudan kullanmasını önler. Tüm uygulama exception'larını tek CATCH bloğunda yakalama imkânı sağlar.

Kaynağa Git

14.7 Bir Tip Exception Fırlatın Orijinal Kaynak

Çoğu durumda birden fazla exception tipi fırlatmak gereksizdir. Çağıran genellikle bunların hepsini aynı şekilde ele alır. Tek bir üst tip kullanın ve alt sınıflarla durumlara izin verin.

✓ İYİ KULLANIM
METHODS generate
  RAISING
    cx_generation_error.
✗ KÖTÜ KULLANIM
METHODS generate
  RAISING
    cx_abap_generation
    cx_hdbr_access_error
    cx_model_read_error.   " çağıran bunların hepsini farklı mı işleyecek?

💡 Uzman Yorumu: Birden fazla exception tipi, çağırana "bunları farklı işleyebilirsin" demektir. Eğer çağıran bunların hepsini aynı şekilde işleyecekse, tek tip yeterlidir.

Kaynağa Git

14.8 Alt Sınıflarla Hata Durumlarını Ayırt Edin Orijinal Kaynak

Tek exception üst tipi kullanın ama alt sınıflarla ayrımı isteğe bağlı olarak mümkün kılın. Bu, çağıranın gerekirse ayrım yapmasına izin verirken zorlamaz.

✓ İYİ KULLANIM
CLASS cx_bad_generation_variable DEFINITION INHERITING FROM cx_generation_error.
CLASS cx_bad_code_composer_template DEFINITION INHERITING FROM cx_generation_error.

TRY.
    generator->generate( ).
  CATCH cx_bad_generation_variable.
    log_failure( ).
  CATCH cx_bad_code_composer_template INTO DATA(bad_template_exception).
    show_error_to_user( bad_template_exception ).
  CATCH cx_generation_error INTO DATA(other_exception).
    RAISE EXCEPTION NEW cx_application_error( previous =  other_exception ).
ENDTRY.

💡 Uzman Yorumu: Bu desen, Java'nın checked/unchecked exception hiyerarşisine benzer. Üst sınıf hepsini yakalar; alt sınıflar özel durumlara izin verir. En iyi tasarım esnekliği bu şekilde sağlanır.

Kaynağa Git

14.9 CX_STATIC_CHECK Kullanın Orijinal Kaynak

Yönetilebilir exception'lar için (kullanıcı giriş doğrulaması, alternatifi olan eksik kaynak) CX_STATIC_CHECK'ten türetin. Bu tip metod imzasında belirtilmeli ve yakalanmalı ya da iletilmelidir.

✓ İYİ KULLANIM
CLASS cx_file_not_found DEFINITION INHERITING FROM cx_static_check.

METHODS read_file
  IMPORTING
    file_name_enterd_by_user TYPE string
  RAISING
    cx_file_not_found.

💡 Uzman Yorumu: CX_STATIC_CHECK sözdizimi hatası olmadan geçilemez, bu nedenle çağıranlar exception'ı kabul etmek zorundadır. Bu, hata durumlarını açıkça ele almayı zorunlu kılar.

Kaynağa Git

14.10 CX_NO_CHECK Kullanın Orijinal Kaynak

Genellikle kurtarılamaz durumlar için (zorunlu kaynağa erişim başarısızlığı, çözülemez bağımlılık) CX_NO_CHECK kullanın. Bu tip metod imzasında belirtilmez.

✓ İYİ KULLANIM
CLASS cx_out_of_memory DEFINITION INHERITING FROM cx_no_check.

METHODS create_guid
  RETURNING
    VALUE(result) TYPE /bobf/conf_key.
" cx_out_of_memory imzada yok - kurtarılamaz bir durum

💡 Uzman Yorumu: CX_NO_CHECK, bellek yetersizliği gibi kurtarılamaz durumlar için tasarlanmıştır. Bu exception'ların imzada görünmemesi kasıtlıdır; çağıranın yapabileceği bir şey yoktur.

Kaynağa Git

14.11 CX_DYNAMIC_CHECK Kullanın Orijinal Kaynak

CX_DYNAMIC_CHECK için kullanım alanları nadirdir. Çağıranın bir exception'ın ortaya çıkıp çıkmayacağını tam ve bilinçli olarak kontrol edebildiği durumlarda CX_STATIC_CHECK yerine düşünün.

💡 Uzman Yorumu: CX_DYNAMIC_CHECK, çalışma zamanında kontrol edilen ama derleme zamanında zorunlu olmayan exception'lar içindir. Çok nadir kullanılır; çoğu durumda CX_STATIC_CHECK veya CX_NO_CHECK daha uygun seçenektir.

Kaynağa Git

14.12 Dump Yapın Orijinal Kaynak

Durum o kadar ağırsa ki alıcının kurtarma imkânı kesinlikle yoksa (bellek tahsisi başarısızlığı, kesinlikle dolu olması gereken tablo okuma başarısızlığı gibi) dump yapın.

✓ İYİ KULLANIM
RAISE SHORTDUMP TYPE cx_sy_create_object_error.  " NW 7.53 ve üzeri
MESSAGE x666(general).                           " NW 7.53 öncesi

💡 Uzman Yorumu: Dump, son çare olmalıdır. Sistem durumu o kadar bozuktur ki devam etmek daha büyük sorunlara yol açabilir. Bunu yalnızca programlama hatası veya tamamen kurtarılamaz sistem hataları için kullanın.

Kaynağa Git

14.13 RAISE EXCEPTION NEW Tercih Edin Orijinal Kaynak

NW 7.52 ve üzeri sürümlerde RAISE EXCEPTION TYPE yerine RAISE EXCEPTION NEW kullanın. Daha kısadır.

✓ İYİ KULLANIM
RAISE EXCEPTION NEW cx_generation_error( previous = exception ).
✗ KÖTÜ KULLANIM
RAISE EXCEPTION TYPE cx_generation_error
  EXPORTING
    previous = exception.    " gereksiz uzun

💡 Uzman Yorumu: MESSAGE eklentisini yoğun kullanıyorsanız TYPE varyantı daha uygun olabilir. Aksi takdirde NEW varyantı her zaman tercih edilmelidir.

Kaynağa Git

14.14 Yabancı Exception'ları Sarın Orijinal Kaynak

Diğer bileşenlerden gelen exception'ları iletmek yerine, kendinize ait exception tipinde sarın. Bu, Demeter yasasına uyum sağlar ve bağımlılıkları azaltır.

✓ İYİ KULLANIM
METHODS generate RAISING cx_generation_failure.

METHOD generate.
  TRY.
      generator->generate( ).
    CATCH cx_amdp_generation_failure INTO DATA(exception).
      RAISE EXCEPTION NEW cx_generation_failure( previous = exception ).
  ENDTRY.
ENDMETHOD.
✗ KÖTÜ KULLANIM
METHODS generate RAISING cx_sy_gateway_failure.
" cx_sy_gateway_failure başka bileşene ait - kodunuza yabancı element giriyor

💡 Uzman Yorumu: Yabancı exception'ları doğrudan iletmek, çağıranın o bileşen hakkında bilgi sahibi olmasını gerektirir. Bu, katmanlar arası bağımlılık yaratır. Sarma işlemi sizi o bağımlılıktan izole eder.

Kaynağa Git

15. Yorumlar

15.1 Kodda İfade Edin Orijinal Kaynak

Yorumların söyleyeceği şeyi kod aracılığıyla söyleyin. Kodu mümkün olduğunca açık ve anlaşılır yapın.

✓ İYİ KULLANIM
METHOD correct_day_to_last_in_month.
  WHILE is_invalid( date ).
    reduce_day_by_one( CHANGING date = date ).
  ENDWHILE.
ENDMETHOD.
✗ KÖTÜ KULLANIM
" correct e.g. 29.02. in non-leap years as well as result of a date calculation would be
" something like the 31.06. that has to be corrected to 30.06.
METHOD fix_day_overflow.
  DO 3 TIMES.
    lv_dummy = cv_date.
    IF ( lv_dummy EQ 0 ).
      cv_date+6(2) = cv_date+6(2) - 1.
    ELSE.
      EXIT.
    ENDIF.
  ENDDO.
ENDMETHOD.    " yorum gerekirken kod bozuk - kodu düzeltin

💡 Uzman Yorumu: Clean Code yorumu yasaklamaz; daha iyi alternatifleri kullanmayı teşvik eder. Eğer kod açıklama gerektiriyorsa, önce kodu daha açık hale getirmeyi deneyin.

Kaynağa Git

15.2 Yorumlar Kötü İsimlerin Mazereti Değil Orijinal Kaynak

İsimleri açıklamak yerine isimleri iyileştirin. Yorumlar kötü isimlendirmenin geçici bir yamadır.

✓ İYİ KULLANIM
DATA(input_has_entries) = has_entries( input ).
✗ KÖTÜ KULLANIM
" checks whether the table input contains entries
DATA(result) = check_table( input ).    " yorum gerekiyorsa isim kötü

💡 Uzman Yorumu: Yorum, değişken veya metod adının yetersizliğini gizler. İsmi açıklayan bir yorumunuz varsa, yorumu silin ve ismi düzeltin.

Kaynağa Git

15.3 Metod Kullanın, Yorum Değil Orijinal Kaynak

Kodu bölümlere ayırmak için yorum yerine metodlar kullanın. Metodlar amacı, yapıyı ve bağımlılıkları çok daha açık şekilde ortaya koyar.

✓ İYİ KULLANIM
DATA(statement) = build_statement( ).
DATA(data) = execute_statement( statement ).
✗ KÖTÜ KULLANIM
" -----------------
" Build statement
" -----------------
DATA statement TYPE string.
statement = |SELECT * FROM d_document_roots|.

" -----------------
" Execute statement
" -----------------
DATA(result_set) = adbc->execute_sql_query( statement ).
result_set->next_package( IMPORTING data = data ).

💡 Uzman Yorumu: Kodunuzda başlık yorumları yazma ihtiyacı hissediyorsanız, bu bölümleri ayrı metodlara çıkarmanın zamanı gelmiş demektir. Metodlar yorumlardan daha güçlüdür: test edilebilir ve yeniden kullanılabilirler.

Kaynağa Git

15.4 Neden Yorum Yazın Orijinal Kaynak

Ne yaptığınızı değil, neden yaptığınızı açıklayan yorumlar yazın. Kod "ne" yaptığını zaten söyler; "neden" ise arka planı, kısıtlamaları veya iş gereksinimini açıklar.

✓ İYİ KULLANIM
" can't fail, existence of >= 1 row asserted above
DATA(first_line) = table[ 1 ].
✗ KÖTÜ KULLANIM
" select alert root from database by key
SELECT * FROM d_alert_root WHERE key = key.   " kod zaten bunu söylüyor

💡 Uzman Yorumu: "Neden" yorumu gelecekteki geliştiriciye bağlamı verir. "Neden bu yol seçildi?", "Bu neden önemli?", "Bu yaklaşımın neden sınırlılıkları var?" gibi sorulara cevap verir.

Kaynağa Git

15.5 Tasarım Belgeye Gider Orijinal Kaynak

Tasarım kararları ve mimariye ilişkin uzun açıklamalar koda değil, tasarım belgelerine aittir. Kodu okumak için kitap okumak zorunda kalınmamalıdır.

💡 Uzman Yorumu: Uzun yorum blokları genellikle kimse tarafından okunmaz. Eğer tasarım belgesi gerekiyorsa, wikide veya SharePoint'te oluşturun ve kodda bağlantı verin.

Kaynağa Git

15.6 " ile Yorum Yapın Orijinal Kaynak

Yorum satırları için * yerine " kullanın. Tırnak yorumları yanındaki ifadelerle birlikte girintilenir; yıldız yorumlar ise garip yerlere girintilenir.

✓ İYİ KULLANIM
METHOD do_it.
  IF input IS NOT INITIAL.
    " delegate pattern
    output = calculate_result( input ).
  ENDIF.
ENDMETHOD.
✗ KÖTÜ KULLANIM
METHOD do_it.
  IF input IS NOT INITIAL.
* delegate pattern          " * garip bir yere girintiledi
    output = calculate_result( input ).
  ENDIF.
ENDMETHOD.

💡 Uzman Yorumu: Tırnak yorumlar koda yapışır ve birlikte girintilenebilir. Yıldız yorumlar her zaman satır başında kalır, bu da girintileme tutarsızlığı yaratır.

Kaynağa Git

15.7 Yorumu İfadenin Önüne Koyun Orijinal Kaynak

İlişkili olduğu ifadenin önüne yorum koyun, arkasına değil. Önceki yorum, "neyi" açıklar; sonraki yorum neyle ilgili olduğunu belirsiz kılar.

✓ İYİ KULLANIM
" delegate pattern
output = calculate_result( input ).
✗ KÖTÜ KULLANIM
output = calculate_result( input ).
" delegate pattern    " hangi ifadeyle ilgili? önceki mi, sonraki mi?

output = calculate_result( input ).  " delegate pattern  " satır sonu yorum - karışık

💡 Uzman Yorumu: Yorum, açıkladığı ifadeden önce gelmelidir. Bu, okuyucunun kodu önce anlamasını, sonra yorumu okumasını sağlar; neyin açıklandığı her zaman bellidir.

Kaynağa Git

15.8 Kodu Silin, Yorum Haline Getirmeyin Orijinal Kaynak

Yorum haline getirilmiş kodu silin. Uygulama çalışıyor ve testler yeşilse, bu kod açıkça gerekli değil demektir. Gerekirse versiyonlama geçmişinden geri getirilir.

✗ KÖTÜ KULLANIM
* output = calculate_result( input ).    " bu kod neden burada? güvenli mi silmek?

💡 Uzman Yorumu: Yorum haline getirilmiş kod şunu söyler: "Bunu silmek korktum." Versiyon kontrol sisteminize güvenin. Kod her zaman geçmişte mevcut olacak.

Kaynağa Git

15.9 Manuel Versiyonlama Yapmayın Orijinal Kaynak

Kodda ticket/kullanıcı açıklama yorumları eklemeyin. Versiyonlama zaten versiyon kontrol sistemi tarafından yapılıyor.

✗ KÖTÜ KULLANIM
* ticket 800034775 ABC ++ Start
output = calculate_result( input ).
* ticket 800034775 ABC ++ End    " versiyon kontrol sistemi bunu zaten biliyor

💡 Uzman Yorumu: Atıf yorumları kodu kirletir ve gerçek bir değer katmaz. Transport order notları neden bir şeyin değiştirildiğini açıklamak için çok daha uygun bir yerdir.

Kaynağa Git

15.10 FIXME, TODO, XXX Kullanın Orijinal Kaynak

Geçici sorunları belirtmek için tanınmış etiketleri kullanın ve kendi kimliğinizi ekleyin. Bu, soruların kime yöneltileceğini belirler.

✓ İYİ KULLANIM
METHOD do_something.
  " XXX FH delete this method - it does nothing
  " TODO AB refactor this when ticket #1234 is resolved
  " FIXME MK this crashes with empty input - bug #5678
ENDMETHOD.

💡 Uzman Yorumu: FIXME = düzeltilmesi gereken hata, TODO = yakın gelecekte yapılacak iş, XXX = çalışıyor ama daha iyi olabilir. Kimlik eklemeyi unutmayın: soruları kime yönelteceğinizi bilmek önemlidir.

Kaynağa Git

15.11 Metod İmzası ve Son Yorumları Eklemeyin Orijinal Kaynak

Metod imzası yorumları veya ENDIF/ENDMETHOD yorumları eklemeyin. Modern IDE'ler bu bilgiyi kolayca gösterir.

✗ KÖTÜ KULLANIM
* <SIGNATURE>
* | Static Public Method CALIBRATION_KPIS=>CALCULATE_KPI
* | [->] STRATEGY_ID  TYPE STRATEGY_ID
* | [<-] KPI          TYPE T_SIMULATED_KPI
* </SIGNATURE>

METHOD get_kpi_calc.
  IF has_entries = abap_false.
    result = 42.
  ENDIF.  " IF has_entries = abap_false    " gereksiz
ENDMETHOD.   " get_kpi_calc               " gereksiz

💡 Uzman Yorumu: ADT'de F2, SE24'te Signature düğmesi ile metod imzasına anında erişebilirsiniz. Bu yorumlar eski dönemin eserleriydi; şimdi sadece gürültü.

Kaynağa Git

15.12 Mesaj Metinlerini Kopyalamayın Orijinal Kaynak

Mesaj metinlerini yorum olarak kopyalamayın. Mesajlar koddan bağımsız olarak değişir ve yorum hızla eskiyerek yanıltıcı hale gelir.

✗ KÖTÜ KULLANIM
" alert category not filled    " yarın bu mesaj değişecek ama yorum kalmaya devam eder
MESSAGE e003 INTO dummy.

💡 Uzman Yorumu: ADT'de mesaj ID'si üzerine tıklayarak mesaj metnini anında görebilirsiniz. Yorumlar güncellenmez; mesaj metin deposu ise güncellenir. Kopyalamak yerine araca güvenin.

Kaynağa Git

15.13 ABAP Doc Sadece Public API İçin Orijinal Kaynak

ABAP Doc'u yalnızca public API'ları belgelemek için yazın; iç yapı için değil. ABAP Doc tüm yorumlar gibi hızla eskir ve yanıltıcı hale gelebilir.

💡 Uzman Yorumu: ABAP Doc, Javadoc gibi API tüketicilerine yönelik belgeleme sağlar. Ancak her sınıf ve metoda yazmak, bakımı zor eski belgeleme yığını oluşturur. Yalnızca gerçekten public API için kullanın.

Kaynağa Git

15.14 Pragma Tercih Edin Orijinal Kaynak

ATC tarafından tanımlanan ilgisiz uyarıları bastırmak için pseudo yorum yerine pragma kullanın. Pseudo yorumlar büyük ölçüde eski ve pragmalarla değiştirilmiştir.

✓ İYİ KULLANIM
MESSAGE e001(ad) INTO DATA(message) ##NEEDED.
✗ KÖTÜ KULLANIM
MESSAGE e001(ad) INTO DATA(message). "#EC NEEDED    " eski stil pseudo yorum

💡 Uzman Yorumu: ABAP_SLIN_PRAGMAS programını veya SLIN_DESC tablosunu kullanarak eski pseudo yorumlar ile karşılık gelen pragmalar arasındaki eşlemeyi bulabilirsiniz.

Kaynağa Git

16. Biçimlendirme

16.1 Tutarlı Olun Orijinal Kaynak

Bir projenin tüm kodunu aynı şekilde biçimlendirin. Yabancı koda dokunduğunuzda, o projenin biçimlendirme stiline uyun; kendi kişisel stilinizi dayatmayın.

💡 Uzman Yorumu: Tutarsız biçimlendirme, "bu neden farklı?" sorusunu gündeme getirir ve okuyucuyu anlamlı bir fark olduğunu düşündürür. Tutarlılık dikkat dağıtmadan koda odaklanmayı sağlar.

Kaynağa Git

16.2 Okumak İçin Optimize Edin Orijinal Kaynak

Geliştiriciler zamanlarının çoğunu kod okuyarak geçirir. Kod yazmak günün çok küçük bir bölümünü kaplar. Bu nedenle okuma ve hata ayıklama için optimize edin, yazma için değil.

✓ İYİ KULLANIM
DATA:
  a TYPE b,
  c TYPE d,
  e TYPE f.
✗ KÖTÜ KULLANIM
DATA:
  a TYPE b
  ,c TYPE d
  ,e TYPE f.    " virgülü başa koymak yazmayı kolaylaştırır ama okumayı zorlaştırır

💡 Uzman Yorumu: "Yazmayı kolaylaştırmak" için yapılan biçimlendirme hacks'leri, okumayı zorlaştırır. Her kod satırı onlarca kez okunur ama yalnızca bir kez yazılır.

Kaynağa Git

16.3 ABAP Formatter Kullanın Orijinal Kaynak

Aktifleştirmeden önce ABAP Formatter'ı uygulayın (SE80/SE24'te Shift+F1, ADT'de Pretty Printer). Biçimlenmemiş büyük legacy kodlarda yalnızca seçili satırlara uygulamayı düşünün.

💡 Uzman Yorumu: Formatter'ı seçici kullanmak büyük diff'lerin oluşmasını önler. Legacy kodu bütünüyle formatlamak istiyorsanız, bunu ayrı bir transport request'te yapın.

Kaynağa Git

16.4 Takım Ayarlarını Kullanın Orijinal Kaynak

Her zaman takımınızın ABAP Formatter ayarlarını kullanın. Büyük harf/küçük harf tercihlerini ve girinti ayarlarını proje düzeyinde belirleyin.

💡 Uzman Yorumu: ADT'de proje bazlı formatter ayarları yapabilirsiniz. Bu, tüm ekip üyelerinin aynı biçimlendirmeyi kullanmasını otomatik sağlar ve "büyük harf mi küçük harf mi?" tartışmalarını önler.

Kaynağa Git

16.5 Satır Başına Bir İfade Orijinal Kaynak

Her satıra yalnızca bir ifade yazın. Birden fazla ifadeyi tek satırda birleştirmek okumayı ve hata ayıklamayı zorlaştırır.

✓ İYİ KULLANIM
DATA do_this TYPE i.
do_this = input + 3.
✗ KÖTÜ KULLANIM
DATA do_this TYPE i. do_this = input + 3.    " iki ifade, bir satır

💡 Uzman Yorumu: Birden fazla ifadeyi tek satırda birleştirmek, debugger ile adım adım ilerlerken hangi ifadenin çalıştırıldığını belirsiz kılar. Her satırda tek ifade bu sorunu ortadan kaldırır.

Kaynağa Git

16.6 Makul Satır Uzunluğu Orijinal Kaynak

Maksimum 120 karakter satır uzunluğuna uyun. İnsan gözü çok geniş satırları okumakta zorlanır. ADT'de 120 karakter sınırını görsel çizgi olarak yapılandırabilirsiniz.

💡 Uzman Yorumu: 80 karakter sınırı eski terminal döneminden gelir ve ABAP için çok kısıtlayıcıdır. ABAP'ın yapısal sözdizimi göz önüne alındığında 120 karakter daha pratiktir.

Kaynağa Git

16.7 Kodu Yoğunlaştırın Orijinal Kaynak

Gereksiz boşluk eklemeyerek kodu yoğunlaştırın. Gereksiz boşluklar okumayı zorlaştırır ve gürültü ekler.

✓ İYİ KULLANIM
DATA(result) = calculate( items ).
✗ KÖTÜ KULLANIM
DATA(result)        =      calculate(    items =   items )   .    " gereksiz boşluklar

💡 Uzman Yorumu: Hizalama amacıyla eklenen boşluklar, değişken adı uzunlukları değiştiğinde tüm satırları yeniden düzenlemenizi gerektirir. Bunu ABAP Formatter'a bırakın.

Kaynağa Git

16.8 Tek Boş Satır Ekleyin Orijinal Kaynak

Farklı şeyleri birbirinden ayırmak için tek boş satır kullanın, birden fazla değil. Birden fazla boş satır gereksiz yere alanı kaplar.

✓ İYİ KULLANIM
DATA(result) = do_something( ).

DATA(else) = calculate_this( result ).
✗ KÖTÜ KULLANIM
DATA(result) = do_something( ).



DATA(else) = calculate_this( result ).    " üç boş satır - gereksiz

💡 Uzman Yorumu: Çok fazla boş satır eklemek, metodun tek bir şey yapmadığının göstergesi olabilir. Boş satır ihtiyacı hissediyorsanız, o bölümü ayrı bir metoda çıkarmanın zamanı gelmiş olabilir.

Kaynağa Git

16.9 Boş Satır Konusunda Obsesif Olmayın Orijinal Kaynak

Her ifadeyi boş satırlarla ayırma alışkanlığından kaçının. Birbirine ait ifadeler bir arada durmalı.

✓ İYİ KULLANIM
METHOD do_something.
  do_this( ).
  then_that( ).
ENDMETHOD.
✗ KÖTÜ KULLANIM
METHOD do_something.

  do_this( ).

  then_that( ).

ENDMETHOD.    " her ifade arasında boş satır - aşırı parçalama

💡 Uzman Yorumu: Boş satırlar anlam taşımalıdır: "bu ifadeler farklı bir şey yapıyor". Anlamsız boş satırlar dikkati dağıtır ve metodun ne kadar büyük göründüğünü yapay olarak artırır.

Kaynağa Git

16.10 Aynı Nesneye Atamaları Hizalayın Orijinal Kaynak

Aynı nesneye ait atamaları hizalayın ama ilgisiz atamalar arasında hizalamaya gerek yok.

✓ İYİ KULLANIM
structure-type = 'A'.
structure-id   = '4711'.

" ya da daha iyisi
structure = VALUE #( type = 'A'
                     id   = '4711' ).
✗ KÖTÜ KULLANIM
customizing_reader = fra_cust_obj_model_reader=>s_get_instance( ).
hdb_access         = fra_hdbr_access=>s_get_instance( ).   " ilgisiz atamalar hizalanmış

💡 Uzman Yorumu: Hizalama görsel olarak ilişkiyi ortaya koyar. Aynı yapının alanları arasında hizalama anlamlıdır. İlgisiz atamalar arasında hizalama ise yanıltıcıdır.

Kaynağa Git

16.11 Parantezleri Satır Sonunda Kapatın Orijinal Kaynak

Parantezleri satır sonunda kapatın; ayrı satırda değil. Ayrı satırda kapatılan parantez gereksizce kod uzunluğunu artırır.

✓ İYİ KULLANIM
modify->update( node           = if_fra_alert_c=>node-item
                key            = item->key
                data           = item
                changed_fields = changed_fields ).
✗ KÖTÜ KULLANIM
modify->update( node           = if_fra_alert_c=>node-item
                key            = item->key
                data           = item
                changed_fields = changed_fields
).    " ayrı satırda kapanan parantez gereksiz

💡 Uzman Yorumu: Kapanan parantezi son parametrenin yanında bırakmak kodu daha kompakt tutar. Ayrı satırda kapatma yalnızca kodun daha uzun görünmesini sağlar ve bir değer katmaz.

Kaynağa Git

16.12 Tek Parametreli Çağrıları Tek Satırda Tutun Orijinal Kaynak

Tek parametreli çağrıları tek satırda tutun. Gereksiz satır kırmaları okunabilirliği azaltır.

✓ İYİ KULLANIM
DATA(unique_list) = remove_duplicates( list ).
remove_duplicates( CHANGING list = list ).
✗ KÖTÜ KULLANIM
DATA(unique_list) = remove_duplicates(
                         CHANGING
                           list = list ).    " tek parametre için gereksiz uzun

💡 Uzman Yorumu: Çok parametreli çağrılar için satır kırma mantıklıdır. Ama tek bir parametre için birden fazla satır kullanmak gereksiz alan israfıdır.

Kaynağa Git

16.13 Parametreleri Çağrının Arkasında Tutun Orijinal Kaynak

Parametreleri mümkün olduğunda çağrının aynı satırında tutun. Satır çok uzarsa bir sonraki satıra taşıyın.

✓ İYİ KULLANIM
DATA(sum) = add_two_numbers( value_1 = 5
                             value_2 = 6 ).

DATA(sum) = add_two_numbers(
                value_1 = round_up( input DIV 7 ) * 42 + round_down( 19 * step_size )
                value_2 = VALUE #( ( `Calculation failed with a very weird result` ) ) ).

💡 Uzman Yorumu: Parametre çok uzunsa yeni satıra geçin ama yeni satır = yeni seviye girintileme demektir. Girinti, parametrelerin hangi metodun girdileri olduğunu açıkça göstermelidir.

Kaynağa Git

16.14 Parametreleri Çağrının Altına Hizalayın Orijinal Kaynak

Satır kırıldığında parametreleri çağrının altına 4 boşlukla girintileyin.

✓ İYİ KULLANIM
DATA(sum) = add_two_numbers(
                value_1 = 5
                value_2 = 6 ).
✗ KÖTÜ KULLANIM
DATA(sum) = add_two_numbers(
    value_1 = 5
    value_2 = 6 ).    " az girintileme hangi metoda ait olduğunu belirsiz kılar

💡 Uzman Yorumu: Yeterli girintileme, parametrelerin hangi metoda ait olduğunu görsel olarak gösterir. Az girintileme ise parametreleri bağımsız ifadeler gibi gösterir.

Kaynağa Git

16.15 Çoklu Parametreleri Ayrı Satırlara Bölün Orijinal Kaynak

Birden fazla parametreyi ayrı satırlara bölün. Parametreleri aynı satırda sıralamak, birinin nerede bitip diğerinin nerede başladığını belirsiz kılar.

✓ İYİ KULLANIM
DATA(sum) = add_two_numbers( value_1 = 5
                             value_2 = 6 ).
✗ KÖTÜ KULLANIM
DATA(sum) = add_two_numbers( value_1 = 5 value_2 = 6 ).    " parametre sınırları belirsiz

💡 Uzman Yorumu: Parametreler aynı satırda sıralandığında, özellikle değerler de ifade içeriyorsa, bir parametrenin nerede bitip diğerinin nerede başladığını anlamak çok zorlaşır.

Kaynağa Git

16.16 Parametreleri Hizalayın Orijinal Kaynak

Parametreleri hizalayın. Bu, parametre adı ile değer arasındaki sınırı net gösterir.

✓ İYİ KULLANIM
modify->update( node           = if_fra_alert_c=>node-item
                key            = item->key
                data           = item
                changed_fields = changed_fields ).
✗ KÖTÜ KULLANIM
modify->update( node = if_fra_alert_c=>node-item
                key = item->key
                data = item
                changed_fields = changed_fields ).    " düzensiz kenar, okunması zor

💡 Uzman Yorumu: Hizalanmış parametreler tablo gibi görünür: ad sütunu ve değer sütunu. Bu düzenli yapı, bir bakışta tüm parametreleri ve değerlerini anlamayı kolaylaştırır.

Kaynağa Git

16.17 Satır Çok Uzunsa Yeni Satıra Geçin Orijinal Kaynak

Satır çok uzarsa, atamayı yeni satıra alın ve metod çağrısını girintileyin.

✓ İYİ KULLANIM
DATA(some_super_long_param_name) =
  if_some_annoying_interface~add_two_numbers_in_a_long_name(
      value_1 = 5
      value_2 = 6 ).

💡 Uzman Yorumu: Çok uzun değişken veya metod adları bazen satırı 120 karakteri aşmaya zorlar. Bu durumda atamayı bir satır, çağrıyı sonraki satırlara bölerek okunabilirliği koruyun.

Kaynağa Git

16.18 Girintile ve Sekmeye Yapış Orijinal Kaynak

Parametre anahtar sözcüklerini 2 boşlukla, parametreleri 4 boşlukla girintileyin. Girintilemek için Tab tuşunu kullanın.

✓ İYİ KULLANIM
DATA(sum) = add_two_numbers(
              EXPORTING
                value_1 = 5
                value_2 = 6
              CHANGING
                errors  = errors ).

DATA(sum) = add_two_numbers(
                value_1 = 5
                value_2 = 6 ).    " anahtar sözcük yoksa 4 boşluk

💡 Uzman Yorumu: Tutarlı girintileme kuralı öğrenildiğinde, kod yapısı zihinde otomatik olarak ayrıştırılır. Rastgele girintileme ise her seferinde aktif düşünme gerektirir.

Kaynağa Git

16.19 Inline Bildirimleri Girintile Orijinal Kaynak

VALUE veya NEW ile inline bildirimlerini metod çağrısıymış gibi girintileyin.

✓ İYİ KULLANIM
DATA(result) = merge_structures( a = VALUE #( field_1 = 'X'
                                              field_2 = 'A' )
                                 b = NEW /clean/structure_type( field_3 = 'C'
                                                                field_4 = 'D' ) ).

💡 Uzman Yorumu: VALUE # ve NEW # yapıları görsel olarak metod çağrısına çok benzer. Aynı girintileme kurallarını uygulamak tutarlılığı sağlar ve kodu daha tahmin edilebilir kılar.

Kaynağa Git

16.20 Tip Cümlelerini Hizalamayın Orijinal Kaynak

Değişken adları ve TYPE cümleleri arasında hizalama yapmayın. Değişken ve onun tipi birbirine yakın durmalı; aşırı hizalama bağı kopuk gösterir.

✓ İYİ KULLANIM
DATA name TYPE seoclsname.
DATA reader TYPE REF TO /clean/reader.
✗ KÖTÜ KULLANIM
DATA name   TYPE seoclsname.
DATA reader TYPE REF TO /clean/reader.    " hizalama iki sütun var gibi gösteriyor

💡 Uzman Yorumu: TYPE hizalaması değişken ve tip arasındaki bağı görsel olarak zayıflatır. Ayrıca uzun değişken adları eklendiğinde tüm satırların yeniden düzenlenmesini gerektirir.

Kaynağa Git

16.21 Zincirleme Atamalar Yapmayın Orijinal Kaynak

Zincirleme atamalardan kaçının. Bu okuyucuyu şaşırtır ve inline bildirimlerle çalışmaz.

✓ İYİ KULLANIM
var2 = var3.
var1 = var3.
✗ KÖTÜ KULLANIM
var1 = var2 = var3.    " JavaScript'teki a = (b == c) ile karıştırılabilir

💡 Uzman Yorumu: ABAP'ta = hem karşılaştırma hem atama için kullanılır. Zincirleme atama bu belirsizliği daha da artırır. Ayrıca inline bildirimlerle uyumlu değildir.

Kaynağa Git

17. Test

17.1 Test Edilebilir Kod Yazın Orijinal Kaynak

Tüm kodu otomatik olarak test edebileceğiniz şekilde yazın. Bunu yapmak için kodunuzu refactor etmeniz gerekiyorsa, önce bunu yapın. Eklediğiniz her yeni özelliği en az birim testi ile doğrulayın.

�� Uzman Yorumu: Test edilemeyen kod, kalitesi hakkında hiçbir garanti verilemeyen koddur. Test edilebilirlik genellikle iyi tasarımın yan ürünüdür; Dependency Injection, arayüzler ve küçük sınıflar hem iyi tasarımı hem de test edilebilirliği sağlar.

Kaynağa Git

17.2 Başkalarının Sizi Mock'lamasını Sağlayın Orijinal Kaynak

Başkaları tarafından tüketilecek kod yazıyorsanız, onların kendi kodları için birim testleri yazabilmesini sağlayın. Tüm dış yüzlerde arayüzler ekleyin, entegrasyon testlerini kolaylaştıran test double'ları sağlayın.

💡 Uzman Yorumu: Bir kütüphane veya API yazan geliştiricinin sorumluluğu, tüketicilerin test yazabilmesini sağlamaktır. Sınıf tabanlı bir API sunun ve arayüz sağlayın; böylece tüketiciler mock test double'lar oluşturabilir.

Kaynağa Git

17.3 Okunabilirlik Kuralları Orijinal Kaynak

Test kodunuzu üretim kodunuzdan daha okunabilir yapın. Kötü üretim kodunu iyi testlerle telafi edebilirsiniz, ama testlerinizi bile anlayamıyorsanız kaybolmuşsunuzdur. Test kodunu standartlara ve kalıplara bağlı kalacak kadar basit ve anlaşılır tutun.

💡 Uzman Yorumu: Test kodu üretim kodu kadar önemsiz değildir; aksine daha kritik olabilir. Bir yıl sonra bile anlayabileceğiniz testler yazın. Karmaşık testler, test etme sırasında farkında olmadan bir hata üretilip üretilmediğini gizler.

Kaynağa Git

17.4 Kopya Yapmayın Orijinal Kaynak

Geliştirme nesnesinin $TMP kopyasını oluşturup onun üzerinde denemeler yaparak çalışmaya başlamayın. Başkalarının bu nesnelerden haberi olmaz ve çalışmanızın durumunu bilemezler. Kopyayı silmeyi de unutursunuz.

💡 Uzman Yorumu: $TMP kopyalar hem yer israfıdır hem de kafa karışıklığı kaynağıdır. Doğrudan gerçek nesne üzerinde çalışın ve otomatik testlerle doğrulayın. Bu disiplin uzun vadede çok daha verimlidir.

Kaynağa Git

17.5 Public'leri Test Edin Orijinal Kaynak

Sınıfların public bölümlerini, özellikle implemente ettikleri arayüzleri test edin. İç yapıyı (private/protected) değil, dışa açık davranışı doğrulayın.

💡 Uzman Yorumu: Private metodları test etme ihtiyacı genellikle tasarım sorunlarının habercisidir. "Bu private metod ayrı bir sınıf olabilir mi?" diye sorun. Eğer cevap evetse, o sınıfı çıkarın ve ayrı test edin.

Kaynağa Git

17.6 Kapsam Konusunda Obsesif Olmayın Orijinal Kaynak

Kod kapsamı, test etmeyi unuttuğunuz kodu bulmak içindir; rastgele bir KPI'yı karşılamak için değil. Assert olmayan sahte testler yazmayın. %100 kapsamdan daha az ile mükemmel testleriniz olabilir.

💡 Uzman Yorumu: %100 kapsam hedeflemek genellikle değersiz testler üretir. Gerçek değer, önemli iş mantığının test edildiğinden emin olmaktır. Rakamları hedeflemek yerine kaliteye odaklanın.

Kaynağa Git

17.7 Yerel Test Sınıflarını Adlandırın Orijinal Kaynak

Yerel test sınıflarını "ne zaman" veya "ne verildiğinde" bölümüne göre adlandırın. Test sınıfının adı senaryoyu açıklamalıdır.

✓ İYİ KULLANIM
CLASS ltc_when_all_entries_are_clean DEFINITION FOR TESTING ...
CLASS ltc_given_empty_table DEFINITION FOR TESTING ...
✗ KÖTÜ KULLANIM
CLASS ltc_fra_online_detection_api DEFINITION FOR TESTING ...   " test edilen sınıfı tekrar ediyor
CLASS ltc_test DEFINITION FOR TESTING ...                        " test olmayan ne ki?

💡 Uzman Yorumu: Test sınıfının adı, o sınıftaki testlerin ortak bağlamını açıklamalıdır. Sınıf adını tekrar etmek gereksizdir; herkes zaten hangi sınıfı test ettiğini biliyor.

Kaynağa Git

17.8 Testleri Yerel Sınıflara Koyun Orijinal Kaynak

Birim testlerini test edilen sınıfın yerel test include'una koyun. Bu, geliştiricilerin refactoring sırasında testleri bulmasını sağlar ve tek tuş basışıyla ilgili tüm testlerin çalıştırılmasına olanak tanır.

💡 Uzman Yorumu: Yerel test include (TEST INCLUDE veya Test Classes tab) testlerin üretim kodunun yanında yer almasını sağlar. Bu, testlerin gözden kaçmamasını garantiler.

Kaynağa Git

17.9 Yardımcı Metodları Yardımcı Sınıflara Koyun Orijinal Kaynak

Birden fazla test sınıfı tarafından kullanılan yardım metodlarını yardım sınıfına koyun. Kalıtım (is-a) veya delegasyon (has-a) ilişkisiyle kullanıma açın.

✓ İYİ KULLANIM
CLASS lth_unit_tests DEFINITION ABSTRACT.
  PROTECTED SECTION.
    CLASS-METHODS assert_activity_entity
      IMPORTING
        actual_activity_entity   TYPE REF TO zcl_activity_entity
        expected_activity_entity TYPE REF TO zcl_activity_entity.
ENDCLASS.

CLASS ltc_unit_tests DEFINITION INHERITING FROM lth_unit_tests FINAL FOR TESTING
  DURATION SHORT
  RISK LEVEL HARMLESS.

💡 Uzman Yorumu: Test yardım sınıfları DRY prensibini test koduna da uygular. Tekrarlayan assertion veya setup kodu yardım sınıfına taşınmalı ve paylaşılmalıdır.

Kaynağa Git

17.10 Test Sınıfları Nasıl Çalıştırılır Orijinal Kaynak

ABAP Development Tools'da testleri hızlı çalıştırmak için klavye kısayolları:

Kısayol Etki
Ctrl+Shift+F9 Test ilişkileri dahil tüm testleri önizle
Ctrl+Shift+F10 Sınıftaki tüm testleri çalıştır
Ctrl+Shift+F11 Testleri çalıştır + kapsam ölçümü
Ctrl+Shift+F12 Test ilişkilerindeki testleri de çalıştır

💡 Uzman Yorumu: Bu kısayolları ezberlemenizi kesinlikle öneririm. Testleri kod değişikliğinden hemen sonra çalıştırmak, sorunları erken tespit etmenin en hızlı yoludur.

Kaynağa Git

17.11 Test Edilen Kodu Anlamlı Adlandırın Orijinal Kaynak

Test edilen kodu temsil eden değişkeni anlamlı adlandırın. Anlam bulamazsanız varsayılan olarak "cut" (code under test) kullanın.

✓ İYİ KULLANIM
DATA blog_post TYPE REF TO ...
DATA empty_blog_post TYPE REF TO ...
DATA cut TYPE REF TO ...    " anlam bulamazsanız
✗ KÖTÜ KULLANIM
DATA clean_fra_blog_post TYPE REF TO ...    " sınıf adını gereksizce tekrar ediyor

💡 Uzman Yorumu: "cut" evrensel bir kısaltmadır. Değişken adı, test durumunun durumunu açıklayabiliyorsa (empty_blog_post, published_blog_post) bunu tercih edin. "cut" ise karmaşık testlerde bile hızlıca ne test edildiğini anlamayı sağlar.

Kaynağa Git

17.12 Implementation'lara Karşı Değil Arayüzlere Karşı Test Edin Orijinal Kaynak

Test edilen kodu sınıf yerine arayüzle tiplendirilmiş değişkende tutun. Bu, public API'yı test ettiğinizi garanti eder.

✓ İYİ KULLANIM
DATA code_under_test TYPE REF TO some_interface.
✗ KÖTÜ KULLANIM
DATA code_under_test TYPE REF TO some_class.    " sınıfa bağlı - iç yapıyı test etmeye açık

💡 Uzman Yorumu: Arayüz üzerinden test etmek, testlerinizin yalnızca public davranışa bağlı olmasını sağlar. Sınıf iç yapısı değişse bile testleriniz çalışmaya devam eder.

Kaynağa Git

17.13 Çağrıyı Ayrı Metoda Çıkarın Orijinal Kaynak

Test edilen metodun birçok parametre veya hazırlık verisi gerektiriyorsa, çağrıyı varsayılan değerlere sahip bir yardım metoduna çıkarın.

✓ İYİ KULLANIM
METHODS map_xml_to_itab
  IMPORTING
    xml_string TYPE string
    config     TYPE /clean/xml2itab_config DEFAULT default_config
    format     TYPE /clean/xml2itab_format DEFAULT default_format.

DATA(itab) = map_xml_to_itab( '<xml></xml>' ).
✗ KÖTÜ KULLANIM
DATA(itab) = cut->map_xml_to_itab( xml_string = '<xml></xml>'
                                   config     = VALUE #( 'some meaningless stuff' )
                                   format     = VALUE #( 'more meaningless stuff' ) ).

💡 Uzman Yorumu: Test bağlamında önemsiz parametreler gereksiz karmaşıklık yaratır. Varsayılan değerleri olan yardım metodları, testin gerçek amacına odaklanmanızı sağlar.

Kaynağa Git

17.14 Dependency Inversion Kullanın Orijinal Kaynak

Tüm bağımlılıkları constructor aracılığıyla geçirin. Setter injection veya FRIENDS injection kullanmayın.

✓ İYİ KULLANIM
METHODS constructor
  IMPORTING
    customizing_reader TYPE REF TO if_fra_cust_obj_model_reader.

METHOD constructor.
  me->customizing_reader = customizing_reader.
ENDMETHOD.
✗ KÖTÜ KULLANIM
" Setter injection - üretim kodu kasıtsız kullanıma açık
METHODS set_customizing_reader
  IMPORTING
    customizing_reader TYPE REF TO if_fra_cust_obj_model_reader.

💡 Uzman Yorumu: Constructor injection en temiz bağımlılık enjeksiyon yöntemidir. Nesne oluşturulduktan sonra bağımlılıkları değiştirmeye izin vermez, bu da nesnenin tutarlı bir durumda kalmasını garantiler.

Kaynağa Git

17.15 ABAP Test Double Aracını Kullanın Orijinal Kaynak

ABAP test double aracını (cl_abap_testdouble) kullanın. Elle yazılmış test double sınıflarından daha kısa ve anlaşılırdır.

✓ İYİ KULLANIM
DATA(customizing_reader) = CAST /clean/customizing_reader(
  cl_abap_testdouble=>create( '/clean/default_custom_reader' ) ).
cl_abap_testdouble=>configure_call( customizing_reader )->returning( sub_claim_customizing ).
customizing_reader->read( 'SOME_ID' ).

💡 Uzman Yorumu: cl_abap_testdouble, elle yazılmış mock sınıflardan çok daha az kod gerektirir ve daha güçlüdür. Beklentileri yapılandırmak, gerçek çağrıları doğrulamak ve return değerleri ayarlamak için tam destek sunar.

Kaynağa Git

17.16 Test Araçlarından Yararlanın Orijinal Kaynak

Genel olarak clean bir programlama stili, standart ABAP birim testleri ve test double'larla işin büyük çoğunluğunu yapmanıza imkân tanır. Mevcut çerçevelerin bir listesi için SAP örnekler deposuna bakın.

💡 Uzman Yorumu: SAP, test izolasyonu için çeşitli araçlar sunar. Bu araçları keşfetmek için zaman ayırın; doğru aracı seçmek test kodu yazma miktarını önemli ölçüde azaltır.

Kaynağa Git

17.17 Test Seams'i Geçici Çözüm Olarak Kullanın Orijinal Kaynak

Tüm diğer teknikler başarısız olduğunda veya legacy kodun tehlikeli sığ sularında test seams kullanın. Bunlar invaziv ve uzun vadede zordur; yalnızca geçici çözüm olarak kullanın.

💡 Uzman Yorumu: Test seams (TEST-SEAM/END-TEST-SEAM) üretim koduna test kancaları ekler. Bu yöntem, kodu "kirletir" ama legacy kodu test altına almak için bazen tek yol budur. Refactoring tamamlandığında kaldırın.

Kaynağa Git

17.18 LOCAL FRIENDS Kullanın Orijinal Kaynak

CREATE PRIVATE ile tanımlanmış sınıflara test erişimi sağlamak için LOCAL FRIENDS kullanın.

✓ İYİ KULLANIM
CLASS /clean/unit_tests DEFINITION.
  PRIVATE SECTION.
    DATA cut TYPE REF TO /clean/interface_under_test.
    METHODS setup.
ENDCLASS.

CLASS /clean/class_under_test DEFINITION LOCAL FRIENDS unit_tests.

CLASS unit_tests IMPLEMENTATION.
  METHOD setup.
    DATA(mock) = cl_abap_testdouble=>create( '/clean/some_mock' ).
    cut = NEW /clean/class_under_test( mock ).
  ENDMETHOD.
ENDCLASS.

💡 Uzman Yorumu: LOCAL FRIENDS, CREATE PRIVATE sınıfları test için erişilebilir kılar. Bu, sınıfın dışarıdan oluşturulmasını sınırlandırırken test kodu için istisnaya izin verir.

Kaynağa Git

LOCAL FRIENDS'i Kötüye Kullanmayın Orijinal Kaynak

LOCAL FRIENDS'i test edilen koda mock veri enjekte etmek için kötüye kullanmayın. Bu testleri kırılgan yapar; iç yapı değiştiğinde testler bozulur.

✗ KÖTÜ KULLANIM
CLASS /dirty/class_under_test DEFINITION LOCAL FRIENDS unit_tests.
CLASS unit_tests IMPLEMENTATION.
  METHOD returns_right_result.
    cut->some_private_member = 'AUNIT_DUMMY'.    " private üyeye doğrudan erişim kırılgan

💡 Uzman Yorumu: Private üyelere doğrudan erişim, testi iç yapıya bağlar. İç yapı refactor edildiğinde test de bozulur. Constructor injection kullanmak bu sorunu tamamen önler.

Kaynağa Git

17.20 Production Koduna Test Özellikleri Eklemeyin Orijinal Kaynak

Üretim koduna yalnızca otomatik test için kullanılacak özellikler eklemeyin.

✗ KÖTÜ KULLANIM
IF is_unit_test_running = abap_true.
  "some logic here that runs only during unit tests
ENDIF.
" Üretim kodu test durumunu bilmemelidir!

💡 Uzman Yorumu: Üretim kodu test durumundan haberdar olmamalıdır. Bu, SoC (Separation of Concerns) prensibini ihlal eder. Test seams veya dependency injection kullanın.

Kaynağa Git

17.21 Alt Sınıf Oluşturarak Mock Yapmayın Orijinal Kaynak

Metodları mock'lamak için alt sınıf oluşturup geçersiz kılmayın. Bu kırılgandır ve gerçek tüketicilerin de sınıfınızı miras almasını mümkün kılar.

✗ KÖTÜ KULLANIM
CLASS unit_tests DEFINITION INHERITING FROM /dirty/real_class FOR TESTING [...].
  PROTECTED SECTION.
    METHODS needs_to_be_mocked REDEFINITION.    " kırılgan ve FINAL tasarımı bozar

💡 Uzman Yorumu: Alt sınıf mock, FINAL tasarımını ihlal eder ve refactoring'de kolayca kırılır. Arayüze dayalı tasarım ve cl_abap_testdouble çok daha sağlam bir alternatif sunar.

Kaynağa Git

17.22 Gerekmeyen Şeyleri Mock'lamayın Orijinal Kaynak

Verilerinizi olabildiğince kesin tanımlayın: testinizin gerektirmediği veriler ayarlamayın, hiç çağrılmayan nesneleri mock'lamayın.

✓ İYİ KULLANIM
cut = NEW /clean/class_under_test( db_reader = db_reader
                                   config    = VALUE #( )
                                   writer    = VALUE #( ) ).
✗ KÖTÜ KULLANIM
cut = NEW /dirty/class_under_test( db_reader = db_reader
                                   config    = config      " gerçekten gerekli mi?
                                   writer    = writer ).   " test bu mock'u çağırıyor mu?

💡 Uzman Yorumu: Gereksiz mock'lar testlerin ne yaptığını gizler. Okuyucu "bu mock neden burada?" diye merak eder. Yalnızca gerçekten test için gerekli olan şeyleri mock'layın.

Kaynağa Git

17.23 Test Framework'leri Oluşturmayın Orijinal Kaynak

Birim testleri için veri içi çerçeveler oluşturmayın. Test case ID'leri veri sağlamaya karar veren çerçeveler oluşturursanız, kodu uzun vadede yaşatamayacaksınız.

✓ İYİ KULLANIM
cl_abap_testdouble=>configure_call( test_double )->returning( data ).
✗ KÖTÜ KULLANIM
test_double->set_test_case( 1 ).
CASE test_case.
  WHEN 1.
  WHEN 2.
ENDCASE.    " ölçeği artıkça yönetilmesi imkânsız hale gelir

💡 Uzman Yorumu: Test case ID'leriyle veri yönetimi, testleri ve veriyi ayrı dosyalarda depolamak gibi yaklaşımlar uzun vadede bakımı imkânsız hale getirir. Her test kendi verisini inline tanımlamalıdır.

Kaynağa Git

17.24 Test Metodu İsimleri Orijinal Kaynak

Test metodunu verileni ve bekleniyi yansıtacak şekilde adlandırın.

✓ İYİ KULLANIM
METHOD reads_existing_entry.
METHOD throws_on_invalid_key.
METHOD detects_invalid_input.
✗ KÖTÜ KULLANIM
METHOD get_conversion_exits.      " başarı mı başarısızlık mı bekleniyor?
METHOD test_loop.                 " test neden başka bir şey olsun?
METHOD parameterized_test.        " amacı ne?
METHOD get_attributes_wo_w.       " "_wo_w" ne demek? Bir yıl sonra hatırlanabilir mi?

💡 Uzman Yorumu: İyi bir test metod adı, test başarısız olduğunda ne beklediğinizi hemen anlatır. "throws_on_empty_input" başarısız olduğunda "ahh, boş girişte exception atılmıyor" diye hemen anlarsınız.

Kaynağa Git

17.25 given-when-then Kullanın Orijinal Kaynak

Test kodunuzu given-when-then paradigmasına göre düzenleyin: önce given bölümünde başlatın, sonra when bölümünde test edilen şeyi çağırın, ardından then bölümünde sonucu doğrulayın.

✓ İYİ KULLANIM
METHOD throws_on_empty_input.
  " given - henüz veri yok

  " when
  DATA(is_valid) = cut->is_valid_input( '' ).

  " then
  cl_abap_unit_assert=>assert_false( is_valid ).
ENDMETHOD.

💡 Uzman Yorumu: given-when-then yapısı, testin ne yaptığını üç ayrı endişeye böler: hazırlık, eylem ve doğrulama. Bu, testlerin okunmasını ve yazılmasını büyük ölçüde kolaylaştırır.

Kaynağa Git

17.26 When Tam Olarak Bir Çağrıdır Orijinal Kaynak

"When" bölümünün test edilen sınıfa tam olarak bir çağrı içerdiğinden emin olun. Birden fazla çağrı, metodun odağının olmadığını ve çok fazla şeyi test ettiğini gösterir.

✓ İYİ KULLANIM
METHOD rejects_invalid_input.
  " when - sadece bir çağrı
  DATA(is_valid) = cut->is_valid_input( 'SOME_RANDOM_ENTRY' ).
  " then
  cl_abap_unit_assert=>assert_false( is_valid ).
ENDMETHOD.

💡 Uzman Yorumu: Tek bir "when" çağrısı, testin tam olarak bir davranışı test etmesini sağlar. Test başarısız olduğunda nedenin hangi çağrıda olduğu konusunda hiç belirsizlik olmaz.

Kaynağa Git

17.27 TEARDOWN Eklemeyin Orijinal Kaynak

TEARDOWN metodları genellikle yalnızca veritabanı girişlerini veya diğer harici kaynakları temizlemek için gereklidir. Test sınıfı üyelerini (cut ve test double'lar gibi) sıfırlamak gereksizdir; setup tarafından üzerine yazılırlar.

💡 Uzman Yorumu: TEARDOWN her testten sonra çalışır. Eğer gerçekten veritabanı veya dosya sistemi gibi harici kaynaklar oluşturmuyorsanız, buna ihtiyacınız yoktur. Gereksiz TEARDOWN testleri yavaşlatır ve karmaşıklaştırır.

Kaynağa Git

17.28 Anlamı Kolayca Görün Orijinal Kaynak

Hangi verilerin önemli olduğunu ve hangilerin yalnızca kodun çalışmasını sağlamak için orada olduğunu kolayca anlayabilmeyi sağlayın. Önemi olmayan şeyler için belirgin anlamsız isim ve değerler kullanın.

✓ İYİ KULLANIM
DATA(alert_id) = '42'.                             " bilinen anlamsız sayı
DATA(detection_object_type) = '?=/"&'.             " klavye kazası
CONSTANTS some_random_number TYPE i VALUE 782346.  " açıklayıcı değişken adı
✗ KÖTÜ KULLANIM
DATA(alert_id) = '00000001223678871'.        " bu alert gerçekten var mı?
DATA(detection_object_type) = 'FRA_SCLAIM'.  " bu tip gerçek customizing'e mi atıfta bulunuyor?

💡 Uzman Yorumu: Test verisinin anlamsız olduğu açık olmalıdır. Gerçek gibi görünen test verisi okuyucuyu "bu özel değer neden önemli?" diye merak ettirir ve gereksiz araştırmaya yol açar.

Kaynağa Git

Farkları Kolayca Görün Orijinal Kaynak

Okuyucuları küçük farkları bulmak için uzun anlamsız dizeleri karşılaştırmaya zorlamayın. Farklar açıkça görünür olmalıdır.

✓ İYİ KULLANIM
exp_parameter_in = VALUE #(
  ( parameter_name = '...END1' )
  ( parameter_name = '...END2' ) ).
" Fark: END1 vs END2 - hemen görünür

💡 Uzman Yorumu: Test verisi arasındaki farkları vurgulayın, gizlemeyin. Uzun, neredeyse aynı string'ler arasındaki tek karakterlik fark bulunmaz ve testler yanıltıcı hale gelir.

Kaynağa Git

Sabitler Kullanın Orijinal Kaynak

Test verisinin amacını ve önemini açıklamak için sabitler kullanın.

✓ İYİ KULLANIM
CONSTANTS some_nonsense_key TYPE char8 VALUE 'ABCDEFGH'.

METHOD throws_on_invalid_entry.
  TRY.
      cut->read_entry( some_nonsense_key ).    " sabit amacı açıklıyor
      cl_abap_unit_assert=>fail( ).
    CATCH /clean/customizing_reader_error.
  ENDTRY.
ENDMETHOD.

💡 Uzman Yorumu: "some_nonsense_key" sabit adı "bu gerçek bir anahtar değil, geçersiz bir girdi" demektir. Bu, testin amacını kod yorumu olmadan açıklar.

Kaynağa Git

Az, Odaklı Assertion'lar Orijinal Kaynak

Yalnızca test metodunun hakkında olduğu şeyi, az sayıda assertion ile doğrulayın. Çok fazla assertion, metodun odağının olmadığını gösterir.

✓ İYİ KULLANIM
METHOD rejects_invalid_input.
  DATA(is_valid) = cut->is_valid_input( 'SOME_RANDOM_ENTRY' ).
  cl_abap_unit_assert=>assert_false( is_valid ).   " tek, odaklı assertion
ENDMETHOD.
✗ KÖTÜ KULLANIM
METHOD rejects_invalid_input.
  DATA(is_valid) = cut->is_valid_input( 'SOME_RANDOM_ENTRY' ).
  cl_abap_unit_assert=>assert_false( is_valid ).
  cl_abap_unit_assert=>assert_not_initial( log->get_messages( ) ).   " alakasız?
  cl_abap_unit_assert=>assert_equals( act = sy-langu exp = 'E' ).     " alakasız?
ENDMETHOD.

💡 Uzman Yorumu: Bir test metodundaki çok fazla assertion, testin birden fazla şeyi doğruladığı anlamına gelir. Bu, test başarısız olduğunda hangi özelliğin bozulduğunu belirsizleştirir.

Kaynağa Git

Doğru Assert Tipini Kullanın Orijinal Kaynak

Doğru assertion tipini kullanın. assert_equals çok şey yapar (tip eşleştirme, ayrıntılı hata mesajı) ve hata mesajında ne yanlış gittiğini gösterir.

✓ İYİ KULLANIM
cl_abap_unit_assert=>assert_equals( act = table
                                    exp = test_data ).
✗ KÖTÜ KULLANIM
cl_abap_unit_assert=>assert_true( xsdbool( act = exp ) ).
" Bu başarısız olduğunda hata mesajı "false was not true" der - hiçbir bilgi vermez

💡 Uzman Yorumu: assert_equals başarısız olduğunda "expected: X, but was: Y" gibi anlamlı mesajlar üretir. assert_true ise yalnızca "false was not true" der. Doğru assertion tipi, hata ayıklama süresini önemli ölçüde kısaltır.

Kaynağa Git

İçeriği Değil Miktarı İddia Edin Orijinal Kaynak

Mümkünse sayı yerine içeriği doğrulayın. Sayılar değişebilir ama beklentiler karşılanmış olabilir; ya da tersine.

✓ İYİ KULLANIM
assert_contains_exactly( actual   = table
                         expected = VALUE string_table( ( `ABC` ) ( `DEF` ) ( `GHI` ) ) ).
✗ KÖTÜ KULLANIM
assert_equals( act = lines( log_messages )
               exp = 3 ).    " neden tam 3? içerik doğru mu?

💡 Uzman Yorumu: Miktar assertion'ları kırılgandır: eklenen bir log mesajı tüm miktar testlerini bozabilir. İçerik doğrulaması hem daha sağlam hem de daha anlamlıdır.

Kaynağa Git

İçeriği Değil Kaliteyi İddia Edin Orijinal Kaynak

Sonucun meta kalitesiyle ilgileniyorsanız ama gerçek içerikle değilseniz, uygun bir assertion ifade edin.

✓ İYİ KULLANIM
assert_all_lines_shorter_than( actual_lines        = table
                               expected_max_length = 80 ).
" Gerçek içerik önemli değil, uzunluk önemli
✗ KÖTÜ KULLANIM
assert_equals( act = table
               exp = VALUE string_table( ( `ABC` ) ( `DEF` ) ( `GHI` ) ) ).
" Refactoring farklı ama geçerli içerik üretse tüm testler bozulur

💡 Uzman Yorumu: Tam içerik doğrulaması testleri kırılgan yapar. Eğer gerçekten önem verdiğiniz şey kalite (uzunluk, format, sıra) ise, bunu doğrudan test edin.

Kaynağa Git

FAIL Kullanın Orijinal Kaynak

Beklenen exception'ları kontrol etmek için FAIL kullanın.

✓ İYİ KULLANIM
METHOD throws_on_empty_input.
  TRY.
      cut->do_something( '' ).
      cl_abap_unit_assert=>fail( ).    " exception atılmadıysa test başarısız
    CATCH /clean/some_exception.
      " then - beklenen durum
  ENDTRY.
ENDMETHOD.

💡 Uzman Yorumu: fail() çağrısı, "buraya ulaşılması beklenmiyordu" demektir. Exception atılmazsa kod fail() satırına gelir ve testi başarısız kılar. Bu, beklenen exception'ların kesin olarak doğrulanmasını sağlar.

Kaynağa Git

Beklenmedik Exception'ları İletin Orijinal Kaynak

Beklenmedik exception'ları yakalayıp test başarısız kılmak yerine iletin. Böylece test kodu mutlu yola odaklanır ve okunması çok daha kolaydır.

✓ İYİ KULLANIM
METHODS reads_entry FOR TESTING RAISING /clean/some_exception.

METHOD reads_entry.
  DATA(entry) = cut->read_something( ).    " exception buradan iletilir
  cl_abap_unit_assert=>assert_not_initial( entry ).
ENDMETHOD.
✗ KÖTÜ KULLANIM
METHOD reads_entry.
  TRY.
      DATA(entry) = cut->read_something( ).
    CATCH /clean/some_exception INTO DATA(unexpected_exception).
      cl_abap_unit_assert=>fail( unexpected_exception->get_text( ) ).   " gereksiz karmaşık
  ENDTRY.
  cl_abap_unit_assert=>assert_not_initial( entry ).
ENDMETHOD.

💡 Uzman Yorumu: Beklenmedik exception'ları yakalamak, test kodunu gereksiz yere uzatır. RAISING ile iletmek test çerçevesinin exception'ı raporlamasını sağlar ve test kodu temiz kalır.

Kaynağa Git

Özel Assertion'lar Yazın Orijinal Kaynak

Kodu kısaltmak ve tekrarden kaçınmak için özel assertion'lar yazın. Test kodu için de DRY prensibi geçerlidir.

✓ İYİ KULLANIM
METHODS assert_contains
  IMPORTING
    actual_entries TYPE STANDARD TABLE OF entries_tab
    expected_key   TYPE key_structure.

METHOD assert_contains.
  TRY.
      actual_entries[ key = expected_key ].
    CATCH cx_sy_itab_line_not_found.
      cl_abap_unit_assert=>fail( |Couldn't find the key { expected_key }| ).
  ENDTRY.
ENDMETHOD.

" Çağrı
assert_contains( actual_entries = entries  expected_key = key ).

💡 Uzman Yorumu: Özel assertion'lar, tekrar eden test mantığını kapsüller ve anlamlı hata mesajları üretir. Test kodu da refactor edilmeli; kopyala-yapıştır yerine yeniden kullanılabilir assertion'lar oluşturun.

Kaynağa Git

Pratik Uygulama İpuçları

Günlük Geliştirme Pratikleri

Bu bölümde, Clean ABAP prensiplerini günlük iş akışınıza entegre etmenize yardımcı olacak pratik ipuçları ve genişletilmiş örnekler bulacaksınız. Teoriden pratiğe geçişte en sık karşılaşılan sorular ele alınmaktadır.

Kaynağa Git

Yaygın Kötü İsimlendirme Örnekleri ve Çözümleri

Aşağıda gerçek ABAP projelerinde sık karşılaşılan kötü isimlendirme örnekleri ve bunların Clean ABAP versiyonları yer almaktadır.

✗ KÖTÜ KULLANIM - Gerçek projelerden kötü isimler
DATA lv_flag TYPE c.              " hangi bayrak? ne anlamına geliyor?
DATA it_data TYPE STANDARD TABLE OF ty_s.  " 'data' nedir? 'ty_s' ne tipi?
DATA lv_cnt TYPE i.               " count mu, counter mi?
DATA wa_line TYPE ty_s.           " wa_ öneki ve anlamız satır

METHODS process
  IMPORTING
    im_obj TYPE REF TO lcl_obj    " im_ öneki gereksiz, obj belirsiz
  EXPORTING
    ex_rc TYPE i.                 " ex_ öneki ve 'rc' dönüş kodu anlamsız
✓ İYİ KULLANIM - Clean ABAP versiyonları
DATA has_valid_entries TYPE abap_bool.
DATA sales_orders TYPE STANDARD TABLE OF sales_order_type.
DATA order_count TYPE i.
DATA current_order TYPE sales_order_type.

METHODS validate_and_process_order
  IMPORTING
    order TYPE REF TO /clean/sales_order
  RETURNING
    VALUE(result) TYPE /clean/validation_result.

💡 Uzman Yorumu: Eski ABAP geleneklerinden (lv_, it_, wa_, im_, ex_ önekleri) vazgeçmek ilk başta zor gelebilir. Ekibinizle bir anlaşma yapın ve yeni geliştirmelerde bu önekleri kullanmayı bırakın. Legacy kodu dokunduğunuzda yavaş yavaş dönüştürün.

Kaynağa Git

Büyük Metodları Adım Adım Küçültme

500 satırlık bir metod gördüğünüzde ne yaparsınız? Tüm metodu bir anda refactor etmeye çalışmak tehlikeli olabilir. İşte güvenli bir yaklaşım:

✗ KÖTÜ KULLANIM - 500 satırlık dev metod (kısaltılmış)
METHOD process_sales_document.
  " 50 satır veri bildirimi
  DATA: lv_vbeln TYPE vbeln,
        lv_kunnr TYPE kunnr,
        lv_netwr TYPE netwr,
        ...

  " Müşteri doğrulama - 100 satır
  SELECT SINGLE * FROM kna1 INTO wa_kna1
    WHERE kunnr = im_kunnr.
  IF sy-subrc <> 0.
    ev_error = 'X'.
    EXIT.
  ENDIF.
  ...

  " Fiyat hesaplama - 150 satır
  ...

  " Stok kontrolü - 100 satır
  ...

  " Belge oluşturma - 100 satır
  ...
ENDMETHOD.
✓ İYİ KULLANIM - Aşama aşama küçültülmüş versiyonu
METHOD process_sales_document.
  DATA(customer) = validate_customer( customer_id ).
  DATA(pricing)  = calculate_pricing( customer = customer
                                      items    = line_items ).
  DATA(stock)    = check_stock_availability( items = line_items ).
  result = create_sales_document( customer = customer
                                  pricing  = pricing
                                  stock    = stock ).
ENDMETHOD.

METHOD validate_customer.
  TRY.
      result = customer_repository->find_by_id( customer_id ).
    CATCH /clean/customer_not_found.
      RAISE EXCEPTION NEW /clean/invalid_customer_id( customer_id = customer_id ).
  ENDTRY.
ENDMETHOD.

METHOD calculate_pricing.
  result = pricing_engine->calculate(
    customer   = customer
    items      = items
    valid_from = sy-datum ).
ENDMETHOD.

METHOD check_stock_availability.
  result = inventory_service->check_availability(
    items       = items
    check_date  = sy-datum ).
ENDMETHOD.

METHOD create_sales_document.
  DATA(doc_builder) = NEW /clean/sales_doc_builder( ).
  doc_builder->set_customer( customer ).
  doc_builder->set_pricing( pricing ).
  doc_builder->set_stock_check( stock ).
  result = doc_builder->build( ).
ENDMETHOD.

💡 Uzman Yorumu: Büyük metodları adım adım küçültürken "Strangler Fig" desenini uygulayın: yeni işlevselliği küçük temiz metodlara yazın, yavaş yavaş eski kodu yeni metodlara yönlendirin. Her adımda testlerin yeşil kaldığını doğrulayın.

Kaynağa Git

Dependency Injection Gerçek Dünya Örneği

Dependency Injection'ın nasıl uygulandığını somut bir örnekle görelim. Bu desen hem test edilebilirliği hem de esnekliği artırır.

✓ İYİ KULLANIM - Tam Dependency Injection Örneği

" Arayüz tanımı
INTERFACE /clean/if_email_sender.
  METHODS send
    IMPORTING
      to      TYPE string
      subject TYPE string
      body    TYPE string
    RAISING
      /clean/cx_email_send_failure.
ENDINTERFACE.

" Üretim implementasyonu
CLASS /clean/smtp_email_sender DEFINITION
  PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES /clean/if_email_sender.
ENDCLASS.

CLASS /clean/smtp_email_sender IMPLEMENTATION.
  METHOD /clean/if_email_sender~send.
    " SMTP üzerinden gerçek email gönderimi
    " ...
  ENDMETHOD.
ENDCLASS.

" Servis sınıfı - injection ile
CLASS /clean/order_notification_service DEFINITION
  PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    METHODS constructor
      IMPORTING
        email_sender TYPE REF TO /clean/if_email_sender.
    METHODS notify_customer
      IMPORTING
        order_id    TYPE /clean/order_id
        customer_id TYPE kunnr.
  PRIVATE SECTION.
    DATA email_sender TYPE REF TO /clean/if_email_sender.
ENDCLASS.

CLASS /clean/order_notification_service IMPLEMENTATION.
  METHOD constructor.
    me->email_sender = email_sender.
  ENDMETHOD.
  METHOD notify_customer.
    DATA(customer) = customer_repo->find( customer_id ).
    email_sender->send(
      to      = customer->get_email( )
      subject = |Order { order_id } Confirmed|
      body    = build_confirmation_body( order_id ) ).
  ENDMETHOD.
ENDCLASS.

" Üretim kodu - gerçek email sender
DATA(notification_service) = NEW /clean/order_notification_service(
  email_sender = NEW /clean/smtp_email_sender( ) ).

" Test kodu - mock email sender
DATA(mock_sender) = CAST /clean/if_email_sender(
  cl_abap_testdouble=>create( '/clean/if_email_sender' ) ).
DATA(notification_service_under_test) = NEW /clean/order_notification_service(
  email_sender = mock_sender ).

💡 Uzman Yorumu: Bu örnek, arayüz-uygulama-servis üçlüsünün nasıl çalıştığını gösteriyor. Üretim kodunda gerçek SMTP sender, test kodunda ise mock sender kullanılıyor. Servis sınıfı hangi implementasyonu kullandığını bilmiyor.

Kaynağa Git

Exception Hiyerarşisi Tasarımı

İyi tasarlanmış bir exception hiyerarşisi, çağıranların hem genel hem de özel hataları yakalamasına izin verir.

✓ İYİ KULLANIM - İyi tasarlanmış exception hiyerarşisi

" Temel application exception
CLASS /clean/cx_application_error DEFINITION
  PUBLIC ABSTRACT INHERITING FROM cx_static_check.
  PUBLIC SECTION.
    METHODS constructor
      IMPORTING
        textid   LIKE if_t100_message=>t100key OPTIONAL
        previous LIKE previous OPTIONAL.
ENDCLASS.

" Domain exception'ları
CLASS /clean/cx_customer_error DEFINITION
  PUBLIC ABSTRACT INHERITING FROM /clean/cx_application_error.
ENDCLASS.

CLASS /clean/cx_customer_not_found DEFINITION
  PUBLIC FINAL INHERITING FROM /clean/cx_customer_error.
  PUBLIC SECTION.
    DATA customer_id TYPE kunnr READ-ONLY.
    METHODS constructor
      IMPORTING
        customer_id TYPE kunnr
        previous    LIKE previous OPTIONAL.
ENDCLASS.

CLASS /clean/cx_customer_credit_limit_exceeded DEFINITION
  PUBLIC FINAL INHERITING FROM /clean/cx_customer_error.
  PUBLIC SECTION.
    DATA customer_id   TYPE kunnr READ-ONLY.
    DATA credit_limit  TYPE netwr READ-ONLY.
    DATA order_amount  TYPE netwr READ-ONLY.
ENDCLASS.

" Kullanım - katmanlı yakalama
TRY.
    order_service->create_order( customer_id = '1000'
                                 amount      = 50000 ).
  CATCH /clean/cx_customer_not_found INTO DATA(not_found).
    " Müşteri bulunamadı - kullanıcıya bildir
    show_message( |Customer { not_found->customer_id } not found| ).
  CATCH /clean/cx_customer_credit_limit_exceeded INTO DATA(limit_exc).
    " Kredi limiti aşıldı - yöneticiye ilet
    notify_manager( limit_exc ).
  CATCH /clean/cx_customer_error INTO DATA(cust_err).
    " Diğer müşteri hataları - genel işlem
    log_error( cust_err ).
  CATCH /clean/cx_application_error INTO DATA(app_err).
    " Tüm uygulama hataları - hata sayfası
    show_error_page( ).
ENDTRY.

💡 Uzman Yorumu: Hiyerarşi, en özel exception'dan en genel olana doğru yakalanır. Bu, hem özel durumları ele alma hem de genel fallback sağlama imkânı tanır. ABSTRACT üst sınıflar yanlışlıkla doğrudan kullanımı engeller.

Kaynağa Git

Birim Testi Tam Örneği

Aşağıda given-when-then yapısını kullanan eksiksiz bir birim testi örneği yer almaktadır.

✓ İYİ KULLANIM - Tam birim testi örneği

CLASS ltc_order_validator DEFINITION FINAL FOR TESTING
  DURATION SHORT
  RISK LEVEL HARMLESS.

  PRIVATE SECTION.
    DATA cut TYPE REF TO /clean/if_order_validator.
    DATA mock_customer_repo TYPE REF TO /clean/if_customer_repository.

    METHODS setup.
    METHODS given_valid_customer RETURNING VALUE(result) TYPE kunnr.
    METHODS given_customer_with_no_credit RETURNING VALUE(result) TYPE kunnr.

    METHODS validates_existing_customer FOR TESTING.
    METHODS rejects_unknown_customer FOR TESTING.
    METHODS rejects_customer_without_credit FOR TESTING.
    METHODS validates_minimum_order_amount FOR TESTING.
ENDCLASS.

CLASS ltc_order_validator IMPLEMENTATION.

  METHOD setup.
    mock_customer_repo = CAST /clean/if_customer_repository(
      cl_abap_testdouble=>create( '/clean/if_customer_repository' ) ).
    cut = NEW /clean/order_validator(
      customer_repository = mock_customer_repo ).
  ENDMETHOD.

  METHOD given_valid_customer.
    result = '0000001000'.
    cl_abap_testdouble=>configure_call( mock_customer_repo
      )->returning( VALUE /clean/customer( id              = result
                                           credit_limit    = 100000
                                           credit_used     = 0 ) ).
    mock_customer_repo->find_by_id( result ).
  ENDMETHOD.

  METHOD given_customer_with_no_credit.
    result = '0000002000'.
    cl_abap_testdouble=>configure_call( mock_customer_repo
      )->returning( VALUE /clean/customer( id           = result
                                           credit_limit = 1000
                                           credit_used  = 1000 ) ).
    mock_customer_repo->find_by_id( result ).
  ENDMETHOD.

  METHOD validates_existing_customer.
    " given
    DATA(customer_id) = given_valid_customer( ).
    DATA(order) = VALUE /clean/order( customer_id = customer_id
                                      amount      = 500 ).

    " when
    DATA(result) = cut->validate( order ).

    " then
    cl_abap_unit_assert=>assert_true( result->is_valid ).
  ENDMETHOD.

  METHOD rejects_unknown_customer.
    " given
    cl_abap_testdouble=>configure_call( mock_customer_repo
      )->raising( NEW /clean/cx_customer_not_found( customer_id = 'UNKNOWN' ) ).
    mock_customer_repo->find_by_id( 'UNKNOWN' ).
    DATA(order) = VALUE /clean/order( customer_id = 'UNKNOWN'
                                      amount      = 500 ).

    " when
    DATA(result) = cut->validate( order ).

    " then
    cl_abap_unit_assert=>assert_false( result->is_valid ).
    cl_abap_unit_assert=>assert_char_cp(
      act = result->error_message
      exp = '*not found*' ).
  ENDMETHOD.

  METHOD rejects_customer_without_credit.
    " given
    DATA(customer_id) = given_customer_with_no_credit( ).
    DATA(order) = VALUE /clean/order( customer_id = customer_id
                                      amount      = 500 ).

    " when
    DATA(result) = cut->validate( order ).

    " then
    cl_abap_unit_assert=>assert_false( result->is_valid ).
  ENDMETHOD.

  METHOD validates_minimum_order_amount.
    " given
    DATA(customer_id) = given_valid_customer( ).
    DATA(order) = VALUE /clean/order( customer_id = customer_id
                                      amount      = 0 ).    " sıfır tutar

    " when
    DATA(result) = cut->validate( order ).

    " then
    cl_abap_unit_assert=>assert_false( result->is_valid ).
    cl_abap_unit_assert=>assert_char_cp(
      act = result->error_message
      exp = '*minimum*' ).
  ENDMETHOD.

ENDCLASS.

💡 Uzman Yorumu: Bu test örneği birçok Clean Code prensibini bir arada gösteriyor: anlamlı test sınıfı adı, setup metodunda DI, given yardım metodları, açık given-when-then yapısı ve odaklı assertion'lar. Bu şablonu kendi projelerinizde kullanabilirsiniz.

Kaynağa Git

Modern ABAP Sözdizimi Karşılaştırma Tablosu

Eski ve modern ABAP sözdiziminin yan yana karşılaştırması:

Eski Stil Modern Stil
MOVE 'X' TO flag. flag = abap_true.
CREATE OBJECT obj TYPE lcl. DATA(obj) = NEW lcl( ).
ADD 1 TO counter. counter += 1.
TRANSLATE str TO UPPER CASE. str = to_upper( str ).
DESCRIBE TABLE itab LINES cnt. cnt = lines( itab ).
READ TABLE itab INTO wa WITH KEY k = v. DATA(wa) = itab[ k = v ].
LOOP AT itab INTO wa. ... ENDLOOP. LOOP AT itab REFERENCE INTO DATA(wa). ... ENDLOOP.
CONCATENATE s1 s2 INTO result. result = |{ s1 }{ s2 }|.
IF NOT x IS INITIAL. IF x IS NOT INITIAL.
CLEAR itab. REFRESH itab. CLEAR itab.

💡 Uzman Yorumu: Modern ABAP sözdizimi sadece daha kısa değil, aynı zamanda tip güvenli ve daha az hata eğilimlidir. ABAP Development Tools'un Quick Fix özelliği eski sözdizimini otomatik olarak yenisiyle değiştirmenize yardımcı olabilir.

Kaynağa Git

Clean ABAP Kontrol Listesi

Kod incelemesi sırasında kullanabileceğiniz kontrol listesi:

İsimler

  • ☐ Tüm değişken ve metod isimleri açıklayıcı ve telaffuz edilebilir mi?
  • ☐ Kısaltmalar ve kodlama önekleri (lv_, it_, im_) kaldırıldı mı?
  • ☐ Koleksiyonlar çoğul, tekil öğeler tekil adlandırıldı mı?
  • ☐ Sınıflar isim, metodlar fiil içeriyor mu?

Metodlar

  • ☐ Her metod 20 satırdan az mı?
  • ☐ Her metod tek bir şey mi yapıyor?
  • ☐ 3'ten az IMPORTING parametresi var mı?
  • ☐ Boolean parametre yerine ayrı metod kullanıldı mı?
  • ☐ RETURNING mi EXPORTING yerine kullanılıyor?

Hata Yönetimi

  • ☐ Dönüş kodu yerine exception kullanılıyor mu?
  • ☐ Exception'lar anlamlı bilgi taşıyor mu?
  • ☐ Sınıf tabanlı exception mı kullanılıyor?

Test

  • ☐ Tüm public metodlar test edildi mi?
  • ☐ given-when-then yapısı kullanıldı mı?
  • ☐ Test double'lar arayüz üzerinden oluşturuldu mu?
  • ☐ Her test metodu tek bir davranışı mı test ediyor?

Sınıflar

  • ☐ Kalıtım için tasarlanmamış sınıflar FINAL mı?
  • ☐ Üyeler varsayılan olarak PRIVATE mi?
  • ☐ Public metodlar bir arayüz üzerinden mi?
  • ☐ Bağımlılıklar constructor injection ile mi enjekte ediliyor?

💡 Uzman Yorumu: Bu kontrol listesini code review sürecinize entegre edin. Her pull request veya transport request onayında bu maddeleri sistematik olarak kontrol etmek, kaliteyi önemli ölçüde artırır.

Kaynağa Git

Sık Yapılan Hatalar ve Çözümleri

Clean ABAP'a geçiş sürecinde en sık yapılan hatalar ve bunları nasıl düzelteceğiniz:

Hata 1: Tüm kurallara aynı anda uymaya çalışmak

✗ YANLIŞ YAKLAŞIM
" Tüm kodunuzu bir haftada Clean ABAP'a geçirmeye çalışmak
" → Projeyi riske atar ve ekibi bunaltır
✓ DOĞRU YAKLAŞIM
" Her sprint'te 1-2 kural seçin
" Sprint 1: Kötü metod isimleri düzeltildi
" Sprint 2: Boolean parametreler kaldırıldı
" Sprint 3: Büyük metodlar bölündü
" ...

Hata 2: Yorumları silip içerik eklememeк

✗ YANLIŞ YAKLAŞIM
" "Kodda ifade et" kuralını yanlış anlayıp tüm yorumları silmek
" ama kodu açıklayıcı hale getirmemek
✓ DOĞRU YAKLAŞIM
" Yorumu sil → ama kodu daha açıklayıcı hale getir
" Yorum: "bu fonksiyon müşteriyi doğrular"
" Aksiyon: validate_customer( ) metodunu çıkar, yorum gerekli olmaz

Hata 3: Birim testleri yazmadan refactor etmek

✗ YANLIŞ YAKLAŞIM
" Önce refactor et, sonra test yaz
" → Refactoring sırasında davranış değişikliğini fark edemezsiniz
✓ DOĞRU YAKLAŞIM
" Önce mevcut davranışı test et (characterization tests)
" Sonra refactor et
" Her adımda testlerin yeşil kaldığını doğrula

Hata 4: Herkesi aynı anda ikna etmeye çalışmak

✓ DOĞRU YAKLAŞIM
" Bir pilot projeyle başlayın
" Sonuçları ölçün (hata sayısı, geliştirme hızı, onboarding süresi)
" Verilere dayanarak diğer projelere genişletin
" Başarı hikayeleri paylaşın

💡 Uzman Yorumu: Clean Code'a geçiş bir maraton, sprint değil. Küçük, tutarlı adımlar atın ve ilerlemeyi kutlayın. Her geliştirici bu yolculukta farklı bir noktada başlar; sabrınızı koruyun ve ekibi yargılamayın.

Kaynağa Git

İleri Okuma ve Kaynaklar

Clean ABAP yolculuğunuzu derinleştirmek için önerilen kaynaklar:

📚 Kitaplar

  • Clean Code - Robert C. Martin
  • The Pragmatic Programmer
  • Refactoring - Martin Fowler
  • Clean Architecture - Robert C. Martin
  • Working Effectively with Legacy Code

🌐 Web Kaynakları

🛠️ Araçlar

  • ABAP Test Cockpit (ATC)
  • Code Inspector (SCI)
  • ABAP Unit Test Framework
  • cl_abap_testdouble
  • ABAP Development Tools (ADT)

💡 Uzman Yorumu: Bu kaynaklar Clean Code yolculuğunuzda size eşlik edecek. Ancak en iyi öğrenme yolu pratik yapmaktır. Her gün biraz Clean Code, zaman içinde büyük bir fark yaratır.

Kaynağa Git

Sonuç

Clean ABAP Yolculuğunuzda Başarılar

Bu kılavuz, SAP Clean ABAP stilkılavuzunun kapsamlı bir Türkçe çevirisi ve genişletilmiş yorumudur. 150'den fazla kural, gerçek kod örnekleri ve uzman yorumlarıyla ABAP geliştirme kalitenizi sistematik olarak artırmanıza yardımcı olmayı hedeflemektedir.

Unutmayın: Temiz kod, ahlaki bir yükümlülük değil; takımınıza ve gelecekteki kendinize duyduğunuz saygının göstergesidir. Bugün yazdığınız kod, altı ay sonra siz de dahil olmak üzere başkaları tarafından okunacak. O okuyucuya borçlu olduğunuz en iyi şey, açık ve anlaşılır bir koddur.

Kaynağa Git

Clean ABAP Manifestosu

" Clean ABAP'ta çalışmanın özü:

" Gizem değil, netlik.
IF order IS NOT INITIAL AND order->is_valid( ).
  process_order( order ).
ENDIF.

" Kısalık değil, açıklık.
METHODS process_customer_order_with_validation
  IMPORTING valid_customer_order TYPE REF TO /clean/customer_order.

" Zekâ değil, basitlik.
DATA(total) = REDUCE netwr( INIT sum = 0
                             FOR item IN line_items
                             NEXT sum = sum + item-amount ).

" Kendi kendine, yorumsuz.
METHOD place_order.
  validate_order( ).
  reserve_inventory( ).
  charge_customer( ).
  send_confirmation( ).
ENDMETHOD.

💡 Son Söz: "Programların insanlar tarafından okunması için yazıldığını ve yalnızca makineler tarafından yürütülmesinin tesadüf olduğunu aklınızdan çıkarmayın." — Harold Abelson

Kaynağa Git