Die Signatur einer Methode ist das, was der Aufrufer sieht, bevor er sich fĂŒr sie entscheidet. Alles, was sie verschweigt, wird spĂ€ter zum Fehler.
Die Anzahl
Als grobe Staffel: keiner ist ideal, einer ist normal, zwei sind hÀufig, drei sind eine Frage wert, ab vier lohnt ein Parameterobjekt.
Der Grund ist nicht Ăsthetik, sondern die Aufrufstelle:
ErstelleRechnung(42, 17, true, false, null, 3, "EUR");
// Was ist 17? Was bedeutet das zweite false?Zwei Auswege. Benannte Argumente kosten nichts und wirken sofort:
ErstelleRechnung(
kundenId: 42,
zahlungsfristTage: 17,
mitMehrwertsteuer: true,
alsEntwurf: false,
rabattgruppe: null,
mahnstufe: 3,
waehrung: "EUR");Ein Parameterobjekt ist die stĂ€rkere Lösung, sobald die Werte zusammengehören â und das tun sie meistens, sonst stĂŒnden sie nicht in derselben Signatur:
public sealed record Rechnungsauftrag(
int KundenId,
int ZahlungsfristTage,
bool MitMehrwertsteuer,
string Waehrung);
ErstelleRechnung(auftrag);Der Boolean-Parameter
Ein bool in einer Signatur heisst fast immer: Diese Methode tut zwei Dinge, und der Aufrufer sucht sich eines aus.
Schalter
public void Speichere(
Kunde kunde, bool alsEntwurf)
{
if (alsEntwurf) { ⊠}
else { ⊠}
}
// Aufrufstelle:
Speichere(kunde, true);
// true was?Zwei Methoden
public void SpeichereEntwurf(Kunde k)
public void Veroeffentliche(Kunde k)
// Aufrufstelle:
SpeichereEntwurf(kunde);Rechts steht an der Aufrufstelle, was passiert. Und keine der beiden Methoden enthĂ€lt mehr ein if ĂŒber den Modus.
Wann ein `bool`-Parameter in Ordnung ist
Wenn er eine echte Eigenschaft der Daten beschreibt und nicht den Modus der Methode: Sortiere(absteigend: true) ist vertretbar â beide FĂ€lle machen dasselbe, nur in anderer Richtung. Ein benanntes Argument macht es an der Aufrufstelle vollends klar.
Nebenwirkungen, die in der Signatur fehlen
Der teuerste Fall: Die Methode tut etwas, das ihr Name nicht andeutet.
public bool PruefePasswort(string benutzer, string passwort)
{
var konto = _konten.Finde(benutzer);
if (konto.PasswortHash == Hash(passwort))
{
Sitzung.Initialisiere(konto); // â startet nebenbei eine Sitzung
return true;
}
return false;
}Wer PruefePasswort in einem Batchlauf aufruft, um Konten zu validieren, startet dabei Sitzungen. Das ist kein hypothetisches Problem â es ist eines der klassischen Beispiele aus Clean Code, weil es so oft vorkommt.
Die Leitplanke dafĂŒr heisst Command-Query-Separation:
Eine Methode beantwortet eine Frage oder verĂ€ndert etwas â nicht beides.
bool PruefePasswort(...) beantwortet eine Frage und darf nichts verĂ€ndern. void MeldeAn(...) verĂ€ndert etwas und gibt nichts zurĂŒck. Wo beides zusammenfĂ€llt, ist der RĂŒckgabewert typischerweise eine Quittung (Sitzung MeldeAn(...)) â und der Name sagt, dass etwas geschieht.
`out`-Parameter
out ist im TryâŠ-Muster etabliert (int.TryParse, Dictionary.TryGetValue) und dort völlig in Ordnung. Ausserhalb davon ist ein out-Parameter fast immer ein zweiter RĂŒckgabewert â und den drĂŒckt ein Tupel oder ein record besser aus, weil er einen Namen bekommt und sich weiterreichen lĂ€sst.