Rheinwerk Computing < openbook >


 
Inhaltsverzeichnis
Materialien
Vorwort
1 Java ist auch eine Sprache
2 Imperative Sprachkonzepte
3 Klassen und Objekte
4 Arrays und ihre Anwendungen
5 Der Umgang mit Zeichenketten
6 Eigene Klassen schreiben
7 Objektorientierte Beziehungsfragen
8 Ausnahmen müssen sein
9 Geschachtelte Typen
10 Besondere Typen der Java SE
11 Generics<T>
12 Lambda-Ausdrücke und funktionale Programmierung
13 Architektur, Design und angewandte Objektorientierung
14 Java Platform Module System
15 Die Klassenbibliothek
16 Einführung in die nebenläufige Programmierung
17 Einführung in Datenstrukturen und Algorithmen
18 Einführung in grafische Oberflächen
19 Einführung in Dateien und Datenströme
20 Einführung ins Datenbankmanagement mit JDBC
21 Bits und Bytes, Mathematisches und Geld
22 Testen mit JUnit
23 Die Werkzeuge des JDK
A Java SE-Module und Paketübersicht
Stichwortverzeichnis


Download:

- Listings, ca. 2,7 MB


Buch bestellen
Ihre Meinung?



Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenboom

Einführung, Ausbildung, Praxis
Buch: Java ist auch eine Insel


Java ist auch eine Insel

Pfeil 7 Objektorientierte Beziehungsfragen
Pfeil 7.1 Assoziationen zwischen Objekten
Pfeil 7.1.1 Unidirektionale 1:1-Beziehung
Pfeil 7.1.2 Zwei Freunde müsst ihr werden – bidirektionale 1:1-Beziehungen
Pfeil 7.1.3 Unidirektionale 1:n-Beziehung
Pfeil 7.2 Vererbung
Pfeil 7.2.1 Vererbung in Java
Pfeil 7.2.2 Spielobjekte modellieren
Pfeil 7.2.3 Die implizite Basisklasse java.lang.Object
Pfeil 7.2.4 Einfach- und Mehrfachvererbung *
Pfeil 7.2.5 Sehen Kinder alles? Die Sichtbarkeit protected
Pfeil 7.2.6 Konstruktoren in der Vererbung und super(…)
Pfeil 7.3 Typen in Hierarchien
Pfeil 7.3.1 Automatische und explizite Typumwandlung
Pfeil 7.3.2 Das Substitutionsprinzip
Pfeil 7.3.3 Typen mit dem instanceof-Operator testen
Pfeil 7.4 Methoden überschreiben
Pfeil 7.4.1 Methoden in Unterklassen mit neuem Verhalten ausstatten
Pfeil 7.4.2 Mit super an die Eltern
Pfeil 7.4.3 Finale Klassen und finale Methoden
Pfeil 7.4.4 Kovariante Rückgabetypen
Pfeil 7.4.5 Array-Typen und Kovarianz *
Pfeil 7.5 Drum prüfe, wer sich dynamisch bindet
Pfeil 7.5.1 Gebunden an toString()
Pfeil 7.5.2 Implementierung von System.out.println(Object)
Pfeil 7.5.3 Nicht dynamisch gebunden bei privaten, statischen und finalen Methoden
Pfeil 7.5.4 Dynamisch gebunden auch bei Konstruktoraufrufen *
Pfeil 7.5.5 Eine letzte Spielerei mit Javas dynamischer Bindung und überdeckten Attributen *
Pfeil 7.6 Abstrakte Klassen und abstrakte Methoden
Pfeil 7.6.1 Abstrakte Klassen
Pfeil 7.6.2 Abstrakte Methoden
Pfeil 7.7 Schnittstellen
Pfeil 7.7.1 Schnittstellen sind neue Typen
Pfeil 7.7.2 Schnittstellen deklarieren
Pfeil 7.7.3 Abstrakte Methoden in Schnittstellen
Pfeil 7.7.4 Implementieren von Schnittstellen
Pfeil 7.7.5 Ein Polymorphie-Beispiel mit Schnittstellen
Pfeil 7.7.6 Die Mehrfachvererbung bei Schnittstellen
Pfeil 7.7.7 Keine Kollisionsgefahr bei Mehrfachvererbung *
Pfeil 7.7.8 Erweitern von Interfaces – Subinterfaces
Pfeil 7.7.9 Konstantendeklarationen bei Schnittstellen
Pfeil 7.7.10 Nachträgliches Implementieren von Schnittstellen *
Pfeil 7.7.11 Statische ausprogrammierte Methoden in Schnittstellen
Pfeil 7.7.12 Erweitern und Ändern von Schnittstellen
Pfeil 7.7.13 Default-Methoden
Pfeil 7.7.14 Erweiterte Schnittstellen deklarieren und nutzen
Pfeil 7.7.15 Öffentliche und private Schnittstellenmethoden
Pfeil 7.7.16 Erweiterte Schnittstellen, Mehrfachvererbung und Mehrdeutigkeiten *
Pfeil 7.7.17 Bausteine bilden mit Default-Methoden *
Pfeil 7.7.18 Initialisierung von Schnittstellenkonstanten *
Pfeil 7.7.19 Markierungsschnittstellen *
Pfeil 7.7.20 (Abstrakte) Klassen und Schnittstellen im Vergleich
Pfeil 7.8 SOLIDe Modellierung
Pfeil 7.8.1 DRY, KISS und YAGNI
Pfeil 7.8.2 SOLID
Pfeil 7.8.3 Sei nicht STUPID
Pfeil 7.9 Zum Weiterlesen
 

Zum Seitenanfang

7.8    SOLIDe Modellierung Zur vorigen ÜberschriftZur nächsten Überschrift

Wer gute objektorientierte Software schreiben möchte, sollte sich an einige Designprinzipien halten. Es sind Best-Practice-Methoden, die natürlich nicht zwingend sind, aber in der Regel das Design verbessern.

 

Zum Seitenanfang

7.8.1    DRY, KISS und YAGNI Zur vorigen ÜberschriftZur nächsten Überschrift

Die ersten drei Regeln sind:

  • DRY (Don’t Repeat Yourself): »Wiederhole dich nicht.« Codeduplizierung sollte vermieden und doppelter Code in Methoden ausgelagert werden. Das heißt auch, dass bestehender Code (aus etwa eigenen Bibliotheken, der Java SE oder quelloffenen Bibliotheken) verwendet werden soll.

  • KISS (Keep It Simple, Stupid): »Halte es einfach und idiotensicher«. Ein Problem soll einfach und leicht verständlich gelöst werden. Für Entwickler bedeutet dies: einfacher Code, wenige Zeilen Code, auf den ersten Blick verständlich.

  • YAGNI (You Ain’t Gonna Need It): Das Prinzip »Du wirst es nicht brauchen« soll uns daran erinnern, einfachen Code zu schreiben und nur das zu programmieren, was im Moment in der Anforderung auch erwartet wird. YAGNI ist ein zentraler Punkt im Extreme Programming (XP) und der Idee »Implementiere immer die einfachste mögliche Lösung, die funktioniert«, denn wenn etwas programmiert wird, was später nie produktiv wird, ist es Zeit- und Geldverschwendung, aber der Code muss dennoch dokumentiert, gewartet und getestet werden.

 

Zum Seitenanfang

7.8.2    SOLID Zur vorigen ÜberschriftZur nächsten Überschrift

Michael Feathers hat die Abkürzung SOLID eingeführt und fünf Punkte benannt, die einen guten objektorientierten Entwurf ausmachen. Die einzelnen Kriterien selbst stammen von unterschiedlichen Autoren.

S: Single Responsibility Principle (SRP)

Etwas flapsig ausgedrückt steht das Prinzip für: »Mache genau eine Sache, die aber richtig.« Ein Typ sollte genau eine Verantwortung (engl. responsibility) haben, sodass bei Änderungen im besten Fall auch nur eine Stelle angepasst werden muss und nicht viele Stellen. Das Gegenteil sind sogenannte Gott-Klassen, die alles können – ein Anti-Pattern. Robert Martin, der das SRP in seinem Buch »Agile Software Development: Principles, Patterns, and Practices« beschreibt, sagt auch: »Es sollte nie mehr als einen Grund geben, eine Klasse zu ändern.« Was heißt das nun praktisch?

Nehmen wir an, eine Person-Klasse speichert Namen, PLZ und Alter. An PLZ und Alter gibt es Anforderungen: Eine deutsche PLZ besteht nur aus Ziffern, ist 5 Stellen lang, und ein Alter ist sicherlich nicht negativ und nach oben beschränkt. Allerdings sind diese beiden Validierungen zwei unterschiedliche Dinge, also übernimmt die Person-Klasse Verantwortlichkeiten, die an sich mit einer Person nichts zu tun haben. Demnach gibt es zwei Gründe, warum die Klasse bei einer Änderung der Validierung angepasst werden muss; und zwei Gründe sind mehr als ein Grund und folglich ein Bruch des SRP.

Treibt die Modellierung das SRP ins Extrem, entstehen sehr viele kleine Typen. Damit ist auch dem Codeversteher nicht geholfen, wenn Verantwortlichkeiten wegen Unübersichtlichkeit nicht mehr zu verstehen sind.

O: Open/closed principle

Bertrand Meyer formuliert 1988 in seinem Buch »Object-Oriented Software Construction«, dass Module sowohl offen (für Erweiterungen) als auch verschlossen (für Modifikationen) sein müssen. Unter dem Begriff Modul müssen sich Java-Entwickler einen Typ vorstellen. Eine herkömmliche Klasse ist insbesondere mit privaten Zuständen geschlossen für Modifikationen, aber eine Unterklasse erlaubt ohne Codeänderungen der Oberklasse die Erweiterung um neue Zustände oder durch das Überschreiben von Methoden eine Anpassung einer Implementierung. Eine Unterklasse darf Methoden allerdings keine andere Semantik geben, sonst würde das die Geschlossenheit brechen.

L: Liskov Substitution Principle (LSP)

Barbara Liskov hielt 1987 den Vortrag »Data abstraction and hierarchy«, in dem es um die Tatsache ging, dass es möglich sein sollte, Objekte in Programmen durch Objekte eines Untertyps zu ersetzen, ohne dass die Korrektheit leidet. Damit der Austausch funktioniert, muss natürlich der Untertyp wissen, was »korrekt« ist, damit Methoden nicht eine falsche Implementierung realisieren, die das Verhalten brechen. Flapsig ausgedrückt: Kinder müssen das Verhalten der Eltern erben und respektieren. In Java ist das nicht einfach, denn syntaktische Konstrukte wie Preconditions, Postconditions und Invarianten gibt es nicht; Java-Entwickler müssen also rein aus dem Javadoc, der textuellen Information also, herausziehen, was ein korrektes Verhalten ist.

I: Interface Segregation Principle (ISP)

Das ISP wird Robert Cecil Martin zugeschrieben, als er für Xerox am Druckersystem arbeitete. Die zentrale Aussage ist: »Viele Client-spezifische Schnittstellen sind besser als eine allgemeine Schnittstelle.« Der Client ist der Nutzer eines Java-Typs, und mit Schnittstelle ist verallgemeinert das Angebot an Methoden gemeint. Praktisch heißt das Folgendes: Es gibt Typen, die sehr viele Methoden haben und dann ein »allgemeiner« Typ wären. Werden solche Objekte herumgereicht, dann bekommen die Programmstellen immer das gesamte Objekt mit allen Methoden. Das komplette Angebot an Methoden ist aber nicht immer nötig und vielleicht sogar gefährlich. Besser ist es, die API klein zu halten und damit nur den verschiedenen Stellen das zu ermöglichen, was auch benötigt wird.

D: Dependency Inversion Principle (DIP)

»Hänge nur von Abstraktionen ab, nicht von Spezialisierungen.« So hat es Robert Cecil Martin formuliert, ursprünglich etwas länger.[ 178 ](Die erste Fassung lautet: »A. High-level modules should not depend on low-level modules. Both should depend on abstractions. B. Abstractions should not depend on details. Details should depend on abstractions.« ) Gut zu erkennen ist das Prinzip in der Schichtenarchitektur: Eine obere Schicht greift auf Dienste einer tieferen Schicht zurück. Die obere Schicht sollte sich aber nicht an konkrete Typen klammern, sondern nur von Basistypen wie Java-Schnittstellen abhängen. In diesem Zusammenhang passt gut das Prinzip Programmieren gegen Schnittstellen.

Das große Ganze

Wie in einem Quentin-Tarantino-Film hängt alles irgendwie in einem großen Designuniversum zusammen. Jedoch haben die Entwurfspraktiken Schwerpunkte: Das SRP nimmt sich Typen vor und die Architektur im Großen. Das Open-Closed-Prinzip handelt von Typen und ihren Erweiterungen. LSP handelt von Vererbung und Untertypen. Und das ISP handelt von Geschäftslogik und Abhängigkeiten der Typen.

 

Zum Seitenanfang

7.8.3    Sei nicht STUPID Zur vorigen ÜberschriftZur nächsten Überschrift

Jedem »tue« in SOLID steht ein »lass es« in STUPID gegenüber. Das Akronym steht für die die dunkle Seite:

  • Singleton: Ein Singleton ist ein Objekt, das es im System nur einmal geben kann. Solche Objekte gibt es immer wieder, und sie sind an sich nichts Schlimmes. Problematisch ist jedoch, dass viele Entwickler das Singleton selbst als Klasse schreiben, und dann entsteht schnell eine Implementierung, die sich durch den globalen Zustand schlecht testen lässt. Besser ist es, Frameworks zu nutzen, die für uns dann ein Exemplar bereitstellen.

  • Tight Coupling (enge Kopplung): Das Ziel guten Entwurfs ist die Reduktion von Abhängigkeiten; auf je weniger Module/Pakete/Typen ein Stück Code zurückgreift, desto besser. Konkret: Je weniger import-Deklarationen es gibt, umso besser.

  • Untestability (Nicht-Testbarkeit): Wird erst nach dem Design und der Programmierung über das Testen nachgedacht, ist es oft schon zu spät – schnell entsteht schwer zu testender Code, besonders wenn die Kopplung zu eng ist. Besser ist der Ansatz der testgetriebenen Entwicklung, bei der die Testbarkeit das Design beeinflusst. Am besten überlegen sich Designer und Entwickler im Vorfeld, wie eine bestimmte Klasse und Funktionalität getestet werden kann, bevor es an die intensive Implementierung geht.

  • Premature Optimization (voreilige Optimierung): Entwickler meinen, ein Gefühl dafür zu haben, welche Programmteile Performance verschlingen und welche Teile schnell sind. Oft irren sie sich, verschenken aber viel Zeit bei der Optimierung dieser vermeindlich langsamen Stellen. Der beste Ansatz ist, nach KISS eine einfache Lösung zu realisieren und dann über einen Profiler sich genau die Stellen aufzeigen zu lassen, die Nacharbeit erfordern.

  • Indescriptive Naming (nichtbeschreibende Benennung): Variablennamen wie one, z, l, myvariable, var1, val10, theInt, aDouble, _1bool, button123 sind wenig sprechend und müssen vermieden werden. Der Programmleser sollte sofort wissen, worum es sich bei der Variablen handelt.

  • Duplikationen: Code, der mit kleinen Änderungen 1:1 kopiert wurde, ist zu vermeiden. Codeduplikate lassen sich mit Werkzeugen und IDE-Plugins relativ gut finden.

 


Ihre Meinung?

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de

<< zurück
 Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Java ist auch eine Insel Java ist auch eine Insel

Jetzt Buch bestellen


 Buchempfehlungen
Zum Rheinwerk-Shop: Captain CiaoCiao erobert Java

Captain CiaoCiao erobert Java




Zum Rheinwerk-Shop: Java SE 9 Standard-Bibliothek

Java SE 9 Standard-Bibliothek




Zum Rheinwerk-Shop: Algorithmen in Java

Algorithmen in Java




Zum Rheinwerk-Shop: Objektorientierte Programmierung

Objektorientierte Programmierung




 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und in die Schweiz

InfoInfo



 

 


Copyright © Rheinwerk Verlag GmbH 2021

Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.

Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 

[Rheinwerk Computing]



Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de



Cookie-Einstellungen ändern