Einsatz von Execptions

Wenn ich in einer Funktion einer Funktion eine Exception generiere, dann muss sie doch wie folgt aussehen, oder?

public void myfunc(List<ID> ids) throws IllegalArgumentException {
    	      if (ids == null || ids.size() == 0) throw new IllegalArgumentException("<mein Text>");
              ...    	      
       }

Zwei weitere Fragen, wo ich mir auch noch unsicher bin sind:

  1. Wenn ich die obige Funktion “myfunc” von einer anderen Funktion aufrufe, also in der Form
public void myfuncCall(List<ID> ids) /* throws IllegalArgumentException */ {
    	      myfunc(id);
       }

Muss ich der Funktion “myfuncCall” auch die Angabe “throws IllegalArgumentException” definieren?

  1. Wenn ich ein Interface habe, also z.B.
public interface myInterface {
         ...
         public void myfunc(List<ID> ids); /* throws IllegalArgumentException  (1. Beispiel) */ 
         ...
}

Muss ich dieser Funktion auch die throw - Anweisung mit angeben?

In Deinem Fall MUSST Du es nicht. Da Du hier unchecked Exceptions verwendest, kannst Du es überall weg lassen. Nur beim Werfen von checked Exceptions müsstest Du sie entweder mit try-catch behandeln oder einfach weiter werfen. Das müsste dann mit der throws Klausel auch an der entspr. Methode angezeigt werden.

Du KANNST die throws Klausel auch mit unchekced Exceptions verwenden. Das kann zu Dokumentationszwecken sinnvoll sein. Ich würde das aber eher sparsam einsetzen. In Deinem Beispiel, wo es um die Validierung von Parametern geht, würde ich es nicht machen.

auch bei der Implementation von myfunc selber (nicht nur bei 1. und 2.) throws-Angabe nicht zwingend

gilt für alle RuntimeExceptions, von der IllegalArgumentException erbt

[ot]Und nur als Anmerkung: Anstatt ids.size() == 0 besser ids.isEmpty() Immer schön mal einen Blick in die API Dokumentation werfen! ;-)[/ot]

[ot]Wobei ich persönlich das Prüfen der Argumente und das eventuelle manuelle Werfen einer Exception nicht so schön finde. Das würde ich maximal an einer Schnittstelle zu anderen Systemen machen.[/ot]

Und mMn sollte eine NPE geworfen werden, wenn ids null ist.

zu letztem Punkt gibt es ja breite Diskussionen,
um es nicht für sich stehen zu lassen werde ich einmal dagegen anreden,
aber zumindest von meiner Seite hoffentlich vermeiden, durch weitere Antworten den Thread allein darauf zu konzentrieren :wink:
(Antwort(en) aber erlaubt) :

wozu überhaupt eine IllegalArgumentException wenn ids leer, warum nicht auch dann eine NullPointerException?
weil eine IllegalArgumentException eine konkrete Aussage hat, die zumindest theoretisch gesondert geloggt werden könnte,
bei Auftreten während Tests sofort die Richtung vorgibt usw.

für eine NullPointerException gilt das nicht, deren Ursache ist für den Empfänger unklar, da kann es alle möglichen Probleme geben,
Komponente allgemein nicht richtig konfiguriert, Datei- oder DB-Fehler, schlicht Programmierfehler bei einer Sonder-Situation usw.

dazu das praktische Argument, nur eine einheitliche statt zwei Exceptions zu haben

und das Universalargument, dass, entgegen auch gewissen Java-API-Verwendungen, eine NullPointerException sich nach ihren Namen richten sollte,
genau bei einem null-Zugriff kommt und aus keinem anderen Grund, sollte NIE selber geworfen werden

wenn man Parameter bzw. Argumente gar nicht prüft und letztlich schlechtes Argument als Ursache für eine NullPointerException in einer Methode findet, ist das legitim,
Check gespart, mehr Mühe beim Suchen gehabt,
wenn man aber schon extra den Check macht, dann doch auch gleich konkrete Information werfen statt genauso nebulösen Fehler, der kaum hilft,
ob der Parameter null war oder z.B. leere Liste, kann man ja gleich mit in die Exception schreiben, als Text dahinter

fertig :wink:

Da stimme ich dir zu. Ergänzend (auch ohne eine lange Diskussion beginnen zu wollen) führe ich noch folgende Argumente für die NPE auf.
Ich schätze für Parametervalidierung guavas Preconditions oder für null-Checks auch Objects#requireNonNull() (seit Java 7).
Der Dokumentation von Objects#requireNonNull() entnimmt man:

Checks that the specified object reference is not null. This method is designed primarily for doing parameter validation in methods and constructors, as demonstrated below:public Foo(Bar bar) { this.bar = Objects.requireNonNull(bar); }

Alternativ kann man auch die requireNonNull-Varianten mit message-Argument verwenden, um deutlich zu machen, dass es sich um eine Parametervalidierung handelt und welcher Parameter gerade geprüft wurde.

Wie gesagte, würde ich die Prüfung im Ganzen nur selten machen. Bei einer Methode ‘findByIds(…)’ würde ich davon ausgehen, dass der Aufrufer mindestens eine Id übergibt. Da gäbe es bei mir kein Null- oder EmptyCheck. Wenn nun jemand Null übergibt, fliegt bei Zugriff halt eine NPE.

Solche Prüfungen sprecht häufig für unsauberen Code.

Nein, gerade das ist guter Stil. Erstens ist sauber dokumentiert welche Bedingungen die Argumente erfüllen müssen damit die Methode ausgeführt werden kann. Zweitens sind nicht nur Argumentprüfungen möglich sondern auch eine Prüfung auf den validen Zustand des Objekts selbst. Drittens, wenn im Code viele Probleme durch die Prüfung von Vor-/Nachbedingungen, Invarianten erkannt werden, können Unit-Tests oft einfacher gestaltet werden da elementare Fehler vom Code geprüft werden. Und viertens sorgt man so dafür dass das Objekt eben nicht in einen halbgaren Zustand gerät als mit einer NPE mitten drin. Lies dir zu den Themen Vor-/Nachbedingungen, Varianten, Invarianten mal ein paar Ideen von Bertrand Meyer durch und wie das z.B. in Eiffel umgesetzt ist.

Das sehe ich anders. Natürlich kann es auch Sinn haben, ein Objekt zu validieren, wenn es sich um eine komplexere Struktur handelt. Das sehe ich aber eher für externe Schnittstellen.

Zu erstens: Die Dokumentation sollte eigentlich aus der Signatur der Methode hervorgehen. Hält man sich hier an CleanCode ist eine zusätzliche Prüfung oft nicht notwendig und bläht nur den Code auf.

Zu zweitens: Klar kann es sinnvoll sein, ein Objekt inhaltlich zu validieren. Da habe ich auch keine Probleme mit. Ich bevorzuge allerdings eine validate-Methode, die dann extern verwendet werden kann.

Zu drittens: Ich verstehe nicht, wie sich eine solche Prüfung positiver auf einen Unittest auswirken sollte. Eine NPE in einem Unittest ist sehr schnell auffindbar und mit Hilfe des Stacktraces sollte das Auffinden des Fehlers kein Problem sein.

Zu viertens: Diesen “halbgaren Zustand” wird es hoffentlich nicht geben, da alles durch Tests geprüft ist. Wenn eine Methode von aussen erreichbar ist (z.B. über einen Websevice), dann sollte man natürlich sicherstellen, dass die Eingangsdaten konsistent sind. Aber innerhalb der Anwendung ist das mMn nicht notwendig.

ich will eigentlich auch keine weitere diskusion führen, aber gerne mal meine ansicht einbringen

  1. die verwendung von TO ist hier ein klares anzeichen für schlechten code, denn es wird versucht mit exceptions den programm-fluss zu steuern, was ja mal ein absolutes no-go ist
    besser wäre ein passender return-type sowie ein entsprechendes return anstatt eine exception zu werfen und diese dann in einem try-catch behandeln zu müssen

  2. abgesehen davon das man exceptions nicht zur programm-fluss-steuerung nutzt sind runtime-exceptions in der regel eh code-fehler da eigentlich alle durch entsprechende prüfungen vermeidbar sind
    NPE durch if(object==null), (A)IOOBE durch range-check, IAE/ISE durch korrekte input-/parameter-validation … etc
    darum ist es mir auch schleierhaft warum man eine runtime-exception überhaupt als throws angeben sollte … damite eine korrekte doc erzeugt wird ? schwachsinn … und dem compiler ist es auch egal

  3. die beiden ersten punkte ergeben natürlich den dritten : korrekte input-/parameter-prüfungen sind definitiv notwendig, jedoch sollte man statt exceptions entsprechende returns nutzen und diese dann im caller prüfen
    exceptions geben einen “störfall”/“fehler”/nicht definiertes verhalten" an und sollten auch nur dafür genutzt werden

zum code von TO

null und empty in einem if und dann mit IAE abschießen weil man void nutzt ?
autsch
wenn man eine methode hat von der man weis das diese mit dem inhalt einer liste irgendwas machen soll dann sollte man vorher sicherstellen das diese liste weder null noch leer ist
die prüfung auf NULL ergibt sich schon alleine daraus das man vorher ja irgendwas mit der liste machen muss, also vorher diese referenz schon mal in der hand hat bevor man überhaupt zum call der unter-methode kommt, wie hier überhaupt NULL ankommen kann wenn man doch vorher definitiv mindestens ein add() haben muss was schon eine NPE auslösen würde … eigentlich unbegreiflich
einzige erklärung : irgendwo die List als member definiert, aber den konstruktor-aufruf irgenwo in einen inneren bedingten block gepackt von dem nicht sichergestellt ist das dieser auch immer aufgerufen wird
korrekte lösung in dem fall : konstruktor-aufruf verschieben das dieser immer ausgeführt wird

auch recht merkwürdig ist die prüfung das überhaupt auf eine leere liste geprüft wird, denn es macht doch nur sinn eine methode auszuführen die mit der List was macht wenn in dieser überhaupt daten vorhanden sind
hier wäre dann als erklärung höchstens noch drin das halt der add()-call in irgend einem block sitzt der entweder nicht immer ausgeführt wird oder der halt ein leeres ergebnis liefern kann (z.b. wenn eine DB-abfrage keinen datensatz liefert)
hier sollte man dann schon eher beim add() prüfen (bzw direkt danach) ob der vorgang des “befüllens” überhaupt erfolgreich war und in der List auch mindestens ein datensatz enthalten ist

wie Sym schon schrieb : bei einer methode die was mit ner List und irgendwelchen IDs macht die in dieser enthalten sind, gehe ich eigentlich von aus der caller mir auch mindestens einen datensatz übergibt
wenn, warum auch immer, NULL übergeben wird liegt der fehler beim caller, und es fliegt halt eine NPE, und wenn die List leer ist ergibt halt der loop (was sollte man sonst groß sinnvoll machen) halt schlicht einach kein ergebnis und man hätte so (von “void” als return ausgehend) eben keinen merkbaren seiten-effekt der methode
trifft allerdings auch nur zu wenn man eine solche methode nach außen als public zur verfügung stellt
wenn man sowas nur intern private nutzt hat man noch an ganz anderen stellen im code einiges zu korrigieren

@TO
es gibt java keine funktionen, sondern nur methoden

[QUOTE=Sym]Das sehe ich anders. Natürlich kann es auch Sinn haben, ein Objekt zu validieren, wenn es sich um eine komplexere Struktur handelt. Das sehe ich aber eher für externe Schnittstellen.

Zu erstens: Die Dokumentation sollte eigentlich aus der Signatur der Methode hervorgehen. Hält man sich hier an CleanCode ist eine zusätzliche Prüfung oft nicht notwendig und bläht nur den Code auf.

Zu zweitens: Klar kann es sinnvoll sein, ein Objekt inhaltlich zu validieren. Da habe ich auch keine Probleme mit. Ich bevorzuge allerdings eine validate-Methode, die dann extern verwendet werden kann.

Zu drittens: Ich verstehe nicht, wie sich eine solche Prüfung positiver auf einen Unittest auswirken sollte. Eine NPE in einem Unittest ist sehr schnell auffindbar und mit Hilfe des Stacktraces sollte das Auffinden des Fehlers kein Problem sein.

Zu viertens: Diesen “halbgaren Zustand” wird es hoffentlich nicht geben, da alles durch Tests geprüft ist. Wenn eine Methode von aussen erreichbar ist (z.B. über einen Websevice), dann sollte man natürlich sicherstellen, dass die Eingangsdaten konsistent sind. Aber innerhalb der Anwendung ist das mMn nicht notwendig.[/QUOTE]

Jedes Objekt hat eine externe Schnittstelle, nämlich die public-Methoden. Diese Schnittstelle wird von einem Verwender benutzt, egal ob der Verwender eine andere Klasse, Funktion, Modul oder was auch immer ist.

Aus der Dokumentation geht genau die Signatur hervor jedoch nicht welcher Bedingungen erfüllt sein müssen damit die Methode aufgerufen werden darf. Falls man das in einen Kommentar darüber verfasst, sehe ich nicht den Unterschied dazu es gleich im Code zu verfassen, letzteres ist nicht fragil und die Einhaltung wird erzwungen.

Ein Objekt auf konsistenten Zustand zu überprüfen kann nicht nur sinnvoll sein, es ist sinnvoll, dass gehört zum Thema Klasseninvarianten. Klasseninvarianten helfen auch beim Thema Multithreading, da sich explizit Gedanken über die wait-queues und conditions gemacht werden muss und so besser über das Locking-Verhalten sinniert werden kann. Niemand hindert einen daran die validate-Methode zur Prüfung von Vor-/Nachbedingungen zu verwenden, so ist sichergestellt dass das Objekt nicht in einen inkonsistenten Zustand gerät.

Unit-Tests prüfen nur einen bestimmten Aspekt mit oft eingeschränkten, festgelegten Werten. Implementierte Bedingungen schützen zur Laufzeit. Unit-Tests und DbC-Methoden ergänzen sich übrigens. Und man “hofft” nicht das es einen halbgaren Zustand nicht geben wird sondern man baut Software so das es diesen nicht geben kann. Traurigerweise unterstützen extrem wenig Sprachen diese Möglichkeiten in der Sprache selbst, bekannte Sprachen mit nativer Unterstützung wären z.B. Ada, Eiffel und Clojure. Um in anderen Sprachen mit weniger Boilerplate zurechtzukommen müssen Drittanbieterbibliotheken her.

[quote=Unregistered]1) die verwendung von TO ist hier ein klares anzeichen für schlechten code, denn es wird versucht mit exceptions den programm-fluss zu steuern, was ja mal ein absolutes no-go ist
besser wäre ein passender return-type sowie ein entsprechendes return anstatt eine exception zu werfen und diese dann in einem try-catch behandeln zu müssen[/quote]
das sieht aber nach einer reichlich verstaubten Ansicht aus,
in einer Welt vor Exceptions wurde alles mit Rückgabewerten ausgedrückt, aber heute in Java?
wozu gibt es überhaupt die IllegalArgumentException in der API,
sollte die Methode (oder eher JEDE Methode) vielleicht noch allgemeines try/catch bauen und jede denkbare Exception in einen Rückgabewert umwandeln?

die zweite Ansicht im Posting, Checks wären ja überhaupt nicht nötig, Aufrufer ist selber schuld, ist eigentlich noch abenteuerlicher,
wobei dies immerhin komische return-Values verhindert, auf normale Exceptions zusteuert (vielleicht aber nicht immer, vielleicht passiert auch einfach gar nix…)

eine Methode wie Integer.parseInt() (schmeißt übrigens NumberFormatException (Unterklasse IllegalArgumentException) auch bei null, nicht NullPointerException)
wird an vielleicht 100 Stellen im Programm verwendet,
sollen alle diese Stellen mit Extra-Code zur Sicherheit auf einen bestimmten Rückgabewert schauen (abgesehen davon dass bei int kein Rückgabewert frei ist)
damit nicht womöglich falsche Zahl in Konto-Überweisung kommt usw?

nein, eine Exception ist immer die sorgenfreiere Variante,
sie bricht die aktuelle Aktion ab, was im Fehlerfall geboten ist,
Programmfluss-Steuerung, in der Tat, etwas ganz normales

ein try/catch ist eine gesicherte Stelle des Aufrufers für Logging, Konsequenzen bedenken, neu Zustand prüfen und evtl. Aktion (oder andere) neu versuchen

*** Edit ***

das wurde übrigens gerade erst gefragt in diesem Thread, man muss nicht alles von Geburt an wissen, kein Grund für Beleidigungen, schäme dich,
dieses Forum ist aber so frei dass alle es verkraften können wenn es stehen bleibt, muss nicht gelöscht werden

Es ist eine valide Möglichkeit nur ist die Unterstützung in Java dafür so nicht richtig vorhanden, in Scala z.B. könnte man das mit den Either oder Try erledigen, im Prinzip bekommt man bei letzerer Möglichkeit das Ergebnis gewrappt in ein Success oder einen Failure mit entsprechender Exception. So schlecht ist das nicht, da der Aufrufer direkt sehen kann das die Möglichkeit eines Fehlers besteht. Exceptions sind da wirklich eher nur für wirklich schlimme Sachen gedacht. Aber sowas in Java nachzubauen und das auch konsequent durchzuziehen und dann von allen Projektbeteiligten…das ist anstrengend.

(Obwohl ich das eigentlich als “unöflich” empfinde, meine so genannten “Two cents”, obwohl ich nicht alle anderen Antworten komplett gelesen habe: )

  1. Die geeignetste Lösung hängt vom Anwendungsfall ab. (Schwurbel…).

Es ist ein gewaltiger Unterschied zwischen einer public-Methode in einer public-Klasse/Interface, und einer private-Methode. Bei letzterer kann man mit solchen expliziten Tests deutlich sparsamer sein, weil man (bis zu einem gewissen Grad) davon ausgehen können muss, dass derjenige, der die Methode aufruft, weiß, was er dort tut. Eine public-Methode sollte im Idealfall immer die Vorbedingungen rigoros testen, im Sinne von Preconditions, wie sie ThreadPool schon angesprochen hat. (Es gibt wenigSTe Ausnahmen dafür, z.B. wenn Performance wirklich höchst kritisch und der Test vergleichsweise “aufwändig” ist).

  1. Dokumentation!!!1111einselfelf

Die Vorbedingungen, die erfüllt sein müssen, sollten in der JavaDoc der Methode erwähnt werden. Auch oder sogar gerade, wenn sie NICHT explizit überprüft werden - d.h. auch oder sogar gerade bei private methods.

/**
 * Does something with the IDs...
 *
 * @param ids The IDs
 * @throws IllegalArgumentException If the given list is <code>null</code>
 * or the list is empty
 */ 
public void myfunc(List<ID> ids) {
    if (ids == null) {
        throw new IllegalArgumentException("ids are null");
    }
    if (ids.isEmpty()) {
        throw new IllegalArgumentException("ids are empty");
    }
    process(ids);
}

/**
 * Does something with the first ID. This method assumes
 * that the given list is not <code>null</code> and contains
 * at least one element. 
 *
 * @param ids The IDs
 */
private void process(List<ID> ids) {
    ID id = ids.get(0);
    whatever(id);
}
  1. Man sollte sich überlegen, ob man “fail fast” will.

Es wurde erwähnt, dass z.B. eine NullPointerException eben fliegt wenn sie fliegt, und man das !=null deswegen nicht als Vorbedingung prüfen muss. Einerseits stimmt das zwar, aber in vielen Fällen ist es besser, diese Prüfung dort zu machen, wo der Fehler herkommt, statt auf den Stack trace zu vertrauen, der einem nur sagt, wo der Fehler auftritt.
Im speziellen: Wenn man einen setter aufruft, und an anderer Stelle davon ausgeht, dass das Objekt, das dort gesetzt wurde, nicht null ist, bringt einem die NullPointerException gerade mal gar nichts.

private Object object = defaultObject;

/** ... Object may never be null ... */
void setObject(Object object) {
    this.object = object;
}

void methodThatIsCalledFromSomewhere() {
    // Kein null-check...
    object.doSomething();
}

Dort fliegt zwar ggf. die NullPointerException, aber “welcher Id!ot” die setObject mit einem falschen Argument aufgerufen hat, erkennt man daran nicht.
Etwas allgemeiner: Man sollte sich immer peinlichst genau über den Zustandsraum seines Objektes im Klaren sein. Das heißt, dass man es bei allen Methoden, die den Zustandsraum direkt verändern (speziell bei settern oder Konstruktoren) mit den Prüfungen vielleicht etwas genauer nehmen sollte…

Für die Gewissenhaften
[spoiler]
Ich weiß tatsächlich von Projekten in “relativ professionellem (?)” Umfeld, wo große (!) Codeblöcke in

    ...
} catch (NullPointerException e) {}

eingewickelt wurden. Da läuft es einem echt mit 50Hz kalt den Rücken rauf und runter… :verzweifel:
[/spoiler]

Mit Java 8 ist auch ein “monadischer” Stil möglich, z.B. lässt sich Scalas Try fast(*) vollständig simulieren. Dabei hat die abstrakte Klasse Try<T> zwei Unterklassen Success<T> und Failure<T>, um das jeweilige Ergebnis zu wrappen - einen Wert im Erfolgsfall und eine Exception im Fehlerfall. Der Witz ist, dass man statt wie bei “fail fast” sofort zu reagieren mit diesen Werten bis zum Ende weiterrechnet (dabei eventuell sogar mehrere Try-Werte miteinander auf verschiedene Weisen miteinander kombiniert), und erst dann hineinschaut. Findet man einen Wert, ist alles in Ordnung, ansonsten findet man den ersten Fehler, der in der Berechnung aufgetreten ist. Ein Beispiel:

Try<String> string = getLineFromFile(...);
Try<String[]> splittedString = string.map(s -> s.split(",")).filter(array -> array.length == 3, () -> new IllegalArgumentException("3 Teile erwartet"));
Try<Integer[]> ints = splittedString.map(array -> { int[] ints = new int[3]; for(int i = 0;i<3;i++) ints** = Integer.parseInt(array**); return ints;});
Try<Boolean> isTriple = ints.map(ints -> int[0]*ints[0] + ints[1]*ints[1] == ints[2]*ints[2]);
if(isTriple.isSuccess()) {
   System.out.println("%d,%d und %d bilden %s pythagoräisches Tripel", ints.get()[0],ints.get()[1],ints.get()[2],isTriple().get() ? "ein":"kein");
} else {
   System.out.println("Ein Fehler ist aufgetreten: %s %s", isTriple().getException().getClass(), isTriple().getException().getMessage());
}

Das sieht wahrscheinlich erst einmal recht ungewöhnlich aus, aber wenn man sehr viele Fehlermöglichkeiten hat, und nicht viel tun kann, um sich von einem Fehler zu erholen, kann dieser Stil bequemer sein als das klassische Exception-Handling.

(*) “Fast”, weil die Fehlerbehandlung bei Lambdas einiges zu wünschen übrig lässt.

hoffentlich ist es in Scala schöner…

ein Stil a la

int k = ..;

hat sich von der ersten Programmiersprache an bewährt, findet sich überall, selbst bei PHP (! :wink: ) mehr oder weniger,
ich glaube nicht dass das je in weitläufiger Programmierung auszutauschen ist,
schon Boolean gegenüber primitiven Datentyp hats schwer

try/catch ist dagegen (jetzt bin ich mal so konservativ wie der Rückgabewert-Anonyme) auch schon eine neue Sache, aber wenigstens relativ modular,
ganze Methoden/ Klassen/ separate APIs können ohne es auskommen, wenn nur an wichtigen zentralen Programmstellen,
Programm schichtweise aufzubauen statt jede Codezeile zu infizieren/ dominieren

[QUOTE=Marco13]Es wurde erwähnt, dass z.B. eine NullPointerException eben fliegt wenn sie fliegt, und man das !=null deswegen nicht als Vorbedingung prüfen muss. Einerseits stimmt das zwar, aber in vielen Fällen ist es besser, diese Prüfung dort zu machen, wo der Fehler herkommt, statt auf den Stack trace zu vertrauen, der einem nur sagt, wo der Fehler auftritt.
Im speziellen: Wenn man einen setter aufruft, und an anderer Stelle davon ausgeht, dass das Objekt, das dort gesetzt wurde, nicht null ist, bringt einem die NullPointerException gerade mal gar nichts.[/QUOTE]
Zum einen finde ich, das Setter immer null zulassen sollten. Ich würde Methoden, die einen definierten Zustand erwarten immer anders benennen (zumindest solange es in Java noch keine Properties wie in C# gibt). Und Dein Beispiel ist wirklich unschön, weil ich die Methode auch ohne vorherigen Setter aufrufen könnte. Wenn das Objekt wirklich eine solch große Rolle spielt, gibt es andere (und wesentlich klarere) Konzepte, dies zu realisieren.

Wenn es für den Zustand wichtig ist, dann ist es natürlich sinnvoll, eine Prüfung am Anfang der Methode zu machen.

Beispiel Das Speichern eines Produktes:

in der Methode saveProduct(Product product) {} würde z.B. prüfen, ob das Produkt auch gespeichert werden kann und alle fachlichen (entsprechend auch technische) Bedingungen erfüllt sind. Ich würde aber nicht prüfen, ob das übergebene Produkt nicht null ist, denn davon würde ich ausgehen.

Konsistenzchecks sollten natürlich gemacht werden. Aber diese sind eher nicht die Regel (zumindest nicht bei dem, was ich kenne).

Es sollte nur ein suggestives Beispiel sein, und … ich hatte absichtlich private Object object = defaultObject; geschrieben. Das ganze kann sich auch auf „verstecktere“ Dinge beziehen, wie beim ursprünglichen „myfunc“-Beispiel mit dem „isEmpty“. Es ging ja wirklich nur um die generelle Idee, einen konsistenten Zustand sicherzustellen.