Emre Göçmen Blog

SAP ABAP Yeni Sözdizimi: Kapsamlı Bir Rehber

5 dk. okuma
2511 görüntülenme
0 yorum

Emre Göçmen

Yazar

SAP ABAP Yeni Sözdizimi: Kapsamlı Bir Rehber

SAP ABAP Yeni Sözdizimi: Kapsamlı Bir Rehber

İçindekiler

  1. Giriş
  2. Temel Yeni Sözdizimi Özellikleri
  3. Pratik Uygulama Örnekleri
  4. İleri Düzey Konular
  5. Performans İyileştirmeleri
  6. Sonuç
  7. Ek Kaynaklar

1. Giriş

SAP ABAP (Advanced Business Application Programming), SAP sistemlerinde iş uygulamalarını geliştirmek için kullanılan güçlü ve esnek bir programlama dilidir. SAP S/4HANA ve modern SAP teknolojilerinin ortaya çıkışıyla birlikte, ABAP dili de önemli ölçüde gelişerek modern programlama paradigmalarını desteklemek için yeni sözdizimi özellikleri kazanmıştır.

ABAP'ın yeni sözdizimi (genellikle "ABAP Modern Syntax" veya "ABAP 7.4+" olarak anılır), daha okunabilir, sürdürülebilir ve verimli kod yazmanıza olanak tanıyan çeşitli yapılar ve operatörler sunar. Bu yenilikler sayesinde geliştiriciler daha az kod yazarak daha güçlü uygulamalar oluşturabilir, böylece geliştirme süresi kısalır ve kod kalitesi artar.

Bu rehberde, ABAP'ın yeni sözdizimi özelliklerini detaylı bir şekilde inceleyecek, pratik örneklerle bu özelliklerin nasıl kullanılacağını gösterecek ve modern ABAP programlama tekniklerini ele alacağız.

2. Temel Yeni Sözdizimi Özellikleri

2.1 Yerel Veri Bildirimleri

Klasik ABAP'ta, bir değişken tanımlayıp değer atamak için iki ayrı ifade kullanılırdı. Yeni sözdizimi ile birlikte, değişkenleri tanımlarken aynı zamanda değer atayabilirsiniz. Bu, kod yazımını daha özlü ve anlaşılır hale getirir.

Eski Sözdizimi:

DATA: lv_number TYPE i,
      lv_text   TYPE string.

lv_number = 42.
lv_text   = 'Merhaba Dünya'.

Yeni Sözdizimi:

DATA(lv_number) = 42.
DATA(lv_text)   = 'Merhaba Dünya'.

ABAP derleyicisi, atanan değere göre veri türünü otomatik olarak çıkarır. Bu, değişken bildirimine olan ihtiyacı azaltır ve kodun daha kısa ve okunabilir olmasını sağlar.

Yerel Değişken Bildiriminin Sınırlamaları:

  • Yerel değişkenler sadece program içerisinde kullanılabilir; sınıf üyeleri veya global değişkenler için bu yöntem kullanılamaz.
  • DATA(...) değişkeni, aynı kapsamda birden fazla kez bildirilemez.
  • İlk değer ataması yapılmalıdır; DATA(lv_var) gibi boş bir bildirim geçersizdir.

2.2 Satır İçi Bildirimler

Yeni sözdiziminin en güçlü özelliklerinden biri, SQL sorgularında, dahili tablo işlemlerinde ve döngülerde satır içi değişken bildirimi yapabilme yeteneğidir.

SQL Sorgularında Satır İçi Bildirimler:

SELECT carrid, connid, fldate, price
  INTO TABLE @DATA(lt_flights)
  FROM sflight
  WHERE carrid = 'LH'.

LOOP İfadelerinde Satır İçi Bildirimler:

LOOP AT lt_flights INTO DATA(ls_flight).
  WRITE: / |Uçuş: { ls_flight-connid }, Tarih: { ls_flight-fldate }|.
ENDLOOP.

READ TABLE İfadelerinde Satır İçi Bildirimler:

READ TABLE lt_flights INTO DATA(ls_first_flight) INDEX 1.
IF sy-subrc = 0.
  WRITE: / |İlk uçuş: { ls_first_flight-connid }|.
ENDIF.

2.3 String Şablonları (String Templates)

String şablonları, metin ve değişkenleri kolay ve okunabilir bir şekilde birleştirmenize olanak tanır. Bu özellik, birden çok CONCATENATE ifadesi kullanmak yerine tek bir satırda metin oluşturmanızı sağlar.

DATA(lv_firstname) = 'Ahmet'.
DATA(lv_lastname)  = 'Yılmaz'.

" Klasik yöntem
CONCATENATE 'Merhaba ' lv_firstname ' ' lv_lastname INTO DATA(lv_greeting_old).

" String şablonu kullanımı
DATA(lv_greeting_new) = |Merhaba { lv_firstname } { lv_lastname }|.

" Formatlanmış çıktı
DATA(lv_price)        = 1250.55.
DATA(lv_order_date)   = '20210515'.
DATA(lv_order_output) = |Sipariş Tarihi: { lv_order_date DATE = USER } - Tutar: { lv_price DECIMALS = 2 } TL|.

WRITE: / lv_greeting_new,
       / lv_order_output.

Şablon Formatları:

  • DATE = USER/ISO/RAW: Tarih biçimlendirme
  • TIME = USER/ISO/RAW: Saat biçimlendirme
  • DECIMALS = n: Ondalık basamak sayısı
  • WIDTH = n: Sabit genişlik
  • ALIGN = LEFT/CENTER/RIGHT: Hizalama
  • CASE = UPPER/LOWER: Büyük/küçük harf

2.4 VALUE Operatörü

VALUE operatörü, yapıları ve iç tabloları tek bir ifadede doldurmanıza olanak tanır. Bu, kod okunabilirliğini artırır ve yapılandırılmış verilerin daha düzgün işlenmesini sağlar.

Yapı Oluşturma:

TYPES: BEGIN OF ty_employee,
         id         TYPE i,
         first_name TYPE string,
         last_name  TYPE string,
         hire_date  TYPE d,
       END OF ty_employee.

DATA(ls_employee) = VALUE ty_employee(
  id         = 12345
  first_name = 'Ahmet'
  last_name  = 'Yılmaz'
  hire_date  = '20210101'
).

İç Tablo Oluşturma:

DATA(lt_employees) = VALUE tt_employee(
  ( id = 1  first_name = 'Ali'    last_name = 'Kaya'    hire_date = '20200101' )
  ( id = 2  first_name = 'Ayşe'   last_name = 'Demir'   hire_date = '20200315' )
  ( id = 3  first_name = 'Mehmet' last_name = 'Şahin'   hire_date = '20200610' )
  ( id = 4  first_name = 'Zeynep' last_name = 'Çelik'   hire_date = '20201201' )
).

Mevcut Yapıları Kopyalama ve Değiştirme (BASE):

DATA(ls_employee_updated) = VALUE ty_employee(
  BASE ls_employee
  first_name = 'Ahmet Can'
  hire_date  = '20210201'
).

2.5 REDUCE Operatörü

REDUCE operatörü, bir iç tablodaki değerleri özetlemek ve bir toplamdaki (aggregate) değeri hesaplamak için kullanılır.

TYPES: BEGIN OF ty_sales,
         product_id TYPE string,
         quantity   TYPE i,
         price      TYPE p DECIMALS 2,
       END OF ty_sales.

DATA(lt_sales) = VALUE tt_sales(
  ( product_id = 'A001' quantity = 5  price = 10.50 )
  ( product_id = 'B002' quantity = 2  price = 25.75 )
  ( product_id = 'A001' quantity = 3  price = 10.50 )
  ( product_id = 'C003' quantity = 1  price = 99.99 )
).

" Toplam satış tutarını hesaplama
DATA(lv_total_sales) = REDUCE decfloat34(
  INIT total = 0
  FOR ls_sale IN lt_sales
  NEXT total = total + ( ls_sale-quantity * ls_sale-price )
).

WRITE: / |Toplam Satış Tutarı: { lv_total_sales DECIMALS = 2 } TL|.

2.6 FOR İfadesi

FOR ifadesi, tablolardaki verileri işlemek ve filtrelemek için kullanılır. Hem VALUE hem de diğer işlemci operatörleriyle birlikte kullanılabilir.

Sıralı Sayılar Oluşturma:

DATA(lt_numbers) = VALUE tt_i(
  FOR i = 1 THEN i + 1 UNTIL i > 10
  ( i )
).

Filtrelenmiş Tablo Oluşturma:

DATA(lt_lh_flights) = VALUE tt_flights(
  FOR ls_flight IN lt_flights
  WHERE ( carrid = 'LH' )
  ( ls_flight )
).

Dönüştürülmüş Tablo Oluşturma:

DATA(lt_prices) = VALUE tt_price(
  FOR ls_flight IN lt_flights
  ( carrier_id = ls_flight-carrid
    flight_id  = ls_flight-connid
    amount     = ls_flight-price * '1.19' "KDV eklenmiş fiyat
    currency   = ls_flight-currency )
).

2.7 FILTER Operatörü

FILTER operatörü, bir iç tabloyu belirli bir koşula göre filtrelemek için kullanılır. Bu, belirli kriterlere göre tablo alt kümesi oluşturmak için kullanışlıdır.

DATA(lt_lh_flights) = FILTER #( lt_flights WHERE carrid = 'LH' ).
DATA(lt_expensive_flights) = FILTER #( lt_flights WHERE price > 500 ).

EXCEPT ve IN Seçenekleri:

" 'LH' ve 'LX' dışındaki uçuşlar
DATA(lt_other_flights) = FILTER #( lt_flights EXCEPT WHERE carrid = 'LH' OR carrid = 'LX' ).

" Belirli uçuş numaralarını içeren uçuşlar
DATA(lt_selected_connids) = VALUE tt_connid( ( '0400' ) ( '0401' ) ( '0402' ) ).
DATA(lt_selected_flights) = FILTER #( lt_flights IN lt_selected_connids WHERE connid = table_line ).

2.8 Lambda İfadeleri

Lambda ifadeleri, sık kullanılan işlemleri gerçekleştirmek için kullanılır. Özellikle büyük kod bloklarını basitleştirerek kodun daha okunabilir olmasını sağlar.

DATA(lv_total) = REDUCE i(
  INIT s = 0
  FOR i = 1 UNTIL i > 10
  NEXT s = s + i
).

" Lambda ifadesiyle sayıların karelerinin toplamını hesaplama
DATA(lv_sum_of_squares) = REDUCE i(
  INIT s = 0
  FOR i = 1 UNTIL i > 10
  LET square = i * i IN
  NEXT s = s + square
).

WRITE: / |1'den 10'a kadar sayıların toplamı: { lv_total }|.
WRITE: / |1'den 10'a kadar sayıların karelerinin toplamı: { lv_sum_of_squares }|.

3. Pratik Uygulama Örnekleri

3.1 Müşteri Sipariş Raporlama

TYPES: BEGIN OF ty_customer,
         id      TYPE i,
         name    TYPE string,
         city    TYPE string,
         country TYPE string,
       END OF ty_customer.

TYPES: BEGIN OF ty_order,
         order_id    TYPE i,
         customer_id TYPE i,
         order_date  TYPE d,
         total       TYPE p DECIMALS 2,
         currency    TYPE c LENGTH 3,
         status      TYPE string,
       END OF ty_order.

" Örnek veri oluşturma
DATA(lt_customers) = VALUE tt_customer(
  ( id = 1 name = 'ABC Şirketi'  city = 'İstanbul' country = 'TR' )
  ( id = 2 name = 'XYZ Ltd. Şti.' city = 'Ankara'   country = 'TR' )
  ( id = 3 name = 'MNO GmbH'      city = 'Berlin'   country = 'DE' )
).

DATA(lt_orders) = VALUE tt_order(
  ( order_id = 1001 customer_id = 1 order_date = '20210101' total = 1250.75 currency = 'TRY' status = 'Tamamlandı' )
  ( order_id = 1002 customer_id = 1 order_date = '20210115' total = 750.50  currency = 'TRY' status = 'Tamamlandı' )
  ( order_id = 1003 customer_id = 2 order_date = '20210120' total = 2500.00 currency = 'TRY' status = 'İşleniyor' )
  ( order_id = 1004 customer_id = 3 order_date = '20210125' total = 900.00  currency = 'EUR' status = 'Tamamlandı' )
  ( order_id = 1005 customer_id = 1 order_date = '20210210' total = 1800.25 currency = 'TRY' status = 'İşleniyor' )
).

" 1. Müşteri siparişlerini birleştiren ve raporlayan program
LOOP AT lt_customers INTO DATA(ls_customer).
  WRITE: / |Müşteri: { ls_customer-name } ({ ls_customer-city }, { ls_customer-country })|.
  
  " Müşterinin tüm siparişlerini filtrele
  DATA(lt_customer_orders) = FILTER #( lt_orders WHERE customer_id = ls_customer-id ).
  
  " Toplam sipariş tutarını hesapla
  DATA(lv_total_try) = REDUCE decfloat34(
    INIT t = 0
    FOR ls_order IN lt_customer_orders WHERE ( currency = 'TRY' )
    NEXT t = t + ls_order-total
  ).
  
  " Her bir siparişi listele
  LOOP AT lt_customer_orders INTO DATA(ls_order).
    WRITE: /5 |Sipariş: { ls_order-order_id } - { ls_order-order_date DATE = USER } - { ls_order-total DECIMALS = 2 } { ls_order-currency } - Durum: { ls_order-status }|.
  ENDLOOP.
  
  WRITE: / |Toplam TRY Siparişleri: { lv_total_try DECIMALS = 2 } TRY|.
  SKIP 1.
ENDLOOP.

3.2 Veri Dönüştürme ve Analiz

" Satış verileri
TYPES: BEGIN OF ty_sales_data,
         region    TYPE string,
         product   TYPE string,
         quantity  TYPE i,
         sales     TYPE p DECIMALS 2,
         currency  TYPE c LENGTH 3,
         sale_date TYPE d,
       END OF ty_sales_data.

DATA(lt_sales_data) = VALUE tt_sales_data(
  ( region = 'Marmara'  product = 'Laptop'    quantity = 5  sales = 25000.00 currency = 'TRY' sale_date = '20210105' )
  ( region = 'Ege'      product = 'Telefon'   quantity = 10 sales = 15000.00 currency = 'TRY' sale_date = '20210110' )
  ( region = 'Marmara'  product = 'Telefon'   quantity = 8  sales = 12000.00 currency = 'TRY' sale_date = '20210115' )
  ( region = 'İç Anadolu' product = 'Tablet'  quantity = 3  sales = 6000.00  currency = 'TRY' sale_date = '20210120' )
  ( region = 'Marmara'  product = 'Tablet'    quantity = 6  sales = 12000.00 currency = 'TRY' sale_date = '20210125' )
  ( region = 'Ege'      product = 'Laptop'    quantity = 4  sales = 20000.00 currency = 'TRY' sale_date = '20210130' )
).

" 1. Ürüne göre toplam satış analizi
TYPES: BEGIN OF ty_product_sales,
         product  TYPE string,
         quantity TYPE i,
         sales    TYPE p DECIMALS 2,
       END OF ty_product_sales.

DATA(lt_product_sales) = VALUE tt_product_sales(
  FOR GROUPS product OF ls_sale IN lt_sales_data
  GROUP BY ls_sale-product
  LET total_quantity = REDUCE i( INIT q = 0
                                  FOR gs IN GROUP product
                                  NEXT q = q + gs-quantity )
      total_sales = REDUCE decfloat34( INIT s = 0
                                       FOR gs IN GROUP product
                                       NEXT s = s + gs-sales )
  IN ( product  = product
       quantity = total_quantity
       sales    = total_sales )
).

WRITE: / 'Ürüne Göre Satış Analizi:'.
LOOP AT lt_product_sales INTO DATA(ls_product_sales).
  WRITE: / |Ürün: { ls_product_sales-product } - Adet: { ls_product_sales-quantity } - Toplam Satış: { ls_product_sales-sales DECIMALS = 2 } TRY|.
ENDLOOP.
SKIP 1.

" 2. Bölgeye göre toplam satış analizi
TYPES: BEGIN OF ty_region_sales,
         region   TYPE string,
         quantity TYPE i,
         sales    TYPE p DECIMALS 2,
       END OF ty_region_sales.

DATA(lt_region_sales) = VALUE tt_region_sales(
  FOR GROUPS region OF ls_sale IN lt_sales_data
  GROUP BY ls_sale-region
  LET total_quantity = REDUCE i( INIT q = 0
                                 FOR gs IN GROUP region
                                 NEXT q = q + gs-quantity )
      total_sales = REDUCE decfloat34( INIT s = 0
                                      FOR gs IN GROUP region
                                      NEXT s = s + gs-sales )
  IN ( region   = region
       quantity = total_quantity
       sales    = total_sales )
).

WRITE: / 'Bölgeye Göre Satış Analizi:'.
LOOP AT lt_region_sales INTO DATA(ls_region_sales).
  WRITE: / |Bölge: { ls_region_sales-region } - Adet: { ls_region_sales-quantity } - Toplam Satış: { ls_region_sales-sales DECIMALS = 2 } TRY|.
ENDLOOP.

4. İleri Düzey Konular

4.1 ABAP Nesne Yönelimli Programlama

Yeni sözdizimi özellikleri, nesne yönelimli ABAP programlamasını daha güçlü ve esnek hale getirir.

CLASS lcl_product_manager DEFINITION.
  PUBLIC SECTION.
    TYPES: BEGIN OF ty_product,
             id          TYPE string,
             name        TYPE string,
             price       TYPE p DECIMALS 2,
             category    TYPE string,
             stock_level TYPE i,
           END OF ty_product.
    
    TYPES: tt_products TYPE TABLE OF ty_product WITH KEY id.
    
    METHODS:
      constructor,
      add_product IMPORTING is_product TYPE ty_product,
      get_products RETURNING VALUE(rt_products) TYPE tt_products,
      get_available_products RETURNING VALUE(rt_products) TYPE tt_products,
      calculate_inventory_value RETURNING VALUE(rv_value) TYPE decfloat34.
      
  PRIVATE SECTION.
    DATA: mt_products TYPE tt_products.
ENDCLASS.

CLASS lcl_product_manager IMPLEMENTATION.
  METHOD constructor.
    " Örnek ürünleri başlat
    mt_products = VALUE #(
      ( id = 'P001' name = 'Laptop Pro'  price = 12500.00 category = 'Elektronik' stock_level = 10 )
      ( id = 'P002' name = 'Akıllı Saat' price = 2450.75  category = 'Giyilebilir' stock_level = 15 )
      ( id = 'P003' name = 'Kulaklık'    price = 850.50   category = 'Aksesuar'   stock_level = 0 )
      ( id = 'P004' name = 'Tablet Max'  price = 5750.25  category = 'Elektronik' stock_level = 8 )
    ).
  ENDMETHOD.
  
  METHOD add_product.
    APPEND is_product TO mt_products.
  ENDMETHOD.
  
  METHOD get_products.
    rt_products = mt_products.
  ENDMETHOD.
  
  METHOD get_available_products.
    " Stokta olan ürünleri filtrele
    rt_products = FILTER #( mt_products WHERE stock_level > 0 ).
  ENDMETHOD.
  
  METHOD calculate_inventory_value.
    " Tüm envanter değerini hesapla
    rv_value = REDUCE decfloat34(
      INIT value = 0
      FOR ls_product IN mt_products
      NEXT value = value + ( ls_product-price * ls_product-stock_level )
    ).
  ENDMETHOD.
ENDCLASS.

" Sınıfı kullanma
START-OF-SELECTION.
  DATA(lo_product_manager) = NEW lcl_product_manager( ).
  
  " Yeni ürün ekle
  lo_product_manager->add_product( VALUE #( 
    id = 'P005' 
    name = 'Dış Disk' 
    price = 1250.00 
    category = 'Depolama' 
    stock_level = 12 
  ) ).
  
  " Mevcut ürünleri listele
  WRITE: / 'Tüm Ürünler:'.
  LOOP AT lo_product_manager->get_products( ) INTO DATA(ls_product).
    WRITE: / |{ ls_product-id } - { ls_product-name } - { ls_product-price DECIMALS = 2 } TL - Stok: { ls_product-stock_level }|.
  ENDLOOP.
  
  SKIP 1.
  
  " Stokta olan ürünleri listele
  WRITE: / 'Stokta Olan Ürünler:'.
  LOOP AT lo_product_manager->get_available_products( ) INTO ls_product.
    WRITE: / |{ ls_product-id } - { ls_product-name } - { ls_product-price DECIMALS = 2 } TL - Stok: { ls_product-stock_level }|.
  ENDLOOP.
  
  SKIP 1.
  
  " Toplam envanter değerini göster
  DATA(lv_inventory_value) = lo_product_manager->calculate_inventory_value( ).
  WRITE: / |Toplam Envanter Değeri: { lv_inventory_value DECIMALS = 2 } TL|.

4.2 ABAP CDS (Core Data Services)

ABAP CDS, veri modelleme ve HANA veritabanı özelliklerinden tam olarak yararlanmak için kullanılan modern bir yaklaşımdır.

@AbapCatalog.sqlViewName: 'ZSALESREPORT'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Satış Raporu'
define view Z_SALES_REPORT
  as select from vbak as SalesHeader
    inner join vbap as SalesItem on SalesHeader.vbeln = SalesItem.vbeln
    inner join mara as Material on SalesItem.matnr = Material.matnr
    inner join kna1 as Customer on SalesHeader.kunnr = Customer.kunnr
{
    key SalesHeader.vbeln as SalesDocument,
    key SalesItem.posnr as SalesDocumentItem,
    SalesHeader.erdat as CreationDate,
    Customer.kunnr as CustomerId,
    Customer.name1 as CustomerName,
    Customer.land1 as Country,
    Material.matnr as MaterialNumber,
    Material.maktx as MaterialDescription,
    @Semantics.quantity.unitOfMeasure: 'OrderUnit'
    SalesItem.kwmeng as OrderQuantity,
    SalesItem.meins as OrderUnit,
    @Semantics.amount.currencyCode: 'DocumentCurrency'
    SalesItem.netwr as NetAmount,
    SalesHeader.waerk as DocumentCurrency,
    
    // Hesaplanan alanlar
    case SalesHeader.faksk
      when 'A' then 'Sipariş'
      when 'B' then 'Teklif'
      else 'Diğer'
    end as DocumentType,
    
    // Vergi dahil tutar hesaplama
    @Semantics.amount.currencyCode: 'DocumentCurrency'
    case
      when SalesItem.mwskz = 'A1' then SalesItem.netwr * 1.18
      when SalesItem.mwskz = 'A2' then SalesItem.netwr * 1.08
      else SalesItem.netwr
    end as GrossAmount
}
where SalesHeader.vbtyp = 'C'  // Sadece siparişleri seç

4.3 AMDP (ABAP Managed Database Procedures)

AMDP, ABAP koduyla entegre edilmiş HANA SQLScript veya SQL kullanarak veritabanı düzeyinde kod pushdown sağlar.

CLASS zcl_sales_analysis DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES: if_amdp_marker_hdb.
    
    TYPES: BEGIN OF ty_sales_by_region,
             region_id   TYPE string,
             region_name TYPE string,
             total_sales TYPE p LENGTH 15 DECIMALS 2,
             currency    TYPE c LENGTH 3,
           END OF ty_sales_by_region.
    
    TYPES: tt_sales_by_region TYPE TABLE OF ty_sales_by_region.
    
    METHODS: get_sales_by_region
      IMPORTING VALUE(iv_year)        TYPE numc4
      EXPORTING VALUE(et_sales)       TYPE tt_sales_by_region
                VALUE(ev_total_sales) TYPE decfloat34.
      
ENDCLASS.

CLASS zcl_sales_analysis IMPLEMENTATION.

  METHOD get_sales_by_region BY DATABASE PROCEDURE
                             FOR HDB
                             LANGUAGE SQLSCRIPT
                             OPTIONS READ-ONLY.
                             
    -- HANA SQLScript ile bölgeye göre satışları hesapla
    lt_sales = SELECT  reg.region_id,
                      reg.region_name,
                      SUM(si.netwr) AS total_sales,
                      sh.waerk AS currency
              FROM vbak AS sh
                INNER JOIN vbap AS si ON sh.vbeln = si.vbeln
                INNER JOIN kna1 AS cust ON sh.kunnr = cust.kunnr
                INNER JOIN zregions AS reg ON cust.regio = reg.region_id
              WHERE SUBSTRING(sh.erdat, 1, 4) = :iv_year
                AND sh.vbtyp = 'C'  -- Sadece siparişler
              GROUP BY reg.region_id, reg.region_name, sh.waerk
              ORDER BY total_sales DESC;
    
    -- Toplam satışları hesapla
    lv_total = SELECT SUM(total_sales) AS grand_total
               FROM :lt_sales;
    
    -- Sonuçları döndür
    et_sales = SELECT * FROM :lt_sales;
    ev_total_sales = :lv_total.grand_total;
    
  ENDMETHOD.

ENDCLASS.

4.4 RAP (RESTful ABAP Programming Model)

RAP, SAP Fiori uygulamaları ve SAP API Hub üzerinden OData servisleri sağlamak için kullanılan modern bir programlama modelidir.

" RAP İş Nesnesi Davranışı
managed implementation in class zbp_i_product unique;
define behavior for ZI_Product alias Product
persistent table zproduct
lock master
authorization master ( instance )
etag master LastChangedAt
{
  create;
  update;
  delete;

  field ( readonly ) ProductUUID;
  field ( mandatory ) ProductID, ProductName, Price;
  field ( readonly ) CreatedBy, CreatedAt, LastChangedBy, LastChangedAt;

  validation validatePrice on save { field Price; }
  validation validateProductID on save { field ProductID; }

  determination setInitialValues on modify { create; }

  mapping for zproduct
  {
    ProductUUID = product_uuid;
    ProductID = product_id;
    ProductName = product_name;
    Category = category;
    Price = price;
    Currency = currency;
    Description = description;
    StockQuantity = stock_quantity;
    UnitOfMeasure = unit_of_measure;
    CreatedBy = created_by;
    CreatedAt = created_at;
    LastChangedBy = last_changed_by;
    LastChangedAt = last_changed_at;
  }
}

5. Performans İyileştirmeleri

Yeni ABAP sözdizimi, kodunuzu sadece daha okunabilir ve sürdürülebilir hale getirmekle kalmaz, aynı zamanda performansını da önemli ölçüde artırabilir. İşte bazı önemli performans iyileştirme teknikleri:

5.1 İç Tablo İşlemlerinde Performans İyileştirme

" 1. LOOP...WHERE yerine FILTER operatörü kullanma
" Kötü performans:
LOOP AT lt_flights INTO DATA(ls_flight) WHERE carrid = 'LH'.
  " İşlemler
ENDLOOP.

" İyi performans:
LOOP AT FILTER #( lt_flights WHERE carrid = 'LH' ) INTO DATA(ls_flight).
  " İşlemler
ENDLOOP.

" 2. İç içe döngüler yerine FOR...IN ifadesi kullanma
" Kötü performans:
LOOP AT lt_flights INTO DATA(ls_flight).
  LOOP AT lt_bookings INTO DATA(ls_booking) WHERE carrid = ls_flight-carrid 
                                              AND connid = ls_flight-connid.
    " İşlemler
  ENDLOOP.
ENDLOOP.

" İyi performans:
DATA(lt_combined) = VALUE tt_combined(
  FOR ls_flight IN lt_flights
  FOR ls_booking IN lt_bookings
  WHERE ( carrid = ls_flight-carrid AND connid = ls_flight-connid )
  ( carrid      = ls_flight-carrid
    connid      = ls_flight-connid
    fldate      = ls_flight-fldate
    bookid      = ls_booking-bookid
    customid    = ls_booking-customid )
).

LOOP AT lt_combined INTO DATA(ls_combined).
  " İşlemler
ENDLOOP.

5.2 Kod Pushdown (HANA Optimizasyonu)

SAP HANA veritabanının gücünden yararlanmak için, olabildiğince çok işlemi veritabanı katmanına "itmek" (push down) önemlidir.

" 1. ABAP içinde hesaplama yerine CDS görünümlerinde hesaplama
" Kötü performans (ABAP katmanında hesaplama):
SELECT carrid, connid, fldate, price, currency
  FROM sflight
  INTO TABLE @DATA(lt_flights)
  WHERE carrid = 'LH'.

DATA(lv_total) = REDUCE decfloat34(
  INIT sum = 0
  FOR ls_flight IN lt_flights
  NEXT sum = sum + ls_flight-price
).

" İyi performans (veritabanı katmanında hesaplama):
SELECT SINGLE SUM( price ) AS total
  FROM sflight
  WHERE carrid = 'LH'
  INTO @DATA(lv_total).

" 2. GROUP BY ile veritabanı katmanında gruplama
" Kötü performans (ABAP katmanında gruplama):
SELECT carrid, connid, fldate, price, currency
  FROM sflight
  INTO TABLE @DATA(lt_flights).

DATA: lt_carriers TYPE TABLE OF t_carrier,
      ls_carrier  TYPE t_carrier.

LOOP AT lt_flights INTO DATA(ls_flight).
  READ TABLE lt_carriers ASSIGNING FIELD-SYMBOL()
    WITH KEY carrid = ls_flight-carrid.
  IF sy-subrc <> 0.
    ls_carrier-carrid = ls_flight-carrid.
    ls_carrier-total = ls_flight-price.
    APPEND ls_carrier TO lt_carriers.
  ELSE.
    -total = -total + ls_flight-price.
  ENDIF.
ENDLOOP.

" İyi performans (veritabanı katmanında gruplama):
SELECT carrid, 
       SUM( price ) AS total
  FROM sflight
  GROUP BY carrid
  INTO TABLE @DATA(lt_carriers).

6. Sonuç

ABAP yeni sözdizimi, SAP geliştirme süreçlerini daha modern, verimli ve sürdürülebilir hale getiren önemli bir gelişimdir. Bu rehberde ele alınan özellikler, kod yazımında daha az çaba ile daha yüksek kalite elde etmenize yardımcı olur.

Yeni sözdiziminin sunduğu avantajlar şunlardır:

  • Daha özlü ve okunabilir kod
  • Daha az tekrarlayan kod bloğu
  • Daha güçlü tip güvenliği
  • Daha iyi veritabanı entegrasyonu
  • Daha yüksek kod performansı
  • Modern programlama paradigmalarıyla uyum

SAP geliştirme projelerinizde yeni sözdizimi özelliklerini kullanarak, daha kaliteli ve sürdürülebilir uygulamalar geliştirebilirsiniz. Bu özellikler, özellikle S/4HANA ve SAP Cloud Platform projelerinde büyük önem taşımaktadır.

7. Ek Kaynaklar

Yorumlar

0

Yorum yapmak için giriş yapmalısınız.

Henüz yorum bulunmamaktadır.

İlk yorumu yapan siz olun.

Emre Göçmen

Yazar & Geliştirici

SAP ABAP & Full Stack geliştirici olarak deneyimlerim, becerilerim ve kariyer yolculuğum hakkında blog yazılarım.

Kategori

SAP

SAP

Yazılardan Haberdar Olun

Yeni yazılardan ilk siz haberdar olmak için e-posta bültenime abone olun.