Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
se:programmierung [2010-05-31 17:29] stefan |
se:programmierung [2014-04-05 11:42] (aktuell) |
||
---|---|---|---|
Zeile 6: | Zeile 6: | ||
* Verwende keine globalen Variablen (auch keine Singletons)! \cite{Smacchia2009a} | * Verwende keine globalen Variablen (auch keine Singletons)! \cite{Smacchia2009a} | ||
* Konstruktoren sollten keine "echte" Arbeit verrichten. \cite{Hevery2008} | * Konstruktoren sollten keine "echte" Arbeit verrichten. \cite{Hevery2008} | ||
+ | * "The most reliable way to minimize the creation of regression bugs is to avoid modifying the existing code." \cite{Miller2007a} | ||
+ | |||
+ | ===== Single Responsibility Principle ===== | ||
+ | * Validierung sollte auf Ebene des Domänendatenmodells durchgeführt werden und nicht als Teil des Domänenmodells. Beispiel: Prüfung einer gültigen PLZ nicht in Klasse ''Adresse'', sondern in eigener Klasse ''PLZ''. \cite[S.107]{Westphal2012} | ||
+ | * Wenn man richtig konsequent nach SRP arbeiten will, benutzt man semantisch genaue Datentypen für Eigenschaften, z.B. ''Fullname'' oder ''PhoneNumber'' bei ''Person''en. Dadurch baut man sich eine Hierarchie von Datentypen auf: große Datentypen setzen sich aus kleineren Datentypen zusammen. \cite[S.108]{Westphal2012} | ||
+ | * Bei 1:n- oder m:n-Beziehungen liegt häufig auch eine komplexere Semantik vor. Diese sollte in spezielle Datentypen ausgelagert werden. \cite[S.109]{Westphal2012} | ||
===== Werkzeuge ===== | ===== Werkzeuge ===== | ||
Zeile 31: | Zeile 37: | ||
* ''default''-Zweig von ''switch''-Anweisungen explizit implementieren/dokumentieren | * ''default''-Zweig von ''switch''-Anweisungen explizit implementieren/dokumentieren | ||
* Wertebereiche von Variablen im Hinterkopf behalten bei der Wahl eines Datentyps | * Wertebereiche von Variablen im Hinterkopf behalten bei der Wahl eines Datentyps | ||
+ | |||
+ | In \cite[45:00]{RubyRogues47} sprechen sich die Teilnehmer dafür aus, nicht in allen internen Komponenten erneut Datengültigkeitsprüfungen durchzuführen (also auf defensive Programmierung zu verzichten), sondern lediglich in einer "Guard"-Klasse, deren einzige Aufgabe (-> Single Responsibility Principle) es ist, Eingaben zu validieren. Alles, was in das System reinkommt, muss diese zentrale Prüfung bestehen, sodass im Inneren des Systems von gültigen Daten ausgegangen werden kann. | ||
===== Codeoptimierungen ===== | ===== Codeoptimierungen ===== | ||
Zeile 61: | Zeile 69: | ||
* die Optimierung ist evtl. plattformabhängig | * die Optimierung ist evtl. plattformabhängig | ||
* Optimierung ist zusätzlicher Aufwand (-> sollte lieber in die Entwicklung gesteckt werden) | * Optimierung ist zusätzlicher Aufwand (-> sollte lieber in die Entwicklung gesteckt werden) | ||
- | |||
- | ===== Designprinzipien ===== | ||
- | **nach \cite[S. 87]{Bleek2008}** | ||
- | * **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 | ||
- | |||
- | **nach \cite{Martin2009}**: | ||
- | * **Single Responsibility Principle (SRP)**: A class should have one, and only one, reason to change. | ||
- | * **Open Closed Principle (OCP)**: You should be able to extend a classes behavior, without modifying it. | ||
- | * **Liskov Substitution Principle (LSP)**: Derived classes must be substitutable for their base classes. | ||
- | * **Dependency Inversion Principle (DIP)**: Depend on abstractions, not on concretions. | ||
- | * **Interface Segregation Principle (ISP)**: Make fine grained interfaces that are client specific. | ||
- | |||
- | ==== ToDo ==== | ||
- | * Law of Demeter | ||
- | * Test-first | ||
===== Checklisten ===== | ===== Checklisten ===== | ||
Zeile 94: | Zeile 84: | ||
- Do new candidates write code during their interview? | - Do new candidates write code during their interview? | ||
- Do you do hallway usability testing? | - Do you do hallway usability testing? | ||
+ | |||
+ | ==== Code is considered to be "done", when: ==== | ||
+ | **nach \cite{Roden2010b}** | ||
+ | - It does satisfy all its functional and non-functional requirements. | ||
+ | - It does not contain any known errors. | ||
+ | - It has been commented and documented. | ||
+ | - It has been either pair-programmed or reviewed. | ||
+ | - It has been developed test-driven using 4-Step TDD. | ||
+ | - It does not need to be refactored or rearranged. | ||
+ | - It has been written according to well-known best practices. | ||
+ | - It does conform to accepted coding standards. | ||
+ | - It does pass static code analysis without any errors or warnings. | ||
+ | - It has been integrated and does not break the integration build. | ||
+ | - It has been checked in into source control. | ||
==== When to throw an exception ==== | ==== When to throw an exception ==== | ||
Zeile 116: | Zeile 120: | ||
===== Punkte, die man für den erfolgreichen Betrieb der Software berücksichtigen sollte ===== | ===== Punkte, die man für den erfolgreichen Betrieb der Software berücksichtigen sollte ===== | ||
**nach \cite{Nygard2009}** | **nach \cite{Nygard2009}** | ||
- | |||
* Stabilität der Software | * Stabilität der Software | ||
* "consistent long-term availability of features the users care about" | * "consistent long-term availability of features the users care about" |