# ABAP CDS Views ile Performanslı Veri Modelleme: İleri Seviye Mimari Rehberi
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*