
028: Recycling-Heroes - Configuration API (Settings)
Damit wir einfach auf die Daten der Business Configuration zugreifen können, definieren wir eine API, die wir im System dann wiederverwenden können. Hier werden auch die verschiedenen ABAP Artefakte näher erklärt.
Inhaltsverzeichnis
Einleitung
Nachdem wir die Business Configuration angelegt haben, benötigen wir nun eine API im System, um auf die Inhalte zugreifen zu können. Für unsere Tests später, wurden auch schon einige Werte gepflegt, die wir dann für Zugriffe verwenden können. Bei Feldern mit einem X, wollen wir prüfen, ob das Feature aktiv ist und bei den anderen Werten wollen wir die konkreten Werte haben.
Anlage
Die neue API legen wir im SHARE Paket an, da wir sie später für die anderen Entwicklungen freigeben wollen. Dazu verwenden wir die IDE Action zur Anlage der neuen Klassen, da uns die Action bereits einige Punkte bei der Generierung abnimmt. Wir geben den Objektnamen, die Beschreibung und den Namen der Instanz an. Die Namen der Objekte werden dann automatisch vorgeschlagen und wir übernehmen diese. Ist die Generierung abgeschlossen, erhalten wir eine Übersicht aller Objekte und können dorthin navigieren.
Dazu rufen wir im ersten Schritt die Factory auf. Diese soll uns später die Instanzen erzeugen, um auf die aktuelle Konfiguration zugreifen zu können. Zusätzlich hat die Factory den Injector als GLOBAL FRIEND. Diese Beziehung wird benötigt, damit der Injector das Double Attribut in der Klasse überschreiben kann. Die eigentliche Create Methode liefert eine neue Instanz der Konfiguration oder das Double, wenn dieses gesetzt sein sollte.
Schauen wir uns nun den Injector an. Da dieser als FOR TESTING gekennzeichnet ist, kann er nur im Falle von Unit Tests verwendet werden. Der Injector kümmert sich darum, dass wir Test Doubles in den Prozess bekommen, wenn wir Unit Tests durchführen wollen. Außerhalb von Unit Tests kann die Klasse nicht verwendet werden, was für uns eine Absicherung ist, damit in Produktion niemand falsche Objekte in die Verarbeitung bringt.
Interface
Kümmern wir uns nun um die Implementierung des Interfaces. Wir benötigen verschiedene Typen, Konstanten und Methoden für die spätere Implementierung. Beginnen wir daher im ersten Schritt mit der Konstantenstruktur für die verschiedenen Einstellungen, die wir bisher als Festwerte in der Domäne hinterlegt haben. Den verschiedenen Feldern können wir sprechende Namen geben, da wir hier nicht auf 10 Zeichen begrenzt sind. Als zweite Konstantenstruktur legen wir die verschiedenen Prozesse an, die uns im Customizing zur Verfügung stehen. Grundsätzlich führen wir den Schritt durch, um alle konstante Werte im Zugriff zu haben und dem Verwender eine saubere Schnittstelle zu bieten. Die Abgrenzung kann später für Berechtigungen verwendet werden, wird aber in unserem Fall erst einmal nicht weiter benötigt.
Später soll uns die Methode GET_VALUE einen Einzelwert aus dem Customzing zurückgegeben, in diesem Fall den Wert im Feld Value. Für die späteren Lesezugriffe benötigen wir noch einen entsprechenden Typen, der unseren Core Data Service widerspiegelt. Die zweite Methode GET_VALUES soll uns eine entsprechende Range aus den Werten erzeugen, wenn wir mehr als eine Zeile und von/bis Werte haben. Als dritte Methode legen wir IS_ACTIVE an, diese soll einfach einen booleschen Wert zurückliefern, um die Funktion zu identifizieren und ob diese aktiv im System ist.
Implementierung
In der Klasse implementieren wir nun die verschiedenen Methoden über das Interface. Um an die Werte zu kommen, implementieren wir uns eine private Methode, um den Core Data Service zu lesen und die gefundenen Werte zurückzugeben. Bei dem Select grenzen wir die verschiedenen Konfigurationen ab und verwenden den PRIVILEGED ACCESS um die Access Control zu umgehen. Damit ist sichergestellt, dass während der Prozessausführung immer die Werte gelesen werden können, auch wenn der User vielleicht keine Berechtigungen zur Anzeige oder Pflege hat, die er in diesem Moment auch gar nicht benötigt.
Implementieren wir nun die Methode GET_VALUES und rufen die neue Methode auf, um alle Daten zu lesen. Im nächsten Schritt wollen wir dann die Range befüllen und müssen entsprechend auf die gepflegten Werte reagieren. Wir wollen nur Zeilen verarbeiten, wo eines der beiden Wertefelder befüllt ist. Dann fügen wir eine initiale Zeile in die Range ein und setzen eine Referenz, um die weiteren Felder im Nachgang zu befüllen. Dann vergleichen wir die Felder, sind beide Felder befüllt, übernehmen wir diese und setzen ein BETWEEN in die Option. Die anderen Felder übernehmen wir nach LOW und befüllen die Option mit einem EQUAL. Die Warnung könnten wir mit einem Initialwert in Option beheben, für den Anfang setzen wir sie aber erst einmal später.
Implementieren wir nun die Methode GET_VALUE. Dabei wollen wir nur einen Wert lesen und über Return an den Aufrufer zurückgeben. Dazu lesen wir wieder die entsprechende Konfiguration und lassen uns dann die erste Zeile zurückgeben. Für diesen Fall verwenden wir ein VALUE Statement und setzen den Wert auf OPTIONAL. Wird zum Beispiel kein Eintrag gefunden, weil die Konfiguration nicht verfügbar ist, dann wird eine leere Struktur zurückgegeben. Zum Abschluss geben wir den Wert der Struktur zurück.
Als letzten Schritt implementieren wir die IS_ACTIVE Methode, um zu prüfen, ob das Kennzeichen auf ABAP_TRUE steht und damit die Funktion aktiv ist. Dazu verwenden wir die Methode GET_VALUE um den Wert der Konfiguration zu erhalten und vergleichen diesen dann gegen ABAP_TRUE. Das Ergebnis geben wir dann an den Aufrufer zurück.
Test
Um die Implementierung einfach zu testen, legen wir einen lokalen Unit Test in der Klasse an. Damit können wir unsere Implementierung ganz einfach und nachhaltig prüfen. Dazu wechseln wir auf den Reiter "Test Classes" im unteren Teil der Klasse. Über das Template TESTCLASS legen wir uns eine leere Testklasse an. Per Tabulator können wir durch die einzelnen Bestandteile navigieren und benennen die Methode um. Dann erzeugen und wir über die Factory eine Instanz unserer Konfiguration. Über das Objekt lassen wir uns einen Wert zurückgeben, dazu greifen wir über die Instanz auf die Konstanten der Klasse zu. Damit lassen wir uns die DEFAULT_CAPACITY zurückgeben. Als einfache Validierung prüfen wir, ob die Variable nicht mehr initial ist.
Wir setzen nun einen Breakpoint im Code und starten den Unit Test über STRG + SHIFT + F10. Im Debugger können wir uns den Inhalt der Variable RESULT anschauen und finden dort unser Customizing von 120. Damit ist der einfache Test abgeschlossen und die Logik funktioniert so weit.
Release
Im letzten Schritt wollen wir einen C1 Contract auf den Objekten erzeugen, damit wir die API später auch in den anderen Software Komponenten verwenden können. Dafür müssen wir alle Objekte freigeben bis auf die eigentliche Klasse mit der Implementierung. Das Interface benötigen wir zum Aufruf und zur Definition von Variablen, die Factory zum Instanziieren und den Injector zur Entkopplung in anderen Tests.
Beginnen wir also im ersten Schritt mit der Freigabe des Interfaces. Dies können wir direkt über den Kontext es Objekts machen. Die Freigabe für ABAP Cloud reicht hier, da wir die Klasse nicht in der Key User Extensibility verwenden werden. Bei der Überprüfung erhalten wir zahlreiche Warnungen, da bestimmte Rückgabetypen des Interfaces nicht freigegeben sind. Daher müssen wir zuerst noch im Interface einige Typen umbauen. Erstellen wir für die Config ID und den Prozesstypen einen entsprechenden lokalen Typen und tauschen die bestehenden Typen und Konstanten mit dem neuen Typen aus. Damit geben wir über das Interface den neuen Typen nach außen frei und die Konstanten können nun mit diesem Typen verwendet werden. Zum Abschluss müssen wir auch noch für den VALUE einen Typen anlegen und diesen in der Methode GET_VALUE austauschen.
Geben wir nun noch einmal das Interface frei, dann sind alle Warnungen verschwunden, alle Typen, die wir nach außen geben, sind auch als Typ im Interface verfügbar und freigegeben. Damit können wir nun auch die Factory und den Injector freigeben und sind mit der API fertig.
Zusammenfassung
In der heutigen Folge haben wir für die Konfiguration eine API erstellt, diese nach allen Kriterien der Testbarkeit und Erweiterbarkeit erstellt. Zum Abschluss haben wir die API auch für anderen Software Komponenten im System freigegeben und können diese später nutzen.
Damit sind wir am Ende, ich bedanke mich für die Aufmerksamkeit und bis zum nächsten Mal.
YouTube
Video