CONSTRUCTOR & Co. [Sammeln & Seltenes]


Die Objektorientierung mit ABAP®: Vererbung, Dynamische Programmierung, GUI Controls (u.a. ALV im OO).

Moderatoren: Jan, Steff

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes] ~ Optionale Param

Beitragvon ewx » 07.01.2019, 19:04

Was optionale Parameter und deren Bündelung in einer Struktur angeht...
ralf.wenzel hat geschrieben:Für den Constructor gilt, was für alle Methoden gilt: Viele Parameter deuten darauf hin, dass in der Methode prozedural programmiert wurde. Komplexe Daten übergibt man am Besten als komplexe Struktur oder gleich als Objekt, weil sich die Schnittstelle nicht (oder automatisch mit-)ändert, wenn sich die übergebenen Parameter ändern. Es muss sich für einen Parameter nur die Konsistenzprüfung ändern, schon muss muss man ganzen Konstruktor neu testen. Außerdem führen viele Parameter bei jeder Methode zu vielen Testläufen, weil (wenn man es ordentlich macht) jedes Testtupel von mindestens einem Testlauf getroffen wird.


Da zeige ich dir in unserem System auf die Schnell 5077 Negativbeispiele:
Alle BAPI_* Funktionsbausteine. Da sind alle Kopfdaten in einer Kopfstruktur und so weiter. Das hilft dir aber auch nicht weiter, weil es innerhalb der Struktur diverse Abhängigkeiten gibt.

Letztendlich ist es egal, ob ich einen neuen Parameter hinzufüge oder der Zugrunde liegenden Struktur ein Feld: Ich muss Anpassungen vornehmen. Habe dabei im Testumfeld sogar den Vorteil, dass mir das System sagt, welche Methodenaufrufe ich alle anfassen muss (sofern ich den neuen Parameter nicht als optional kennzeichne).

Schön finde ich die von Paul Hardy vorgestellte Methode in seinem Buch ABAP to the future:
Preconditions and Postconditions

Er hat eine einfache Methode geschrieben, mit der man die Bedingungen für die Parameter sprachlich gut erfassen kann:
Code: Alles auswählen
zcl_dbc=>require(
    that = 'DATE is given, TIME is given or DATE and TIME are given'
    which_is_true_if = boolc( ( date is initial and time is not initial )
                           or ( date is not initial and time is initial )
                           or ( date is not initial and time is not initial ) ) ).

Das ist jetzt natürlich ein einigermaßen doofes Beispiel und ja, man kann die Bedingung auch einfach so als CHECK programmieren.
Es macht aber deutlich, was die Funktion erwartet.

Wo ich regelmäßig stolpere ist, wenn ich ein GUI-Control baue, dass ich für den Aufrufer möglichst einfach aufrufbar machen möchte.
Einfach heißt in dem Fall, dass der Aufrufer den Namen eines Custom-Containers oder eine Containerinstanz übergeben kann.
1.: bekommt der CONSTRUCTOR diese beiden Parameter mit?
2.: oder mache ich eine extra Methode DISPLAY?

(1) hat den Vorteil, dass ich im PBO einfach programmieren kann:
Code: Alles auswählen
IF myObject IS INITIAL. o_object = new #( container_name = 'CC_HUGO' ). ENDIF.

Evtl. will ich aber die Instantiierung viel früher machen, weil bereits Daten gelesen werden...? Dann müsste ich Variante (2) verwenden.
(2) hat den Nachteil, dass der Aufrufer wissen muss, dass er diese Methode zur Anzeige aufrufen muss.
ewx
Top Expert
 
Beiträge: 3885
Registriert: 04.08.2003, 19:55
Wohnort: Schleswig-Holstein
Dank erhalten: 343 mal

Sponsor

Alte ABAP-Entwicklerweisheit: Weißt du weder aus noch ein, baust du einen BADI ein

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitragvon ralf.wenzel » 07.01.2019, 19:26

Der Aufrufer guckt sich sicherlich die Klassenschnittstelle (also die öffentlichen Komponenten) an, ehe er eine Klasse verwendet. Somit wird er die Display-Methode sehen, darum verwende ich immer Methode 2.

Zum anderen Thema: Man kann einer Meinung sein oder eben nicht. Für mich gehören semantisch zusammengehörige Daten in ein Datenobjekt. Je nach Art der Daten ist das eine Struktur, eine Tabelle oder eben ein Objekt.

Ich packe gerade und habe kein System, vielleicht schaffe ich es morgen beim Kunden, dazu was zu schreiben.


Ralf
ralf.wenzel
Top Expert
 
Beiträge: 3374
Registriert: 18.09.2004, 13:03
Wohnort: Hamburg
Dank erhalten: 213 mal
Ich bin: Freiberufler/in

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes] ~ Anforderung

Beitragvon ewx » 07.01.2019, 19:28

Ein großes Problem bei Parametern ist m.E. häufig, dass gar nicht genau definiert ist, wann wie welche Parameter mit welchen Werten gefüllt sein müssen oder dürfen.
Wenn ich bei der Timestamp-Methode bleibe, dann möchte ich evtl. prüfen, ob die übergebenen Daten auch wirklich ein Datum oder eine Uhrzeit sind:
Code: Alles auswählen
IF i_datum(4) > 3000. RAISE wrong_year.
IF i_datum+4(2) = '00' or i_datum+4(2) > 12. RAISE wrong_month.
IF i_datum+6(2) = '00' or i_datum+6(2) > 31. RAISE wrong_day.


Aber wenn ich das mache und z.B. das Jahr prüfen möchte, dann hängt es von der Anwendung ab, welche Gültigkeiten gelten sollen. Wenn ich das Datum für Personen prüfen möchte, dann kann ich vielleicht grob sagen: es lebt keiner mehr, der vor 1900 geboren wurde. Wenn die Anwendung jetzt aber erweitert wird, so dass auch das Geburtsdatum der Eltern und Großeltern eingetragen werden muss...?

Und selbst wenn das Datum oder die Uhrzeit falsch sind, weil sie von einer Schnittstelle falsch geliefert werden: ist _meine_ Methode dann dafür verantwortlich, wenn der timestamp falsch erzeugt wird?
Was sind geeignete Maßnahmen, um fehlerhafte Parameter abzufangen? Muss ich für jede Eventualität eine Sicherung einbauen?

Und auch dann: Bei einem Datum kann ich Prüfungen machen und kann auch gut argumentieren, dass _meine_ Methode keine fehlerhaften Timestamps erzeugen wird. Wenn dann wirklich über eine Schnittstelle falsche Daten geliefert werden, müssen diese an anderer Stelle geprüft werden. Oder die Methoden muss erweitert werden, so dass Fehler korrigiert werden.

Aber auch hier ist es immer noch einfach. Ich muss mich als Programmierer entscheiden ob und wie ich eine Fehlerbehandlung machen möchte.

Kompliziert wird es dann, wenn immer mehr Parameter für bestimmte Fälle dazu kommen und hinterher gar nicht mehr klar ist, was wie in welcher Kombination überhaupt möglich ist.
Da mag man dann sagen: "tja, schlecht konzipiert", aber so sieht doch der Arbeitsalltag bei Programmierern häufig aus.
Wo ist dann der Punkt wo ich sagen muss: "Jetzt muss eine neue/ zweite/ dritte Methode her" oder "Jetzt muss ich mal alle Parameter hinterfragen"?
Selbst wenn man das machen würde, scheitert es häufig daran, dass man das gar nicht mehr testen kann.
ewx
Top Expert
 
Beiträge: 3885
Registriert: 04.08.2003, 19:55
Wohnort: Schleswig-Holstein
Dank erhalten: 343 mal

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes] ~ Optionale Param

Beitragvon black_adept » 07.01.2019, 20:49

ewx hat geschrieben:Wo ich regelmäßig stolpere ist, wenn ich ein GUI-Control baue, dass ich für den Aufrufer möglichst einfach aufrufbar machen möchte.
Einfach heißt in dem Fall, dass der Aufrufer den Namen eines Custom-Containers oder eine Containerinstanz übergeben kann.
1.: bekommt der CONSTRUCTOR diese beiden Parameter mit?
2.: oder mache ich eine extra Methode DISPLAY?
Wofür soll jetzt die Extramethode gut sein bzw. was macht die anders als der Konstruktor?
Davon abgesehen - wenn du es wirklich einfach halten willst nimm einen Parameter - dafür vom Typ "ANY" und schreib in die Beschreibung rein was erwartet wird. Im Coding kannst du dann je nach übergebenem Typ ( Referenz oder C-Feld ) intern unterscheiden. Nachteil ist halt die dadurch auf die Runtime verschobene Typprüfung - Vorteil die einfache Bedienbarkeit. Manchmal muss man halt entscheiden was man für wichtiger hält.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de
black_adept
Top Expert
 
Beiträge: 3195
Registriert: 08.01.2003, 13:33
Wohnort: Lehrte ( bei Hannover )
Dank erhalten: 559 mal
Ich bin: Freiberufler/in

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes] ~ Optionale Param

Beitragvon a-dead-trousers » 07.01.2019, 22:43

black_adept hat geschrieben:Wofür soll jetzt die Extramethode gut sein bzw. was macht die anders als der Konstruktor?

Wie ich schon erwähnt hab ist der einzig wirkliche Vorteil, dass die "Redefinierbarkeit" voll gegeben ist.
Mit dem Nachteil, dass man eben eine eigene Methode dafür (ver-)braucht.

Was mir persöhnlich noch an der Extramethode gegenüber der Konstruktorinitialisierung besser gefällt, ist das nachgelagerte Fehlerhandling. Beim Konstruktor hat man im Fehlerfall (Exceptionhandling hin oder her) *kein* Objekt, was man (theoretisch) im weiteren Verlauf berücksichtigen muss. Bei einem "leeren" Konstruktor und einer Extramethode ist das Objekt nach dem CREATE oder NEW() ohne weitere notwendige Prüfungen immer vorhanden. Selbst wenn das INITIALIZE nicht funktioniert hat, kann man das Objekt noch verwenden und es kann auch noch Auskunft über seinen Status geben (IS_INITIALIZED, GET_LAST_ERROR usw.)
Natürlich kann man darüber jetzt streiten, ob man das alles nicht doch besser mit Exception-Klassen löst oder nicht. Ich bin da je nach Anwendungsumfang recht flexibel. Mal machen echte Exceptions mehr Sinn und ein anderes Mal doch die "Statusauskunft". Vielleicht sehe ich das auch deswegen nicht so eng, weil Exceptions für mich immer irgendwie den Touch haben "hier ist Endstation und nichts geht mehr" und ich sie daher immer sehr sparsam verwendet hab. Ich hab auch schon mal mit dem "Resumeable" herumgespielt, aber das wirkt vom Verhalten her nicht so ganz wie aus einem Guß. Es ist IMHO auch nicht so leicht zu durchschauen wann, wie und wo das "Resume" jetzt eigentlich mit der Arbeit fortsetzt.
Kommen dann noch ein, zwei oder mehrere CLEANUP dazu ... :?
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.07
Basis: 7.40
a-dead-trousers
Top Expert
 
Beiträge: 3179
Registriert: 07.02.2011, 13:40
Dank erhalten: 789 mal
Ich bin: Entwickler/in

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes] ~ Optionale Param

Beitragvon black_adept » 07.01.2019, 23:21

a-dead-trousers hat geschrieben:Wie ich schon erwähnt hab ist der einzig wirkliche Vorteil, dass die "Redefinierbarkeit" voll gegeben ist.
Mit dem Nachteil, dass man eben eine eigene Methode dafür (ver-)braucht.

Vielleicht ist das ja genau der Grund, warum es den Konstruktor gibt - gemacht für den gegenteiligen Fall. Wenn ich mit meinem Objekt sicher stellen will, dass auch alle abgeleiteten Klassen gewisse Standards einhalten kann ich durch meine Definition des Konstruktors festlegen, dass all diese meine Initialisierungen durchlaufen müssen und nicht irgendwelchen Schlonz machen können, indem sie meine Initialisierungen redefinieren.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de
black_adept
Top Expert
 
Beiträge: 3195
Registriert: 08.01.2003, 13:33
Wohnort: Lehrte ( bei Hannover )
Dank erhalten: 559 mal
Ich bin: Freiberufler/in

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes] ~ Optionale Param

Beitragvon ralf.wenzel » 08.01.2019, 09:07

ewx hat geschrieben:Ein großes Problem bei Parametern ist m.E. häufig, dass gar nicht genau definiert ist, wann wie welche Parameter mit welchen Werten gefüllt sein müssen oder dürfen.
Wenn ich bei der Timestamp-Methode bleibe, dann möchte ich evtl. prüfen, ob die übergebenen Daten auch wirklich ein Datum oder eine Uhrzeit sind:
Code: Alles auswählen
IF i_datum(4) > 3000. RAISE wrong_year.
IF i_datum+4(2) = '00' or i_datum+4(2) > 12. RAISE wrong_month.
IF i_datum+6(2) = '00' or i_datum+6(2) > 31. RAISE wrong_day.



Und genau sowas gehört in meinen Augen in die IF-Implementierung rein, die sicherstellt, dass ich der Methode nur gültige Datumsangaben übermittle. Die empfangende Methode sollte das nicht erst noch verproben müssen (um dann Ausnahmen zu werfen, wenn die Angaben ungültig sind). Der Vorteil bei Objekten ist halt: Sie können sich schön auf Konsistenz selbst prüfen und was immer das Objekt rausgibt, ist konsistent. Das ist ein Beispiel für "datenspezifische Logik". Einer Methode potentiell ungültige Daten vor die Füße zu werfen, finde ich schon deshalb doof, weil dann die Methode einen Fehler wirft, die gar nicht fehlerhaft ist, sondern deren Arbeitsvoraussetzungen. Den Fehler sucht man dann im Aufrufer, den man erstmal suchen muss.

Abgesehen davon gilt das, was ich über OO im Allgemeinen geschrieben habe: OO ist das Kommunizieren von Objekten mittels Methodenaufrufen. Kann man wollen, kann man lassen, aber es mal so und mal so zu machen, finde ich verwirrend.

Aber wie ich schon schrieb: Ich habe nicht den Anspruch, dass jeder meiner Meinung ist ;) Ich wollte hier nur beschreiben, wie ich es in diesem Falle mache (sozusagen als Denkanstoß) und begründen, warum das so ist.

Vom eigentlichen Thema entwickeln wir uns übrigens weg. Wir sollten uns ggf. wieder mehr der Objekterzeugung widmen.

a-dead-trousers hat geschrieben:Natürlich kann man darüber jetzt streiten, ob man das alles nicht doch besser mit Exception-Klassen löst oder nicht. Ich bin da je nach Anwendungsumfang recht flexibel. Mal machen echte Exceptions mehr Sinn und ein anderes Mal doch die "Statusauskunft". Vielleicht sehe ich das auch deswegen nicht so eng, weil Exceptions für mich immer irgendwie den Touch haben "hier ist Endstation und nichts geht mehr"


Davon solltest du dich lösen. Eine Ausnahmebehandlung ist (ganz grob gesagt) für alle Fälle sinnvoll, wo auch ein "if sy-subrc ne 0" sinnvoll ist. Das muss nicht in einer Fehlermeldung enden, sondern kann durchaus ein alternatives operatives Coding sein.

Aber ein Constructor, der keine Ausnahme wirft UND kein Objekt erzeugt, würde mich überraschen. Dafür sind Ausnahmen da: Ich will was, ich kriege es nicht, also kommt eine Ausnahme.


Ralf
ralf.wenzel
Top Expert
 
Beiträge: 3374
Registriert: 18.09.2004, 13:03
Wohnort: Hamburg
Dank erhalten: 213 mal
Ich bin: Freiberufler/in

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes] ~ Optionale Param

Beitragvon ewx » 09.01.2019, 11:20

black_adept hat geschrieben:
ewx hat geschrieben:Wo ich regelmäßig stolpere ist, wenn ich ein GUI-Control baue, dass ich für den Aufrufer möglichst einfach aufrufbar machen möchte.
Einfach heißt in dem Fall, dass der Aufrufer den Namen eines Custom-Containers oder eine Containerinstanz übergeben kann.
1.: bekommt der CONSTRUCTOR diese beiden Parameter mit?
2.: oder mache ich eine extra Methode DISPLAY?

Wofür soll jetzt die Extramethode gut sein bzw. was macht die anders als der Konstruktor?

Sie macht nichts anders, sondern nur "separat".
Wäre in sofern sinnvoll, wenn der CONSTRUCTOR noch weitere Parameter bräuchte.
Dann würde man diese Anzeige-relevanten Parameter schon mal auslagern.
black_adept hat geschrieben:Davon abgesehen - wenn du es wirklich einfach halten willst nimm einen Parameter - dafür vom Typ "ANY" und schreib in die Beschreibung rein was erwartet wird. Im Coding kannst du dann je nach übergebenem Typ ( Referenz oder C-Feld ) intern unterscheiden. Nachteil ist halt die dadurch auf die Runtime verschobene Typprüfung - Vorteil die einfache Bedienbarkeit. Manchmal muss man halt entscheiden was man für wichtiger hält.

puh. Das ist aber schon einigermaßen dirty... ;)
ewx
Top Expert
 
Beiträge: 3885
Registriert: 04.08.2003, 19:55
Wohnort: Schleswig-Holstein
Dank erhalten: 343 mal

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitragvon ralf.wenzel » 09.01.2019, 11:23

Das ist nicht nur dirty, sondern der Aufrufer wird kaum verstehen, was er mitgeben muss. Also muss er die Methode lesen und das ist eigentlich gegen das Konzept.


Ralf
ralf.wenzel
Top Expert
 
Beiträge: 3374
Registriert: 18.09.2004, 13:03
Wohnort: Hamburg
Dank erhalten: 213 mal
Ich bin: Freiberufler/in

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes] ~ Optionale Param

Beitragvon black_adept » 09.01.2019, 13:36

ewx hat geschrieben:puh. Das ist aber schon einigermaßen dirty... ;)
ralf.wenzel hat geschrieben:Das ist nicht nur dirty, sondern der Aufrufer wird kaum verstehen, was er mitgeben muss. Also muss er die Methode lesen und das ist eigentlich gegen das Konzept.
Schau dir mal in ABAP2XLSX die Methoden an, die irgendwie mit Spalten zu tun haben. Einerseits kann man die Spalten nummerisch, andererseits in der Excel-üblichen Schreibweise "A-Z,AA-ZZ, AAA..." angeben. Nahezu alle Methoden, die irgendwo eine Spalte erwarten sind so nett dem Aufrufer sowohl das eine als auch das andere zu erlauben, je nachdem was gerade beim Aufrufer zur Verfügung steht.
Ist im Endeffekt nichts anderes als was SAP bei diversen Befehlen auch von Haus aus kann - z.B. beim ASSIGN COMPONENT comp OF STRUCTURE struc , wo je nach Typ von comp anders verfahren wird.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de
black_adept
Top Expert
 
Beiträge: 3195
Registriert: 08.01.2003, 13:33
Wohnort: Lehrte ( bei Hannover )
Dank erhalten: 559 mal
Ich bin: Freiberufler/in

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitragvon black_adept » 09.01.2019, 13:45

Nachtrag zu eben: Ja - ich verwende tatsächlich solche Klassen, die auf verschiedene Eingabetypen leicht unterschiedlich reagieren. Beispiel ist eine Utilitymethode, die mir einen Feldkatalog zurückliefert. Und ob ich nun eine Tabelle, eine Struktur, eine Referenz auf eine Tabelle oder Struktur übergebe. Die Methode gibt mir immer schön einen Feldkatalog zurück.
Man sollte mit solchen Sachen auch nicht um sich werfen bloß weil man es kann. Denn der Verlust der statischen Typprüfung sollte immer im Hinterkopf bleiben, so dass solch "Typ-überladene" Parameter die absolute Ausnahme bleiben sollten. Aber in dem o.a. Fall ist die Schlichtheit der Verwendung in meinen Augen zu präferieren.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Für diese Nachricht hat black_adept 2 Dankeschön bekommen :
a-dead-trousers, ralf.wenzel
black_adept
Top Expert
 
Beiträge: 3195
Registriert: 08.01.2003, 13:33
Wohnort: Lehrte ( bei Hannover )
Dank erhalten: 559 mal
Ich bin: Freiberufler/in

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitragvon a-dead-trousers » 09.01.2019, 21:32

black_adept hat geschrieben:Beispiel ist eine Utilitymethode, die mir einen Feldkatalog zurückliefert. Und ob ich nun eine Tabelle, eine Struktur, eine Referenz auf eine Tabelle oder Struktur übergebe. Die Methode gibt mir immer schön einen Feldkatalog zurück.

Ja, die Methode hab ich auch. 8)
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.07
Basis: 7.40
a-dead-trousers
Top Expert
 
Beiträge: 3179
Registriert: 07.02.2011, 13:40
Dank erhalten: 789 mal
Ich bin: Entwickler/in

Re: CONSTRUCTOR & Co. [Sammeln & Seltenes]

Beitragvon ralf.wenzel » 09.01.2019, 21:37

Die haben wir wohl alle :D


Ralf
ralf.wenzel
Top Expert
 
Beiträge: 3374
Registriert: 18.09.2004, 13:03
Wohnort: Hamburg
Dank erhalten: 213 mal
Ich bin: Freiberufler/in

Vorherige

Zurück zu ABAP Objects®

  Aktuelle Beiträge   
Java Definition Interface/Abstrakte Klasse
vor 2 Stunden von nickname8 1 Antw.
WF - Containeroperation
vor 7 Stunden von bapimueller 0 Antw.
gelöst BANF-Freigabe
vor 7 Stunden von schusterd 1 Antw.
gelöst Serialnummern bei BANFen/Bestellungen angeben
vor 7 Stunden von mareikemei92 3 Antw.
Datumsdifferenz berechnen
Gestern von DeathAndPain 3 Antw.

  Ähnliche Beiträge beta
Haste mal nen Constructor
01.12.2005, 16:21 von ereglam 1 Antw.

 

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder