26. Juni 2017
Matthias Siegmund
0

Mit dem Bypass dem SAP-Monolithen zu Leibe rücken!

Zurück zum Standard durch individuelle Integrationen!

arterienverkalkung-saxonia-systemsVerengungen und Erkrankungen der Herzkranzgefäße durch Arterienverkalkung gehören inzwischen schon fast zum „Standard“. In der Bundesrepublik Deutschland leiden ca. eine Million Menschen an koronarer Herzkrankheit. Gründe für diese Verengung sind Stoffwechselerkrankungen der Herzkranzgefäße, die Einlagerungen in die Gefäßwand zur Folge haben. Durch die Verengungen kann das Herz nicht mehr ausreichend mit Blut und Sauerstoff versorgt werden, was zu einem Engegefühl in der Brust und zu Atemnot führen kann. Diese Symptome können den Patienten in seiner Leistungsfähigkeit stark einschränken und auch zu einem lebensbedrohlichen Herzinfarkt führen. Eine Bypass-Operation ist hier häufig der letzte Ausweg, um den notwendigen Blutfluss wieder sicherzustellen und die Lebensqualität der betroffenen Personen langfristig zu verbessern.

Was hat eine Bypass-Operation mit Softwaresystemen zu tun?

In vielen Firmen stellt ein SAP-System ein zentrales Herzstück in der Unternehmensinfrastruktur dar. Die darin enthaltenen Daten und abgebildeten Geschäftsprozesse sind die Lebensadern der Firma. Doch auch dieses Herzstück und die Lebensadern sind zunehmend von „virtueller“ Verkalkung betroffen, die das Gesamtsystem bedrohen.

Steigende Anforderungen, zunehmende Funktionalität und der Druck zur Individualisierung erfordern immer mehr Spezialentwicklungen und Anpassungen am Herzstück des Unternehmens. Jedes neue Feature erhöht die Komplexität des Gesamtsystems und wirkt sich somit direkt auf Stabilität, Qualität, Performance und Wartbarkeit aus. Es besteht daher sehr leicht die Gefahr, dass diese Entwicklungen für Spezialfälle das System „verstopfen“.software-systeme-saxonia-systems Anfänglich unbemerkt, können sich so schnell „gewachsene“ Altsysteme entwickeln, die nicht mehr die gewünschte Leistungsfähigkeit „vergangener Tage“ haben. Aktuelle Anforderungen an Time to Market, Nutzererlebnis und Flexibilität lassen sich somit immer schwerer bewerkstelligen. Darüber hinaus wird die Upgrade Fähigkeit zunehmend gefährdet.

Diese „Gefahren“ sind in der Softwarearchitektur hinlänglich bekannt und wurden bereits in den späten 70er Jahre durch Edward Yourdon und Larry Constantine in Structured design – Fundamentals of a discipline of computer program and systems design adressiert. In der UNIX-Philosophie wird es kurzum auf den Punkt gebracht: Write programs that do one thing and do it well. Write programs to work together.

Vielfach werden diese zentralen Prinzipien in Bezug auf SAP-Umgebungen jedoch verletzt und monolithische Systeme geschaffen, die immer mehr Anforderungen gerecht werden müssen und mit immer mehr Funktionalitäten außerhalb des eigentlichen Kerngeschäftes „überladen“ werden. Das Herz übernimmt sozusagen auch noch Arbeiten der Lunge und der Niere.

Die Bypass-Operation in der Software

herz-saxonia-systemsDie Saxonia Systems AG hat dafür ein Lösungsszenario entwickelt, das sowohl den Anforderungen an Time to Market, Nutzererlebnis und Flexibilität als auch den Anforderungen an Verlässlichkeit, Datensicherheit und Funktionsumfang gerecht wird.

Mit einem „virtuellen Bypass“ werden Funktionalitäten über definierte Schnittstellen in eine individuelle Drittlösung ausgelagert. Die Datenbasis ist und bleibt dabei immer das SAP-System – das Prinzip einer Single Source of Truth bleibt vollständig gewahrt.

Durch die Verwendung von OData Services, zentralen Gateway-Komponenten als Zugriffspunkt und modernen Front-End Frameworks entstehen somit smarte Business Applikationen, die sich nahtlos in das bestehende System integrieren.

Der Bypass-Schnelltest

sap-bypassing-schnellcheck-saxonia-systems

Haben Sie eine der Fragen mit Ja beantwortet? Dann lassen Sie uns gemeinsam über ein für Sie passendes Bypassing-Szenario sprechen.

12. Juni 2017
Tom Graeber
0

SE16H – HANA für eine konventionelle Datenbank

Power-Usern, Administratoren, Consultants und Entwicklern sind sie nur zu gut bekannt: die Transaktionen SE16 und SE16N. Sie sind ein bewährtes Mittel um schnell Informationen zu Tabelleninhalten zu bekommen und, zumindest in Test- und Entwicklungssystemen, Datensätze direkt auf Tabellenebene anzulegen, zu löschen oder zu manipulieren. In diesem Artikel möchte ich die relativ neue Transaktion SE16H vorstellen, die als Weiterentwicklung der SE16N betrachtet werden kann.

mehr

22. Mai 2017
Vladilen Traktovenko
0

Set Your VALUE!

Einführung (What’s up?)

Jeder, der mit ABAP schon etwas programmiert hat, kennt das Schlüsselwort VALUE. Es wird z.B. in DATA-Anweisungen für die Start-/Wert-Definition bei Deklarationen der Konstanten, Variablen, Klassen-Attribute, Funktionsparameter u.ä. genutzt. Seit dem ABAP-Release 7.40 hat das Schlüsselwort VALUE eine ganz neue Rolle bekommen und stellt unter anderem einen Wertoperator dar. Über die verschiedenen Möglichkeiten, die dieser Operator bringt, wollen wir in diesem Artikel sprechen.

Da die Funktionalität des Operators VALUE mit jedem ABAP-Release und fast mit jedem Servicepack erweitert wird, ist es wichtig zu erwähnen, dass die hier beschriebenen Syntax und Funktionalitäten auf dem Stand vom Release 7.40, SP08 basieren. Diesen Stand haben wir ausgewählt, da er heute im Unterschied zu ganz neuen Releases (z.B. 7.50, 7.51) bei den meisten SAP-Anwendern bereits in Entwicklungs- und Testsystemen erreicht ist und die unten beschriebenen Funktionalitäten in der täglichen Entwicklung benutzt werden können.

VALUE ist einer der eingebauten Konstruktoroperatoren, zu den auch folgende Operatoren zählen: NEW, CONV, CORRESPONDING, CAST, REF, EXACT, REDUCE, FILTER, COND, SWITCH. Als Wertoperator findet VALUE seine Anwendung dort, wo die Inhalte der Strukturen bzw. internen Tabellen konstruiert werden müssen. In der Praxis ist das am meisten der Fall beim Testen des Codes z. B. bei Unit-Tests mit Hilfe von ABAP Unit.

Initialisieren von Strukturen (Give It Structure)

Die Anwendung des neuen Operators VALUE ergibt bereits bei Strukturen mehrfache Möglichkeiten. Dabei kann man nicht nur flache Strukturen, sondern auch die verschachtelten Typen relativ elegant initialisieren. Hier ist ein Beispiel:

Zuerst deklarieren wir einen Strukturtyp und verwenden ihn bei der Typdefinition eines Feldes der lokalen Strukturvariable ls_position (Abbildung 1).

TYPES:
BEGIN OF tys_artikel,
nr    TYPE i,
name  TYPE string,
END OF tys_artikel.
* Struktur mit einem Strukturfeld
DATA:
BEGIN OF ls_position,
kd_nr   TYPE i,
artikel TYPE tys_artikel,
menge   TYPE i,
END OF ls_position.

Abbildung 1: Deklaration eines Strukturtypen und Verwendung bei der Typdefinition

Es gibt unterschiedliche Varianten, wie die Struktur ls_position nun initialisiert werden kann.

Vor dem Release 7.40 hätten wir eventuell zuerst eine Variable für innere Struktur definiert und gefüllt (Abbildung 2):

* Variante 1
DATA ls_artikel_a TYPE tys_artikel.
ls_artikel_a-nr   = 2358.
ls_artikel_a-name = 'Stift'.

 Abbildung 2: Verwendung vor Release 7.40

Das kann mit der neuen Syntax schon etwas anders gemacht werden (Abbildung 3):

* mit der neuen Syntax
DATA(ls_artikel_n) = VALUE tys_artikel( nr = 2358 name = 'Stift').

Abbildung 3: Verwendung mit der neuen Syntax

Damit kann man auch die Hauptstruktur initialisieren (Abbildung 4):

ls_position = VALUE #(
kd_nr   = 1234
artikel = ls_artikel_n
menge   = '2' ).

Abbildung 4: Initialisierung der Hauptstruktur

Die zweite Variante wäre dann mit direktem Zugriff auf die Felder der Unterstruktur (Abbildung 5):

* Variante 2
ls_position = VALUE #(
kd_nr = 1234
artikel-nr   = 2358
artikel-name = 'Stift'
menge = '2' ).

Abbildung 5: Verwendung mit direktem Zugriff auf die Felder der Unterstruktur

Und als dritte Variante kann man einen geschachtelten VALUE-Operator direkt für die Definition des Strukturfeldes verwenden (Abbildung 6):

* Variante 3
ls_position = VALUE #(
kd_nr = 1234
artikel = VALUE #(
nr = 2358
name = 'Stift' )
menge = '2' ).

Abbildung 6: direkte Definition des Strukturfeldes durch Verwenden von geschachteltem VALUE-Operator

Bei der Anwendung des neuen Operators sollte berücksichtigt werden, dass eine neue Struktur erzeugt wird, die dann einer Variable zugewiesen wird. Das ist besonders wichtig, wenn nicht alle Felder der Struktur auf einmal initialisiert werden sollen. So ist es auch mit unserem Beispiel mit der Variable ls_artikel_a (Abbildung 7).

ls_artikel_a-nr   = 2358.
ls_artikel_a-name = 'Stift'.

Abbildung 7: Erzeugung neuer Struktur bei Anwendung des neuen Operators

Wenn wir jetzt das Feld name ändern wollen, sollen wir wie vor dem Release 7.40 so vorgehen (Abbildung 8):

ls_artikel_a-name = 'Bleistift'.

Abbildung 8: Änderung eines Feldes der Struktur

Wenn wir stattdessen die ähnlich aussehende Zuweisung mit dem Operator VALUE verwenden, bekommen wir zuerst keinen Syntaxfehler (Abbildung 9).

ls_artikel_a = VALUE #( name = 'Bleistift' ).

Abbildung 9: Verwendung der Zuweisung mit dem Operator VALUE

Der wesentliche Unterschied liegt daran, dass die letzte Anweisung eine neue Struktur erzeugt, die im Feld nr den initialen Integerwert von Null hat, die dann der Variable ls_artikel_a zugewiesen wird. Dieses Problem kann mit dem Zusatz BASE gelöst werden, den wir etwas weiter besprechen werden.

Initialisieren von Tabellen (Set The Table)

Richtig interessant und vielseitig zeigt sich der Einsatz des Operators VALUE für die Initialisierung der internen Tabellen, was an folgendem Beispiel verdeutlicht werden soll. Dafür definieren wir zwei neue Tabellentypen und entsprechende Tabellenvariablen (Abbildung 10).

TYPES:
tyt_artikel   TYPE STANDARD TABLE OF tys_artikel WITH DEFAULT KEY,
tyt_position  LIKE STANDARD TABLE OF ls_position WITH DEFAULT KEY.
DATA:
lt_art_liste  TYPE tyt_artikel,
lt_bestellung TYPE tyt_position.

Abbildung 10: Definition zwei neuer Tabellentypen und der entsprechenden Variablen

Beim Initialisieren des Tabelleninhalts werden einzelne Zeilen innerhalb des Operators in Klammern gesetzt. Dies könnte wie folgt aussehen (Abbildung 11):

* Variante 1
lt_art_liste = VALUE #(
( nr = 2358 name = 'Stift' )
( nr = 1111 name = 'Kleber' )
( name = 'Block' nr = 3247 ) ). " andere Feldreihenfolge erlaubt

Abbildung 11: Initialisieren des Tabelleninhaltes

Dadurch, dass die Zuweisung der einzelnen Felder immer nach Feldnamen erfolgt, muss innerhalb einer Klammer eine explizite Reihenfolge nicht beachtet werden. Im letzten Beispiel (s. Abb. 11, die letzte Zeile) wird dies demonstriert.

An dieser Stelle machen wir einen kleinen Absprung, um noch eine interessante Möglichkeit zum Definieren eines Standardwerts bei Tabellenausdrücken mit dem Operator VALUE zu zeigen. So kann eine Zeile vorbereitet werden, die anstelle von nicht gefundenen Zeilen der internen Tabelle lt_art_liste verwendet werden muss (Abbildung 12):

* Fehlerzeile
DATA(ls_nicht_gef) = VALUE tys_artikel( nr = 0 name = 'Nicht gefunden').

Abbildung 12: Definieren eines Standardwerts bei Tabellenausdrücken mit dem Operator VALUE

Nun wird diese Zeile als Standardwert genutzt, wenn die benötigte Zeile nicht gefunden wird (Abbildung 13):

ls_artikel_a = VALUE #( lt_art_liste[ nr = 55555 ] DEFAULT ls_nicht_gef ).
* oder
ls_artikel_a = VALUE #( lt_art_liste[ nr = 55555 ] OPTIONAL ).

Abbildung 13: Verwendung des Standardwertes aus Abbildung 12

In der letzten Zeile der Abb. 13 bekommt die Variable ls_artikel_a eine initiale Struktur vom Typ tys_artikel zugewiesen. In beiden Varianten wird die Ausnahme der Klasse CX_SY_ITAB_LINE_NOT_FOUND unterdrückt.

Nun behandeln wir weiter die Befüllung der Tabellen. Einzelne Zeilen der Zieltabelle lt_bestellung können direkt durch vorbereitete Strukturvariablen (s. Abb. 6) gefüllt werden. Das gilt auch für einzelne Zeilen aus einer anderen Tabelle. Das sehen Sie im nächsten Code-Beispiel sowohl für die ganze Zeile als auch für das interne Strukturfeld (Abbildung 14). Hier haben wir die vorbereitete Strukturvariable ls_position aus der Abb. 6 und die Tabelle lt_art_liste aus der Abb. 11 verwendet:

* Variante 2
lt_bestellung = VALUE #(
( ls_position )
( kd_nr = 1234 artikel = lt_art_liste[ 2 ] menge = 1 )
( kd_nr = 5678 artikel = ls_artikel_n      menge = 5 )
( kd_nr = 5678 artikel = lt_art_liste[ 3 ] menge = 5 ) ).

Abbildung 14: Befüllung einzelner Zeilen der Zieltabelle durch vorbereitete Strukturvariablen

Wiederholen sich die Werte einzelner Felder in den Zeilen einer internen Tabelle (s. Abb. 14), so besteht die Möglichkeit diese zusammenzufassen (Abbildung 15):

* Variante 3
lt_bestellung = VALUE #(
kd_nr = 1234 ( artikel = lt_art_liste[ 1 ]  menge = 2 )
( artikel = lt_art_liste[ 2 ]  menge = 1 )
kd_nr = 5678 menge = 5 ( artikel = lt_art_liste[ 1 ] )
( artikel = lt_art_liste[ 3 ] ) ).

Abbildung 15: Zusammenfassen sich wiederholender Werte einzelner Felder

Um noch eine Möglichkeit zu veranschaulichen, erstellen wir zuerst zwei neue interne Tabellen, jeweils eine pro Kunde (Abbildung 15):

* Variante 4
DATA(lt_bestellung1) = VALUE tyt_position(
kd_nr = 1234 ( artikel = lt_art_liste[ 1 ]  menge = 2 )
( artikel = lt_art_liste[ 2 ]  menge = 1 ) ).
DATA(lt_bestellung2) = VALUE tyt_position(
kd_nr = 5678 menge = 5 ( artikel = lt_art_liste[ 1 ] )
( artikel = lt_art_liste[ 3 ] ) ).

Abbildung 16: Erstellen einer neuen internen Tabelle für jeden Kunden

Befüllen wir nun die Tabelle lt_bestellung aus den gerade erstellten Tabellen lt_bestellung1 und lt_bestellung2 (Abbildung 17):

* Tabelle aus zwei Tabellen füllen (Konkatenation)
lt_bestellung = VALUE #(
( LINES OF lt_bestellung1 )
( )                           " leere Zeile
( LINES OF lt_bestellung2 ) ).

Abbildung 17: Befüllung einer Tabelle durch die zwei internen Tabellen (Abbildung 16)

Zwischen den „Bestellungs“-Zeilen wurde in der Abb.17 noch eine leere Zeile eingefügt, um auch diese Möglichkeit zu demonstrieren.

Wichtig zu wissen, dass die Zielvariable im Fall des VALUE-Operators zurückgesetzt wird, noch bevor die neuen Zeilen zusammengesetzt und angefügt werden. Die Folgen dieses Verhaltens lassen sich zeigen, wenn wir die Zuweisung aus der Abb.17 in zwei Schritten machen würden (Abbildung 18):

* Das Gleiche in zwei Schritten versuchen 
* Schritt 1
lt_bestellung = VALUE #(
( LINES OF lt_bestellung1 )
( ) ).

Abbildung 18: Zurücksetzen der Zielvariable beim Verwenden des VALUE-Operators

Nun versuchen wir im zweiten Schritt, die teils gefüllte Tabelle lt_bestellung selbst zu nutzen, um das gleiche Ziel wie in der Abb.17 zu erreichen (Abbildung 19):

* Schritt 2
lt_bestellung = VALUE #(
( LINES OF lt_bestellung )
( LINES OF lt_bestellung2 ) ).

Abbildung 19: Nutzung der Tabelle lt_bestellung

Als Ergebnis dieser Zuweisung wird die Tabelle lt_bestellung nur die Zeilen der Tabelle lt_bestellung2 beinhalten, da die Tabelle lt_bestellung noch vor der Ausführung des VALUE-Konstruktors geleert wird.

Der Zusatz BASE kann in diesem Fall das Problem lösen. Aber bevor wir seine Verwendung näher betrachten, möchten wir noch eine Syntaxerweiterung für LINES OF zeigen. Nehmen wir uns der Aufgabe an, eine größere Tabelle in zwei kleinere Tabellen aufzuteilen (Abbildung 20). Dafür nehmen wir die Tabelle lt_bestellung und füllen sie nochmal aus den zwei Tabellen lt_bestellung1 und lt_bestellung2:

* nochmal richtig füllen
lt_bestellung = VALUE #(
( LINES OF lt_bestellung1 )
( LINES OF lt_bestellung2 ) ).

Abbildung 20: Tabelle aus zwei Tabellen füllen

Nun leeren wir die Tabellen lt_bestellung1 und lt_bestellung2 und füllen sie aus der größeren Tabelle neu (Abbildung 21):

CLEAR: lt_bestellung1, lt_bestellung2.
* Tabelle in zwei Tabellen aufteilen (Distribution)
lt_bestellung1 = VALUE #( ( LINES OF lt_bestellung TO 2 ) ).
lt_bestellung2 = VALUE #( ( LINES OF lt_bestellung FROM 3 ) ).
FREE lt_bestellung.  " Speicher der großen Tabelle freigeben

Abbildung 21: Aufteilung einer Tabelle

Wenn die große Tabelle nicht mehr benötigt wird, ist es sinnvoll den reservierten Speichern sofort nach der Aufteilung wieder freizugeben. Die Zusätze FROM und TO können natürlich zusammen genutzt werden, um nur einen Teil der Quelltabelle in eine andere Tabelle zu kopieren.

VALUE mit BASE (Build a Base)

Wie bereits beschrieben wurde, funktioniert der VALUE-Operator für interne Tabellen grundsätzlich ähnlich der INSERT-Anweisung. Um die APPEND-Funktionalität hinzubekommen, d.h. die neuen Zeilen in einer internen Tabelle anzufügen, wird der Zusatz BASE genutzt (Abbildung 22). BASE deklariert das Datenobjekt, das als Grundlage für den Aufbau durch den VALUE-Operator genommen wird. Das Datenobjekt muss den Typ der Zielvariable haben oder darin implizit konvertierbar sein.

Im Beispiel mit zwei Schritten (s. Abb. 18, 19) kann dann der Schritt 2 mit dem BASE-Einsatz folgendermaßen umgeschrieben werden (Abbildung 22):

* Schritt 2 mit BASE
lt_bestellung = VALUE #( BASE lt_bestellung
( LINES OF lt_bestellung2 ) ).

Abbildung 22: Einsatz des Zusatzes BASE

Bei dieser Syntax wird die Schattentabelle im Speicher zuerst mit dem Inhalt der internen Tabelle lt_bestellung initialisiert, dann wird die Tabelle lt_bestellung geleert und die neuen Zeilen aus der Tabelle lt_bestellung2 der Schattentabelle angefügt. Am Ende wird der Inhalt der Schattentabelle der Variable lt_bestellung zugewiesen.

BASE-Zusatz kann auch für den Strukturaufbau behilflich sein, da er statt einer leeren Struktur des vorgegebenen Typs eine bereits gefüllte Struktur dieses Typs als Grundlage nutzen lässt. So ändern wir dann die Felder der existierenden Struktur (Abbildung 23):

* Struktur mit BASE ändern
ls_artikel_a = VALUE #( BASE ls_artikel_a
name = 'Bleistift' ).

Abbildung 23: BASE-Zusatz als Hilfe für den Strukturaufbau

Es sieht in diesem Beispiel mit einem Feld eventuell wenig lukrativ aus. Stellen Sie sich aber vor, dass die Zielstruktur mehrere (z.B. 30) Felder hat, von denen einige (z.B. 5) geändert werden sollen. Dann kann diese Änderung mit einem VALUE-Operator gemacht werden (Abbildung 24):

* große Struktur mit BASE ändern
ls_strukt30 = VALUE #( BASE ls_strukt30
feld3  = …
feld12 = …
feld15 = …
feld27 = …
feld29 = … ).

Abbildung 24: Änderung mehrerer Felder in einer Zielstruktur durch VALUE-Operator

Diese Schreibweise kann im Vergleich mit der “Klassischen” schon mehr Befürworter finden, obwohl es in dem Fall eher die Geschmackssache ist. Als „Klassisch“ wird die Schreibweise vor dem Release 7.40 gemeint, die wir zum Vergleich hier aufführen (Abbildung 25):

* Struktur „klassisch“ ändern
ls_strukt30-feld3  = … .
ls_strukt30-feld12 = … .
ls_strukt30-feld15 = … .
ls_strukt30-feld27 = … .
ls_strukt30-feld29 = … .

Abbildung 25: “Klassische“ Änderung einer Struktur

VALUE mit LET (Let It Be)

Mit VALUE-Operator, wie auch mit anderen Konstruktoroperatoren, kann ein LET-Ausdruck verwendet werden um lokale Hilfsvariablen zu definieren. Der Wirkungsbereich dieser Variablen breitet sich nur auf entsprechendes Konstruktor aus.

Ein LET-Ausdruck kann z. B. die Funktion des BASE-Zusatzes teilweise übernehmen. Der Schritt 2 in unserem Beispiel mit Zusammenfügen der zwei Tabellen (s. Abb. 23) kann dann so aussehen (Abbildung 26):

* Schritt 2 mit LET
lt_bestellung = VALUE #( LET temp = lt_bestellung IN
( LINES OF  temp )
( LINES OF lt_bestellung2 ) ).

Abbildung 26: Zusammenfügen zweier Tabellen mit LET-Ausdruck

In diesem Fall wie beim BASE-Zusatz erfolgt die Zuweisung der temp-Variable, bevor die Tabelle lt_bestellung geleert wird.

Auch ein Methoden-Aufruf kann im LET-Ausdruck verwendet werden (Abbildung 27):

* LET mit Methodenaufruf
TYPES:
BEGIN OF guid_line,
nr    TYPE i,
guid  TYPE guid_16,
END OF guid_line,
tyt_guid TYPE STANDARD TABLE OF ty_guid_line WITH EMPTY KEY.
DATA lt_guid TYPE tyt_guid.
DO 20 TIMES.
lt_guid = VALUE #( LET new_guid = cl_reca_guid=>get_new_guid( ) IN
BASE lt_guid
( nr = sy-index guid = new_guid ) ).
ENDDO.

Abbildung 27: LET-Ausdruck mit Methoden-Aufruf

In diesem Beispiel fügen wir zwanzig Zeilen in die Tabelle lt_guid mit den Nummer- und GUID-Spalten. Jede Zeile enthält dann eine andere GUID. Statt DO-Schleife kann man aber auch einen FOR-Ausdruck nutzen.

VALUE mit FOR (Now for It)

Für die Erzeugung der größeren Menge von Testdaten kann es nützlich sein, den Iterationsausdruck FOR mit VALUE zusammen zu verwenden. Der Operator FOR implementiert einen ausdrucksfähigen LOOP, der in manchen Konstruktoroperatoren genutzt werden kann.

Mit dem FOR kann man direkt einfache Daten in einer Tabelle erzeugen. Die GUID-Tabelle aus dem letzten Beispiel (s. Abb. 27) kann dann so gefüllt werden (Abbildung 28):

* Tabelle mit Testdaten füllen
lt_guid = VALUE #( LET new_guid = cl_reca_guid=>get_new_guid( ) IN
FOR j = 1 UNTIL j <= 100
( nr = j guid = new_guid ) ).

Abbildung 28: Befüllen einer Tabelle mit dem Operator FOR

Man kann eine Tabelle auch in eine andere kopieren, wobei das Kopieren entweder vollständig oder teilweise nach bestimmter Logik passieren kann (Abbildung 29):

* Ein Teil der Tabelle kopieren
DATA(lt_guid_neu) = VALUE tyt_guid(
FOR ls_guid IN lt_guid WHERE ( nr > 50 )
( ls_guid )
).

Abbildung 29: Kopieren einer Tabelle in eine Andere

Oder die Tabelle wird mehrfach mit Modifikationen kopiert (Abbildung 30):

* Tabelle mehrfach mit Modifikationen kopieren
DATA(lt_guid_gross) = VALUE tyt_guid(
FOR j = 0 UNTIL j < 100
FOR ls_guid IN lt_guid INDEX INTO ind
( nr = 100 * j + ind guid = ls_guid-guid )
).

Abbildung 30: Kopieren einer Tabelle mit mehrfachen Modifikationen

In diesem Beispiel wird der GUID-Wert aus jeder Zeile der Quelltabelle lt_guid übernommen, die Nummer wird aber modifiziert (neu berechnet). Die Zieltabelle lt_guid_gross wird nach dem Ausführen des Ausdrucks 10.000 Zeilen beinhalten.

Die Tabellen aus dem letzten Beispiel (s. Abb. 30) haben nur je zwei Spalten. Dadurch ist das Ausschreiben jeder Spalte beim Kopieren nicht wirklich problematisch. Allerdings kann es zu Unübersichtlichkeit führen, wenn die Zeilenstruktur mehrere Spalten hat. An dieser Stelle kann die oben beschriebene Strukturänderung mit VALUE und BASE (s. Abb. 23) helfen. Wenn wir sie anwenden, müssen wir nur die Spalten ausschreiben, die geändert werden sollen. Mit dem Einsetzen dieser Änderungsmethode sieht das Beispiel aus der Abb. 30 folgendermaßen aus (Abbildung 31):

* Strukturänderung mit VALUE und BASE anwenden
lt_guid_gross = VALUE tyt_guid(
FOR j = 0 UNTIL j < 100
FOR ls_guid IN lt_guid INDEX INTO ind
(  VALUE #( BASE ls_guid nr = 100 * j + ind )
).

Abbildung 31: Strukturänderung mit Hilfe von VALUE und BASE

Initialisieren von elementaren Typen (Make It Elementary)

Es gibt eine interessante Möglichkeit, den Operator VALUE für die Erzeugung der Initialwerte für fast beliebige (bis auf generische) Datentypen zu verwenden.

Diese Funktionalität kann angewendet werden, wenn wir z.B. eine Methode mit einem Pflichtparameter aufrufen und den Initialwert des Parameters übergeben wollen. Beispiel (Abbildung 32):

* Initialwert mit VALUE
CLASS class1 DEFINITION.
PUBLIC SECTION.
CLASS-METHODS meth1 IMPORTING iv_par TYPE sy.
ENDCLASS.
CLASS class1 IMPLEMENTATION.
METHOD meth1.
*  ...
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
class1=>meth1( VALUE #( ) ).

Abbildung 32: Verwendung des Operators VALUE für die Erzeugung von Initialwerten

Vor dem Release 7.40 hätten wir eine Variable vom Typ sy definiert, sie eventuell geleert und dann beim Aufruf der Methode übergeben. Der VALUE-Operator vereinfacht diesen Schritt erheblich.

Fazit (It’s cool, isn’t it?)

Der Operator VALUE lässt den Code für schnelle Erzeugung von Testdaten, Mapping der Daten an Schnittstellen zwischen Klassen und Systemen bzw. zwischen alten und neuen Programmen kompakt und übersichtlich schreiben.

In diesem Artikel wurde gezeigt, wie vielfaltig und ausdrucksreich nur ein Operator sein kann. Dabei haben wir noch lange nicht alle Möglichkeiten, die der Operator VALUE mitbringt, beschreiben können.

Die Verwendung der Konstruktor-Operatoren verlangt gute Syntaxkenntnisse und Erfahrung in der praktischen Anwendung. Die Vorteile dieser Operatoren sind offensichtlich. Sie können allerdings ziemlich schnell zu Nachteilen werden, wenn ein Entwickler z.B. versucht, komplexe Logik in einen Programmausdruck zu packen.

Vergessen Sie bitte nicht, dass der Code, den Sie schreiben, auch besser wartbar sein soll. Das bedeutet, dass auch andere Entwickler in der Lage sein sollen, den Code schnell zu verstehen und anzupassen. Wenn hier die goldene Mitte zwischen Übersichtlichkeit und Verständlichkeit gefunden wird, wird der VALUE-Operator sehr gute Hilfe in Ihrer täglichen Arbeit leisten.

24. April 2017
Cihan Toraman
0

Speicheroptimierung in der SAP-Entwicklung

Der Shared Memory ist ein Bereich vom Anwendungspuffer des Applikationsservers und kann als Zwischenablage für große Datenmengen genutzt werden. Dieser Artikel behandelt die explizite Ablage von Daten im transaktionsübergreifenden Anwendungspuffer mittels der Anweisung EXPORT TO SHARED BUFFER.

mehr

13. Februar 2017
Tom Graeber
0

Datenaustausch über die Transaktionen CG3Y und CG3Z

Ein Transfer beliebiger Dateien zwischen dem Rechner des Anwenders und einem SAP-Anwendungsserver ist normalerweise nicht vorgesehen. Mit den Transaktionen CG3Y und CG3Z besteht jedoch auf einfache Weise die Möglichkeit dazu. Für verantwortungsbewusste Entwickler und Tester können die Transaktionen nützlich sein, Systemadministratoren müssen dagegen mögliche Gefahren ausschließen.

mehr

9. Januar 2017
Matthias Siegmund
0

Interimsmodell – Wie bekomme ich meinen Datenbestand gesetzeskonform?

Eine Lösung der Saxonia Systems AG …

Gesetz zur Digitalisierung der Energiewende

Am 20. Dezember 2016 hat die Bundesnetzagentur mit ihren Beschlüssen BK6-16-200 und BK7-16-142 die Festlegungen zur Anpassung der elektronischen Marktkommunikation im Strom- und Gassektor an die Erfordernisse des „Gesetz zur Digitalisierung der Energiewende“ (GDEW) bekannt gegeben. Darin werden die Betreiber von Elektrizitätsversorgungsnetzen verpflichtet, spätestens bis zum 01. Februar 2018 flächendeckend alle Marktlokationen mittels einer eigenständigen Identifikationsnummer (Marktlokations-ID) zu identifizieren.

mehr

7. Dezember 2016
Matthias Siegmund
0

Das Interimsmodell ebnet den Weg zum smarten Netz

Neue Gesetze erfordern neue Lösungen …

Das Interimsmodell für Messsysteme als Übergangslösung in der Energiewende

Am 02. September 2016 ist das „Gesetz zur Digitalisierung der Energiewende“ in Kraft getreten. Auf Basis des Messstellenbetriebsgesetzes (MsbG) mit den Regelungen für den „Smart-Meter-Rollout“ in Deutschland, ist eine Implementierung neuer, intelligenter Messsysteme und moderner Messeinrichtungen erforderlich. Das bedeutet weitreichende prozessuale Anpassungen für eine Integration in die bestehenden IT-Systeme und die Prozesse der elektronischen Marktkommunikation.

mehr

25. April 2016
Ringo Liebscher
0

SAP Fiori – Apps für das ERP

Fiori ist die wichtigste Technologie für moderne SAP-Benutzeroberflächen in den nächsten Jahren. Sie umfasst weit mehr als hübsche Oberflächen-Elemente: die Umsetzung der App-Philosophie, anwendungsübergreifende Funktionen sowie ein durchdachter Entwurfsprozess führen zu mehr Effizienz und weniger Hürden bei der Bedienung von SAP-Anwendungen.

mehr

7. Dezember 2015
Katrin Hammer
2

Gefahren durch modifizierte Cookies

Zum Ende des vierten Quartals sind wieder vermehrt Cookies im Umlauf. Wie entstehen diese und wie kann der Client damit umgehen? Gerade die modifizierten Cookies können Probleme verursachen, sowohl beim Client als auch auf dem Server. Die richtige Vorbereitung kann helfen, mit dieser Gefahr umzugehen.

mehr

17. August 2015
Ringo Liebscher
0

SAP-Zugriff ohne Schmerz – REST-Webservices für SAP

In Unternehmen mit SAP-Systemen besteht häufig die Anforderung, auch anderen Anwendungen den Zugriff auf die darin gepflegten Daten zu ermöglichen. In einer Reihe von Fällen sollen Lese- und Schreiboperationen sofort – synchron – ausgeführt werden. Wenn zusätzlich ein geringer Overhead oder die Zugriffsmöglickeit für unterschiedliche Client-Anwendungen (Desktop, Web, Mobile, Cloud) gefragt sind, dann sind REST-Webservices eine favorisierte Schnittstellentechnologie.

mehr