Kommunikation von Klassen und Methoden

Getting started ... Alles für einen gelungenen Start.
24 Beiträge • Seite 1 von 2 (current) Nächste
24 Beiträge Seite 1 von 2 (current) Nächste

Kommunikation von Klassen und Methoden

Beitrag von Abapsocke (ForumUser / 49 / 6 / 0 ) »
Ich tue mich noch schwer mit dem Export und Import von Daten bei Klassen in Abap OO.
Folgendes Szenario:

In einer Klasse erzeuge ich in einer Methode eine Variable, die ich an eine andere Klasse übergeben will, aber ich bekomme den Syntax nicht hin.

Die Klasse 1 heißt als Beispiel zcb_ichweißnichtwie 1 und der Wert der an Klasse 2 übergeben werden soll, wird in der Methode "Testlauf" als Exportparameter vom Typ boolean übergeben.
Die Klasse 2 heißt zcb_immernochnicht und soll nun den Wert der Klasse 1 in einer Methode "testlauf2" aufrufen und verwenden.
Wie muss der Syntax lauten, um den genauen Wert der Klasse 1 aufzurufen und einzubinden?

Bitte als Beispiel der Code wie er in einer lokalen Klasse und nicht mit dem classbuilder geschrieben werden würde.

gesponsert
Stellenangebote auf ABAPforum.com schalten
kostenfrei für Ausbildungsberufe und Werksstudenten


Re: Kommunikation von Klassen und Methoden

Beitrag von SaskuAc (Specialist / 321 / 37 / 43 ) »
okay, hier ein einfaches beispiel das dir evtl helfen könnte.
Disclaimer: es wäre aber allgemein gut, wenn du dich mit den übergabeparametern in OO nochmal beschäftigen würdest:

Code: Alles auswählen.


class lcl_1 defintion. 

public section. 

methods: 
get_value_of_var_1 returning value(rv_var) type char01. 

data: var2 type string. 

private section. 

data: var01 type char01. 

endclass. 

class lcl_1 implementation. 

method get_value_of_var_1. 
rv_var = var01. 
endmethod. 

endclass. 

class lcl_2 definition. 
public section. 

methods: bla. 

private section. 
data: mv_bla type char01. 
data: mv_bla_2 type string. 

endclass. 

class lcl_2 implementation. 
 method bla. 
" erstelle das objekt der klasse
data(ref_1) = new lcl_1( ).

" nun hast du 2 möglichkeiten 

" 1. über eine methode mit returning value - dies sollte bei attributen immer gemacht werden, wenn sie außerhalb verwendet werden sollen, denn man könnte in die methode get_value_of_var_1 eventuell eine berechtigungsprüfung einbauen oder änliches 
mv_bla = ref_1->get_value_of_var_1( ).

" 2. über ein public ( öffentliches ) attribut - sollte eigentlich nie gemacht werden - aber möglich ist es. man kann es z. b. bei wirklich unkritischen sachen machen 
mv_bla_2 = ref_1->var2. 
endmethod. 
endclass.
änlich kann man es natürlich auch bei statischen attributen machen.

Ich hoffe ich konnte dir weiterhelfen

PS: etwaige Syntax fehler bitte ignorieren, falls vorhanden. Habe das jetzt hier im Forum Editor zusammengetippt ohne in meine IDE zu springen

Folgende Benutzer bedankten sich beim Autor SaskuAc für den Beitrag:
Hotzenplotz


Re: Kommunikation von Klassen und Methoden

Beitrag von 4byte (Specialist / 124 / 37 / 35 ) »
Ergänzend einfach noch folgende Begriffe:
Kapselung: Variablen/Datenfelder sollten nur innerhalb ihrer Klasse verwendet werden und sind nicht sichtbar nach außen.
Der Zugriff auf diese Daten erfolgt über definierte Schnittstellen: GETTER und SETTER
Mögliches Schreiben auf die Variablen über eine SETTER Schnittstelle. Hier können dann z.B. Plausibilätsprüfungen eingebaut werden.
Ein Lesen der Datenfelder über GETTER Schnittstelle. Hier werden die Klassenattribute gelesen und zurück gegeben.

Die Getter / Setter Methoden einfach public halten.

Grüße 4Byte
Es gibt 10 Menschen die binär verstehen :)

Re: Kommunikation von Klassen und Methoden

Beitrag von DeathAndPain (Top Expert / 1795 / 213 / 396 ) »
Oder einfach klassisch-prozedural programmieren, dann hat man den ganzen Stress nicht, und der Quellcode ist besser lesbar. *duckundweg*

Re: Kommunikation von Klassen und Methoden

Beitrag von Abapsocke (ForumUser / 49 / 6 / 0 ) »
das mit Gettern und Settern ist mir schon klar, aber nur weil man etwas machen soll, muss es doch eine möglichkeit geben das zu umgehen, sonst wäre es ja unsinn zu lernen, wie man getter und Setter einsetzt, wenn man es ohnehin nicht ohne tun kann.

Defakto verstehe ich euch jetzt so: In dem Moment wo ich mit einer Klasse auf die Variablen und Constanten einer andere zugreifen will, muss ich mit Gettern und Settern arbeiten. D.H alle diese Werte kommen eigentlich ins Private.

Ok, dazu habe ich mir auch schon einiges angelesen, aber in dem konkreten Fall hilft mir das nicht weiter.

Ich brauche da wirklich ein konkretes Beispiel mit zwei Klassen. (hier ein bisschen pseudocode)

Code: Alles auswählen.

Klasse test1
*hier möchte ich den Wert der Variablen
ed_full exportieren, die vorher in der Methode der Klasse verändert wurde. 
ed_full = 'x'.

Klasse test 2
*hier möchte ich den Wert der Variablen ed_full importieren, die vorher in der Klasse test 1 verändert wurde. 
While ed_full is not inital "falls so möglich"
do this
Endwhile.
Alternativ.. gibt es ne Möglichkeit ein geraisdes Event mit einem If zu verbinden. In dem Sinne "wenn event x stattgefunden hat.. mache dies"

und noch eine Frage: mit Type Ref to zeige ich im prinzip auf eine klasse, aber ohne wertübertragung? Also vom Verständnis her: du sollst so aussehen wie!

Re: Kommunikation von Klassen und Methoden

Beitrag von 4byte (Specialist / 124 / 37 / 35 ) »
Abapsocke hat geschrieben:das mit Gettern und Settern ist mir schon klar, aber nur weil man etwas machen soll, muss es doch eine möglichkeit geben das zu umgehen, sonst wäre es ja unsinn zu lernen, wie man getter und Setter einsetzt, wenn man es ohnehin nicht ohne tun kann.
Siehe den Post SaskuAc: Du kannst einfach ein öffentliches Attribut der Klasse anlegen. Entweder als Instanz oder statisch. Somit brauchst du keine SETTER / GETTER.
Abapsocke hat geschrieben:und noch eine Frage: mit Type Ref to zeige ich im prinzip auf eine klasse, aber ohne wertübertragung? Also vom Verständnis her: du sollst so aussehen wie!
Ich vergleiche das immer gerne mit einem Bauplan. Bei der Objektinstanziierung wird dann das Objekt entsprechend der Vorlage (Klasse) erzeugt.
Abapsocke hat geschrieben:Alternativ.. gibt es ne Möglichkeit ein geraisdes Event mit einem If zu verbinden. In dem Sinne "wenn event x stattgefunden hat.. mache dies"
Mhh bei Klassenbasierten Ausnahmen wüsste ich grad nicht wie :roll: Hier hast du ja folgenden Aufbau:

Code: Alles auswählen.

try.
* Mache was einen Dump Auslösen könnte
catch z_ex into data(lo_cx)
* Fange Dump ab.
* Hole Fehlernachricht.
data(lv_err_txt) = lo_cx->get_text( ).
endtry.
Du könntest eine eigene Exceptionklasse erstellen und dann im Fehlerfall

Code: Alles auswählen.

 RAISE EXCEPTION TYPE Z_EX EXPORTING z_err_id = '1' textid = z_ex=>z_exerr_msg
den Code übertragen.
Diesen dann im CATCH Block auslesen. z_err_id ist dann ein Attribut, dass in die Textnachricht z_err_msg per Platzhalter eingefügt wird.
Es gibt 10 Menschen die binär verstehen :)

Re: Kommunikation von Klassen und Methoden

Beitrag von SaskuAc (Specialist / 321 / 37 / 43 ) »
Abapsocke hat geschrieben: Alternativ.. gibt es ne Möglichkeit ein geraisdes Event mit einem If zu verbinden. In dem Sinne "wenn event x stattgefunden hat.. mache dies"
Entweder exceptions ... oder aber direkt Events .. du kannst dazu dann handler Methoden definieren, die das Event vom Objekt abfangen und dann verarbeiten. und wenn du später dann mal wissen möchtest ob dieses oder jenes stattgefunden hat, kann man sich ja verschiedene Hilfsvariablen anlegen ( Eine Tabelle mit Eventnamen, variablen die Flags enthalten, usw. )

DeathAndPain hat geschrieben:Oder einfach klassisch-prozedural programmieren, dann hat man den ganzen Stress nicht, und der Quellcode ist besser lesbar. *duckundweg*
Ich verstehe es, wenn Leute nicht OO-Programmieren wollen. Aber ich bestreite wehement, dass der Quellcode lesbarer wird, wenn man prozedural programmiert ... Meiner Meinung nach ist er dann seltenst gut strukturiert und ausreichend dokumentiert. Bei OO kann man anhand der Klassen super strukturieren und auch leichter dokumentieren ... Ich weiß nicht inwieweit du schon mit OO gearbeitet hast, aber ich glaube dir würde es generell gut gefallen, wenn du es einmal verstanden hast. Weil ab dann ist es wesentlich leichter ;) - aber gut, ich will hier jetzt keine OO VS. Prozedural Diskussion anfachen, die haben wir hier schon oft genug :D


Abapsocke hat geschrieben:das mit Gettern und Settern ist mir schon klar, aber nur weil man etwas machen soll, muss es doch eine möglichkeit geben das zu umgehen, sonst wäre es ja unsinn zu lernen, wie man getter und Setter einsetzt, wenn man es ohnehin nicht ohne tun kann.

Defakto verstehe ich euch jetzt so: In dem Moment wo ich mit einer Klasse auf die Variablen und Constanten einer andere zugreifen will, muss ich mit Gettern und Settern arbeiten. D.H alle diese Werte kommen eigentlich ins Private.

Ok, dazu habe ich mir auch schon einiges angelesen, aber in dem konkreten Fall hilft mir das nicht weiter.

Ich brauche da wirklich ein konkretes Beispiel mit zwei Klassen. (hier ein bisschen pseudocode)

Code: Alles auswählen.

Klasse test1
*hier möchte ich den Wert der Variablen
ed_full exportieren, die vorher in der Methode der Klasse verändert wurde. 
ed_full = 'x'.

Klasse test 2
*hier möchte ich den Wert der Variablen ed_full importieren, die vorher in der Klasse test 1 verändert wurde. 
While ed_full is not inital "falls so möglich"
do this
Endwhile.
okay, hier nochmal zwei kurze ( getrennte ) beispiele wie man auf attribute zugreifen kann.

Öffentliche Attribute

Code: Alles auswählen.

class class_1 definition. 

public section. 
 " definiert ein öffentliches Instanzattribut, welches bei jedem neuem Objekt anders gespeichert ist. 
 data: var_01 type string. 
" definiert ein statisches (Klassen-)Attribut, welches bei jedem Objekt gleich ist. 
 class-data: var_02 string. 

endclass. 

class class_1 implementation. 

endclass. 

class class_2 definition. 

public section. 
methods get_member_var. 
methods get_static_var.

endclass. 

class class_2 implementation. 

method get_member_var. 

" hier könnte man statt einer Inline Deklaration auch direkt eine existierende Variable ( z. B. im Definitionsbereich ) ansprechen
" das Wort 'new' erstellt ein neues objekt und gleichzeitig eine Referenz der Klasse class_1. Die Referenz und das Objekt werden allerdings nach diesem Statement gleich wieder gelöscht. ( weil die Referenz nirgends abgespeichert wird ... Daher macht das Beispiel theoretisch keinen Sinn .. verdeutlicht dennoch wie man etwas benutzen kann ) 
" ich würde hier gleich auf den Wert von var_01 gehen, ohne eine Methode aufzurufen.
data(local_var) = new class_1( )->var_01. 

endmethod. 

method get_static_var. 

" hier greife ich auf das statische Attribut 'var_02' der Klasse 'class_1' zu ohne eine getter methode zu verwenden. 
data( local_var) = class_1=>var_02. 

endmehtod. 

endclass.  
ich hoffe das Beispiel mit öffentlichen attributen ist klar.

Getter / Setter

Code: Alles auswählen.

class class_1 definition. 

public section. 
  methods set_var_01 importing iv_01 type string.
  methods get_var_01 returning value(rv_01) type string. 
  class-methods: set_var_02 importing iv_02 type string. 
  class-methods: get_var_02 returning value(rv_02) type string. 

private section. 
  data: var_01 type string. 
  class-data: var_02 string. 

endclass. 

class class_1 implementation. 

method set_var_01. 

 " eine einfache prüfung ob der wert überhaupt gesetzt werden soll 
if strlen( iv_01 ) < 5. 
  var_01 = iv_01. 
 endif. 

endmethod.

method get_var_01. 

" z. b. irgend eine Berechtigungsprüfung

rv_01 = var_01. 

endmethod.

method set_var_02. 

 " eine einfache prüfung ob der wert überhaupt gesetzt werden soll 
" im prinzip aber das gleiche wie für Instanzattribute, nur dass dieser wert immer bestehen bleibt nachdem die Klasse ein mal verwendet worden ist im programm 
if strlen( iv_02 ) < 10.  
  var_02 = iv_02. 
 endif. 

endmethod.

method get_var_02. 

" z. b. irgend eine Berechtigungsprüfung
" wieder im prinzip das gleiche wie für die Instanzattribute. 

rv_02 = var_02. 

endmethod.

endclass.

class class_2 definition. 

public section. 

" der wird ja bei jedem neuem objekt aufgerufen. 
methods: constructor. 
" wird bei jeder 1. Verwendung der Klasse in einem Programm verwendet. 
class-methods: class_constructor. 

endclass. 

class class_2 implementation. 

method constructor. 

data(lo_class_1) = new class_1( ). 
" jetzt ist var_01 von lo_class_1 noch leer und liefert nichts
data(lv_value) = lo_class_1->get_var_01( ). 

lo_class_1->set_var_01( 'Test' ). 
" jetzt steht in lv_value 'Test'. hätten wir z. B. Test123 mitgegeben in der SETTER wäre lv_value auch wieder leer, da durch unsere prüfung var_01 in class_1 nicht befüllt würde ( da mehr als 5 Zeichen ) 
lv_value = lo_class_1->get_var_01( ). 

endmethod. 

method class_constructor. 


" hier bekommen wir dann 'test_stat' bei der getter Variable 
class_1=>set_var_02( 'test_stat' ). 
data(lv_value_stat) = class_1=>get_var_02( ). 


endmethod. 

endclass.  

ich hoffe das prinzip wird halbwegs klar .. persönlich würde ich immer auf setter und getter setzen, da man zur not schnell eine prüfung einbauen kann, selbst wenn man aktuell keine braucht. Außerdem kann es bei der Vermeidung von Programmierfehlern helfen. Aber natürlich muss man nicht immer auf die Methoden setzen. Wenn ich jetzt einfache Variablen habe, die theoretisch irrelevant sind ( wobei sich ja dann die Frage stellt, warum man die überhaupt braucht ) mache ich das Attribut auch mal öffentlich.

Hoffe das ich helfen konnte.

Beste Grüße

PS: bitte wieder schreibfehler, falls vorhanden, im Code nicht beachten .. habe immer noch keinen Editor auf diesem PC ...

Re: Kommunikation von Klassen und Methoden

Beitrag von ewx (Top Expert / 4784 / 294 / 628 ) »
SaskuAc hat geschrieben:persönlich würde ich immer auf setter und getter setzen, da man zur not schnell eine prüfung einbauen kann, selbst wenn man aktuell keine braucht. Außerdem kann es bei der Vermeidung von Programmierfehlern helfen. Aber natürlich muss man nicht immer auf die Methoden setzen. Wenn ich jetzt einfache Variablen habe, die theoretisch irrelevant sind ( wobei sich ja dann die Frage stellt, warum man die überhaupt braucht ) mache ich das Attribut auch mal öffentlich.


Ich benutze fast nie GETTER und SETTER. Natürlich übergebe ich Werte mit SET_xyz an eine Klasse oder hole mir Daten mit GET_abcd, aber das sind fast nie GETTER und SETTER im eigentlichen Sinn. GETTER und SETTER sind für mich Methoden, die ganz blöd einen privaten Wert nach außen geben. Da die Klassen jedoch viel komplexe Objekte verwalten (Material, Kundenauftrag etc) ist es IMHO nicht sinnvoll, für jedes Attribut eines Objektes einen GETTER zur Verfügung zu stellen.
GET_MTART
GET_MAKT
GET_...

Mit der Einführung des Strukturzugriffs lässt sich das wieder einfacher machen:

Code: Alles auswählen.

DATA(materialart) = o_material->get_mara( )-mtart.
Aber auch hier: Warum sollte ich in einem "Klassenverbund", in dem alle Klassen irgendwie miteinander auskommen müssen, bestimmte Informationen verstecken, nur weil ich der Meinung bin, dass diese von außen nicht wichtig sind? Das weiß ich noch gar nicht. Also stelle ich lieber (fast) alle Attribute auf öffentlich und der Verwender hat alle Möglichkeiten ohne dass die Stabilität der Klasse eingeschränkt wird.

Man muss dann natürlich aufpassen, dass man nicht von außen Funktionalität an die Klasse baut, die eigentlich in die Klasse gehört.

Und ja, bei Objekten kann ich natürlich von außen auf ein Objekt zugreifen und dies auch verändern und so die Klassenintegrität verletzen.
Programmieren ist halt manchmal auch gefährlich... ;)
SaskuAc hat geschrieben:PS: bitte wieder schreibfehler, falls vorhanden, im Code nicht beachten .. habe immer noch keinen Editor auf diesem PC ...
Dagegen gibt's jetzt was von Larsiohvam (Zumindest für den atom edtitor):
https://atom.io/packages/linter-abaplint

Re: Kommunikation von Klassen und Methoden

Beitrag von DeathAndPain (Top Expert / 1795 / 213 / 396 ) »
SaskuAc hat geschrieben:Ich verstehe es, wenn Leute nicht OO-Programmieren wollen. Aber ich bestreite wehement, dass der Quellcode lesbarer wird, wenn man prozedural programmiert ...
Mein Lieblingszitat: "I don’t know the answer but I do know that debugging what happens after pressing a command in VA01 is easier to follow than the equivalent in ME21N. Or is that just because I am an OO novice?"
Meiner Meinung nach ist er dann seltenst gut strukturiert und ausreichend dokumentiert. Bei OO kann man anhand der Klassen super strukturieren und auch leichter dokumentieren ...
Dass das falsch ist, zeigt schon ein einfacher Vergleich zwischen Funktionsbausteinen und Methoden (Funktionsgruppen und Klassen haben ja technisch durchaus eine gewisse Ähnlichkeit und dienen letztlich demselben Zweck). Schau Dir an, wie Du bei Funktionsbausteinen Online-Doku hinterlegen kannst, bis hinunter zu Einzeldokus für jeden einzelnen Parameter, der im Interface direkt am Parameter angezeigt und dessen Existenz durch eine Lampe sichtbar gemacht wird. Und dann schau Dir im Vergleich Deine Dokumentationsmöglichkeiten bei Klassen und Methoden an. Da gibt es nur wenige Texte, die man hinterlegen kann, und die sind im Menü versteckt. Die Konsequenz ist auch offensichtlich, selbst wenn Du Dir SAP-Standard-Code anschaust: Wieviele Funktionsbausteine haben eine ordentliche Online-Doku, und wieviele Klassenmethoden haben eine solche?

Im objektorientierten Bereich dokumentiert kein Schwein. Das mag bitter sein, aber es ist die gelebte Realität. Die Leute glauben, dass ihr Code auch ohne Kommentar verständlich sei, weil sie selber wissen, was ihre Klassen machen und wie sie gedacht sind. OO basiert aber darauf, dass Klassen und Methoden verwendet werden wie ABAP-Befehle. Das geht aber nur, wenn man genau versteht, was sie machen, was das Soll-Ergebnis ist. Wenn man einen ABAP-Befehl nicht versteht, liest man einfach nach, notfalls bei Google. Versteht man eine Klasse nicht und weiß nicht, was für Informationen in ihr versteckt sind und wie sie zu interpretieren sind, dann ist man aufgeschmissen. (Sowas ähnliches kannste auch mit FBs machen, indem Du per Setter-FBs Informationen in den globalen Feldern der Funktionsgruppe versteckst, die dann beeinflussen, wie andere FBs derselben Funktionsgruppe sich verhalten. Davon halte ich auch nichts, solange es nicht elitär dokumentiert ist. Liegt auf einem ähnlichen Niveau wie das Verstecken von Daten im ABAP-Memory, die dann an anderer Stelle scheinbar vom Himmel fallen.)

Und nun stell Dir vor, in solch einer Klasse ist ein Bug. Da siehste ein komisches Verhalten und weißt nie, ob das so sein soll und Du nur die Funktionsweise der Klasse bzw. Methode nicht genau verstanden hast, oder ob es ein Bug ist. Das obige Zitat hat nicht ohne Grund seine Daseinsberechtigung.

In der Theorie ist OO wunderbar (wenngleich alles andere als performant in Bereichen, an denen Performance abseits von Datenbankzugriffen eine Rolle spielt). Aber in der gelebten Praxis muss man bei einem fremden OO-Programm einen um Größenordnungen höheren Aufwand treiben um zu verstehen, was da passiert und wo der Fehler liegen könnte. Die erforderliche exzellente Doku schreibt fast niemand, und im System kann man sie auch viel schlechter ablegen als bei prozeduralem Code. Obendrein ist OO durch teils antiquiert wirkende akademische Vorgaben, die in der Praxis nichts bringen, aufgebläht, etwa dass eine Methode räumlich vor ihrer ersten Nutzung stehen muss, so dass man bei lokalen Methoden im Prinzip gezwungen ist, die ganzen lokalen Methoden, die man nachher verwenden wird, am Anfang in ein Include zu packen (das geht bis zu idiotischen Konstruktionen wie "DEFINITION DEFERRED"). Da war man mit Formroutinen vor 20 Jahren schon weiter. Die können stehen, wo sie wollen; der ABAP-Interpreter findet sie. Oder dass man separat Definition und Implementierung schreiben muss und diese räumlich auseinanderstehen, so dass man da, wo der Code der (lokalen) Methode steht, nicht sieht, wie sie parametrisiert ist (es sei denn, man macht sich die Mühe und schreibt das nochmal in Kommentarcode ab, der natürlich nicht mehr hinhaut, sobald ein Parameter ergänzt wird. FB's pflegen ihren Kommentar in solchen automatisch nach).

Generell versaut die Unterstützung im Editor auch die Moral. Wenn ich sehe, der Code wird zu lang, eigentlich sollte ich das der Übersichtlichkeit halber in eine aussagekräftig benamte und parametrisierte Unterroutine packen, dann schreibe ich in der SE38 einfach den Perform, doppelklicke auf den Namen und bekomme den Prozedurrumpf automatisch erzeugt, so dass ich flüssig weiterprogrammieren kann. (In Eclipse geht das leider nicht direkt, aber da habe ich mir problemlos behelfen können, indem ich mir ein FORM-Template definiert habe. Da kopiere ich den gewünschten Formnamen, schreibe FORM, drücke Strg+SPACE, dann Enter, drücke Strg+V und habe den Formrumpf samt Kopfkommentar auch mit wenigen Tastendrücken erzeugt.)

Letzteres könnte man bei Methoden auch machen, aber dann fängt man erst mal wieder an, die Definition auszufüllen, bevor man mit der Implementierung beginnen kann, und wenn man es so macht wie die meisten, dann muss man die Definition ja ans andere Ende des Programms packen. Bevor man sich die Mühe macht, denkt man sich lieber, ach Schei ß drauf, ich mach das jetzt ohne Unterroutine, und schon entsteht wieder Spaghetticode.

Ich mag die Ideen, die hinter OO stecken, durchaus. Aber in der Praxis muss ich leider sagen: "Gut gedacht und schlecht gemacht." Bei riesigen Projekten mit sehr hohem Abstraktionsgrad wie dem, von dem Ralf gelegentlich erzählt, mag das einen Wert haben, aber beim durchschnittlichen Standardprogramm ist es einfach nur belastend. Dabei mag ich Konzepte wie Methoden, die sich funktional mit Return-Parameter aufrufen lassen, eigentlich sehr. Solch Aufruf dient durchaus der besseren Lesbarkeit. Wenn die sich jetzt mit überschaubarem Aufwand (ähnlich einer Formroutine) anlegen ließen...

In dieselbe Kerbe (gut gedacht doch schlecht gemacht) schlägt auch ABAP Doc. Eigentlich eine Superidee, aber dass die Kommentare in der Zeile davor statt wie üblich hinten in derselben Zeile stehen müssen, ruiniert die Code-Lesbarkeit so dermaßen, dass es am Ende nicht zu gebrauchen ist.

Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
Legxis


Re: Kommunikation von Klassen und Methoden

Beitrag von black_adept (Top Expert / 3943 / 105 / 886 ) »
SaskuAc hat geschrieben:[.... Aber ich bestreite wehement, dass der Quellcode lesbarer wird, wenn man prozedural programmiert ... Meiner Meinung nach ist er dann seltenst gut strukturiert und ausreichend dokumentiert. Bei OO kann man anhand der Klassen super strukturieren und auch leichter dokumentieren
Bist du sicher, dass du hinreichend Erfahrung in prozeduraler Programmierung hast um derartige Aussagen zu treffen?
Ein guter Entwickler kann dir sowohl in prozeduraler als auch in einer OO-Umgebung gut strukturierte Programme schreiben. Und ein unfähiger Entwickler hinterlässt in beiden Fällen unwartbares Chaos.
SaskuAc hat geschrieben:Ich weiß nicht inwieweit du schon mit OO gearbeitet hast, aber ich glaube dir würde es generell gut gefallen, wenn du es einmal verstanden hast.
Und das ist eine Frechheit!

Folgende Benutzer bedankten sich beim Autor black_adept für den Beitrag:
ST22

live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: Kommunikation von Klassen und Methoden

Beitrag von DeathAndPain (Top Expert / 1795 / 213 / 396 ) »
So sehe ich das auch. Aber angesichts der Tatsache, dass dies leider gelebte Realität ist, dass viele Entwickler (auch externe Berater usw.) so programmieren, ist mir in dem Falle ein klassisch-prozeduraler Code lieber. Denn wenn schlampig entwickelt worden ist und man keine Wahl hat und an dem Code etwas machen muss, dann hat man bei herkömmlicher Programmierung immer noch die bedeutend besseren Karten.

Vor allem, wenn es sich um Feigenblatt-OO handelt (definiere eine Klasse und schreibe das Nutzprogramm in den Konstruktor).

Re: Kommunikation von Klassen und Methoden

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
Ob diese Diskussion je aufhört? Wobei man nicht vergessen sollte, dass der Rat, es prozedural zu lösen, offensichtlich als Provokation gemeint war. Wenn ich jemanden frage, welche Papiere ich für die Einreise nach Russland brauche, erwarte ich nicht die Antwort "fahr' nach Holland, da brauchst du gar keine".

Übrigens hat das Beispiel mit dem LOOP mir gezeigt, wie sehr ich inzwischen anders denke.

PERFORM...
Prüfung

PERFORM....
Prüfung

Wenn man gewohnt ist, Methoden zu schreiben, IST die Methode die Prüfung. Schon hier zeigt sich eine völlig andere Denke. Dann heißt die Methode eben nicht "GET_DONOR" gefolgt von der Prüfung, ob der Spender aktiv ist, sondern die Methode heißt "IS_DONOR_ACTIVE" und enthält auch gleich die Prüfung.

Insofern bin ich dankbar für das Beispiel mit dem LOOP, weil es mir selbst mal vor Augen geführt hat, wie ich mich in den letzten Jahren entwickelt habe.

Fakt ist aber, und da muss ich einigen Leuten hier recht geben, dass viele prozedural geschriebene Programme grausig sind. 10.000 Zeilen Coding, davon LOOPs die über 2.000 Zeilen gehen, da fällt dann ein GC_X vom Himmel oder ein Flag in SY-LISEL (das dann gleich kontextabhängig für alle möglichen Flags verwendet wird; man spart sich ja das Deklarieren), das dann plötzlich die Verarbeitung signifikant beeinflusst. Je älter das Coding ist, umso grausiger ist es in aller Regel.

Natürlich gibt es auch schlechtes OO-Coding (und zwar eine Menge davon), aber das mache ich nicht an dem fest, was viele daran kritisieren. Oft gehörte Kritik ist: "Der springt ständig von einer Methode zur nächsten und ich habe keinen Überblick" (das liegt oft daran, dass das Prinzip nicht verstanden wurde), ich kritisiere OO-Coding, wenn ich auf unsauberes OO stoße, wo das Paradigma verletzt wird. Und OO erzieht ein wenig zur Disziplin, weil es bestimmte Dinge nicht mehr zulässt.

Interessant ist, dass ich mich viel weniger im Debugger bewege, seit ich streng OO programmiere. Bestenfalls gehe ich zu einer bestimmten Stelle, um mir Werte im Debugger anzusehen, aber das "Durchhoppeln" habe ich mir fast komplett abgewöhnt. Weil ich OO-Coding oft viel klarer und verständlicher finde als Bandwurm-Coding. Gerade die kritisierten vielen kleinen Methoden führen dazu, dass ich viel mehr auf Zusammenhänge achte als auf einzelne Anweisungen, denn Methoden decken quasi Gedankenschritte ab. Die o. g. Prüfmethode ist so ein Beispiel.

Leider gelingt es nicht vielen, OO gescheit zu erklären. Schon der Erklärungsansatz entscheidet darüber, wie es um die Akzeptanz bestellt ist. Man sollte von Objekten viel mehr sprechen wie von Dingen, denn das beschreiben Objekte in aller Regel. Das zieht viel besser und ist viel bildhafter als jede akademische Beschreibung.

Nehmen wir ein Beispiel: Materialstammanlage mit MATERIAL_MAINTAIN_DARK. Die Herausforderung ist, wenn man einen Materialstamm in zwei Werken in je drei Lagerorten anlegt, man eine bestimmte Struktur einhalten muss, nämlich die, die beim Eingeben auch erfolgt. Für jeden MARD-Satz braucht es einen passenden MARC-Satz und für jeden MARC-Satz einen passenden MARA-Satz, etc.. Man sollte aber aufpassen, nicht zu viele MARA-Sätze zu erzeugen, sonst erzeugt man leicht Inkonsistenzen.

Dieses ganze Gedöns ist aufwendiger als ich glaubte, bis ich anfing, in Objekten zu denken - weil ein Objekt nämlich einen Konstruktor hat. Also war ein MARx-Satz für mich ein "Ding" mit einer gewissen Portion "Eigenintelligenz". Wenn ich ein MARD-Objekt erzeuge, wird automatisch der Konstruktor durchlaufen. Der Konstruktor eines MARD-Satzes prüft, ob es einen passenden MARC-Satz gibt. Gibt es den nicht, wird er erzeugt (bzw. die Erzeugung angestoßen). Das Objekt sorgt also selbst dafür, dass die für sich geltenden Voraussetzungen vorhanden sind. Das erzeugte MARC-Objekt prüft seinerseits, ob es ein passendes MARA-Objekt gibt, etc. Mit FORM-Routinen ginge das auch, aber deutlich aufwendiger (weil ich die Prüfung immer wieder selbst aufrufen muss - ich muss also selbst den Überblick behalten "eine Erzeugung eines MARD-Satzes zieht folgende Schritte nach sich", was ein Objekt mir abnimmt).

Das ist eine stark vereinfachte Darstellung, aber das Prinzip wird hoffentlich klar: Ich habe gekapselte Zuständigkeiten von verschiedenen Objekten, die miteinander "reden" und praktische Automatismen, die mir helfen -- wie heißt noch gleich das Unterprogramm, das beim Aufruf einer Funktionsgruppe automatisch durchlaufen wird und für die initiale Konsistenz der Funktionsgruppe sorgt?

Die Sichtweise auf ein Objekt als "Datencontainer mit Eigenintelligenz" zeigt, dass es durchaus Vorteile hat, in Objekten zu denken und zu handeln, wobei das nur eine Sichtweise ist (das hier ist eine andere). Ich muss für Konsistenzen eben nicht mehr selbst sorgen, sondern mache das einmal und von da an rufe ich das Objekt nur noch auf. Von den Vorteilen von Interfaces als quasi-unterschiedliche Identitäten eines Objektes hab ich da noch gar nicht angefangen, zu schwärmen.

Ja, das wird alles abstrakter und komplizierter. Autos sind heute auch komplizierter als früher, aber wollen wir deshalb alle den Trabbi zurückhaben? Der ist ganz niedlich, wenn man mal einen sieht, aber den Lärm, die Abgase und die Unsicherheit wollen wir nicht als Standard im Verkehrsgeschehen haben, wenn wir mal ein modernes Auto gefahren haben. Die sind indes technische Wunderwerke, die mit aufpassen, dass ich nicht zu nahe auffahre, nicht zu schnell fahre, nicht versehentlich die Spur verlasse, nicht den Blick von der Straße wenden muss, nicht zuviel Gas in der Kurve gebe, beim Bremsen die Lenkfähigkeit nicht verliere, beim Fahren nicht auf eine Karte gucken muss, etc. pp. Und dann haben die bei 250 noch ein deutlich besseres Bremsverhalten als ein Trabbi bei 80.

Im Übrigen haben wir es jeden Tag mit Objekten zu tun. Die Kaffeetasse (bekanntlich das erste, was ein Entwickler morgens anfasst und das letzte, was er nachts loslässt), ist nichts anderes als ein Objekt. Bei meiner Kaffeemaschine kümmere ich mich auch nicht darum, welche Bohnenmenge verwendet wird, wieviel Wasser die Maschine braucht, ob die Tasse nicht überläuft, etc. Das macht das Objekt "Kaffeemaschine" ganz von selbst. Ich (Objekt "Ralf" der Klasse "Durstiger") rufe mit meiner Methode RALF->KAFFEE_WILL( ) nur die Methode DE_LONGHI->KAFFEE_ERZEUGEN( ) der Kaffeemaschine auf, indem ich auf den entsprechenden Knopf drücke. Wie die Maschine intern dafür sorgt, dass ich auch Kaffee bekomme und der bestimmte qualitative und quantitative Eigenschaften hat, kümmert mich nur beim Kauf (quasi dem Implementieren der Klasse).



Ralf *schwärmt immer noch bei jeder Gelegenheit vom BMW i8

Folgende Benutzer bedankten sich beim Autor ralf.wenzel für den Beitrag (Insgesamt 3):
a-dead-trousersST224byte

Bild
Ralf Wenzel Heuristika SAP-Development
25 Jahre SAP-Entwickler • 20 Jahre Freiberufler
PublikationenUngarische NotationXing

Re: Kommunikation von Klassen und Methoden

Beitrag von 4byte (Specialist / 124 / 37 / 35 ) »
Ralf.Wenzel hat geschrieben:Übrigens hat das Beispiel mit dem LOOP mir gezeigt, wie sehr ich inzwischen anders denke.
PERFORM...
Prüfung
PERFORM....
Prüfung
Wenn man gewohnt ist, Methoden zu schreiben, IST die Methode die Prüfung.
Stimme ich zu. Kann man schön mit Exceptions machen :)
Ralf.Wenzel hat geschrieben:Fakt ist aber, und da muss ich einigen Leuten hier recht geben, dass viele prozedural geschriebene Programme grausig sind. 10.000 Zeilen Coding, davon LOOPs die über 2.000 Zeilen gehen, da fällt dann ein GC_X vom Himmel oder ein Flag in SY-LISEL (das dann gleich kontextabhängig für alle möglichen Flags verwendet wird; man spart sich ja das Deklarieren), das dann plötzlich die Verarbeitung signifikant beeinflusst. Je älter das Coding ist, umso grausiger ist es in aller Regel.
Haben wir hier auch. Dient für mich immer als Beispiel wie wichtig Strukur im Programm ist. Prozedual wie OO.
Ralf.Wenzel hat geschrieben:Interessant ist, dass ich mich viel weniger im Debugger bewege, seit ich streng OO programmiere. Bestenfalls gehe ich zu einer bestimmten Stelle, um mir Werte im Debugger anzusehen, aber das "Durchhoppeln" habe ich mir fast komplett abgewöhnt
Geht mir genauso. Dadurch das du weißt das der Rest funktioniert, kannst du direkt die Methode debuggen und kannst dir sicher sein, dass die auch beim mehrmaligen verwenden wieder richtig laufen wird :up:
Ralf.Wenzel hat geschrieben:Gerade die kritisierten vielen kleinen Methoden führen dazu, dass ich viel mehr auf Zusammenhänge achte als auf einzelne Anweisungen, denn Methoden decken quasi Gedankenschritte ab. Die o. g. Prüfmethode ist so ein Beispiel.
Verstehe ich nicht wieso das viele kritisieren. Das hat auch nichts speziell mit OO zu tun. Das kann doch genauso im Prozedualen genutzt werden. Ich "hasse" Methoden / Unterprogramme, die Eierlegende Wollmilchsau sind, da dann meistens nicht mehr erkennbar ist, was sie jetzt alles machen können/sollen. Ich gehe den Weg "Eine Funktionalität / Aufgabe = Eine Methode / Unterprogramm". Nicht mehr nicht weniger.

Und wir sind nicht mal auf das Thema Vererbung eingegangen :D Hab ich auch sehr zu schätzen gelernt, für mehrere Unterklassen nicht immer die selber Funktionalität zu programmieren zu müssen :)

Ich bin erst seit einem Jahr nach meinem Studium als ABAP Entwickler tätig. Dennoch ich mein persönliches Empfinden, dass OO einige Vorteile gegenüber der Prozedualen Progr. hat.

Grüße 4Byte

Folgende Benutzer bedankten sich beim Autor 4byte für den Beitrag:
ralf.wenzel

Es gibt 10 Menschen die binär verstehen :)

Re: Kommunikation von Klassen und Methoden

Beitrag von black_adept (Top Expert / 3943 / 105 / 886 ) »
ralf.wenzel hat geschrieben: Ich (Objekt "Ralf" der Klasse "Durstiger") rufe mit meiner Methode RALF->KAFFEE_WILL( ) nur die Methode DE_LONGHI->KAFFEE_ERZEUGEN( ) der Kaffeemaschine auf, indem ich auf den entsprechenden Knopf drücke. Wie die Maschine intern dafür sorgt, dass ich auch Kaffee bekomme und der bestimmte qualitative und quantitative Eigenschaften hat, kümmert mich nur beim Kauf (quasi dem Implementieren der Klasse).
Wie fängt man einen Elefanten?
OO-Programmierer bestehen darauf, dass der Elefant eine Klasse sei und somit schließlich seine Fangmethoden selbst mitzubringen habe. Und wenn der Elefant Afrika verlassen sollte, dann wird ja automatisch sein Destruktor ausgelöst.

Folgende Benutzer bedankten sich beim Autor black_adept für den Beitrag:
DeathAndPain

live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: Kommunikation von Klassen und Methoden

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
Prozedural-Programmierer jagen Elefanten, indem sie Algorithmus A ausführen:
1.) gehe nach Afrika
2.) beginne am Kap der guten Hoffnung
3.) durchkreuze Afrika von Süden nach Norden bidirektional in Ost-West-Richtung
4.) für jedes Durchkreuzen tue:
5.) fange jedes Tier, das du siehst
6.) vergleiche jedes gefangene Tier mit einem als Elefant bezeichneten Tier
7.) halte an bei Übereinstimmung

Ist das besser?

Der Witz bei einer Klasse ist, dass ich sie selbst programmiere und dann wirklich vorsehen kann, dass es eine Fangmethode gibt -- das geht bei einem realen Elefanten leider nicht.


Ralf
Bild
Ralf Wenzel Heuristika SAP-Development
25 Jahre SAP-Entwickler • 20 Jahre Freiberufler
PublikationenUngarische NotationXing

Vergleichbare Themen

7
Antw.
1374
Views
Kommunikation zwischen zwei Klassen
von abapnewbie » 30.08.2020 15:30 • Verfasst in ABAP Objects®
2
Antw.
3722
Views
Klassen und Methoden als Obsolet markieren
von SaskuAc » 01.02.2018 08:31 • Verfasst in Tips + Tricks & FAQs
8
Antw.
8179
Views
Architektur von Abap-Klassen (Klassen Attribute)
von snooze » 12.04.2005 12:56 • Verfasst in ABAP Objects®
20
Antw.
973
Views
Globale Klassen oder Lokale Klassen
von ZF_SAPler » 29.11.2022 13:47 • Verfasst in ABAP® für Anfänger
9
Antw.
4612
Views
Lokale Klassen in globalen Klassen
von ralf.wenzel » 20.04.2020 22:55 • Verfasst in ABAP Objects®

Newsletter Anmeldung

Keine Beiträge verpassen! Wöchentlich versenden wir lesenwerte Beiträge aus unserer Community.
Die letzte Ausgabe findest du hier.
Details zum Versandverfahren und zu Ihren Widerrufsmöglichkeiten findest du in unserer Datenschutzerklärung.

Unbeantwortete Forenbeiträge

Zwischensumme Adobe Forms
vor 3 Tagen von Lucyalison 1 / 71
Group Items auf einer Filterbar
vor einer Woche von Bright4.5 1 / 111
tRFC Transaktionen SM58
vor 4 Wochen von A6272 1 / 141