Aufgeräumt, und plötzlich andere Zahlen
Refactoring heißt, Code umzubauen, ohne dass sich sein Verhalten ändert. Ein Assistent kann das in Sekunden, und das Ergebnis sieht oft aufgeräumter aus.
Aufgeräumt heißt aber nicht gleich. Diese Lektion zeigt, wie Sie um einen Umbau bitten und mit einem Vorher-Nachher-Vergleich beweisen, dass dieselben Eingaben dieselben Ausgaben ergeben.
Am Ende dieser Lektion
Notiz
Ich kann einen Assistenten um einen Umbau bitten und mit einem Vorher-Nachher-Vergleich beweisen, dass sich das Verhalten nicht geändert hat.
Schlüsselwörter
| Begriff | Was er bedeutet |
|---|---|
| Refactoring | Code umbauen, ohne sein Verhalten zu ändern |
| Verhalten | welche Ausgabe zu welcher Eingabe gehört |
| Vorher-Nachher-Vergleich | dieselben Eingaben auf alter und neuer Fassung |
| Kleiner Schritt | eine Änderung, die Sie in einer Minute lesen können |
| Diff | die Liste dessen, was sich zwischen zwei Fassungen geändert hat |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Bitten Sie um kleine Schritte
Ein Assistent baut gern viel auf einmal um. Dann können Sie die Änderung nicht mehr lesen und nicht mehr beurteilen. Bitten Sie deshalb um einen kleinen Schritt, zum Beispiel: Ziehe die Verdopplung in eine eigene Funktion, sonst nichts.
Sagen Sie dazu, was gleich bleiben muss: Zahlen, Texte und Bedingungen. Ein Umbau ist ein Diff, in dem sich Code nur bewegt.
Erst das Verhalten festhalten, dann umbauen
Bevor etwas umgebaut wird, brauchen Sie einen Maßstab. Halten Sie fest, was der alte Code für viele Eingaben ausgibt, vor allem an den Rändern. Das ist der Vorher-Nachher-Vergleich.
Nach dem Umbau lassen Sie dieselben Eingaben auf der neuen Fassung laufen. Jeder Unterschied ist eine Verhaltensänderung, auch wenn der Code besser aussieht.
Eine mögliche Anfrage an den Assistenten
So könnte eine Anfrage lauten: „Baue punkte(cent) um, sodass der Faktor 2 nur an einer Stelle steht. Ändere keine Zahl und keine Bedingung. Nenne mir jede Zeile, die sich nicht nur bewegt hat.“
Was zurückkommt, ist jedes Mal anders. Verlassen Sie sich nicht auf die Zusicherung, nichts habe sich geändert. Beweisen Sie es mit dem Vergleich.
Zwei Fassungen vergleichen
Die Runs unten schreiben in einen Ordner demo-umbau/ den alten Code, eine sauber umgebaute Fassung, eine zweite, die gleich aussieht, und ein kleines Vergleichsskript. Alle Fassungen sind von Hand geschrieben und keine Antworten eines Assistenten.
Der Code berechnet Bonuspunkte: ein Punkt je volle 50 Cent, ab 1000 Cent doppelt.
Den alten Code schreiben
docker exec -w /home/node/project agent sh -c "mkdir -p demo-umbau && printf '%s\n' '// Punkte fuer einen Einkauf: 1 Punkt je volle 50 Cent, ab 1000 Cent doppelt.' 'function punkte(cent) {' ' if (cent >= 1000) {' ' return Math.floor(cent / 50) * 2;' ' }' ' return Math.floor(cent / 50);' '}' 'module.exports = { punkte };' > demo-umbau/vorher.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die umgebaute Fassung schreiben
docker exec -w /home/node/project agent sh -c "mkdir -p demo-umbau && printf '%s\n' '// Gleiche Rechnung, der Faktor steht jetzt an einer Stelle.' 'function faktor(cent) {' ' return cent >= 1000 ? 2 : 1;' '}' 'function punkte(cent) {' ' return Math.floor(cent / 50) * faktor(cent);' '}' 'module.exports = { punkte };' > demo-umbau/nachher.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Fassung mit der Falle schreiben
docker exec -w /home/node/project agent sh -c "mkdir -p demo-umbau && printf '%s\n' '// Sieht aufgeraeumter aus, rundet aber auf statt ab.' 'function faktor(cent) {' ' return cent >= 1000 ? 2 : 1;' '}' 'function punkte(cent) {' ' return Math.round(cent / 50) * faktor(cent);' '}' 'module.exports = { punkte };' > demo-umbau/falle.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Den Vergleich schreiben
docker exec -w /home/node/project agent sh -c "mkdir -p demo-umbau && printf '%s\n' 'const vorher = require(process.argv[2]).punkte;' 'const nachher = require(process.argv[3]).punkte;' '// Eingaben an den Raendern: null, knapp unter und auf den Grenzen, ein Wert mit Rest.' 'const eingaben = [0, 24, 25, 49, 50, 999, 1000, 1030];' 'let unterschiede = 0;' 'for (const cent of eingaben) {' ' const a = vorher(cent);' ' const b = nachher(cent);' ' if (a === b) continue;' ' unterschiede = unterschiede + 1;' ' console.log(\"cent \" + cent + \": \" + a + \" gegen \" + b);' '}' 'console.log(unterschiede + \" Unterschied(e) bei \" + eingaben.length + \" Eingaben\");' > demo-umbau/vergleich.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Das Vorher mit jeder Fassung vergleichen
docker exec -w /home/node/project/demo-umbau agent sh -c "node vergleich.js ./vorher.js ./nachher.js; node vergleich.js ./vorher.js ./falle.js"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Aufgeräumt kann etwas ändern
Die Falle tauscht nur ein Wort: Math.round statt Math.floor. Es liest sich wie dasselbe, doch ab 25 Cent Rest rundet es auf. Ein Blick auf den Diff hätte das übersehen lassen können, der Vergleich nicht.
Wählen Sie die Eingaben an den Rändern der Regeln, nicht nur gewöhnliche Werte. Zehn und zwanzig Cent hätten die Falle nicht gefunden.
Ein häufiger Fehler
Warnung
Viele denken, wenn die Tests nach dem Umbau grün sind, sei das Verhalten gleich geblieben. Das stimmt nur, wenn die Tests die geänderte Stelle prüfen. Vergleichen Sie darum alte und neue Fassung an den Rändern und nehmen Sie nicht nur die vorhandenen Tests.
Beispiel: zwei Fassungen im Vergleich
| Cent | Vorher | Sauber umgebaut | Falle |
|---|---|---|---|
| 24 | 0 | 0 | 0 |
| 25 | 0 | 0 | 1 |
| 49 | 0 | 0 | 1 |
| 999 | 19 | 19 | 20 |
| 1030 | 40 | 40 | 42 |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ausprobieren: der Vergleich in Python
def punkte_vorher(cent):
if cent >= 1000:
return cent // 50 * 2
return cent // 50
def punkte_nachher(cent):
faktor = 1
if cent >= 1000:
faktor = 2
return cent // 50 * faktor
# Probieren Sie danach (cent + 25) // 50 * faktor aus: Was sehen Sie?
for cent in [0, 24, 25, 49, 50, 999, 1000, 1030]:
if punkte_vorher(cent) != punkte_nachher(cent):
print("Unterschied bei", cent)
print("Vergleich fertig")
Weiter: an einer anderen Änderung ausprobieren
Jetzt ist ein guter Moment, diese Ideen an einer anderen Änderung auszuprobieren. Der Fehler des Labs bleibt unberührt. Wählen Sie lieber eine Funktion in einer Kopie von shop.js, deren Code Sie umbauen lassen können, etwa eine Umbenennung.
Halten Sie zuerst das Verhalten fest, bitten Sie um einen kleinen Schritt und vergleichen Sie danach. Notieren Sie jeden Unterschied und was ihn verursacht hat.