ABAP CDS Views Serisi 3: Performans ve Anotasyonlar
ABAP

ABAP CDS Views Serisi 3: Performans ve Anotasyonlar

SAP projelerinde en sık karşılaştığım sorunlardan biri şu: Geliştirici ekipler, veriyi doğru yerde işlememekten kaynaklanan performans problemleriyle boğuşuyor. Yıllarca SELECT ENDSELECT döngülerinde, uygulama sunucusunda yapılan gereksiz hesaplamalarla vakit kaybettik. CDS Views (Core Data Services) tam da bu noktada oyunun kurallarını değiştiriyor—ama doğru kullanıldığında.

Bu makalede, CDS Views mimarisini sıfırdan değil; zaten temel bilgisi olan geliştiriciler için ileri seviye perspektiften ele alacağız. Hangi senaryolarda CDS Views kullanmalısınız, hangi senaryolarda kaçınmalısınız ve gerçek dünya projelerinde nasıl bir mimari kurarsınız—bunları konuşacağız.

—

CDS Views Neden Sadece “Yeni Bir View Teknolojisi” Değil?

Classic ABAP dünyasından geliyorsanız, CDS Views’ı başlangıçta “database view’ın süslüsü” olarak görmüş olabilirsiniz. Ben de öyle düşündüm—ta ki ilk büyük raporlama projesinde farkı elle tutulur biçimde görene kadar.

CDS’in gerçek gücü şu üç alanda kendini gösteriyor:

1. Code Pushdown Prensibi

Hesaplamaları, filtreleri ve aggregation işlemlerini veritabanı katmanına taşıyorsunuz. HANA’nın in-memory işleme gücünü tam anlamıyla kullanıyorsunuz. Uygulama sunucusu sadece sonucu alıyor.

2. Semantik Zenginleştirme

Annotation’lar sayesinde aynı veri modeli; UI5, Fiori, OData servisleri ve analitik araçlar tarafından tek bir tanımdan türetiliyor. Bir kez tanımla, her yerde kullan.

3. Yeniden Kullanılabilir Katmanlı Mimari

Interface Views, Consumption Views ve Projection Views katmanlamasıyla sürdürülebilir bir veri mimarisi kurabiliyorsunuz.

—

CDS View Mimarisi: Üç Katmanlı Yaklaşım

Projelerde sıkça gördüğüm anti-pattern şu: Her şeyi tek bir dev CDS view’a tıkmak. Hem UI hem iş mantığı hem de raw veri aynı view’da. Bu, birkaç ay sonra bakım kabusu haline geliyor.

SAP’ın önerdiği ve pratikte çok işe yarayan yaklaşım şu katmanlamadır:

[Interface/Basic Views]  →  [Composite Views]  →  [Consumption Views]

(Raw Data)               (Business Logic)        (UI/API Layer)

Katman 1: Interface Views (Temel Veri Katmanı)

Bu katman doğrudan tablolara dokunuyor. Sadece veriyi anlamlı hale getiriyor, iş mantığı yok.

abap

@AbapCatalog.sqlViewName: ‘ZI_SALESORDER’

@AbapCatalog.compiler.compareFilter: true

@AbapCatalog.preserveKey: true

@AccessControl.authorizationCheck: #CHECK

@EndUserText.label: ‘Sales Order – Interface View’

define view ZI_SalesOrder

as select from vbak

association [0..1] to ZI_Customer as _Customer

on $projection.SoldToParty = _Customer.Customer

association [0..1] to ZI_SalesOrg as _SalesOrg

on $projection.SalesOrganization = _SalesOrg.SalesOrganization

{

key vbak.vbeln       as SalesOrder,

  vbak.erdat       as CreationDate,

  vbak.audat       as DocumentDate,

  vbak.kunnr       as SoldToParty,

  vbak.vkorg       as SalesOrganization,

  vbak.netwr       as NetValue,

  vbak.waerk       as DocumentCurrency,

  vbak.auart       as SalesDocumentType,

  // Expose associations

  _Customer,

  _SalesOrg

}

Dikkat edin: Bu view’da hiçbir iş kuralı yok. Sadece alan eşlemeleri ve association tanımları var. Bu katmanı stabil tutmak kritik—üzerine inşa edeceğiniz her şey buraya bağımlı.

Katman 2: Composite Views (İş Mantığı Katmanı)

Burası hesaplamaların, case expression’larının ve birden fazla kaynak birleştirmenin yapıldığı yer.

abap

@AbapCatalog.sqlViewName: ‘ZC_SALESORDER’

@AbapCatalog.compiler.compareFilter: true

@AccessControl.authorizationCheck: #CHECK

@EndUserText.label: ‘Sales Order – Composite View’

define view ZC_SalesOrder

as select from ZI_SalesOrder as SalesOrder

inner join ZI_SalesOrderItem as SalesOrderItem

on SalesOrder.SalesOrder = SalesOrderItem.SalesOrder

association [0..1] to I_Currency as _Currency

on $projection.DocumentCurrency = _Currency.Currency

{

key SalesOrder.SalesOrder,

  SalesOrder.CreationDate,

  SalesOrder.SoldToParty,

  SalesOrder.SalesOrganization,

  // İş Mantığı: Sipariş yaşını hesapla

  $session.system_date – SalesOrder.CreationDate as OrderAgeInDays,

  // İş Mantığı: Değer kategorisi

  case

    when SalesOrder.NetValue >= 100000 then ‘HIGH’

    when SalesOrder.NetValue >= 10000  then ‘MEDIUM’

    else                                    ‘LOW’

  end as ValueCategory,

  // Aggregation: Kalem sayısı

  count( SalesOrderItem.SalesOrderItem ) as ItemCount,

  // Aggregation: Toplam net değer (kalem bazlı)

  sum( SalesOrderItem.NetValue ) as TotalItemValue,

  SalesOrder.DocumentCurrency,

  _Currency

}

group by

SalesOrder.SalesOrder,

SalesOrder.CreationDate,

SalesOrder.SoldToParty,

SalesOrder.SalesOrganization,

SalesOrder.NetValue,

SalesOrder.DocumentCurrency

Katman 3: Consumption Views (Tüketim Katmanı)

UI5, Fiori veya OData servisleri için özelleştirilmiş projection’lar bu katmanda oluyor.

abap

@AbapCatalog.sqlViewName: ‘ZP_SALESORDER’

@AccessControl.authorizationCheck: #CHECK

@EndUserText.label: ‘Sales Order – Fiori List’

// UI Annotation’ları

@UI.headerInfo: {

typeName: ‘Sales Order’,

typeNamePlural: ‘Sales Orders’,

title: { type: #STANDARD, value: ‘SalesOrder’ },

description: { type: #STANDARD, value: ‘SoldToParty’ }

}

// OData Servisi için

@OData.entityType.name: ‘SalesOrderType’

@OData.publish: true

define view ZP_SalesOrder_Fiori

as projection on ZC_SalesOrder

{

@UI.lineItem: [{ position: 10 }]

@UI.selectionField: [{ position: 10 }]

SalesOrder,

@UI.lineItem: [{ position: 20 }]

CreationDate,

@UI.lineItem: [{ position: 30 }]

@UI.selectionField: [{ position: 20 }]

SoldToParty,

@UI.lineItem: [

{ position: 40,

  criticality: ‘ValueCriticality’ }

]

ValueCategory,

// Criticality mapping için hesaplanan alan

case ValueCategory

when ‘HIGH’   then 3  // Green

when ‘MEDIUM’ then 2  // Yellow

else               1  // Red

end as ValueCriticality,

@UI.lineItem: [{ position: 50 }]

ItemCount,

@Semantics.amount.currencyCode: ‘DocumentCurrency’

@UI.lineItem: [{ position: 60 }]

TotalItemValue,

DocumentCurrency,

OrderAgeInDays

}

—

Performans Tuzakları ve Çözümleri

CDS Views yazarken düştüğüm ve ekiplerden sıkça gördüğüm performans hatalarını paylaşayım.

Tuzak 1: Association Yerine Join Kullanmak

Association’lar lazy loading mantığıyla çalışır—yalnızca kullanıldığında JOIN üretir. Ama siz her yere JOIN yazarsanız, gereksiz tablo okumalarını zorunlu kılarsınız.

abap

— YANLIŞ: Her zaman join yapılıyor

define view ZI_Order_Wrong

as select from vbak

inner join kna1 on vbak.kunnr = kna1.kunnr

{

vbak.vbeln as SalesOrder,

kna1.name1 as CustomerName  // Sadece bazı senaryolarda gerekli

}

— DOĞRU: Association kullan, tüketici view’da karar versin

define view ZI_Order_Correct

as select from vbak

association [0..1] to kna1 as _Customer

on $projection.SoldToParty = _Customer.kunnr

{

key vbak.vbeln as SalesOrder,

  vbak.kunnr as SoldToParty,

  _Customer  // Association expose ediliyor

}

Tuzak 2: Client Handling Hatası

Multi-client sistemlerde client field’ını unutmak, cross-client veri okumaya yol açar.

abap

— Her zaman mandt/client’ı kontrol et

define view ZI_MaterialDoc

as select from mkpf

association [1..*] to mseg as _Items

on  $projection.MaterialDocument = _Items.mblnr

// Client koşulunu association’a da ekle

and $projection.FiscalYear        = _Items.mjahr

{

key mkpf.mblnr as MaterialDocument,

key mkpf.mjahr as FiscalYear,

  mkpf.budat as PostingDate,

  _Items

}

Tuzak 3: Gereksiz CASE İfadeleri Üst Üste

Karmaşık CASE ifadelerini üst üste yazmak yerine, ara katmanlarla bölün.

abap

— İş mantığını katmanlara böl

— Önce basit status hesapla (Interface/Composite katmanda)

case vbak.gbstk

when ‘A’ then ‘OPEN’

when ‘B’ then ‘PARTIAL’

when ‘C’ then ‘COMPLETE’

else          ‘UNKNOWN’

end as DeliveryStatus,

— Sonra criticality’yi ayrı bir alanda hesapla (Consumption katmanda)

case DeliveryStatus

when ‘OPEN’    then 2

when ‘PARTIAL’ then 1

when ‘COMPLETE’then 3

else               0

end as DeliveryStatusCriticality

—

Access Control: Güvenliği Unutmayın

CDS Views yazarken en sık atlanan konu: Authorization check. SAP’ın DCL (Data Control Language) mekanizması çok güçlü ama projelerde genellikle son dakikaya bırakılıyor—bu büyük hata.

abap

// ZI_SalesOrder.dcl – Access Control tanımı

@EndUserText.label: ‘Sales Order Access Control’

@MappingRole: true

define role ZI_SalesOrder {

grant

select

on

  ZI_SalesOrder

where

  // Satış organizasyonuna göre yetki kontrolü

  ( SalesOrganization ) =

    aspect pfcg_auth( V_VBAK_VKO,

                      VKORG,

                      ACTVT = ’03’ );

}

Projenin başında bu kontrolü kurun. Sonradan eklemek, tüm türeyen view’ları gözden geçirmenizi gerektirir.

—

Analitik CDS Views: HANA Gücünü Tam Kullanmak

Raporlama senaryolarında Analytical CDS Views (küp ve boyut view’ları) kullanmak, geleneksel raporlamaya göre dramatik performans farkı yaratıyor.

abap

// Boyut View örneği

@Analytics.dataCategory: #DIMENSION

@Analytics.internalName: #LOCAL

@EndUserText.label: ‘Customer Dimension’

define view ZA_Customer_Dim

as select from kna1

{

@ObjectModel.text.element: [‘CustomerName’]

key kna1.kunnr as Customer,

  kna1.name1 as CustomerName,

  kna1.land1 as Country,

  kna1.ktokd as AccountGroup

}

// Küp View örneği

@Analytics.dataCategory: #CUBE

@Analytics.internalName: #LOCAL

@EndUserText.label: ‘Sales Order Cube’

define view ZA_SalesOrder_Cube

as select from ZC_SalesOrder

association [0..1] to ZA_Customer_Dim as _Customer

on $projection.SoldToParty = _Customer.Customer

{

// Measure’lar

@DefaultAggregation: #SUM

@Semantics.amount.currencyCode: ‘DocumentCurrency’

TotalItemValue,

@DefaultAggregation: #SUM

ItemCount,

// Dimension referansları

@AnalyticsDetails.query.display: #KEY_TEXT

SoldToParty,

CreationDate,

SalesOrganization,

ValueCategory,

DocumentCurrency,

_Customer

}

—

Gerçek Dünya Senaryosu: Üretim Raporlama Mimarisi

Geçen yıl bir üretim firmasında kurduğumuz mimariden kısaca bahsedeyim. Sorun şuydu: Üretim emirleri, kalite bildirimleri ve malzeme hareketleri ayrı ayrı raporlanıyordu. Ekipler Excel’de birleştiriyordu. Süreç hem hatalı hem de yavaştı.

Kurduğumuz mimari:

ZI_ProductionOrder  (Interface – PP modülü)

ZI_QualityNotif     (Interface – QM modülü)

ZI_GoodsMovement    (Interface – MM modülü)

     ↓

ZC_ProductionAnalytics (Composite – 3 kaynağı birleştir)

     ↓

ZA_Production_Cube  (Analytic Cube – KPI’lar)

     ↓

ZP_Production_Dashboard (Consumption – Fiori)

Sonuç: Excel süreçleri ortadan kalktı. Raporlama süresi 45 dakikadan gerçek zamana düştü. Ve en önemlisi—yetki kontrolleri merkezi hale geldi.

—

En İyi Pratikler: Mimari Checklist

CDS View geliştirmeden önce şu soruları kendinize sorun:

– [ ] View hangi katmana ait? (Interface / Composite / Consumption)

– [ ] Association mı, JOIN mi kullanmalıyım?

– [ ] Hangi annotation’lar gerekli? (UI, OData, Analytics)

– [ ] Access control tanımlandı mı?

– [ ] Client handling doğru mu?

– [ ] Performans testi yapıldı mı? (SE16N yerine EXPLAIN PLAN ile)

– [ ] Naming convention tutarlı mı? (ZI_, ZC_, ZP_ önekleri)

– [ ] Deprecation stratejisi var mı? (Eski view’lar nasıl kaldırılacak?)

—

Sonuç: CDS Views Bir Teknoloji Değil, Bir Mimari Yaklaşım

CDS Views’ı doğru kullanmak, sadece sözdizimini öğrenmekle bitmiyor. Asıl mesele, verinin hangi katmanda işleneceğine dair doğru mimari kararları vermek.

Kisaca özetlemek gerekirse:

– Interface Views: Stabil, raw veri katmanı—buraya iş mantığı koymayın

– Composite Views: Hesaplamalar, aggregation’lar ve birleştirmeler burada

– Consumption Views: UI ve API’ye özel projection’lar—teknik ayrıntıları gizleyin

– Access Control: Projenin başında kurun, sonraya bırakmayın

– Association vs JOIN: Association’ı tercih edin, JOIN’i bilinçli seçin

Bu mimariyi bir projede oturursa, sonrasında gelen talepler için sadece yeni bir consumption view açmanız yeterli oluyor. Alt katmanları değiştirmeden.

Bir sonraki makalede, CDS Views üzerinde RAP (Restful ABAP Programming) ile tam CRUD servisi nasıl kurulur—onu ele alacağız.

—

Siz bu mimarilerden hangisini projelerinizde uyguladınız? Özellikle access control veya analitik katmanda karşılaştığınız zorlukları yorumlarda paylaşın—birlikte tartışalım. Bu makaleyi faydalı bulduysanız, SAP ekibinizle paylaşmayı unutmayın.

—

İlgili Makaleler:

– ABAP RAP ile OData Servisi Geliştirme: Adım Adım Rehber

– SAP HANA Performans Optimizasyonu: EXPLAIN PLAN Kullanımı

– CDS Views ve Fiori Elements: Annotation Tabanlı UI Geliştirme