Abschnitt 5 · Lektion 8
Synthese: der Werkzeugkasten
Der Abschluss dieses Abschnitts hat kein neues Sprachmittel. Es geht darum, wann man eine Funktion baut und wo man den Schnitt setzt, und das ist eine Frage der Übung, nicht der Syntax.
Erst schneiden, dann tippen
<h1>Ausgabe</h1>
<p>Was dieses Beispiel tut, steht in der Console.</p> // Alles in einem Stück. Läuft, und beim Suchen eines Fehlers muss
// man jede Zeile lesen, um zu wissen, wo man ist.
function zeileAmStueck(titel, nettoInCent) {
const brutto = Math.ceil(nettoInCent + (nettoInCent * 19) / 100);
const euro = Math.floor(brutto / 100);
const rest = String(brutto % 100).padStart(2, "0");
return `${titel}: ${euro},${rest} Euro`;
}
console.log(zeileAmStueck("Kurs", 10000));
// Dieselbe Rechnung, in Stücke geschnitten. Jedes Stück hat einen
// Namen, und jedes lässt sich einzeln ausprobieren.
function prozentVon(betrag, prozent) {
return (betrag * prozent) / 100;
}
function bruttoPreis(netto) {
return Math.ceil(netto + prozentVon(netto, 19));
}
function formatPreis(cent) {
const euro = Math.floor(cent / 100);
const rest = String(cent % 100).padStart(2, "0");
return `${euro},${rest} Euro`;
}
function rechnungszeile(titel, nettoInCent) {
return `${titel}: ${formatPreis(bruttoPreis(nettoInCent))}`;
}
console.log(rechnungszeile("Kurs", 10000));
// Und der eigentliche Gewinn: die Teile sind einzeln prüfbar.
console.log(prozentVon(200, 19), bruttoPreis(100), formatPreis(11990)); Beide Fassungen im Beispiel liefern dasselbe. Die erste ist kürzer, die zweite ist besser, und der Unterschied zeigt sich an drei Stellen.
Beim Lesen: In der zerlegten Fassung sagt jeder Name, was an dieser Stelle passiert. Man muss die Rechnung nicht mehr nachvollziehen, um zu wissen, was sie tut.
Beim Suchen eines Fehlers: Ist die Ausgabe krumm, kannst du jedes Stück einzeln aufrufen und siehst sofort, welches davon falsch rechnet. Im Block am Stück bleibt nur, die Zeilen durchzugehen.
Beim Wiederverwenden: formatPreis brauchst du an fünf anderen Stellen auch. Im Block am Stück steckt sie fest.
Die Regel dahinter: eine Funktion, ein Job, ein Name, der ihn nennt. Und der Weg dorthin führt über das Schneiden vor dem Tippen. Schreib die Zwischenschritte hin, bevor du eine Zeile Code schreibst, so wie du in Lektion 2.8 den Kassenzettel geplant hast, bevor du ihn gerechnet hast.
Funktionen benutzen Funktionen
<h1>Ausgabe</h1>
<p>Was dieses Beispiel tut, steht in der Console.</p> function aufrunden(zahl, stellen) {
const faktor = 10 ** stellen;
return Math.ceil(zahl * faktor) / faktor;
}
function prozentVon(betrag, prozent) {
return (betrag * prozent) / 100;
}
// Diese hier rechnet selbst fast nichts. Sie setzt zusammen.
function bruttoPreis(netto) {
return aufrunden(netto + prozentVon(netto, 19), 0);
}
console.log("Basiswerkzeug:", aufrunden(4.201, 2), prozentVon(200, 19));
console.log("Zusammengesetzt:", bruttoPreis(100), bruttoPreis(1999));
// Der Gewinn zeigt sich beim Ändern. Wird aus 19 Prozent einmal
// ein anderer Satz, steht die Zahl an genau einer Stelle. Sobald die Stücke da sind, setzt du sie zusammen. Eine Funktion darf jede andere aufrufen, und die meisten Funktionen in echtem Code tun genau das: Sie rechnen selbst fast nichts und ordnen nur an, was in welcher Reihenfolge passiert.
bruttoPreis ist so eine. Sie enthält keine einzige eigene Rechnung, sie kombiniert zwei vorhandene. Und das ist kein Umweg, sondern der Punkt: Ändert sich der Steuersatz, steht die Zahl an genau einer Stelle.
Das ist dieselbe Überlegung wie bei der Trennlinie in Lektion 5.1, nur eine Stufe größer. Was einmal dasteht, ändert man einmal.
Eine gute Signatur
<h1>Ausgabe</h1>
<p>Was dieses Beispiel tut, steht in der Console.</p> // Sechs Parameter, und beim Aufruf weiß niemand mehr, welcher
// welcher ist. Zwei davon sind Wahrheitswerte, und die sind am
// Aufruf überhaupt nicht mehr zu lesen.
function zeileLang(titel, netto, satz, waehrung, fett, gerahmt) {
return `${titel} ${netto} ${satz} ${waehrung} ${fett} ${gerahmt}`;
}
console.log(zeileLang("Kurs", 10000, 19, "Euro", true, false));
// Wenige Parameter, klare Reihenfolge, Standardwerte hinten.
// Der Aufruf ist danach im Normalfall kurz.
function zeileKurz(titel, nettoInCent, satz = 19) {
return `${titel}: ${nettoInCent} Cent plus ${satz} Prozent`;
}
console.log(zeileKurz("Kurs", 10000));
console.log(zeileKurz("Buch", 2000, 7)); Die Signatur ist das, was beim Aufruf sichtbar ist, und deshalb entscheidet sie darüber, ob eine Funktion angenehm zu benutzen ist.
Wenige Parameter. Bis drei liest sich ein Aufruf noch. Ab vier fängt das Zählen an, und spätestens dort lohnt die Frage, ob die Funktion nicht zwei Aufgaben auf einmal erledigt.
Klare Reihenfolge. Das Wichtigste zuerst, Zusammengehörendes nebeneinander. Wer rechnungszeile(titel, betrag) liest, muss nicht nachschlagen.
Standardwerte hinten. Damit ist der Normalfall der kürzeste Aufruf, und das ist genau richtig herum.
Besonders unangenehm sind Wahrheitswerte als Argument. zeileLang("Kurs", 10000, 19, "Euro", true, false) sagt niemandem, was true und false dort bedeuten. In Abschnitt 7 siehst du den üblichen Ausweg: ein Objekt mit benannten Eigenschaften statt einer langen Reihe.
Das Warnzeichen heisst „und”
<h1>Ausgabe</h1>
<p>Was dieses Beispiel tut, steht in der Console.</p> // Der Name nennt zwei Dinge, und das "und" ist das Warnzeichen.
function pruefeUndGibAus(preis) {
if (preis <= 0) {
console.log("Ungültiger Preis");
return false;
}
console.log(`Preis: ${preis} Euro`);
return true;
}
pruefeUndGibAus(50);
pruefeUndGibAus(-1);
// Getrennt: die eine entscheidet, die andere schreibt. Die
// entscheidende ist danach überall wiederverwendbar, auch dort,
// wo gar nichts ausgegeben wird.
function istGueltigerPreis(preis) {
return preis > 0;
}
function zeigePreis(preis) {
console.log(istGueltigerPreis(preis) ? `Preis: ${preis} Euro` : "Ungültiger Preis");
}
zeigePreis(50);
zeigePreis(-1);
console.log("Nur die Prüfung, ohne Ausgabe:", istGueltigerPreis(50)); Der einfachste Test, ob ein Schnitt sitzt: Beschreib die Funktion in einem Satz. Brauchst du dafür ein „und”, sind es zwei Funktionen.
pruefeUndGibAus trägt das Warnzeichen sogar im Namen. Sie entscheidet etwas und schreibt etwas. Beides ist für sich nützlich, zusammen ist es unbrauchbar: Wer nur prüfen will, bekommt eine Ausgabe dazu, die er nicht bestellt hat.
Getrennt sieht es anders aus. istGueltigerPreis ist danach überall einsetzbar, auch in einem if, auch in einer Prüfung ohne jede Ausgabe. Und zeigePreis ist eine Zeile lang.
In der Challenge baust du fünf solcher Stücke, und zwei davon setzen die anderen zusammen.
Zum Mitnehmen
Eine Funktion, ein Job, ein Name, der ihn nennt. Was du nicht in einem Satz beschreiben kannst, sind zwei Funktionen.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
Was in dieser Lektion steckt
-
Artikel mit 4 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe im Editor, direkt im Browser geprüft
Öffnet sich mit dem Basis Konto.