ABAP Clean Code

Alles rund um die Sprache ABAP®: Funktionsbausteine, Listen, ALV
68 Beiträge • Vorherige Seite 2 von 5 (current) Nächste
68 Beiträge Vorherige Seite 2 von 5 (current) Nächste

Re: ABAP Clean Code

Beitrag von SaskuAc (Specialist / 321 / 37 / 43 ) »
jocoder hat geschrieben:
08.05.2019 12:53
Um Variablendreher, ungewollte Verschattungen usw. zu finden, verwenden wir schließlich Unit Tests.
Eigentlich erübrigt sich jede weitere Diskussion mit diesem Argument. Mit ordentlich implementierten Unit-Tests sollten keine Fehler, insbesondere dieser Art, auftauchen.

Folgende Benutzer bedankten sich beim Autor SaskuAc für den Beitrag:
Thomas R.


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


Re: ABAP Clean Code

Beitrag von black_adept (Top Expert / 3944 / 105 / 886 ) »
jocoder hat geschrieben:
08.05.2019 12:53
Frage zurück:
Wenn wir das Codebeispiel mit der ungarischen Notation gestaltet hätten, wie kann dann mit der statischen Syntaxprüfung die falsche Verwendung der Variable ausgeschlossen werden?
Der Sinn der Unterroutine war die beiden Changing-Parameter aus den lokalen Variablen zu füllen. Für ein Gültigkeitspräfixing kenne ich die übliche Verwendung "g_" für global, "m_" für Gültigkeit in einer Klasse, "l_" für lokale Gültigkeiten. Eins der 3 Präfixe kann man sich schenken, wenn die anderen beiden nur konsequent durchgeführt werden und man für das 3. Präfix nur verbietet im Namensraum der beiden anderen zu sein. Z.B. könnte man lokale Variablen in der Bezeichnung fast frei wählbar lassen wenn man nur verbietet mit g_ oder m_ zu beginnen. Dies alles kann recht einfach mit der Standardauslieferung des Codeinspektors eingestellt werden.
Dadurch, dass bei den letzten beiden Zuweisungen in dem Fall der vollständigen Präfixierung ein l_ vor beiden Variablen gestanden hätte würde die Aktivierung fehlschlagen, da es keine Variable l_testvariable1 gibt sondern diese durch den Schreibfehler l_testvarablel heißt.
Trotzdem: Denkfehler kann das nicht verhindern - aber Schreibfehler.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: ABAP Clean Code

Beitrag von black_adept (Top Expert / 3944 / 105 / 886 ) »
SaskuAc hat geschrieben:
08.05.2019 13:40
Eigentlich erübrigt sich jede weitere Diskussion mit diesem Argument. Mit ordentlich implementierten Unit-Tests sollten keine Fehler, insbesondere dieser Art, auftauchen.
Irgend etwas an dieser Art Aussage kommt mir bekannt vor.
Bild

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

live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: ABAP Clean Code

Beitrag von Daniel (Specialist / 314 / 68 / 44 ) »
Also das System kompiliert jetzt ...

Wenn das so einfach wäre würde die SAP
sicher nicht so einen Müll ausliefern wie das
gerade im S/4 passiert !

Re: ABAP Clean Code

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
Also, zunächst einmal hat eine Variable in einer Routine einen bestimmten Kontext. Ich habe also eine Methode (oder Form-Routine), die zu einer LIFNR einen Namen ermittelt. Das brauche ich für den Rechnungsempfänger und den Warenempfänger. Dann sehen die Aufrufe so aus:

name_warenempf = get_name_from_lifnr( lifnr_warenemfp ).

name_rgempf = get_name_from_lifnr( lifnr_rgemfp ).

In der Methode heißt das Feld dann immer LIFNR.

Zweitens: In einer Unterroutine spricht man keine globalen Felder an. Das macht die Kapselung kaputt. Insofern ist die Verschattung richtig und gut, weil man nicht versehentlich die globalen Variablen anspricht.

Ich arbeite sehr gern mit me-> bzw. Klassennamen vor der Variable, wenn ich die der Klasse meine. Das "Umbenennen" mache ich per Suchen/Ersetzen binnen Sekunden (kommt auch so oft gar nicht vor).

Ganz ehrlich: Ich habe noch nie ein Problem gesehen, das durch HN gelöst werden würde. Per Mouseover kann ich jederzeit zu jedem Datenobjekt mehr Infos abrufen als ich in ein Präfix stecken kann.


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

Re: ABAP Clean Code

Beitrag von black_adept (Top Expert / 3944 / 105 / 886 ) »
ralf.wenzel hat geschrieben:
08.05.2019 17:05
name_warenempf = get_name_from_lifnr( lifnr_warenemfp ).
@Ralf: Ich mache das leider auch viel zu oft, aber diese Benamung gehört dem Entwickler um die Ohren gehauen.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: ABAP Clean Code

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
Die Namen sollen nur strukturell zeigen, was ich meinte. Dass die Feldnamen selbst Mist sind, ist klar, mir ist auf die Schnelle nichts Besseres eingefallen.

Mir ging es darum, dass die Aufrufer (weil sie einen anderen Kontext haben) unterschiedliche Feldnamen verwenden. Auch unterschiedlich zur eigentlichen Methode.


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

Re: ABAP Clean Code

Beitrag von DeathAndPain (Top Expert / 1795 / 213 / 396 ) »
Daniel hat geschrieben:
07.05.2019 18:00
This kind of prefixing is a relic from the early days of programming, when code was printed out and read on paper, and you didn't want to flip around just to find some variable's type. Modern development environments give easy access to data types, signatures, and object navigation, such that it is no longer needed to get readable code.

Kann man nicht oft genug wiederholen.
So sehr ich auch gegen die HN bin, halte ich diese Begründung dennoch für falsch. In meiner Jugendzeit habe ich viel Basic programmiert, auf dem C64, dem Schneider CPC, dem Amiga. In keinem Basic-Dialekt habe ich jemals HN gesehen.

Später habe ich in einer produktiven Umgebung Informix 4GL programmiert. Auch da gab es keine HN.

Wenn das nicht die "early days" sind, welche sind es dann? Konstrukte wie Klassen gab es damals ja noch gar nicht, also kann es auch keine etablierten HN-Notationen dafür gegeben haben.

Ich habe eher den Eindruck, dass HN sich als fehlgeleiteter Versuch entwickelt hat, die wachsende Abstraktheit moderner Programmiersprachen beherrschbar zu machen. Das ist ja das Interessante, das es im Bereich der technischen Entwicklung immer wieder gibt - dass zwei Paradigmen sich abwechseln und immer eine als die Weiterentwicklung der anderen dargestellt wird. Beispiel seriell/parallel: Der serielle Bus des C64 war, wie der Name schon sagt, seriell. Der C64 hatte aber auch einen (wenig genutzten) Parallelport, über den er viel schneller kommunizieren konnte. Dementsprechend kam bei Druckern auf dem PC der Parallelport, und Festplatten übertrugen über das IDE-Kabel parallel. Dann aber kam Serial ATA und war wesentlich schneller als IDE und EIDE.

Im Bereich der Programmiersprachen war in Maschinensprache (Assembler) die vom Programmierer geforderte Komplexität hoch, da er sich über jedes (immer wieder für andere Zwecke genutzte) Register und die Nummer der Speicherzelle jedes gespeicherten Datums Gedanken machen musste. Mit zunehmenden Hochsprachen wurde dies immer weiter abstrahiert; das Programmieren wurde bedeutend leichter. Irgendwann so leicht, dass man sogar die Meinung zu vertreten begann, die lachhafte Abstraktion der Kopfzeilen interner Tabellen sei den Programmierern nicht mehr zuzumuten.

Im Moment geht der Trend wieder in die andere Richtung. Es gibt Felder ohne Namen, die abstrakt irgendwo im Speicher liegen und von mehreren, unterschiedlich benamten "Referenzen" angesprochen werden. Es gibt Feldsymbole, die auf Werte irgendwelcher Tabellen verweisen, die sich mitändern, wenn man das Feldsymbol ändert. Es gibt Vererbungen und Verschattungen, die kaum mehr zu überblicken sind.

Ich bin gespannt, wann der Trend wieder in die andere Richtung geht.

Re: ABAP Clean Code

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
Es gibt einen erheblichen Unterschied zwischen der Komplexität im Abschnitt "Assembler" und dem letzten Absatz deines Beitrages.

Assembler brachte eine Komplexität mit sich, war also in sich komplex. Das führte zu vereinfachten Hochsprachen (die dann den Nachteil haben, dass z. B. mit Speicherplatz geradezu verschwenderisch umgegangen wird -- wenn man sich überlegt, was auf einem AMIGA alles schon ging an grafischer Komplexität....).

Inzwischen haben wir eine einfache Sprache (ABAP zu lernen, ist nun wirklich nicht schwierig), aber die umgesetzten Geschäftsprozesse sind zum Teil endlos kompliziert, die Zahl der Buchungen wächst ins Unermessliche. Aus beiden Gründen wäre es völlig illusorisch, einen SAP-Kunden "von Hand" auf T-Konten zu buchen.

Nun sind viele dieser Tätigkeiten aber (abstrakt betrachtet) einer gewissen Ähnlichkeit unterworfen. Praktisch jede DB-Selektion endet in einem SELECT und der hat immer denselben schematischen Aufbau. Was also liegt näher als ein (!) generischer SELECT, der von allen verwendet wird? So haben wir das und als es darum ging, Cluster-Tabellen zu integrieren, haben wir das tief in der Persistenzschicht gemacht, damit den Aufrufer gar nicht interessieren muss, ob die Daten aus einem Cluster kommen oder aus einer transparenten Tabelle. Der sagt (schematisch gesehen) nur

Code: Alles auswählen.

result = (table_instance)->read( selkrit ).
Und wenn ich das so zentral verbastele kann ich eben auch eine Funktion dazubasteln, die eine zweite DB-Verbindung aufmacht, die inzwischen recht intensiv verwendet wird.

Natürlich ist eine polymorphe Methode an sich schwierig lesbar, weil sie erst aus ihrem Kontext heraus "rund" ist (darum ist die Doku so wichtig). Aber ich kann eben sehr komplexe Zusammenhänge auf ihren kleinsten gemeinsamen Nenner herunterbrechen und sie gleich behandeln. Und sobald man etwas herunterbricht, wird die Formulierung abstrakt. Das weiß jeder, der öfters mal Gesetze liest oder Beipackzettel.

Es klingt auch schräg, wenn man in einer Methode erstmal feststellen muss, was für Importing-Parameter man überhaupt hat. In meinen SBAL-Logger kann man alles reinwerfen. log->add( xxx ), wobei xxx (type any) eine Message sein kann, ein BAPIRET oder BAPIRET2 als Struktur oder Tabelle, eine Ausnahme (die ggf. weitere Ausnahmen enthalten kann), etc. Es kommt immer korrekt ins Log, weil ich über RTTI identifiziere, was hab ich denn und fallweise sage "ein Feld vom Typ symsgid kommt im Log immer DA hin". Der Aufrufer hat *irgendeine* Meldung, die er ins Log schreiben will, die kippt der da rein und muss sich um nichts kümmern. Das führt natürlich zu einer gewissen Komplexität in meiner Methode, aber die habe ich nur einmal.

Jetzt der obligatorische Auto-Vergleich: Heutige Autos sind viel einfacher zu fahren als frühere -- das bezahlt man mit dem Preis, dass die Autos selbst viel komplexer sind. Man kann die Komplexität nur verschieben, nicht wegmachen. Aber da passt dann das Konzept der versteckten Implementierung ganz gut: Ich löse ein komplexes Problem, verpasse ihm eine gescheite Schnittstelle und eine Dokumentation und schon muss es mich (in der Regel) gar nicht mehr interessieren, wie dieses Problem gelöst wird. Ich muss nicht wissen, wie der Anlasser funktioniert, um ihn oder ein anderes Teil zu tauschen. Ich weiß, wo der Anlasser ist, wie er angeschlossen wird und wie er sich verhalten sollte, wenn er korrekt arbeitet. Wie er funktioniert, muss ich nur wissen, wenn ich den Anlasser selbst reparieren will.


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

Re: ABAP Clean Code

Beitrag von DeathAndPain (Top Expert / 1795 / 213 / 396 ) »
Ich habe ja nicht gesagt, dass es nicht legitim ist, die Sprache weiterzuentwickeln, um komplexere Sachverhalte damit abdecken zu können. Ich habe zunächst nur von einer Pendelbewegung gesprochen, bei der abwechselnd beide Seiten für sich beanspruchen, die fortschrittlichere zu sein. Und sie sind es auch, denn es ist eben kein statisches Pendel, sondern eher eine Spiralbewegung, die sich in einer dritten Dimension einem kollektiven Ziel nähert. Wie gesagt, bei dem Gegensatz serielle gegen parallele Schnittstelle ist es genauso.

Tatsächlich bin ich als Esoteriker überzeugt, dass der ganze Kosmos so funktioniert, aber da kommen wir in das Gebiet der Philosophie. :-)

Das von Dir angeführte Beispiel mit dem SELECT finde ich freilich nicht gut gewählt:
Nun sind viele dieser Tätigkeiten aber (abstrakt betrachtet) einer gewissen Ähnlichkeit unterworfen. Praktisch jede DB-Selektion endet in einem SELECT und der hat immer denselben schematischen Aufbau. Was also liegt näher als ein (!) generischer SELECT, der von allen verwendet wird?
Dann hast Du unterschiedliche Aufrufstellen. Ein SELECT ist ein Befehl. Ein Aufruf des gemeinsamen SELECTs ist ein Befehl. Du ersetzt also einen Befehl durch einen anderen, spart nichts, fügst aber eine Abstraktionsschicht hinzu, die die Sache unübersichtlicher macht. Da haste nichts gewonnen.

Deine übrigen Veranschaulichungen, etwa hinsichtlich des Loggings, kann ich hingegen durchaus nachvollziehen und stimme ihnen auch zu.

Re: ABAP Clean Code

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
DeathAndPain hat geschrieben:
20.05.2019 13:02
Dann hast Du unterschiedliche Aufrufstellen. Ein SELECT ist ein Befehl. Ein Aufruf des gemeinsamen SELECTs ist ein Befehl. Du ersetzt also einen Befehl durch einen anderen, spart nichts, fügst aber eine Abstraktionsschicht hinzu, die die Sache unübersichtlicher macht. Da haste nichts gewonnen.
Ich weiß, dass du kein Freund davon bist - ich habe die Vorteile einer einheitlichen Persistenzschicht kennengelernt und wurde davon überzeugt. Einen Vorteil habe ich genannt: Im Grunde interessiert mich das Medium nicht, auf dem Daten gespeichert sind, wenn ich auf Ebene der Geschäftsobjekte hantiere.


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

Re: ABAP Clean Code

Beitrag von DeathAndPain (Top Expert / 1795 / 213 / 396 ) »
Das ist beim SELECT nicht anders. Da interessiert mich auch nicht - und braucht mich auch nicht zu interessieren - ob da Oracle, Sybase, Informix oder HANA dahinterstecken. :-p

Re: ABAP Clean Code

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
Das ist falsch - hast du eine Clustertabelle, stehst du da mit deinem SELECT. Um mal nur *ein* Beispiel zu bringen.



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

Re: ABAP Clean Code

Beitrag von ewx (Top Expert / 4784 / 294 / 628 ) »
DeathAndPain hat geschrieben:
20.05.2019 13:02
Das von Dir angeführte Beispiel mit dem SELECT finde ich freilich nicht gut gewählt:
Nun sind viele dieser Tätigkeiten aber (abstrakt betrachtet) einer gewissen Ähnlichkeit unterworfen. Praktisch jede DB-Selektion endet in einem SELECT und der hat immer denselben schematischen Aufbau. Was also liegt näher als ein (!) generischer SELECT, der von allen verwendet wird?
Dann hast Du unterschiedliche Aufrufstellen. Ein SELECT ist ein Befehl. Ein Aufruf des gemeinsamen SELECTs ist ein Befehl. Du ersetzt also einen Befehl durch einen anderen, spart nichts, fügst aber eine Abstraktionsschicht hinzu, die die Sache unübersichtlicher macht. Da haste nichts gewonnen.
Doch, du gewinnst was. Nämlich die Möglichkeit, den SELECT durch einen festen Datensatz (oder Datensätze) für Unit-Tests zu ersetzen:
https://github.com/SAP/styleguides/blob ... st-doubles

Wundert mich, dass der Einwand nicht von dir gekommen ist, Ralf... ;)

Re: ABAP Clean Code

Beitrag von ralf.wenzel (Top Expert / 3776 / 176 / 262 ) »
Ja, du hast vollkommen recht, die Persistenzschicht bietet auch diese Möglichkeit.

Aber die Möglichkeit zum Mocking entsteht durch die Kapselung, nicht durch die Persistenzschicht (die zwar auch kapselt, aber in erster Linie abstrahiert). Sprich: Durch das Verschieben eines SELECT in eine Methode erhalte ich die Möglichkeit, ein Mocking zu implementieren. Das ist dann überhaupt nicht mehr abstrakt (und das Mehr an Abstraktion scheint ihn ja zu stören).

Das erhalte ich auch durch die Persistenzschicht, aber eher als Nebeneffekt. Der eigentliche Zweck ist es, eine einheitliche Schnittstelle (ZIF_PERSISTABLE oder so) zu implementieren, die jegliche Form der persistenten Datenspeicherung vereinheitlicht. Im Grunde genommen könnte ich auf diese Art und Weise sogar eine Datei auf einen Applikationsserver speichern mit derselben Anweisung, mit der ich Daten in eine Tabelle schreibe (die Parameter unterscheiden sich freilich und die ganze Implementierung).

Und auch wenn er immer wieder behauptet, einem SELECT sei egal, ob ein konventionelles oder ein HANA-System angesprochen wird, wird das auch durch Wiederholung nicht richtiger. Wer sowas sagt, der hat sich die Dokumentationen und Anleitungen der SAP zu HANA noch nicht angesehen.


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

Vergleichbare Themen

3
Antw.
2107
Views
Diskussionsthema: Clean Code
von c oco » 19.07.2017 14:19 • Verfasst in SAP - Allgemeines
4
Antw.
2792
Views
PAP aus ABAP-Code
von BesenWesen » 21.06.2006 09:49 • Verfasst in ABAP® Core
0
Antw.
1262
Views
ABAP-Code im Info-Set
von helwie » 22.09.2006 23:26 • Verfasst in ABAP® Core
0
Antw.
1532
Views
RSA-Algorithmus im ABAP-Code
von stefan76 » 05.10.2006 17:31 • Verfasst in ABAP® Core
1
Antw.
1514
Views
Testen von ABAP Code
von DavidHenn » 07.07.2011 10:27 • Verfasst in ABAP® Core

Aktuelle Forenbeiträge

PDF-Anzeige unter EDGE
vor 5 Tagen von jocoder 2 / 73

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.

Aktuelle Forenbeiträge

PDF-Anzeige unter EDGE
vor 5 Tagen von jocoder 2 / 73

Unbeantwortete Forenbeiträge

Zwischensumme Adobe Forms
vor 4 Wochen von Lucyalison 1 / 132
Group Items auf einer Filterbar
vor 4 Wochen von Bright4.5 1 / 166