Lokale Klassen

Aus SAP-Wiki
Wechseln zu: Navigation, Suche

Lokale Klassen werden im Gegensatz zu globalen Klassen (Transaktion SE24) lokal im Programm definiert und existieren nur zur Laufzeit des Programms. Sie ersetzen Form-Routinen im Programm.

Abwägung lokale Klassen und Form-Routinen

Argumente für Form-Routinen

  • Vorhandene Reporte werden meist mit der lokalen Modularisierungstechnik Form-Routinen realisiert sein und nicht mit lokalen Klassen und eine Umstellung von Form-Routinen zu lokalen Klassen erfordert Zeit und birgt die Gefahr, dass man Fehler einbaut.
  • SAP-Entwickler kennen manchmal objektorientiertes Programmieren kaum und haben dann Probleme die Syntax von lokalen Klassen und den Ablauf des Reports zu verstehen.
  • Der Verwendungsnachweis bei Form-Routinen funktioniert auch mit Doppelklick auf eine Form-Routine. Bei lokalen Klassen nur über die Verwendungsnachweis-Schaltfläche.Verwendungsnachweis.jpg
  • Form-Routinen lassen sich über Doppelklick auf eine Perform-Routine anlegen.
  • Form-Routinen sind robust, ob die Form-Routinen im Coding vor oder hinter dem Perform-Aufruf stehen. Bei lokalen Klassen muss die Definition&Implementierung der Klasse vor dem Aufruf der Methoden stehen im Coding. Dadurch können die Form-Routinen im Hauptprogramm am Ende des Programms angefügt werden und lässt man alles Coding im Hauptprogramm, reicht "Prüfen", um die Syntaxfreiheit zu prüfen. Klassencoding sollte daher aus Übersichtsgründen in einem Include zusammengefasst werden und um Anfang des Reports eingebunden (nach den sonstigen globalen Data/Types und dem Selektionsbildschirm). Hier muss zur Überprüfung der Syntax jeweils eine Aktivierung durchgeführt werden. Das dauert deutlich länger als das reine "Prüfen".

Argumente für Lokale Klassen

  • Es können mehrere lokale Klassen angelegt werden und semantisch zusammengehörige Programmroutinen gruppieren.
  • Übersichtliche Anzeige lokalen Klassen über Transaktion SE80 (mit Methoden, Attributen, Sichtbarkeit etc.)
  • Obsolete Syntax ist in Methoden verboten und führt zu einer Fehlermeldung beim Syntaxcheck und kann daher vom SAP-Entwickler auch nicht mehr verwendet werden.
  • Differenzierung nach Sichtbarkeit: Public-Methoden, die von außerhalb der Klasse aufgerufen werden und Private-Methoden, die innerhalb der Klasse aufgerufen werden.
  • Bei Lokalen Klassen sich explizit Ausnahmen/Exceptions definieren, die dann vom Aufrufer auch behandelt werden müssen. Andernfalls kommt es zu einem Laufzeitfehler, wenn die Ausnahme ausgelöst wurde, aber nicht behandelt wird.
  • Die Schnittstelle von Lokalen Klassen ist der Schnittstelle von Form-Routinen überlegen
    • Die Schnittstelle von lokalen Klassen bei Definition und bei der Verwendung der Methoden muss passend sein (exporting zu importing, changing zu changing etc.). Bei Form-Routinen kann z. B. ein Parameter "perform name using .." trotzdem in der Form-Routine verändert werden.
    • Form-Routinen lassen noch einen Parameter "Tables" zu. Dieser sehr intransparente Parameter existiert bei Methoden nicht.
    • Bei Methoden gibt es einen Returning-Parameter, der sehr elegant vom Verwender der Methode direkt angesprochen werden kann: "variable = klasse->methode( )." Allerdings ist der Returning-Parameter stets langsamer als der Exporting-Parameter (siehe Tricktresor)
  • Variablen lassen sich sehr differenziert bezüglich ihrer Sichtbarkeit/Gültigkeit anlegen.
    • Globale Variablen: Sichtbarkeit im ganzen Report.
    • Variablen, die in einer Klasse mit Sichtbarkeit PUBLIC angelegt werden: Sichtbarkeit innerhalb der Klasse. Aber auch Ansprechbarkeit der Variable/Attribut über die Klasse von außerhalb der Klasse.
    • Variablen, die in der Klasse mit Sichtbarkeit PRIVATE angelegt werden: Sichtbarkeit lediglich innerhalb der Klasse und all seiner Methoden.
    • Variablen, die lokal innerhalb einer Methode angelegt werden: Sichtbarkeit nur innerhalb der Methode.

Fazit

  • Wird Coding von mehreren Programmen aufgerufen, sollte das Coding in globalen Klassen (Class Builder/Transaktion SE24) erstellt werden. Dies spart bei mehrfacher Verwendung der Funktionen viel Zeit und Testaufwand und vermindert die Fehleranfälligkeit eines Codings. Globale Klassen sind für andere Entwickler transparenter und besser zu finden
  • Sind Reporte bereits produktiv und mit Form-Routinen geschrieben, sollten sie auch nicht auf lokale Klassen umgestellt werden. Es erfordert Zeit, hohe Konzentration und bringt die Gefahr mit sich, Fehler einzubauen bei der Umstellung von Form-Routinen auf lokale Klassen
  • Haben Reporte nur einen kleinen Umfang und sind neu zu erstellen, so sind Form-Routinen ausreichend übersichtlich. Allerdings wird man oft am Beginn der Erstellung eines Programms den Umfang des Codings, bzw. der nötigen Modularisierungseinheiten unterschätzen.
  • Wird ein Programm nur angelegt und umfasst viele Modularisierungseinheiten, sind lokale Klassen deutlich übersichtlicher als Dutzende von Form-Routinen und dann sind lokale Klassen den Form-Routinen vorzuziehen
  • Will man sehr flexibel programmieren mit Vererbung etc., muss man dies mit globalen oder lokalen Klassen tun

Vorlagen und Beispiele

Vorlage Coding für Lokale Klasse

class Klasse definition.
  public section.
    methods test.

  private section.
endclass.
class Klasse implementation.

  method test.
  endmethod.

endclass.
Data: lo_klasse type ref of Klasse.
create object lo_klasse.

Beispiel lokale Klasse im Report

Hier wurden 4 lokale Klassen angelegt für

  • Selektionbildschirm
  • Datenselektion (GET_DATA)
  • ALV-Darstellung (ALV_BUECHER)
  • Eventhandler des ALV-Controls (EVENT_HANDLE)

LokaleKlasse1.jpg

Die meisten Methoden sind PUBLIC angelegt, damit sie von außerhalb der Klasse im Report angesprochen werden können. In der lokalen Klasse ALV_BUECHER gibt es jedoch auch 2 PRIVATE-Methoden ALV_FCAT und ALV_REFRESH, die nur innerhalb der Klasse aufgerufen werden können.

Hier ist dann auf einen Blick sichtbar, dass von außen nur die Methode ALV der Klasse ALV_BUECHER aufgerufen wird.

LokaleKlasse2.jpg

Verwendung Lokales Interface in Lokalen Klassen

Lokale Interfaces werden definiert mit

interface <interfacename>.
  methods ...
endinterface.

und werden dann im Coding eingebunden mit

interfaces <interfacename>.

SAP-Hilfe: Beispiel zu Interfaces in Lokalen Klassen (geringfügig ergänzt).

REPORT demo_interface.
 
INTERFACE status. 
  METHODS write.
ENDINTERFACE.
CLASS counter DEFINITION.
 PUBLIC SECTION.
 
 INTERFACES status. 
 Aliases: write_al for status~write.

 METHODS increment.

PRIVATE SECTION.
 
 DATA count TYPE i.
ENDCLASS.
CLASS counter IMPLEMENTATION.
 METHOD write_al . "vorher status~write
  WRITE: / 'Count in counter is', count.
 ENDMETHOD.

 METHOD increment.
  ADD 1 TO count.
 ENDMETHOD.
ENDCLASS.

Ein Interface kann auch in weiteren Klassen eingebunden werden.

CLASS bicycle DEFINITION.
 PUBLIC SECTION.
 
  INTERFACES status. 
  METHODS drive.

 PRIVATE SECTION.
 DATA speed TYPE i.
ENDCLASS.
CLASS bicycle IMPLEMENTATION.
 METHOD status~write. 
  WRITE: / 'Speed of bicycle is', speed.
 ENDMETHOD.

 METHOD drive.
  ADD 10 TO speed.
 ENDMETHOD.
ENDCLASS.

Ausnahmebehandlung bei Lokalen Klassen/Methoden

Mit dem Methoden-Zusatz EXCEPTIONS werden die Ausnahmen deklariert. Hier die Ausnahme NO_DATA.

CLASS get_data DEFINITION.
  PUBLIC SECTION.
    METHODS get_data_buecher
      RETURNING value(rt_buecher) TYPE tty_buecher
      EXCEPTIONS no_data.
ENDCLASS.                    "get_data DEFINITION

Die Ausnahme wird in der Implementierung der Methode ausgelöst

CLASS get_data IMPLEMENTATION.

  METHOD get_data_buecher.

    SELECT *
      INTO CORRESPONDING FIELDS OF TABLE rt_buecher
      FROM zrebbuecher
      WHERE buchnr IN s_buchnr
       AND  seiten IN s_seiten
       AND  bereich IN s_berei
       AND  verlag  IN s_verlag.

    IF sy-subrc <> 0.
      RAISE no_data.
    ENDIF.

  ENDMETHOD.                    "get_data_buecher

ENDCLASS.                    "get_data DEFINITION

Beim Verwender wird die Ausnahme behandelt

 go_get_data->get_data_buecher(
   RECEIVING rt_buecher = gt_buecher
   EXCEPTIONS no_data   = 1 ).

 IF sy-subrc <> 0.
   MESSAGE i531(0u) WITH 'Keine Daten gefunden'.
   RETURN.
 ENDIF.

Navigation im Coding

Methode Definition, Implementierung und Verwendung

Der Wechsel bei einer Methode zwischen der Definition und Implementierung, bzw. zurück, erfolgt über Doppelklick auf die Methode.

LokaleKlasse7.jpg


Möchte man die Verwendung der Methode angezeigt bekommen, stellt man den Cursor auf die Methode (bei Definition oder Implmentierung) und klickt auf den Verwendungsnachweis Verwendungsnachweis.jpg.

LokaleKlasse8.jpg

Doppelklick springt wie gewohnt zum Coding.

LokaleKlasse9.jpg

Ein weiterer Doppelklick auf die Verwendung der Methode, springt dann wieder zurück zur Implementierung der Methode.

LokaleKlasse10.jpg

Suche nach Definition, Implementierung und Verwendung einer Klasse

Setzt man den Cursor auf den Klassennamen und ruft den dann den Verwendungsnachweis Verwendungsnachweis.jpg auf

LokaleKlasse11.jpg

So sieht man Definition, Implementierung, Definition des Referenzobjektes und die Verwendung der Methoden.

LokaleKlasse12.jpg

Doppelklicks springen zur entsprechenden Codingstelle.


Ein ähnliches Ergebnis gibt es, wenn man im Rahmenprogramm den Klassennamen GET_DATA eingibt und "Suche als Wort".

LokaleKlasse13.jpg

Hier werden allerdings die Methodennamen nicht gefunden und der Klassenname wird nicht erkannt in der Methodenverwendung.

LokaleKlasse14.jpg


Die Suche wird nun erweitert mit "Suche als String".

LokaleKlasse15.jpg

Hier findet er alle relevanten Codingstellen der Klasse. Aber eventuell auch andere Fundstellen außerhalb der Klasse und Kommentare, die auch außerhalb der Klasse gefunden werden.

LokaleKlasse16.jpg

Besonderheiten Lokale Klassen

Reihenfolge Objekte im Coding

Lokale Klassen müssen in der richtigen Reihenfolge im Coding stehen.

Hauptprogramm

  1. Data/Types/Tables
  2. Selektionsbildschirm
  3. Includeeinbindung Klassen
  4. Programmablauf
  5. Module

Include mit Klassen

  1. Eventhandler für Klassen
  2. Klassen

Objektliste neu aufbauen

  • Wird eine neue lokale Klasse in der Transaktion SE80 erstellt oder geändert, ist es oftmals nötig, die Objektliste neu aufzubauen. Es reicht dann nicht den Report, bzw. die Includes zu aktivieren, um die neue/geänderte Klasse zu sehen.

LokaleKlasse17.jpg

Definition lokaler Tabellentyp im Report

Ein lokaler Tabellentyp reagiert bei der Verwendung in lokalen Klassen etwas anders als bei der Verwendung in Form-Routinen.

TYPES: BEGIN OF ty_buecher,
buchnr      TYPE zrebbuchnr, "Buchnummer
autor       TYPE zrebautor,  "Autor
titel       TYPE zrebtitel,  "Titel
...
TYPES: END OF ty_buecher.

TYPES: tty_buecher TYPE STANDARD TABLE OF ty_buecher. " WITH KEY buchnr. 

Wird hier so der Tabellentyp definiert, wie von Form-Routinen gewohnt, gibt es eine Fehlermeldung, wenn dieser Tabellentyp bei einem Returning-Parameter verwendet wird.

LokaleKlasse6.jpg


Es muss nun der Key beim Tabellentyp mitgegeben werden.

TYPES: tty_buecher TYPE STANDARD TABLE OF ty_buecher WITH KEY buchnr. 

Die Syntaxprüfung erfolgt daraufhin ohne Fehler.

LokaleKlasse5.jpg

Umstellung Report von Form-Routinen auf lokale Klassen

Man wird aufgrund begrenzter Zeit und der Gefahr Fehler einzubauen, selten bestehende Reporte auf lokale Klassen umstellen. Aber manchmal ist die Zeit sehr gut investiert es zu tun.

Voraussetzung Umstellung

  • Der Report ist komplex und besteht aus vielen Form-Routinen, bzw. vielen Modularisierungseinheiten
  • Der Report wird regelmäßig überarbeitet nach der Umstellung. Hier kann sich auf der Aufwand der Umstellung lohnen. Für die Umstellung ist bei umfangreichen Programmen mindestens mit einem halben Tag Zeitaufwand zu rechnen, abhängig vom Umfang des Codings, der Anzahl der Form-Routinen und der Komplexität der Schnittstellenparameter.

Vorlage

class Klasse definition.
  public section.
    methods test
     importing ..
     changing ..
     exporting ..
     returning ..

  private section.
endclass.
class Klasse implementation.

  method test.
  endmethod.

endclass.
Data: lo_klasse type ref of Klasse.
create object lo_klasse.

Vorgehensweise Umstellung

  • Es wird eine Form-Routine nach der anderen umgestellt.
  • Die Reihenfolge kann alphabetisch nach den Namen der Form-Routinen sein und die Form-Routinen dann jeweils über SE80 anklicken - oder in der Reihenfolge, in der die Form-Routinen im Code aufgerufen werden.
  • Ziehen einer Version
  • Überlegung welche lokalen Klassen/Methoden man erstellen wird, mit den Kriterien
    • Semantische Zusammengehörigkeit
    • Einfachheit
    • Durchgängigkeit
    • Sprechende Namen
  • Erstellung eines Includes <NAME>_CLASS und Auslagerung der Form-Routinen, die zu lokalen Klassen umgewandelt werden sollen
  • Umstellung der Form-Routinen, die zu einer, bzw. mehreren lokalen Klassen umgewandelt werden.
    • Muster neue Klasse einfügen am Anfang Klasseninclude mit Definition und Implementation
    • Editiersplitter aktivieren für gleichzeitige Darstellung zu kopierende Form-Routine und Definition/Implementation Klasse
    • Coding Form-Routine zur Implementation Methode kopieren
    • Kopieren Verwendungsschnittstelle Form-Routine zur Definition Methode
    • Syntaxcheck und Korrektur Fehler
    • Auskommentieren alte Form-Routine und Syntaxcheck
    • Die Aufrufe der auskommentierten Form-Routinen werden gemeldet und durch Aufrufe Methoden ersetzt
    • Aktivieren bei mit Syntaxfehlerfreiheit

Test

  • schneller Test Anwendung nach jeder erstellten Methode einer lokalen Klasse
  • intensiverer Test nach jeder Erstellung einer lokalen Klasse
  • Integrationstest im Testsystem nach der vollständigen Umwandlung der Form-Routinen zu lokalen Klassen
  • Report ins Qualitätssystem transportieren
  • Nach erfolgreichem Test auskommentierte Form-Routinen löschen (gelöschte Form-Routinen sind über den Versionsvergleich notfalls noch sichtbar)
  • Kritisch prüfen bei der weiteren Überarbeitung, ob die Benennung und Strukturierung der Klassen und Methoden sich bewährt. Ggf. Umbenennung/Restrukturierung der Klassen und Methoden.

Web-Links