**Dies ist eine alte Version des Dokuments!**
Tipps zur (objektorientierten) Programmierung
Werkzeuge
Namensgebung
nach {[quellen:Goodliffe2008|S. 43ff.]}
Klarheit ist wichtiger als Kürze.
Funktionen sollten aus einer externen Sichtweise heraus benannt werden und die logische Operation beschreiben, nicht die Implementierung.
Vermeide Redundanzen in Namen (insb. class
, data
, object
, type
)!
Defensive Programmierung
nach {[quellen:Goodliffe2008|S. 6ff.]}
Defensive Programmierung bedeutet vorsichtiges, überwachtes Programmieren. Jede Komponente wird so entwickelt, dass sie sich selbst so gut wie möglich schützt. Unsichere Annahmen werden eliminiert.
Defensive Programmierung ist nicht Fehlerbehandlung (sollte immer Standard sein!), Testen (stets Teil des Prozesses) und Debuggen (Finden von Fehlern, anstatt sie zu vermeiden)!
Programmiere mit Bedacht und vertraue niemandem (auch nicht dir selbst)!
"Readability is the best single criterion of program quality." {[quellen:Goodliffe2008|S. 17]}
Benutze ein gutes Logging-Tool!
Beispiele
Assert der Vor- und Nachbedingungen und der Invarianten
entsprechende Datentypen für nicht-negative Zahlen verwenden (z.B. unsigned int
) um aufwändige Prüfungen des Wertebereichs zu vermeiden
Rückgabewerte von Funktionen immer prüfen (wofür sind sie sonst da?)
default
-Zweig von switch
-Anweisungen explizit implementieren/dokumentieren
Wertebereiche von Variablen im Hinterkopf behalten bei der Wahl eines Datentyps
Bugfixing
Codeoptimierungen
(siehe Skript Datenstrukturen und Algorithmen)
Constant Propagation: wo es geht Konstanten anstatt von Variablen verwenden
Common Subexpression Elimination: einmalige Berechnung gleicher Ausdrücke
Operator Strength Reducing: Bitshifts beim Rechnen mit Zweierpotenzen verwenden
Copy Propagation: keine überflüssigen oder doppelten Berechnungen
Loop Strength Reduction: Vermeiden überflüssiger Schleifendurchläufe durch Verwenden des passenden Inkrements (z.B. i += 10
anstatt i++
)
Invariant Code Motion: Entfernen invarianter Ausdrücke (Berechnungen mit immer gleichem Ergebnis in der Schleife oder dem Schleifenkopf) aus Schleifen
Loop Jamming: Zusammenfassen mehrerer Schleifen zu einer
Vermeidung unnötiger Indexzugriffe auf Arrays (da interne Multiplikationen zur Ermittlung des Speicherplatzes nötig)
keine überflüssigen Funktionsaufrufe (Operatoren sind meist schneller)
Designprinzipien
nach {[quellen:Bleek2008|S. 87]}
Don't Repeat Yourself (DRY): Funktionen werden nur einmal implementiert und nicht mehrmals (womöglich gar durch Copy-and-Paste) → Modularisierung, bessere Wartbarkeit
Speaking Code Principle (SCP): der Code muss auch ohne Kommentare verständlich sein → bessere Wartbarkeit, einfachere Einarbeitung anderer Entwickler
Separation of Concerns (SoC): jedes Modul hat genau eine Aufgabe → Modularisierung, bessere Wartbarkeit, DRY
Tell, don't ask (TDA): Klassen sollten nicht nach Werten gefragt, sondern aufgefordert werden, eine Funktion zu liefern (z.B. nicht MwSt-Satz abfragen, sondern auffordern, Mehrwertsteuer zu berechnen) → verhindert ausufernde Abhängigkeiten zu anderen Klassen, evtl. jedoch Konflikt zu SoC
ToDo
Single Responsibility Principle
Open Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
Law of Demeter
Test-first