Software Component Management in ABAP Cloud

kategorie
DevOps
Veröffentlicht
autor
Johannes

Software Components sind das zentrale Konzept zur Strukturierung von ABAP-Code auf SAP BTP. Sie bilden die Grundlage für Transport, Versionierung und Modularisierung von Entwicklungsobjekten in ABAP Cloud.

Was ist eine Software Component?

Eine Software Component ist eine logische Einheit, die zusammengehörige ABAP-Entwicklungsobjekte gruppiert:

KonzeptBeschreibung
Software ComponentContainer für ABAP-Packages und deren Objekte
PackageOrdner innerhalb einer Component für feinere Strukturierung
RepositoryGit-Repository, das den Code der Component enthält
BranchVersion/Zweig innerhalb des Repositories
CloneLokale Kopie der Component in einem ABAP-System

Software Components vs. klassische Packages

AspektKlassisch (On-Premise)ABAP Cloud
Oberste EinheitPackage (DEVC)Software Component
TransportTransportaufträgeGit-basiert via gCTS
VersionierungTransportlogsGit-Commits/Branches
AbhängigkeitenPackage-InterfacesComponent Dependencies
ModularisierungOptionalZwingend erforderlich

Architektur von Software Components

┌─────────────────────────────────────────────────────────────────────────────┐
│ SAP BTP ABAP Environment │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Software Component: /DMO/FLIGHT │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │
│ │ │ /DMO/FLIGHT_ │ │ /DMO/FLIGHT_ │ │ /DMO/FLIGHT_ │ │ │
│ │ │ DOMAIN │ │ REUSE │ │ TRAVEL │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ - CDS Entities │ │ - Utility │ │ - RAP BO │ │ │
│ │ │ - Domain Types │ │ Classes │ │ - Service │ │ │
│ │ │ - Data Elements │ │ - Interfaces │ │ - Projection │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │
│ │ │ │
│ │ └──────────────────────────────────────────────────────────────────┘│ │
│ │ ↑ Git Repository ↑ │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Software Component: ZCUSTOM_APP │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ │ │
│ │ │ ZCUSTOM_CORE │ │ ZCUSTOM_UI │ │ │
│ │ │ │ │ │ │ │
│ │ │ - Business Logic│ │ - Services │ ─────depends on────────────┤ │
│ │ │ - RAP BO │ │ - Extensions │ /DMO/FLIGHT │ │
│ │ └─────────────────┘ └─────────────────┘ │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘

Software Component erstellen

Voraussetzungen

  • Administrator-Berechtigung im ABAP Environment
  • Zugriff auf die Fiori Launchpad App “Manage Software Components”
  • Git-Repository (optional für eigene Components)

Schritt 1: Manage Software Components App öffnen

Die App “Manage Software Components” ist der zentrale Einstiegspunkt:

┌────────────────────────────────────────────────────────────────┐
│ Manage Software Components │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Software Components │ │
│ │ │ │
│ │ Component │ Status │ Branch │ Last Commit │ │
│ │ ────────────────┼───────────┼─────────┼────────────── │ │
│ │ /DMO/FLIGHT │ Cloned │ main │ 2 hours ago │ │
│ │ ZCUSTOM_APP │ Not Cloned│ - │ - │ │
│ │ ZINTEGRATION │ Cloned │ develop │ 1 day ago │ │
│ │ │ │
│ │ [+ Create] [Clone] [Pull] [Checkout] │ │
│ └─────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘

Schritt 2: Neue Software Component anlegen

" Eine Software Component wird über die Fiori App angelegt:
" 1. "Create" Button klicken
" 2. Namen vergeben (z.B. ZCUSTOM_APP)
" 3. Beschreibung hinzufügen
" 4. Optional: Git Repository URL angeben
FeldBeispielwertBeschreibung
NameZCUSTOM_APPEindeutiger technischer Name
DescriptionCustom ApplicationLesbare Beschreibung
Repository URLhttps://github.com/Git-Repository (optional)
BranchmainStandard-Branch

Schritt 3: Structure Package anlegen

Jede Software Component benötigt mindestens ein Structure Package:

" Im ADT: File > New > ABAP Package
" - Name: ZCUSTOM_APP (gleicher Name wie Component)
" - Software Component: ZCUSTOM_APP
" - Package Type: Structure Package

Packages innerhalb einer Component

Package-Hierarchie

Software Component: ZCUSTOM_APP
├── ZCUSTOM_APP (Structure Package)
│ │
│ ├── ZCUSTOM_APP_DOMAIN (Development Package)
│ │ ├── CDS Views
│ │ ├── Data Elements
│ │ └── Domains
│ │
│ ├── ZCUSTOM_APP_CORE (Development Package)
│ │ ├── Classes
│ │ ├── Interfaces
│ │ └── RAP Business Objects
│ │
│ ├── ZCUSTOM_APP_SERVICE (Development Package)
│ │ ├── Service Definitions
│ │ ├── Service Bindings
│ │ └── Behavior Definitions
│ │
│ └── ZCUSTOM_APP_TEST (Development Package)
│ └── ABAP Unit Test Classes

Package anlegen in ADT

" File > New > ABAP Package
" 1. Development Package für Domain-Objekte:
" Name: ZCUSTOM_APP_DOMAIN
" Description: Domain objects for Custom App
" Software Component: ZCUSTOM_APP
" Superpackage: ZCUSTOM_APP
" Package Type: Development
" 2. Development Package für Core-Logik:
" Name: ZCUSTOM_APP_CORE
" Description: Core business logic
" Software Component: ZCUSTOM_APP
" Superpackage: ZCUSTOM_APP
" Package Type: Development

Abhängigkeiten zwischen Components

Arten von Abhängigkeiten

TypBeschreibungBeispiel
Direkte AbhängigkeitComponent nutzt Objekte einer anderenZCUSTOM nutzt /DMO/FLIGHT
Transitive AbhängigkeitIndirekte Abhängigkeit über eine dritte ComponentA → B → C
Zirkuläre AbhängigkeitGegenseitige Abhängigkeit (verboten!)A → B → A

Abhängigkeit deklarieren

Abhängigkeiten werden über Package Interfaces gesteuert:

-- Package Interface definieren (exportierte Objekte)
-- Im ADT: Package > New > ABAP Package Interface
-- Beispiel: /DMO/FLIGHT_REUSE exponiert Utility-Klassen
@EndUserText.label: 'Flight Reuse Package Interface'
package interface /dmo/flight_reuse_api
{
-- Alle Klassen mit Prefix CL_ werden exportiert
expose classes matching 'CL_*';
-- Spezifische Interfaces exportieren
expose if_flight_calculator;
expose if_price_provider;
}

Use Access für Abhängigkeiten

" Im Package ZCUSTOM_APP_CORE:
" Rechtsklick > Properties > Use Accesses
" Use Access hinzufügen:
" - Package Interface: /DMO/FLIGHT_REUSE_API
" - Access Mode: Readonly

Code-Beispiel: Component-übergreifende Nutzung

CLASS zcl_custom_flight_service DEFINITION
PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
METHODS:
calculate_flight_price
IMPORTING iv_flight_id TYPE /dmo/flight_id
RETURNING VALUE(rv_price) TYPE /dmo/flight_price
RAISING cx_flight_not_found.
ENDCLASS.
CLASS zcl_custom_flight_service IMPLEMENTATION.
METHOD calculate_flight_price.
" Nutzung einer Klasse aus /DMO/FLIGHT_REUSE
" Dies funktioniert nur, wenn die Abhängigkeit deklariert ist
DATA(lo_calculator) = NEW /dmo/cl_flight_price_calculator( ).
rv_price = lo_calculator->calculate(
iv_flight_id = iv_flight_id
iv_include_taxes = abap_true
).
ENDMETHOD.
ENDCLASS.

Software Component klonen und aktualisieren

Component klonen (erstmalig)

┌────────────────────────────────────────────────────────────────┐
│ Clone Software Component │
│ │
│ Component: ZPARTNER_INTEGRATION │
│ Repository: https://github.com/company/partner-integration │
│ Branch: main │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Clone Progress │ │
│ │ ████████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 42% │ │
│ │ │ │
│ │ - Fetching repository metadata... ✓ │ │
│ │ - Downloading objects... ✓ │ │
│ │ - Importing ABAP objects... ⟳ │ │
│ │ - Activating objects... ○ │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
│ [Cancel] │
└────────────────────────────────────────────────────────────────┘

Pull (Updates holen)

" ABAP-Code zum programmatischen Pull
" (normalerweise über Fiori App)
CLASS zcl_software_component_utils DEFINITION
PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
CLASS-METHODS:
get_component_info
IMPORTING iv_component_name TYPE string
RETURNING VALUE(rs_info) TYPE zsoftware_component_info.
ENDCLASS.
CLASS zcl_software_component_utils IMPLEMENTATION.
METHOD get_component_info.
" Software Component Informationen auslesen
" über die entsprechende API
SELECT SINGLE
component_name,
current_branch,
last_commit_id,
last_commit_date,
clone_status
FROM i_softwarecomponent
WHERE component_name = @iv_component_name
INTO CORRESPONDING FIELDS OF @rs_info.
ENDMETHOD.
ENDCLASS.

Branch wechseln (Checkout)

┌────────────────────────────────────────────────────────────────┐
│ Checkout Branch │
│ │
│ Component: ZCUSTOM_APP │
│ Current Branch: main │
│ │
│ Available Branches: │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ ○ main (default) │ │
│ │ ● develop ← Selected │ │
│ │ ○ feature/new-ui │ │
│ │ ○ hotfix/price-calc │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
│ ⚠ Warning: Local changes will be overwritten! │
│ │
│ [Checkout] [Cancel] │
└────────────────────────────────────────────────────────────────┘

Transport und Deployment

Git-basierter Transport-Workflow

┌─────────────────────────────────────────────────────────────────────────────┐
│ Git-basierter Transport Flow │
│ │
│ DEV System Git Repository QAS/PRD System │
│ ────────── ────────────── ────────────── │
│ │
│ 1. Entwicklung 2. Commit/Push 4. Pull/Deploy │
│ ┌──────────┐ ┌──────────────┐ ┌──────────┐ │
│ │ Code │ ────────────> │ main │ ────────> │ Import │ │
│ │ ändern │ Push │ branch │ Pull │ Objects │ │
│ └──────────┘ └──────────────┘ └──────────┘ │
│ │ │
│ 3. Review │ │
│ ┌──────────┐ ┌──────────────┐ │
│ │ Pull │ <──────────── │ feature │ │
│ │ Request │ Review │ branch │ │
│ └──────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘

Release-Workflow

" Software Component Release-Prozess:
" 1. Entwicklung auf feature-Branch
" 2. Pull Request erstellen
" 3. Code Review durchführen
" 4. Merge in main-Branch
" 5. Tag für Release erstellen
" 6. QAS: Checkout des Tags
" 7. Tests durchführen
" 8. PRD: Checkout des gleichen Tags

Strukturierung großer Projekte

Empfohlene Component-Struktur

ComponentZweckBeispiel-Packages
Z*_FOUNDATIONBasis-Objekte, DomainsZ_DOMAIN, Z_TYPES
Z*_COREBusiness-LogikZ_BO, Z_LOGIC
Z*_SERVICEAPIs und ServicesZ_ODATA, Z_REST
Z*_UIUI-spezifische ObjekteZ_FIORI, Z_ANNOTATIONS
Z*_INTEGRATIONExterne IntegrationenZ_RFC, Z_HTTP
Z*_TESTTest-InfrastrukturZ_UNIT, Z_MOCKS

Beispiel: Multi-Component-Projekt

Enterprise Sales Application
├── ZSALES_FOUNDATION ← Keine Abhängigkeiten
│ ├── ZSALES_FOUNDATION_TYPES
│ └── ZSALES_FOUNDATION_UTILS
├── ZSALES_CORE ← Abhängig von FOUNDATION
│ ├── ZSALES_CORE_ORDER
│ ├── ZSALES_CORE_CUSTOMER
│ └── ZSALES_CORE_PRODUCT
├── ZSALES_SERVICE ← Abhängig von CORE
│ ├── ZSALES_SERVICE_ORDER_API
│ └── ZSALES_SERVICE_CUSTOMER_API
└── ZSALES_UI ← Abhängig von SERVICE
├── ZSALES_UI_ORDER_APP
└── ZSALES_UI_CUSTOMER_APP

Best Practices

Do’s

EmpfehlungBegründung
Eine Component = Ein GeschäftsbereichKlare Verantwortlichkeiten
Explizite Abhängigkeiten definierenVermeidet versteckte Kopplungen
Package Interfaces nutzenKontrolle über exportierte APIs
Konsistente NamenskonventionBessere Übersicht im Repository
Separate Test-PackagesSaubere Trennung von Produktiv-Code
Branch-Strategie definierenmain, develop, feature/*

Don’ts

VermeidenProblem
Alle Objekte in einer ComponentUnübersichtlich, schwer wartbar
Zirkuläre AbhängigkeitenBuild-Fehler, komplexe Updates
Zu tiefe Package-HierarchienNavigation wird schwierig
Generische Namen (ZUTILS, ZMISC)Unklar, wird zur Müllhalde
Packages ohne klaren ScopeVermischung von Verantwortlichkeiten

Namenskonventionen

ObjekttypKonventionBeispiel
Software ComponentZ{PROJEKT}_{BEREICH}ZSALES_CORE
Structure Package= Software Component NameZSALES_CORE
Development PackageZ{PROJEKT}{BEREICH}{FUNKTION}ZSALES_CORE_ORDER
Package InterfaceZ{PACKAGE}_APIZSALES_CORE_ORDER_API

Troubleshooting

Häufige Probleme

ProblemUrsacheLösung
”Component not found”Clone fehltComponent über Manage Software Components klonen
”Dependency error”Fehlende Use AccessPackage Interface und Use Access prüfen
”Activation failed”Objekt-KonflikteAndere Branch auschecken oder Konflikt lösen
”Pull failed”Git-AuthentifizierungCredentials in Destination Service prüfen

Diagnose-Tools

CLASS zcl_component_diagnostics DEFINITION
PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
CLASS-METHODS:
check_component_status
IMPORTING iv_component TYPE string
RETURNING VALUE(rt_issues) TYPE string_table.
ENDCLASS.
CLASS zcl_component_diagnostics IMPLEMENTATION.
METHOD check_component_status.
" 1. Prüfen ob Component geklont ist
SELECT SINGLE clone_status
FROM i_softwarecomponent
WHERE component_name = @iv_component
INTO @DATA(lv_status).
IF sy-subrc <> 0.
APPEND 'Component nicht gefunden' TO rt_issues.
RETURN.
ENDIF.
IF lv_status <> 'CLONED'.
APPEND |Component Status: { lv_status }| TO rt_issues.
ENDIF.
" 2. Prüfen auf nicht-aktivierte Objekte
SELECT COUNT(*)
FROM tadir
WHERE devclass LIKE @iv_component && '%'
AND obj_status <> 'A'
INTO @DATA(lv_inactive_count).
IF lv_inactive_count > 0.
APPEND |{ lv_inactive_count } inaktive Objekte| TO rt_issues.
ENDIF.
ENDMETHOD.
ENDCLASS.

Integration mit CI/CD

Software Components lassen sich in CI/CD-Pipelines integrieren:

# Beispiel: GitHub Actions Workflow
name: ABAP CI/CD
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Import to ABAP System
uses: SAP/abap-pipeline-action@v1
with:
system-url: ${{ secrets.ABAP_SYSTEM_URL }}
component: ZCUSTOM_APP
branch: ${{ github.ref_name }}
- name: Run ABAP Unit Tests
uses: SAP/abap-unit-action@v1
with:
package: ZCUSTOM_APP
coverage-threshold: 80

Vergleich der Transport-Optionen

MerkmalKlassischer TransportgCTSabapGit
ZielgruppeOn-PremiseOn-Premise + BTPAlle
Git-IntegrationNeinJaJa
SAP-SupportJaJaCommunity
BranchingNeinJaJa
CI/CDEingeschränktJaJa
BTP ABAP EnvironmentN/AStandardVia ADT

Weiterführende Themen

Zusammenfassung

Software Component Management ist fundamental für professionelle ABAP Cloud-Entwicklung:

  1. Software Components gruppieren zusammengehörige ABAP-Objekte
  2. Packages ermöglichen feine Strukturierung innerhalb einer Component
  3. Package Interfaces kontrollieren, welche Objekte exportiert werden
  4. Abhängigkeiten zwischen Components müssen explizit deklariert werden
  5. Git-basierter Transport ersetzt klassische Transportaufträge
  6. CI/CD-Integration ermöglicht moderne DevOps-Praktiken

Eine durchdachte Component-Struktur zahlt sich langfristig aus: Der Code bleibt wartbar, Teams können parallel arbeiten, und Änderungen lassen sich sicher durch die Landschaft transportieren.