- Beim Programmieren von links nach rechts bleibt das Programm in dem Moment, in dem Code eingegeben wird, stets in einem gültigen Zustand, wodurch Tool-Unterstützung wie die Autovervollständigung des Editors maximiert wird
- Die List Comprehension in Python behindert die Autovervollständigung, weil nicht deklarierte Variablen und fehlende Typinferenz im Weg stehen
- Rust und JavaScript lassen sich natürlich von links nach rechts aufbauen, wodurch die Verwendung von Variablen und das Erkunden von Methoden intuitiver werden
- Der funktionale Stil in C und Python beeinträchtigt durch die schwache Auffindbarkeit von Funktionsnamen und Strukturen eine effiziente Coding-Erfahrung
- Bei Logik mit hoher Komplexität ist Code, der sich von links nach rechts entfaltet, leichter zu lesen und besser für Wartbarkeit und Erweiterbarkeit geeignet
Von links nach rechts programmieren
Code muss in dem Moment, in dem er eingegeben wird, gültig sein
Die Grenzen von Python-List-Comprehensions
- Die Python-Syntax für List Comprehensions
words_on_lines = [line.split() for line in text.splitlines()] verursacht das Problem, dass der Editor Autovervollständigung und Typinferenz nicht richtig bereitstellen kann, weil auf eine nicht deklarierte Variable (line) zugegriffen werden muss
- Während der schrittweisen Eingabe des Codes
- wenn man etwa
words_on_lines = [line.sp eingibt, kennt der Editor den Typ von line nicht und kann daher keine Methoden vorschlagen
- auch potenzielle Fehler wie Tippfehler im Variablennamen (
lime usw.) lassen sich schwer erkennen
- Um korrekte Vorschläge zu erhalten, muss man unvollständigen Code schreiben, was unintuitiv und unbequem ist
Aufbau von links nach rechts in Rust
- Im Rust-Beispiel (
let words_on_lines = text.lines().map(|line| line.split_whitespace());)
- gilt eine Variable (
line) in dem Moment, in dem sie zusammen mit der anonymen Funktion erstmals erscheint, als deklariert, sodass sofort Autovervollständigung und Methodenvorschläge möglich sind
- auch die Methode
split_whitespace ließ sich dadurch leicht finden, weil sie automatisch vorgeschlagen wurde
- Dieser Ansatz hält das Programm immer in einem zumindest teilweise gültigen Zustand, sodass IDEs und Editoren das Coding in Echtzeit unterstützen können
Progressive Disclosure und API-Usability
- Progressive Disclosure ist ein Gestaltungsprinzip, bei dem Nutzer nur so viel Komplexität sehen, wie sie gerade benötigen; das lässt sich auch auf das Programmieren anwenden
- Beispiel: ähnlich wie bei der UX einer Textverarbeitung, in der relevante Optionen erst erscheinen, wenn ein Bild eingefügt wird
- In C fehlt diese Unterstützung weitgehend
- da sich nicht alle zu
FILE *file gehörenden Funktionen über file. erkunden lassen, muss man Namensmuster von Funktionen (fread, fclose usw.) auswendig lernen, und Funktionen sind schwer zu entdecken
- in einer idealen Sprache könnten passende Funktionen dagegen über Methodenvorschläge nach
file. leicht schrittweise entdeckt werden
Unterschied bei der Auffindbarkeit von Funktionen und Methoden
- Vergleich der Beispiele
map(len, text.split()) in Python und text.split(" ").map(word => word.length) in JavaScript
- in Python muss man oft mehrere Versuche unternehmen, weil Funktionsnamen wie
len, length oder size nicht vorhersehbar sind
- in JavaScript reicht es, nach
word. nur .l einzugeben, und der Editor schlägt Methoden wie length vor, wodurch die Auffindbarkeit hoch ist
- auch Higher-Order Functions wie
map machen den tatsächlichen Rückgabewert und den Datentyp unmittelbar klar erkennbar
Vorteile strukturierten Schreibens bei komplexerer Logik
- Bei Logik mit hoher Komplexität (langer Python-Code mit verschachteltem
filter und lambda)
- muss man wiederholt Anfang und Ende des Codes prüfen, und Bedingungen oder Klammerzuordnungen verschlechtern Lesbarkeit und Verständlichkeit
- In der JavaScript-Version derselben Logik kann man den Code dagegen von oben nach unten und von links nach rechts sequenziell lesen und verstehen
Kernprinzip
Code muss in jedem Moment der Eingabe gültig sein
- Schon die alleinige Eingabe von
text hält das Programm in einem gültigen Zustand
- Auch wenn man bis
text.split(" ") schreibt und anschließend .map(word => word.length) ergänzt, bleibt der Gesamtzustand durchgehend gültig
- Dieses Coding-Muster erhöht die Möglichkeit Echtzeit-Unterstützung durch den Editor und erlaubt es in einer REPL-Umgebung, Ergebnisse sofort zu prüfen
Fazit
- API- und Sprachdesign sollten so gestaltet sein, dass Code auf natürliche Weise von links nach rechts eingegeben werden kann und in jedem Zwischenschritt ein gültiges Programm entsteht
- Gutes API-Design ist der Schlüssel zur Verbesserung dieser Coding-Erfahrung
Noch keine Kommentare.