Wichtige Hinweise zum Programmieren

Werbung
Modul Entwurfsmuster
Prof. Dr. Dominik Gruntz
Prof. Dr. Christoph Denzler
6 Merkpunkte für besseren, objektorientierten Code
Ungarische Notation. C++ Programmierer sind sich gewohnt, in den Variablennamen den Typ und die
Art der Variable (global, statisch oder lokal) einzucodieren. Diese Art der Notation ist von Charles Simonyi
von Microsoft in den 70er Jahren eingeführt worden und hilft bei nicht streng typisierten Programmiersprachen wie z.B. C++. Java und C# haben ein strenges Typsystem, und daher empfehlen sowohl die
Java Code Conventions [1] als auch die .NET Naming Conventions [2] auf die ungarische Notation zu
verzichten. Verwenden Sie daher keine m_ oder _ Präfixe um Instanzvariablen oder lokale Variablen zu
markieren. Wenn es hilft, dann verwenden Sie beim Zugriff auf Instanzvariablen das Schlüsselwort this.
Ihre Methoden sollten so kurz sein, dass sie als ganzes überblickt werden können und dass einfach
festgestellt werden kann, ob eine Variable lokal ist oder nicht.
Bei Konstruktoren, in welchen die Werte von Feldern initialisiert werden, empfehlen wir, als Parameternamen die Feldnamen zu verwenden und mit this auf die Instanzvariablen zuzugreifen.
public Point(int x, int y) { this.x = x; this.y = y; }
Setter- und Getter-Methoden. Zugriff auf Felder sollte immer über Getter- und Setter-Methoden
erfolgen. Der Grund ist, dass solche Klassen einfacher durch ein Proxy ersetzt werden können. Wir
werden dies im Rahmen des Decorator-Patterns diskutieren. Das Programm wird durch die Verwendung
dieser Methoden nicht langsamer ausgeführt, da die JVM diese Methoden eliminieren kann (Inlining). Der
Zugriff auf interne Datenstrukturen (sowohl über Setter- als auch über Getter-Methoden) birgt jedoch die
Gefahr, dass so unkontrollierter Zugriff auf den Zustand der Objekte ermöglicht wird. Diese Probleme
werden wir im Kontext des Prototype-Patterns diskutieren.
Program to an Interface, not an Implementation. Bei der Deklaration von Variablen und Methodenparametern soll als Typ wenn möglich ein Interface verwendet werden und nicht eine konkrete oder
abstrakte Klasse. Damit ist es möglich, solche Methoden auch mit anderen (und insbesondere mit erst
später entwickelten) Implementierungen des Interfaces zu verwenden. Deklarieren Sie also z.B. eine
Liste als
List<?> list = new LinkedList<?>()
Wie unterschiedliche Implementierungen erzeugt werden können, ohne dass dazu der Code, der die
Instanz erzeugt, geändert werden muss, werden wir im Kontext der Factory-Patterns sehen.
Logische Ausdrücke. Logische Ausdrücke können wie Ausdrücke anderer Typen auch in Zuweisungen
und return-Anweisungen verwendet werden; der Code wird dadurch viel lesbarer. Die Methode equals
in der Klasse Point kann wie folgt implementiert werden:
boolean equals(Object p) {
return p instanceof Point && ((Point)p).x == x && ((Point)p).y == y;
}
Dabei wird auch die Eigenschaft ausgenutzt, dass die logischen && und || Operatoren nur bedingt ausgewertet werden. Vermeiden Sie bei solchem Code if-Anweisungen, insbesondere Anweisungen der
Form:
if( <boolean-expression> ) { // bad style
return true;
} else {
return false;
}
Lieber etwas weniger Kommentar, dafür lesbaren Code. Wenn Sie Ihre Programme lesbar
formulieren, muss nicht in einem Kommentar beschrieben werden, was die Anweisungen für eine
Bedeutung haben. Versuchen Sie also so zu programmieren, dass der Code für sich selber steht und
nicht in Kommentaren erklärt werden muss.
Verwenden Sie von Anfang an einen Style-Checker. Wenn Sie erst mitten in einem Projekt einen
Style-Checker verwenden, werden Sie erdrückt von den vielen Warnungen. Eine grössere RefactoringPhase steht dann an. Style-Checker helfen den Code von Anfang an übersichtlich zu schreiben.
[1] http://www.oracle.com/technetwork/java/codeconventions-150003.pdf
[2] http://msdn.microsoft.com/en-us/library/ms229045.aspx
Herunterladen