Beim Clean Coden an den Schnittstellen geschnitten.

Fischkralle

Mitglied
Hey Leute,
Wie dem Titel zu entnehmen geht es bei meiner Frage um Clean Code. Um genauer zu sein um den Teil der losen Kopplung im Roten Grad.
Für die Wiederverwendung von Funktionalität kennt die Objektorientierte Programmierung (OOP) zwei sehr bekannte Kandidaten: Die Vererbung (whitebox – reuse) und die Komposition (blackbox – reuse). Verwendet man Funktionalität wieder durch das Ableiten von einer Klasse, so ist die Subklasse abhängig von der Elternklasse. Dies macht ein System in vielen Fällen unnötig komplex, schlechter testbar und erschwert das Austauschen von Funktionalität zur Laufzeit. CCD hat für das korrekte Ableiten das Liskov Substitution Prinzip (LSP) bereit, das es dabei zu befolgen gilt.

Bei der Komposition verwendet eine Klasse eine andere. Verwendet man dazu eine klar definierte Schnittstelle, fördert das die Entkopplung. Auch können verschiedene Implementationen einfach ausgetauscht werden. Bevor man sich also der Liskov Substitution stellt, fordert Favour Composition over Inheritance, sich die Frage zu stellen, ob man der Komposition nicht Vorrang geben kann.

Because inheritance exposes a subclass to details of its parent’s implementation, it’s often said that ‚inheritance breaks encapsulation„. (Gang of Four 1995:19)

Leider fehlt mir noch der Sinn hinter dem ganzen. Aber lasst mich mal meine Ansicht an Hand eines Beispiels erklären:
Ich möchte mehrere Tiere (Warum auch immer) in einem Programm abbilden. Nehmen wird den Hund, die Katze und die Maus. Alle Tiere sind in der Lage zu Fressen. Ich könnte mir nun eine Klasse Tier schreiben, in der ich die Methode eat() unterbringe. In dieser Methode befindet sich ein Algorithmus, der mit Hilfe von vorgefertigten Variablen errechnet, wie lange das jeweilige Tier essen muss, bis es satt ist.
Diese Klasse wird von allen Tieren geerbt und aufgerufen sobald es ums essen geht.
Mit einem Interface könnte ich die Tiere zwar dazu bringen die Methode eat() anzunehmen, doch müsste ich diese, da sie ja nur abstract ist, in jedem Tier noch einmal ausformulieren.
Möchte ich diese nun ändern muss ich das beim Interace in jeder Tierklasse machen und bei der Vererbung nur in einer.
Ich habe mir schon einiges durchgelesen doch habe ich noch keinen wirklichen Vorteil der losen Kopplung gefunden (oder verstanden)
Ich hoffe hier kann ein wenig Licht ins dunkel der losen Kopplung gebracht werden.
 

Joose

Top Contributor
Mit einem Interface könnte ich die Tiere zwar dazu bringen die Methode eat() anzunehmen, doch müsste ich diese, da sie ja nur abstract ist, in jedem Tier noch einmal ausformulieren.

Nein deine Superklasse "Tier" (von welcher die spezifischen Tiere ja dann wahrscheinlich ableiten) kann abstrakt sein und dieses Interface bzw. dessen Methoden trotzdem implementieren.
Die Subklassen können müssen diese aber nicht überschreiben ;)
 

Kababär

Top Contributor
Ein Interface ist ja nur ein Vertrag, der as Verhalten von Objekten sag ich mal, vorgibt.
Dabei ist es erstmal egal, wie die Klassen die Methode implementieren, hauptsache sie tun es.
Weite dein Beispiel mal aus:
Du hast eine Klasse Baum und eine Klasse Hund. Beide können sich ernähren und das geschieht auch auf total verschiedenen Wegen.
Vererbung würde ich einsetzen, wenn ich eine Klasse um Funktionen erweitern will.
Bspw: Lebewesen kann atmen
Hund extends Lebewesen weil ein Hund atmen kann und sich bewegen kann.
Baum extends Lebewesen ?
Kann ein Baum mehr als nur die 4 Bedingungen für ein biologisches Objekt?

Seltsames Beispiel aber ich hoffe ich konnte helfen.
 

Fischkralle

Mitglied
Hmm.....
Ich danke euch erst mal für die Antworten.
Leider sind das genau die Antworten, die ich auch im Internet überall gefunden hatte. Mir bleibt also immer noch der Vorteil der Interfaces verborgen.
Ich sehe die Dinger sogar als Nachteil an, da ich den Code,der hinter einer solchen Methode steckt ja immer noch selber tippen muss.
Was das jetzt mit der losen Kopplung soll ist mir immer noch nicht bewusst
Ich meine, wenn ich einen........ sagen wir Baum und einen Hund habe, die zwar beide wachsen können, sich der Baum jedoch mit einigen Eigenschaften des Hundes (wie springen oder bellen) schwer tut, und mir die Methode wachsen() über ein Interface rein hole, muss ich den Methoden Rumpf immer noch in jeder Klasse selber schreiben.
Möchte ich nun, aus was für Gründen auch immer, dass die Zeit rückwärts läuft muss ich jede Klasse anpacken, die dieses Interface besitzt. Auch alle x Hunde. Würden die Hunde nun von einer Klasse z.B. MasterDog diese Methode erben,
müsste ich für alle x Hunde nur diese eine Methode in MasterDog ändern und kann so auch keinen Hund vergessen.
 

Kababär

Top Contributor
Betrachte das Ganze doch einfach mal anders rum:
Du arbeitest in einem Team und schreibt ein Programm, das FTP unterstützt. Während du dich mit der Applikation an sich beschäftigst (GUI etc), programmiert dein Partner die Verschlüsselung und stellt dir nun ein Interface bereit, das zwei Methode hat "encrypt" und "decrypt". Wie das implementiert ist, interessiert dich gar nicht, aber du kannst damit arbeiten. Du brauchst ja lediglich nur das Interface. So machen es auch viele Firmen: schreiben Programme und die Schnittstelle zum Kunden ist ein Interface. Der Kunde kann diese Interfaces benutzen ohne zu Wissen was wirklich dahinter steckt (interessiert ihn ja auch nicht, hauptsache es funktioniert). Sehr häufig findet man Interfaces im Server-Client Bereich.
Am Anfang tat ich mir auch schwer damit. Aber da ich jetzt "schon" aktiv ein Jahr programmiere, kann ich sagen, dass Interfaces schon ne gute Sache sind.
 

Flown

Administrator
Mitarbeiter
Lose Kopplung heißt, dass Teile leicht ausgetauscht werden können.
Wie schon beschrieben ist ein Interface eine Garantie für eine gewisse Schnittstelle. Nehmen wir als Beispiel das Interface "Savable":
Java:
public interface Savable<T> {
  public  void save(T t);
}
Jetzt kann ich diverse Implementierungen haben, wie ich ein Objekt speichere: XML, Serialisierung (bytes), Datenbank, ...
Aber was alle dann gemein haben ist die Methodesave(T t) und die dazugehörige Implementierung kann ich leicht austauschen.
Konkret heißt das, dass man das Implementierungsdetail außer acht lässt, was widerum folgt nennt sich dann eben: lose Kopplung.
 

Kopak'rraf

Mitglied
Mein Lieblings-beispiel zu diesem Dilemma ist "Frosch, Ente und Auto quaken lassen"

Vererben solltest du immer nur dann, wenn die Subklasse in einer "Ist ein Beziehung" zu seinem Super steht:
  • Ente ist ein Tier.
  • Frosch ist ein Tier.
  • Aber: Die Ente ist kein Frosch.
Allerdings könnte man auf die Idee kommen, Die "quaken" methode in Tier zum implementieren. Dann hätte diese allerdings auch das Kamel.
Mann könnte auf die Idee kommen die Ente vom Frosch erben zu lassen (oder umgekehrt). Dann konnte der Frosch aber auch watscheln.
Möglich wäre auch eine abstrake zwischenklasse: QuakendeTiere
Allerdings haben wir dann immer noch das Auto model: Ford T. Welches eine quakende Hupe hat. Das kann man gar nicht in diesen Klassenbaum einfügen. Aber dieses Auto soll auch "quaken".

Also ist bei diesen Methoden das Interface Quackable doch besser als eine Vererbung. Um doppelten Code zu vermeiden kannst du dann Traits oder Mixins benutzen.
 

Neumi5694

Top Contributor
Das einfachste "Interface" ist eine Funktion aus 1 Zahl.
Anstatt sin(x) oder cos(x) könnte man ja auch ein Interface bereitstellen mit einer Methode "berechne(x)".
new SinusKlasse().berechne(x)
new CosinusKlasse().berechne(x)

Je nachdem, was man dann haben will, wird eine andere Instanz zugewiesen, die aufgerufene Methode ist jedoch immer gleich, selbst bei einer neuen Implementierung muss in der aufrufenden Klasse - sofern sie die Berechnungsklasse von außen als Parameter kriegt - nichts neu programmiert werden.
 

Flown

Administrator
Mitarbeiter
Warum werden hier alte Themen ausgegraben, wo sich der TO schon lange nicht mehr blicken lassen hat?
 

Fischkralle

Mitglied
Hey,
erst einmal Entschuldigung das ich erst jetzt wieder schreibe aber vor Weihnachten und einem (ungestörten) Urlaub über die Festtage, laufen einige Vorbereitungen voraus.
Das mit der losen Kopplung habe ich nun doch kapiert. Keine Ahnung welchem Beitrag ich das nun zu verdanken habe. Irgendwann beim durchlesen euer Antworten hat es auf einmal klick gemacht und alles war klar.
Danke dafür.
Doch keine Klarheit ohne neue Frage.
Aktuell geht es um Reflection und das Mackieren mit Anotationen.
 

Fischkralle

Mitglied
Hey,
erst einmal Entschuldigung das ich erst jetzt wieder schreibe aber vor Weihnachten und einem (ungestörten) Urlaub über die Festtage, laufen einige Vorbereitungen voraus.
Das mit der losen Kopplung habe ich nun doch kapiert. Keine Ahnung welchem Beitrag ich das nun zu verdanken habe. Irgendwann beim durchlesen euer Antworten hat es auf einmal klick gemacht und alles war klar.
Danke dafür.
Doch keine Klarheit ohne neue Frage.
Aktuell geht es um Reflection und das Mackieren mit Anotationen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Zrebna OutOfMemory-Error beim Build in der CI-Pipeline Allgemeine Java-Themen 5
berserkerdq2 Weiß jemand wie ich im Scenebuilder das Fenster so darstellen kann, dass beim Vollbildmodus die Objekte so angezeigt werden? Allgemeine Java-Themen 1
C Probleme beim Erstellen eines runnable-jar files Allgemeine Java-Themen 1
B Mysteriöse Ergebnisse beim Baccarat Programm? Allgemeine Java-Themen 13
8u3631984 Problem beim Mocken von Record Klassen Allgemeine Java-Themen 4
A Zweite Service Klasse beim Kompilieren Allgemeine Java-Themen 6
B Java Reflection Probleme beim wehcselseitigen Referenzieren zweier Klassen/Objekte Allgemeine Java-Themen 14
B Stringmanipulationen beim Dateinamen Allgemeine Java-Themen 8
B Woher kommen die Bildschirmkoordinaten beim java Robot? Allgemeine Java-Themen 14
Alex_99 Programm stürzt beim Aufruf der Funktion ab? Text ausgeben Allgemeine Java-Themen 45
J Mein Frame friert ein beim Uploaden Allgemeine Java-Themen 4
P Selenium Scriipt zeigt Fehler beim Import Allgemeine Java-Themen 3
A Hilfe beim Verständnis Allgemeine Java-Themen 16
stormyark Problem beim Klassen erstellen Allgemeine Java-Themen 1
K Verbesserung der Laufzeit beim Sortieren von Einwohnern nach ihrem Geburtsjahr Allgemeine Java-Themen 0
B Compiler-Fehler Probleme beim Kompilieren mit Jsoup Allgemeine Java-Themen 8
G javamail Problem beim Empfangen von Nachrichten Allgemeine Java-Themen 3
yakazuqi Fehler beim Laden. JDA (Java Discord API) Allgemeine Java-Themen 1
T Problem beim Umwandeln in eine Jar-Datei Allgemeine Java-Themen 3
W Suche Ursache für NPE - woher kommt sie? (Hilfe beim Debugging) Allgemeine Java-Themen 19
U Fehler beim Compillieren Allgemeine Java-Themen 13
B neuroph hält beim XOR lernen nicht an Allgemeine Java-Themen 13
bueseb84 Fehler beim Import von Maven Dependencies aus lokalem artifactory Allgemeine Java-Themen 2
J Jasper Report - seltame Meldung beim compilieren Allgemeine Java-Themen 3
J Linux .jar beim Start automatisch ausführen Allgemeine Java-Themen 6
T String-Manipulation beim Ablauf in Eclipse und als JAR-File Allgemeine Java-Themen 8
V Threads Probleme beim Aufrufen von Methoden einer anderen Klasse (Threads) Allgemeine Java-Themen 14
M Gibt es eine API die den aktuellen Wert eines Indikators beim Trading zurückgibt? Allgemeine Java-Themen 7
A Fehler beim Öffnen eines Projekts Allgemeine Java-Themen 6
L Compiler-Fehler Generics beim Anhängen von Predicates Allgemeine Java-Themen 1
J WARNING: An illegal reflective access operation has occurred, beim Compilieren von JasperReports, was bedeutet das ? Allgemeine Java-Themen 23
J Problem beim Umstellen auf Java jdk 13 Allgemeine Java-Themen 3
A Problem beim öffnen von Java-Installern Allgemeine Java-Themen 1
J Problem beim Generischen Klassen und Interfaces Allgemeine Java-Themen 2
C Fehler beim Debuggen von Listen Allgemeine Java-Themen 4
L File beim Kopieren in einen anderen Ordner umbenennen Allgemeine Java-Themen 6
B Input/Output Probleme beim Ausführen von Shell-Befehlen mit Java Allgemeine Java-Themen 28
J Probleme beim einbinden von Zip4j library Allgemeine Java-Themen 6
T Compiler-Fehler NoClassDefFoundError beim Laden einer Class Allgemeine Java-Themen 11
S Seitenausrichtung beim Drucken Allgemeine Java-Themen 1
RalleYTN Brauche Hilfe beim Run-Length-Decoding Allgemeine Java-Themen 9
R Optimierung beim Vergleichen von 2 Bildern Allgemeine Java-Themen 23
F SQLite mit Java / Probleme beim INSERT Befehl Allgemeine Java-Themen 4
I Fehler beim Ant-Package erstellen mit Java 9 Allgemeine Java-Themen 1
S Eclipse Probleme beim Implementieren / Ausführen von jUnit 5-Test Suites Allgemeine Java-Themen 14
M Beim Öffnen Dialog Directory und Filetype definieren Allgemeine Java-Themen 2
G Problem beim GUI Allgemeine Java-Themen 9
A Probleme beim Verstehen einer Aufgabenstellung Allgemeine Java-Themen 11
A OOP Problem beim Berechnen der größten Fläche eines Ringes Allgemeine Java-Themen 19
F Problem beim Einlesen einer Textdatei Allgemeine Java-Themen 12
J Konstruktor in JSP beim Kompilieren nicht gefunden Allgemeine Java-Themen 3
perlenfischer1984 Probleme beim Mocken Allgemeine Java-Themen 6
A Fehler beim Aktualisieren JTable Allgemeine Java-Themen 1
D Pivot-Wahl beim QuickSort steigert die Effizienz, eine Lüge??? Allgemeine Java-Themen 17
J-Gallus Erste Schritte Wahrscheinlich Anfänger Fehler beim rechnen. Falsches Ergebnis. Allgemeine Java-Themen 9
U Swing Hilfe beim Quellcode für ein Codierungs-/Decodierungsprogramm Allgemeine Java-Themen 9
H Beim Konstruktor "this" Allgemeine Java-Themen 4
I Problem beim Aufrufen, von Objektmethoden/ -variablen Allgemeine Java-Themen 6
J Interpreter-Fehler Fehler beim Verschlüsseln Invalid AES key length Allgemeine Java-Themen 1
R probleme beim starten von jar unter linux Allgemeine Java-Themen 2
Thallius Swing Merkwürdiges Verhalten beim Panel Tausch Allgemeine Java-Themen 3
Tacofan Sound beim öffnen der GUI Allgemeine Java-Themen 8
Z NullPointerException beim Schreiben einer ArrayList in eine Datei Allgemeine Java-Themen 6
B Endlosschleife beim Verteilen von Objekten Allgemeine Java-Themen 4
V JavaFX Fehler beim Starten einer Jar Allgemeine Java-Themen 7
B Fortschritt beim Schreiben einer Datei ausgeben lassen Allgemeine Java-Themen 7
J JDK installieren Das Jdk funtioniert beim Editor nicht. Allgemeine Java-Themen 3
R Verdrückt beim Sicherheitshinweis Allgemeine Java-Themen 2
M Probleme beim rechnen, bei Zahlen mit führenden Nullen. Allgemeine Java-Themen 7
javampir Input/Output Effizienz beim binären Lesen einer Datei Allgemeine Java-Themen 6
javampir Seltsame Lücken beim Abspielen von Sound Allgemeine Java-Themen 2
RalleYTN JAnsi Warum bleiben die Hintergrundfarben beim Reseten der Konsole? Allgemeine Java-Themen 0
T BufferedImage verändert sich beim Einlsesen Allgemeine Java-Themen 1
E JCuda-0.6.5 Probleme beim ausführen der Datei Allgemeine Java-Themen 0
S Verständnisproblem beim Mocking Allgemeine Java-Themen 8
W JNDI - LDAP - Probleme beim editieren von Usern Allgemeine Java-Themen 0
Athena Programm funktioniert nur beim Debugging korrekt, sonst nicht. Allgemeine Java-Themen 1
N Zahlensysteme umrechnen; Probleme beim Umwandeln Allgemeine Java-Themen 4
K Fehler beim erstellen von .jar Datei Allgemeine Java-Themen 3
M Eclipse Fehler beim Installieren des Plugins "Jigloo" Allgemeine Java-Themen 12
A Eclipse - Fehler beim "RUN" - "Unable to Launch - The selection cannot be launched" Allgemeine Java-Themen 6
G StackoverflowError beim laden einer FXMML Datei Allgemeine Java-Themen 1
L Methoden Methode gibt mir beim verschlüsseln mit RSA 0 bytes aus ? Allgemeine Java-Themen 1
D Selenium WebDriver HtmlUnitDriver Problem beim Automatisieren Allgemeine Java-Themen 1
A Probleme beim auslesen von Quelltext (HTML) Allgemeine Java-Themen 5
D Input/Output Zeilen werden "ignoriert" beim Einlesen aus einer Textdatei Allgemeine Java-Themen 3
L Suchvorschläge beim eingeben einzelner Buchstaben Allgemeine Java-Themen 3
B Compiler-Fehler NullPointerException beim Auslesen von .lang-Datei Allgemeine Java-Themen 3
U Eclipse Java Programm beschädigt .tar.gz dateien beim Entpacken Allgemeine Java-Themen 7
B Fehler beim Auslesen von Einstellungen. Zwei ähnliche Blöcke, nur eins geht. Allgemeine Java-Themen 5
P Auf die Anzahl der Joins achten beim WS design Allgemeine Java-Themen 1
reibi Classpath Classpath Variable beim Tomcat Allgemeine Java-Themen 2
H JUnit Fehler beim Compilieren - erledigt Allgemeine Java-Themen 0
J Fehler beim parsens eine Datums Allgemeine Java-Themen 3
A Java - Beim Abspeichern Redundanzen vermeiden! Allgemeine Java-Themen 6
L einfache Verzinsung mit for-Schleife & Ausschluss von Werten beim Einlesen Allgemeine Java-Themen 5
C Bufferoverflow beim eigenen simpeln Programm Allgemeine Java-Themen 4
MiMa Umlaute beim Einlesen von Dateinamen Allgemeine Java-Themen 12
G Fehler beim instanzieren einer Generischen Klasse Allgemeine Java-Themen 5
K Eclipse Fehler beim Ausführen meines Programms in Eclipse Allgemeine Java-Themen 11

Ähnliche Java Themen


Oben