Java-Version/ Java-Sprache

was immer du mit diesen beiden Alternativen meinst, einen Unterschied kann ich dir da noch viel weniger nennen, und Bytecode ist das so ziemlich das Letzte, was von Belang ist,

Problem, soweit man das nennen könnte, als ein gefundenes Sandkorn im Getriebe genannt,
ist die falsch benannte Variable, und was sich daraus alles entwickeln könnte,

eine weitere kopierte Zwischen-Zeile wie für category üblich, für topic nicht unbedingt erwünscht,
mit gemeinsamen Interface wie für DB-Objekte, falls es mal eins geben sollte, und schwupps einen Bug eingeschleppt,
beim Überblicken der Zeilen nicht direkt auffällig

auf jeden Fall ein Leser erstmal verwirrt wieso hier category beteiligt ist usw.

wenn Verwendung von Klassen überarbeitet wird kann man nach Datentypen textuell suchen,
das ist in der Funktionalität mit Weglassen der Typen sowieso schon Geschichte,
wie auch Methoden-Suche mit Klammern bei mancher ::-Notation,

Variablennamen, soweit grob hilfreich, allgemeine Suche nach ‚topic‘, auch wenn natürlich nicht jeder Variablenname diesen Bestandteil hat, nun auch nicht mehr verläßlich,
‚topicService‘ rettet es noch ein wenig, das zumindest wird als Stelle gefunden


nicht vorhandene Informationen wie bei Methodenaufruf-Ketten
work(a.xy()) // Rückgabewert von xy?
sind eine Sache, da muss der Leser dann wenigstens nachschauen

wenn der Methodenname etwas dazu sagt, dann sollte das stimmen, sonst übel, aber untypisch

Code-Kommentare bei Aufrufern sind immer etwas bedenklich, gewisse Gefahr, nicht mehr aktuell zu sein

falsche Variablennamen können bös in die Irre führen, damit rechnet man am allerwenigsten

einer von hundert Nachteilen, der Funktionalität als Grundprinzip nicht wert ist :wink:

Na dass

public Reply createNewReply(ReplyCreateForm form, User user) {
    return topicService.getById(form.getTopicId())
            .map(topic -> createNewReply(topic, user, form.getContent()))
            .orElseThrow(() -> new DataIntegrityViolationException("Topic not found"));
}

prinzipiell äquivalent ist zu

public Reply createNewReply(ReplyCreateForm form, User user) {
    return topicService.getById(form.getTopicId())
            .map(new Function<Topic,Reply>(){
                       public Reply apply(Topic topic) {
                            return createNewReply(topic, user, form.getContent());
                       }
             }).orElseThrow(new Supplier<DataIntegrityViolationException>(){
                      public DataIntegrityViolationException get() {
                          return new DataIntegrityViolationException("Topic not found");
                      }
            }); 
}

Nur dass das natürlich niemand wirklich schreiben will.

Aber wie gesagt, ich glaube das bringt nichts. Ich erinnere mich an genau solche Diskussionen bei der Einführung von Generics, da gab es auch die „brauchen wir nicht, ist unübersichtlich, versteht keiner, geht auch ohne“-Fraktion. Du verbeißt dich hier in ein Beispiel, das ich ohne großes Nachdenken in einem privaten Projekt fix hingeschmiert habe, und das längst korrigiert ist. Kann ich mit deinem Code auch machen, wetten ich finde auch was zu mäkeln?

bestimmt ne Menge


auch auf die Gefahr hin zu nerven, notfalls einfach ignorieren:
ist eigentlich nicht Generics sowas wie Arbeit mit null während die mühevolle Alternative vorher Option entspricht? :wink:
genauso noch RuntimeException zu Checked Exception

schnell, sauber:

String name = u.getName(); // bei Fehler NullPointerException

...

User u = list.get(4); // bei Fehler ClassCastException

...

User u = userService.get(id); // Methode liefert User oder unsichtbaren Abbruch mit RuntimeException

umständlich an ifs/ catch und Code-Länge, eigene Fehlermeldungen:

Option<User> u = userService.get(id);
wie auch immer Folge-Code-Zeile u.getName();
orElseThrow(  eigene Exception);

...

Object o = list.get(4); 
if (o instanceof User) {
   String name = u.getName();
} else {
  throw eigene Exception;
}

.....

try {
   User u = userService.get(id); // Methode liefert User oder Checked Exception
   String name = u.getName(); 
} catch (irgendeine Exception) {
   // User nicht da, neue Exception werfen oder was auch immer
}

sowohl die Vor-Generics-Zeit als auch Checked Exceptions sind zurecht verpöhnt, aber der Option-Boilerplate code?..

[QUOTE=SlaterB]bestimmt ne Menge


auch auf die Gefahr hin zu nerven, notfalls einfach ignorieren:
ist eigentlich nicht Generics sowas wie Arbeit mit null während die mühevolle Alternative vorher Option entspricht? :wink:
genauso noch RuntimeException zu Checked Exception

schnell, sauber:

String name = u.getName(); // bei Fehler NullPointerException
```[/quote]

Das Problem ist, dass das nicht sofort passieren muss, sondern irgendwo im Code. Die als User getarnte Null kann inzwischen in einer Datenbank gelandet sein, oder als Argument in einem RPC verwendet werden. Houston macht einen Fehler, aber am Ende explodiert der Mars-Rover. Nicht cool.

Die Idee mit Optional ist **nicht**, es durch die ganze Codebasis zu schleifen, sondern auf die Stellen zu beschränken, wo User wirklich "leer" sein kann. Überall wo einfach User steht, sollte dann auch User drin sein und nicht null. Von einer höheren Warte aus gesehen geht es darum, den Typ unseres Wertes so genau wie möglich zu beschreiben, damit uns der Compiler so genau wie möglich über Probleme informiert. Wenn es schon ein Problem gibt, höre ich es lieber vom Compiler als von der Laufzeitumgebung. Null zu verwenden heißt, sich vor möglichen Problemen wegzuducken und zu hoffen, das alles gut geht und niemand seinen null-Check vergißt.

Ich verstehe auch nicht, was das besondere Problem mit map ist. Die Idee dahinter ist einfach, ein Foo<X> kontrolliert in ein Foo<Y> umzuwandeln, sei Foo nun ein Optional oder eine Liste oder ein Set (in Java 8 natürlich über den Umweg Stream, aber das hat ja "historische" Gründe). Generell will ich nicht auf Element-Ebene arbeiten, sondern den Wrapper als Ganzes behandeln. Ein Vorteil ist, dass Foo viel besser als ich weiß, wie es am besten umzuwandeln ist. Stell dir vor, Foo hält seine Daten in einem balancierten Baum. Wenn die Umwandlung wie üblich über eine for-Schleife (und damit ein verstecktes Iterable) realisiere, muss der originale Baum aufgedröselt und der der neue wieder - inklusive Balancierung - aufgebaut werden. Mit map unterliegt Foo solchen Beschränkungen nicht, es kann einfach direkt einen neuen Baum nach Vorlage des alten aufbauen. Das zeigt, dass der neue Stil nicht einfach nur neue Syntax ist, sondern ganz neue Möglichkeiten bietet.

Die Analogie beim zweiten Teil des Posts raffe ich ehrlich gesagt nicht. Ich versuche ja gerade ifs und trys und fors zu **vermeiden**, indem ich meine Daten in eine Art Schlauch, oder besser Verarbeitungspipeline packe, die ifs und trys und fors möglichst schon "eingebaut" hat (wobei man bei Optional natürlich mit den Beschränkungen der Java 8-Implementierung leben muss).

wenn null irgendwo durchkommt, auch in die DB ohne Constraint, dann ist der Wert vielleicht auch erlaubt,

oder ist neuerdings NOT NULL eine Standard-Constraint aller Attribute aller Tabellen?
wie sieht es dazu eigentlich im fJorum aus?

wie ich gerade sehe hat die ROOT-Category null als parent, wird sich das noch konzeptionell ändern oder akzeptabler null-Einsatz?

null-Checks braucht es an wichtigen Stellen, aber wenn man sie vergisst kracht es doch in der Regel unmittelbar,
wenn man dagegen ein orElseThrow() vergisst kann das ganz schön böse enden… :

vielleicht etwas konstruiertes Beispiel, bei dir noch meist Rückgabewerte dabei, die das verhindern

        return Optional.ofNullable(null);
    }

    public void doIt() {
        get().map(str -> createSomething(str)); // .orElseThrow(() -> new RuntimeException());
    }

    String createSomething(String st)  {
        System.out.println("important thing created: " + st);
        return "";
    }

unsichtbarer Bug: eine wichtige Aktion wird nicht ausgeführt, keine Fehlermeldung, vermeintlich normaler Erfolgsausgang

richtig schlimm wird Optional bei Dauereinsatz wie anfangs angedacht

Optional<FlashScope> flashScope = Optional.ofNullable(context.getFlashScope());

was praktisch überall auftrat,

aktuell zum Glück nicht, bei den Anlege-Stellen müsste alternativ auch geprüft werden,

wird sich zeigen wie es weitergeht in der Code-Breite,
etwa bei Verwendungen von Klassen wie Map, vorher 10 Dinge eingefügt, nachher diese 10 Dinge wieder benötigt,
nicht zu testen ob auch vorhanden, eine Zeile später sonst NullPointerException,
da kann man die Hälfe des Codes mit eigenen Exception vollschreiben oder auf guten Verlauf vertrauen


ich sehe übrigens erstaunlich viele Stellen a la

                findRole(ROLE.ROLE_OWNER.name()).
                orElseThrow(RuntimeException::new);
user.getRoles().add(owner_role);

gar keine große Mühe auf eine genaue Fehlermeldung, kein wichtiger Fehler, einfach nur generisches Äquivalent für eine NullPointerException,
mal abgesehen davon dass ansonsten vielleicht die null hinzugefügt werden würde,
Test hier nötig (besser aber eine Methode findRoleMandatory/ NotNull(), die bereits die Exception wirft, nicht an vielleicht bald zig-Codestellen mit orElseThrow() )

wie passt das eigentlich zum Thema
http://forum.byte-welt.net/java-forum-das-java-welt-kompetenz-zentrum-wir-wissen-und-helfen-/allgemeine-themen/16681-streitfrage-fachliche-exceptions.html
mit @Bleiglanz unerbittlicher Meinung, dass keinerlei eigene Exceptions für Fachlichkeiten wie nicht gefundene Objekte nötig sind,
alles auch über Rückgabewerte ginge, was ja auch hier sicher theoretisch möglich ist

planst du da noch Änderungen irgendwann oder stimmen wir mal überein, RuntimeExceptions überall zum Ausgangspunkt einer Aktion gute Sache? :wink:


falls du das Aktuelle dazu meinst, dann wären Listen & komplizierte Trees ja noch eine Sache, die es aber bisher kaum gibt,

aber die Verwendung nur für Optionals, als es noch da war
map(topic -> userService.getById(form.getUserId())
des zuvor geladenen optionalen Topic auf optionalen User ist wohl kaum ‚kontrollierte Umwandlung Foo in ein Foo‘,
sondern Aneinanderreihung getrennter unabhängiger Lade-Vorgänge

dafür die wichtige map()-Syntax zu nutzen, die komplizierte Listen, Abhängigkeit von X auf Y suggeriert, ist gefählich inflationär,
aber mit Option wohl kaum anders machbar wenn nicht wirklich häßlicher Code daraus werden soll, Zwickmühle, Nachteil

[QUOTE=SlaterB]wenn null irgendwo durchkommt, auch in die DB ohne Constraint, dann ist der Wert vielleicht auch erlaubt,

oder ist neuerdings NOT NULL eine Standard-Constraint aller Attribute aller Tabellen?
wie sieht es dazu eigentlich im fJorum aus?

wie ich gerade sehe hat die ROOT-Category null als parent, wird sich das noch konzeptionell ändern oder akzeptabler null-Einsatz?[/quote]

Was soll sonst als Parent angegeben werden? Ich hatte ursprünglich versucht, auf sich selbst zu referenzieren, aber das hat Hibernate gar nicht gern gesehen.

null-Checks braucht es an wichtigen Stellen, aber wenn man sie vergisst kracht es doch in der Regel unmittelbar,
wenn man dagegen ein orElseThrow() vergisst kann das ganz schön böse enden… :

Oh Mann, das ist doch gerade der Punkt: Du musst selbst etwas tun, um den Wert aus dem Optional herauszuholen. Und da hast du die Wahl, was du bei leerem Rückgabewert tust: selbst eine Exception werfen (orElseThrow), einen Defaultwert angeben (orElse, orElseGet), oder eine Exception riskieren, wenn du get verwendest (was du in meinem Code nicht finden wirst).

vielleicht etwas konstruiertes Beispiel, bei dir noch meist Rückgabewerte dabei, die das verhindern

        return Optional.ofNullable(null);
    }
public void doIt() {
    get().map(str -> createSomething(str)); // .orElseThrow(() -> new RuntimeException());
}
String createSomething(String st)  {
    System.out.println("important thing created: " + st);
    return "";
}
unsichtbarer Bug: eine wichtige Aktion wird nicht ausgeführt, keine Fehlermeldung, vermeintlich normaler Erfolgsausgang

Sehr konstruiert. map ist nicht dafür da, eine Aktion auszuführen, sondern einen Wert zu transformieren. Hier hättest du stattdessen die Möglichkeit, es mit ifPresent richtig zu machen (leider gibt es keine Variante, die eine Exception im „leeren“ Fall wirft)

richtig schlimm wird Optional bei Dauereinsatz wie anfangs angedacht

Optional<FlashScope> flashScope = Optional.ofNullable(context.getFlashScope());

was praktisch überall auftrat,

aktuell zum Glück nicht, bei den Anlege-Stellen müsste alternativ auch geprüft werden,

wird sich zeigen wie es weitergeht in der Code-Breite,
etwa bei Verwendungen von Klassen wie Map, vorher 10 Dinge eingefügt, nachher diese 10 Dinge wieder benötigt,
nicht zu testen ob auch vorhanden, eine Zeile später sonst NullPointerException,
da kann man die Hälfe des Codes mit eigenen Exception vollschreiben oder auf guten Verlauf vertrauen

Scala hat eine Map.getOpt Methode, die Option liefert. Habe bis jetzt noch keine Beschwerden gehört.

ich sehe übrigens erstaunlich viele Stellen a la

                findRole(ROLE.ROLE_OWNER.name()).
                orElseThrow(RuntimeException::new);
user.getRoles().add(owner_role);

gar keine große Mühe auf eine genaue Fehlermeldung, kein wichtiger Fehler, einfach nur generisches Äquivalent für eine NullPointerException,
mal abgesehen davon dass ansonsten vielleicht die null hinzugefügt werden würde,
Test hier nötig (besser aber eine Methode findRoleMandatory/ NotNull(), die bereits die Exception wirft, nicht an vielleicht bald zig-Codestellen mit orElseThrow() )

Wie ich schon schrub, ist das System mitten in der Entwicklung, und die Fehlerbehandlung noch ziemlich wirr bis nicht vorhanden. Ich muss erst einmal sehen, wo und wie ich die Fehler abfange, wie das Logging geschehen soll, ob das mit den FlashMessages so in Ordnung ist u.s.w. Das wird auf keinen Fall so bleiben, nur versuche ich vorrangig, etwas Vorzeigbares zu produzieren, bevor ich mich auf sowas konzentriere (Testing ist momentan genau so ein düsteres Kapitel).

wie passt das eigentlich zum Thema
http://forum.byte-welt.net/java-forum-das-java-welt-kompetenz-zentrum-wir-wissen-und-helfen-/allgemeine-themen/16681-streitfrage-fachliche-exceptions.html
mit @Bleiglanz unerbittlicher Meinung, dass keinerlei eigene Exceptions für Fachlichkeiten wie nicht gefundene Objekte nötig sind,
alles auch über Rückgabewerte ginge, was ja auch hier sicher theoretisch möglich ist

planst du da noch Änderungen irgendwann oder stimmen wir mal überein, RuntimeExceptions überall zum Ausgangspunkt einer Aktion gute Sache? :wink:

Exceptions sind nun einmal in vielen Frameworks vorgesehen, und fjorum nutzt Spring sehr weitreichend, also sehe ich das etwas pragmatisch. Prinzipiell hat Bleiglanz recht, es geht auch ohne (z.B. mit dem schon genannten Try aus try4j), aber ich glaube nicht, dass ich das für fjorum flächendeckend einsetzen werde.

falls du das Aktuelle dazu meinst, dann wären Listen & komplizierte Trees ja noch eine Sache, die es aber bisher kaum gibt,

aber die Verwendung nur für Optionals, als es noch da war
map(topic -> userService.getById(form.getUserId())
des zuvor geladenen optionalen Topic auf optionalen User ist wohl kaum ‚kontrollierte Umwandlung Foo in ein Foo‘,
sondern Aneinanderreihung getrennter unabhängiger Lade-Vorgänge

dafür die wichtige map()-Syntax zu nutzen, die komplizierte Listen, Abhängigkeit von X auf Y suggeriert, ist gefählich inflationär,
aber mit Option wohl kaum anders machbar wenn nicht wirklich häßlicher Code daraus werden soll, Zwickmühle, Nachteil

Ich verstehe deine Argumentation nicht. Optional ist ja im Prinzip eine Liste, nur mit einer Maximalkapazität von 1. Warum sollte es sich nicht so verhalten? Was ist daran „inflationär“?

Und natürlich gibt es eine Abgängigkeit von X und Y, du musst map ja eine Function<X,Y> liefern. Und map „suggeriert“ auch nichts, sondern verspricht etwas (nämlich dass Foo ein Funktor ist, und sich entsprechend verhält).

Nebenbei bemerkt könnte man für sowas

topicService.getById(form.getTopicId()).
    flatMap(topic -> userService.getById(form.getUserId()). 
           map(user -> createNewReply(topic, user, form.getContent()))).
    orElseThrow(() -> new DataIntegrityViolationException("Topic or user not found"));

auch eine Helper-Klasse schreiben (hatte ich schon), die es etwas symmetrischer und lesbarer macht (auch wenn es etwas „rückwärts“ aussieht):

Optionals.lift((topic, user) -> createNewReply(topic, user, form.getContent())).
    apply(topicService.getById(form.getTopicId()), userService.getById(form.getUserId())).
    orElseThrow(() -> new DataIntegrityViolationException("Topic or user not found"));

Dabei hätte lift den Typ BiFunction<Optional<A>, Optional<B>, Optional<C>> lift(BiFunction<A,B,C> fn).

ein Versuch mag es vielleicht sein, Erfolg aber nicht :wink:

was ist an
get().map(str -> createSomething(str));
strukturell anders als an
topicService.getById(form.getTopicId()).map(topic -> createNewReply(topic, user, form.getContent()))
?
deine Beispiele haben nur die (gewiss günstige) Hintertür, dass ein Rückgabewert zurückgegeben wird,
deswegen wird gemeckert wenn der else-Fall fehlt,
ohne Rückgabewert kann man den else-Fall, ob mit map oder ifPresent, gleich, einfach weglassen und bekommt den Mega-Bug,
rein auf vollständige Arbeit des Programmierers angewiesen,
mit null unsichtbarer Fehler praktisch strukturell unmöglich, es kracht vielleicht, aber das merkt man dann beim ersten Test


ich habe mir gerade mal einige Beispielseiten zu map und Optional angeschaut, deine Verwendung tauchte noch nirgendwo auf…

stringOrNot.map(s -> Integer.parseInt(s))
ist eine typisches map, das linke wird rechts verwendet um etwas neues zu erstellen, mit Listen sowieso klar,
mit Optional schlimm genug, aber zumindest eine echte Funktion

ein Unterschied zu
map(topic -> userService.getById(form.getUserId())
will dir da nicht auffallen?
das topic links hat mit dem Laden des Users rechts absolut gar nichts zu tun, wird einfach nur als lokale Variable angesammelt,
bis dann alle in dieser lustigen Notation geladen sind um sie gemeinsam zu verwenden?

gewiss auf eine bestimmte Weise geschickt, aber auch irgendwo als Referenz/ typisches map angegeben?
für Leser verwirrend verzerrtes Java, SELBST mit all diesen neumodischen Kram :wink:
eine Fremdnutzung von map()

Alternative wäre aber ja wie gesagt häßlich, man müsste Optional als Variable deklarieren usw.

[QUOTE=SlaterB]ein Versuch mag es vielleicht sein, Erfolg aber nicht :wink:

was ist an
get().map(str -> createSomething(str));
strukturell anders als an
topicService.getById(form.getTopicId()).map(topic -> createNewReply(topic, user, form.getContent()))
?
deine Beispiele haben nur die (gewiss günstige) Hintertür, dass ein Rückgabewert zurückgegeben wird,
deswegen wird gemeckert wenn der else-Fall fehlt,
ohne Rückgabewert kann man den else-Fall, ob mit map oder ifPresent, gleich, einfach weglassen und bekommt den Mega-Bug,
rein auf vollständige Arbeit des Programmierers angewiesen,
mit null unsichtbarer Fehler praktisch strukturell unmöglich, es kracht vielleicht, aber das merkt man dann beim ersten Test
[/quote]

Das ist keine „Hintertür“, das sollte der Normalfall sein. Wie du vielleicht weißt, sollten bei funktionaler Programmierung Seiteneffekte möglichst vermieden werden. OK, das ist in Java nicht immer möglich, trotzdem ist in deinem Beispiel schon einmal nicht koscher, dass der Rückgabewert von createNewReply nicht verwendet wird (und Tools wie FindBugs kreiden das auch an).

ich habe mir gerade mal einige Beispielseiten zu map und Optional angeschaut, deine Verwendung tauchte noch nirgendwo auf…

stringOrNot.map(s -> Integer.parseInt(s))
ist eine typisches map, das linke wird rechts verwendet um etwas neues zu erstellen, mit Listen sowieso klar,
mit Optional schlimm genug, aber zumindest eine echte Funktion

ein Unterschied zu
map(topic -> userService.getById(form.getUserId())
will dir da nicht auffallen?

Willst du mich veralbern? Das komplette Lambda lautet topic -> userService.getById(form.getUserId()).map(user -> createNewReply(topic, user, form.getContent())), und da taucht topic sehr wohl auf der rechten Seite auf, genauso wie in deinem ersten Beispiel. Aber ganz ehrlich, ich fange jetzt hier keinen Lamba-Lernkurs an, vor allem nicht für jemanden, der davon gar nichts wissen will.

auch keine Zeit ein offizielles Beispiel/ irgendeinen Link dazu zu posten (irgendwie lande ich immer dort :wink: )

„If a value is present, apply the provided mapping function to it,“ steht in der API zu Optional.map,
nicht ‚lade was völlig anderes, ignoriere den Wert links, abgesehen davon dass er nicht null ist‘

.map(name -> new FileInputStream(name)) dort ist mal wieder ein Beispiel wo der Wert links rechts genutzt wird

edit: wenn man das zweite map als inneres nimmt dann mag es hinkommen, Klammern zählen also, Einrückung hilft nicht mit…, schöner Code…

Die Einrückung habe ich ja gemacht, um zu verdeutlichen, dass das innere map eben nicht Top-Level ist.

        return topicService.getById(form.getTopicId())
                .<Reply>map(topic-> userService.getById(form.getUserId())
                        .map(user -> createNewReply(topic, user, form.getContent()))
                        .orElseThrow(() -> new DataIntegrityViolationException("User not found")))
                .orElseThrow(() -> new DataIntegrityViolationException("Topic not found"));
    }

das .orElseThrow(() in Zeile 5 bezieht sich auf das gesamte Map in Zeile 4 davor, nicht nur den Teil nach -> ,
das .map() in Zeile 4 bezieht sich aber weder auf das vorherige ganze map noch zumindest auf den ganzen inneren Teil von Zeile 3, sondern nur dem Teil nach -> …
das findest du übersichtlich?

sieht eher nach

    {
        return topicService.getById(form.getTopicId())
                           .<Reply>map(longlonglonglonglonglonglongMethode()
                                   .longlonglonglonglonglonglongMethode2()
                                   .longlonglonglonglonglonglongMethode3())
                           .orElseThrow(() -> new DataIntegrityViolationException("Topic not found"));
    }

aus, die (eine) automatische Formatierung

    {
        return topicService.getById(form.getTopicId())
                           .<Reply>map(category -> userService.getById(form.getUserId())
                                                              .map(user -> createNewReply(category, user, form.getContent()))
                                                              .orElseThrow(() -> new DataIntegrityViolationException(
                                                                                                                     "User not found")))
                           .orElseThrow(() -> new DataIntegrityViolationException("Topic not found"));
    }

ist deutlicher, aber so natürlich kaum durchzuhalten


einzelne übersichtliche Code-Zeilen mit Semikolon,
wenig Methoden-Parametern für kurze Aufrufe,
maximal noch Aufrufketten oder Builder-Pattern mit im Wesentlichen linearen Verlauf,
ansonsten klare if/ else/ Schleife-Strukturen,
auch dieses Java-Grundprinzip dem Fortschritt zu opfern?

wahrscheinlich als Standardlösung nochmal kürzere Methoden,
immer nur einen Parameter laden und die nächste aufrufen…