# Frage zu a)Innere Klassen und b)OO Design



## WeirdAl (11. Jul 2007)

Hallo,
ich programmiere nu schon einige Zeit mehr oder weniger in Java, aber habe mir das Wissen bislang immer über APIs und Foren anhand von konkreten Problemstellungen "nähergebracht". Um mein Wissen über Java auszubauen bzw. zu vertiefen, habe ich mir fürs Erste Bruce Eckels Thinking in Java besorgt. 

a)
Naja egal, jedenfalls behandelt er in seinem Buch intensiv Innere Klassen und zählt u.A. auf, wie man das Factory Pattern mit anonymen Inneren Klassen schöner darstellen kann. Ich habe bislang Innere Klassen nur für enums und im Swing Bereich genutzt. Ansonsten habe ich die Klassen immer in eine eigene Datei gelegt, da ich dies für "schöner" gehalten habe.

Nun zu meiner Frage: Ist es im Allgemeinen eine Geschmacksfrage, ob man Innere Klassen nutzt? Bzw. man kann ja mit Inneren Klassen "private" Klassen, Klassen die nur innerhalb einer Methode sichtbar sind und anonyme Innere Klassen bauen. Wo liegt darin der Sinn bzw. kann mir jemand ein Beispiel dazu geben? (ich glaube private innere Klassen benutzt man für Swing + addActionListener(this) - aber da bin ich mir echt nicht sicher )


b) 
Bruce Eckel schreibt das man "gegen" Klassen und nicht "gegen" Interfaces programmieren sollte, da es ansonsten das Design verkomplizieren kann. Man sollte nur Interfaces nutzen, wenn man merkt das es sinnvoll ist bzw. benötigt wird. (D.h. nicht pro forma einfach alles abstrahieren). Irgendwie ist das gerade anders herum, wie ich es in anderen Büchern gelesen habe. 

Meine Frage hierzu: was haltet ihr davon? Ich finde die Aussage eigentlich "ok", da man recht fix sein Design hat, da man net überall nach potentiellen Interfaces sucht (falls man das überhaupt macht). Man kann sich danach erstmals aufs programmieren konzentrieren und später, falls Änderungen anstehen, das Design an den passenden Stellen ändern. Aber da ich nicht soviel Projekterfahrung habe, jedoch demnächst in einem Team mitarbeite, würde ich vorab gerne Wissen was ihr davon haltet.


Ich hoffe Ihr könnt mir da ein wenig weiterhelfen. Irgendwie vermittelt mir Bruce, dass Innere Klassen super wichtig sind und mir kommts so vor als hätte ich bislang was verpasst 

Cu
Alex


----------



## Beni (11. Jul 2007)

a)
Ich benutze selbst viele innere Klassen. Innere Klassen benutze ich vorallem für hochspezialisierten Code, den niemanden mehr erweitern wird. Lokale Klassen (die in den Methoden), und anonyme Klassen sind dann noch eine Stufe schärfer in ihrer Nicht-Wiederverwendbarkeit.

Vielleicht hilft dir auch ein Grössenkriterium:
Lokale/Anonyme Klassen: < 10 Zeilen Code
Innere Klassen: < 100 Zeilen Code
Normle Klasse: 10 - 5000 Zeilen

b)
Nunja, so ein Allgemeinplatz ist schwer zu widersprechen. Andererseits ist ein "Design einfach halten und fluchen, wenn man es erweitern muss" auch nicht toll. Es kommt auf das richtige Mass an.
Ich denke, das hängt sehr vom Projekt ab: eine Library die nicht abstrahiert, kann man in die Mülltonne werfen. Hier würde ich im Zweifellsfall lieber ein Interface zuviel als zuwenig haben.
Ein spezialisiertes Programm hingegen muss nicht allzusehr abstrahiert sein. Hier ist dann oft weniger mehr.


----------



## hupfdule (11. Jul 2007)

a)

Ich benutze innere Klassen nur dort, wo die Funktionalität so gering ist, dass ich quasi "ein schlechtes Gewissen" hätte, sie in eine extra Datei zu packen. ;-)
Das ist in der Regel auch nur der Fall, wenn die Funktionalität der inneren Klasse nur in der umschließenden Klasse benötigt wird. Anonyme Klassen verwende ich schon häufiger. Und du hast richtig erkannt, dann i.d.R. im Zusammenhang mit Listenern. 

b)
Ja, das ist etwas, was mir auch sehr am Herzen liegt. Es ist leider _sehr_ häufig, dass aus Prinzip gegen ein Interface programmiert wird und dann haufenweise Interfaces herum liegen, die nur von einer einzigen Klasse implementiert werden. In kleinen Projekten mag das noch schick sein, in großen, mit besonders vielen Interfaces ist es einfach nur noch ein Grauen (ich bin grad in so einem Projekt....).
Viel sinnvoller ist es ständig zu prüfen, ob ein Refactoring Sinn macht und in diesem eine Abstrahierung durch Interfaces.
Natürlich kann man auch in vielen Fällen schon zu Beginn abschätzen, dass sich Interfaces lohnen. Dann sollte man sie auch gleich einsätzen. Gegen den Grundsatz "Immer gegen Interfaces programmieren" bin ich jedoch strikt, da er quasi immer falsch aufgefasst wird und zu unübersichtlichen Architekturen führt.


----------



## Philip (12. Jul 2007)

hupfdule hat gesagt.:
			
		

> b)
> Viel sinnvoller ist es ständig zu prüfen, ob ein Refactoring Sinn macht und in diesem eine Abstrahierung durch Interfaces.
> Natürlich kann man auch in vielen Fällen schon zu Beginn abschätzen, dass sich Interfaces lohnen. Dann sollte man sie auch gleich einsätzen. Gegen den Grundsatz "Immer gegen Interfaces programmieren" bin ich jedoch strikt, da er quasi immer falsch aufgefasst wird und zu unübersichtlichen Architekturen führt.



Das seh ich anders. Interfaces machen es übersichtlicher, weil sie die Spezifikation von der Implementierung trennen. Also APIs bestehen bei mir immer fast komplett aus Interfaces und die Implementierung "versteckt" sich dahinter. Und ich wüsste auch nicht, was daran auszusetzen wäre.


----------



## Tellerrand (12. Jul 2007)

> "Interfaces machen es übersichtlicher, weil sie die Spezifikation von der Implementierung trennen."
Jain, hier wird keiner für jede Klasse ein Interface programmieren um die Spezifikation immer von der Implementierung zu trennen. Oder legt hier jedemand für jede Klasse ein Interface an?

> "Also APIs bestehen bei mir immer fast komplett aus Interfaces und die Implementierung "versteckt" sich dahinter."
Kannst du dazu ein Beispiel bringen? Vor wem versteckst du welche Implementierung?
Und wie greift man auf eine API zu, wenn man von außen nur ein Interface sieht? Von diesem Interface kann man ja keine Instanz erzeugen.

> "Und ich wüsste auch nicht, was daran auszusetzen wäre."
Du hast jede Menge Interfaces und Klassen.
Weniger Klassen bedeutet bessere Übersicht.


hupfdule hat es in meinen Augen schon recht gut beschrieben, sobald ein Interface existiert, welches von nur einer Klasse implementiert werden soll, hat man es ein wenig zu kompliziert gemacht.
Ich würde es persönlich anderst (und drastischer) formulieren: Ein Interface bitte nur dann erstellen, wenn es seine Bestimmung (Ersatz für Mehrfachvererbung) erfüllt. Trennung von Implementierung und Spezifikation ist aufgrund guter IDEs, oder auch JavaDoc nicht nötig und würde nur die Klassenanzahl vergrößern.

EDIT: Wirrwar behoben


----------



## Beni (12. Jul 2007)

Dass weniger Klassen höhere Übersicht bedeutet, halte ich für ein Gerücht. Dann schreib ich ja wohl am besten von nun an 10'000 Codezeilen-Klassenmonster, möglichst ohne Kommentare um Platz zu sparen?
Eine gute Unterteilung der Klassen in Modulen, sortiert nach Zusammengehörigkeit/Aufgabe ist IMHO wesentlich wichtiger als möglichst komprimierter Code. Und für diese Trennung sind Interfaces gut:

> Ein Interface bitte nur dann erstellen, wenn es seine Bestimmung (Ersatz für Mehrfachvererbung) erfüllt.

"Interface" heisst "Schnittstelle", nicht "Ersatz für Mehrfachvererbung". Und als Schnittstellen sollten sie dazu dienen Module sauber voneinander zu trennen.
Dann kann man die Module nämlich getrennt verwenden, neu kombinieren, ersetzen, ... ohne ein ganzes Projekt refactorieren zu müssen, und ohne das ganze Projekt verstehen zu müssen.


----------



## byte (13. Jul 2007)

zu b) Bruce Eckel schreibt nicht, dass man gegen Klassen programmieren soll und nicht gegen Interfaces. Er sagt lediglich, dass er der Meinung ist, dass man es von Fall zu Fall entscheiden muss. Sobald für einen Typ denkbar ist, dass es unterschiedliche Implementierungen gibt oder irgendwann geben kann, empfiehlt er selbstverständlich die Verwendung von Interfaces/abstrakten Klassen.

Aber er ist halt der Meinung, dass man im Zweifel das Interface weglassen soll, also dann, wenn es nur eine Implementierung gibt und es nicht denkbar ist, dass irgendwann eine zweite hinzukommt. Dann reicht eine einfache Klasse aus, um den Code nicht unnötig aufzublähen.

Ich sehs übrigens ähnlich wie er. Ich halte es nicht vor schlau, sich blind an irgendwelche Konventionen zu halten. Man muss immer schauen, welchen Zweck die Konvention verfolgt und sie dann gezielt dort einsetzen, wo es Sinn macht. So eben auch beim programmieren gegen Schnittstellen.


----------



## Philip (13. Jul 2007)

Also ich teile nicht die Auffassung von Bruce. Natürlich bin ich auch dafür, dass man es nicht zu kompliziert machen sollte. Aber ich finde, ein Interface kann auch Sinn machen, wenn es nur von einer Klasse implementiert wird. Ich bin der Meinung, dass man lieber ein Interface zuviel als zu wenig schreiben sollte.



			
				Tellerrand hat gesagt.:
			
		

> > "Also APIs bestehen bei mir immer fast komplett aus Interfaces und die Implementierung "versteckt" sich dahinter."
> Kannst du dazu ein Beispiel bringen? Vor wem versteckst du welche Implementierung?
> Und wie greift man auf eine API zu, wenn man von außen nur ein Interface sieht? Von diesem Interface kann man ja keine Instanz erzeugen.



Also mit API meine ich nicht nur ein Interface/Klasse, sondern einen Haufen von Interfaces/Klassen. Nenn' es von mir aus Bibliothek, Framework oder sonst irgendwas.
So erzeugt man die Instanzen: http://de.wikipedia.org/wiki/Fabrikmethode
Die Implementierung wird vor dem Benutzer der API versteckt. Es soll sichergestellt werden, dass er auch wirklich nur die Methoden nutzt, die für ihn bestimmt sind, eben wie der Name schon sagt: Interface. 
Der Vorteil ist auch, wie Beni auch schon geschrieben hat, dass man bei einem Refactoring die Implementierung komplett austauschen kann, ohne dass man sich Sorgen machen muss, dass man irgend eine Methode vergessen hat und andere Programmteile plötzlich nicht mehr kompilieren, weil irgendwas fehlt. Wenn sich an der Schnittstelle etwas ändert, dann muss ich das auch nach aussen zu meinen Kollegen kommunizieren, während ich in meiner Implementierung rumwerkeln kann wie ich will. 

Wenn ich ne Klasse als Schnittstelle zu meinen Kollegen verwende, die von denen über den Konstruktor erzeugt wird und ich hinterher feststelle "oh, jetzt brauch' ich auf einmal doch verschiedene Implementierungen, jetzt wechsel ich auf ein Interface". Dann müssen die deshalb plötzlich ihren Code ändern? Ne, da nehme ich lieber gleich ein Interface und bin meine Sorgen los.


----------



## Tellerrand (13. Jul 2007)

@Beni

> "Dass weniger Klassen höhere Übersicht bedeutet, halte ich für ein Gerücht. Dann schreib ich ja wohl am besten von nun an 10'000 Codezeilen-Klassenmonster, möglichst ohne Kommentare um Platz zu sparen?"

Geht doch nicht darum x Zeilen Code in möglichst wenig Klassen unterzubringen, sondern darum eben nicht mehr Code und mehr Interfaces zu erstellen.
Wenn ich die Wahl habe zwischen "ich lass es so" und "ich bastel noch 5 bis 50 Interfaces ins Projekt", dann ist ersteres übersichtlicher.


> "Eine gute Unterteilung der Klassen in Modulen, sortiert nach Zusammengehörigkeit/Aufgabe ist IMHO wesentlich wichtiger als möglichst komprimierter Code. Und für diese Trennung sind Interfaces gut:"

Für die Kapselung/Spaltung eines Programms in Module braucht es imo keine Interfaces, ich wüsste nicht wieso, hast du da Beispiele?
Ich habe mir da vor Zeiten mal den Grundsatz angeeignet, dass ich ein Interface erst dann nutze, wenn eine abstrakte Klasse nichtmehr funktionieren würde.
Sprich, ich nutze erst dann Interfaces, wenn ich eine Schnittstelle programmieren muss die auch von mehreren Klassen implementiert werden soll. (Da sind wir wieder bei Mehrfachvererbung)


> ""Interface" heisst "Schnittstelle", nicht "Ersatz für Mehrfachvererbung". Und als Schnittstellen sollten sie dazu dienen Module sauber voneinander zu trennen."

Ja es heisst Schnittstelle, aber sie sind dennoch aufgrund der fehlenden Mehrfachvererbung in Java vorhanden. Die Namensgebung würde ich eher darauf zurückführen, dass die Mehrfachvererbung extrem wichtig für Schnittstellen ist. 
_Interfaces erlauben die Mehrfachvererbung wenigstens zum Teil._
Würde es die Mehrfachvererbung geben bräuchte man keine Interfaces 


> "Dann kann man die Module nämlich getrennt verwenden, neu kombinieren, ersetzen, ... ohne ein ganzes Projekt refactorieren zu müssen, und ohne das ganze Projekt verstehen zu müssen."

Wie gesagt, ich kenne da kein Beispiel.
Die Beispiele die ich kenne lassen sich in zwei Schubladen packen:
a) Das Interface welches verwendet wird hätte man auch weglassen können.
b) Es geht nicht anderst aufgrund der fehlenden Mehrfachvererbung.

Eigentlich sind wir uns da auch ziemlich einig, ich verwende nur eine andere Formulierung.
Vielleicht wird das im bezug auf das Factory Beispiel von Philip etwas deutlicher.


@Philip
Die Fabrikklasse ist aber kein Interface 
Es war eher eine rhetorische Frage, denn jedem hier ist klar, dass man irgendwo immer eine Klasse braucht um auf irgendetwas zuzugreifen.

Zu dem Beispiel FactoryPattern.
Nehmen wir die Namen von Wikipedia, dort haben wir das Interface "Produkt".
Wenn man sich nun die Frage stellt warum das ein Interface ist und keine abstrakte Klasse, dann kommt man zwangsläufig zu der Antwort Mehrfachvererbung.
Man könnte "Produkt" auch als abstrakte Klasse implementieren, würde aber dadurch die Möglichkeit verlieren "KonkretesProdukt" von einer anderen Klasse erben zu lassen.

Warum ich das so umständlich formuliere? Ich habe gemerkt, dass wenn ich es auf diese Weise formuliere, dann programmier ich weniger überflüssige Interfaces in ein Projekt hinein und mir bleibt bewusst, was ich überhaupt mit einem Interface anstelle, oder wozu dieses vorhanden ist.


----------



## WeirdAl (13. Jul 2007)

@Tellerand:
Da ich jetzt mit den Inneren Klassen durch bin habe ich gesehen, dass man auch eine Mehrfachvererbung mit Inneren Klassen erreichen kann. Ich habe das zwar noch nie genutzt und werde es denke ich auch nicht nutzen, aber ich wollte das mal der Vollständigkeit halber gesagt haben  

Zudem habe ich nicht so viel Erfahrung wie ihr, da ich so gesehen Berufseinsteiger bin, aber für mich besteht der Unterschied von abstrakten Klassen zu Interfaces im Grad der Abstraktion.
Als Beispiel was ich meine:
-Beim Template Pattern hast Du normal ja auch eine abstrakte Klasse, die nur einen Teil der Methoden als abstrakt definiert. Dadurch hast Du einen (uU großen) Anteil schon programmiert. 
-Im Interface kannst Du, soweit ich weiß, maximal Konstanten und "Methodenrümpfe" definieren. 


Cu
Alex

P.S.: Im Prinzip kannst Du auch die abstrakte Methode ein Interface implementieren lassen.
P.P.S.: Ich finde die "Diskussion" super interessant und sehr lehrreich


----------



## Beni (13. Jul 2007)

> Geht doch nicht darum x Zeilen Code in möglichst wenig Klassen unterzubringen, sondern darum eben nicht mehr Code und mehr Interfaces zu erstellen.
> Wenn ich die Wahl habe zwischen "ich lass es so" und "ich bastel noch 5 bis 50 Interfaces ins Projekt", dann ist ersteres übersichtlicher.

> Für die Kapselung/Spaltung eines Programms in Module braucht es imo keine Interfaces, ich wüsste nicht wieso, hast du da Beispiele?

Nunja, deine Kernaussage ist "weniger ist mehr". Und ich behaupte, dass das so nicht richtig ist :bae:
Meine Kernaussage ist "eine Trennung/Ordnung ist wichtiger".

Ich bezweifle nicht, dass es möglich ist, ohne ein einziges Interface auszukommen. Nur bezweifle ich, dass das Projekt dadurch übersichtlicher wird. Also es geht mir keinesfalls um die rein technischen Möglichkeiten.

> Die Beispiele die ich kenne lassen sich in zwei Schubladen packen:
> a) Das Interface welches verwendet wird hätte man auch weglassen können.
> b) Es geht nicht anderst aufgrund der fehlenden Mehrfachvererbung.

Beispiele für a) gibt es ganz sicher, aber ich behaupte dass es trotz b) auch Beispiele gibt, wenn Java Mehrfachvererbung unterstützen würde. Das Einzige was ich dafür benötige ist deine Einwilligung abstrakte Klasse ohne eine einzige konkrete Methode auch als Interface zu betrachten.

Zum real existierenden Beispiel: ich hab vor einiger Zeit ein Compiler geschrieben. Das Modul Compiler benötigt von irgendwoher eine Eingabe, und muss seine Ausgabe irgendwohin kritzeln können. Also habe ich mir ein Interface "Environment" definiert, welches eine "read" und eine "write"-Methode besitzt (ich will nicht zusehr in die Details gehen, aber ein einfacher Input/OutputStream reicht hier nicht).
Andere Module implementieren nun "Environment", einmal um von der Festplatte zu lesen/schreiben; einmal um die Konsole zu benutzen; einmal für eine Mini-IDE (= ein bessere Texteditor).
Die 3 "Environments" haben nicht viel gemeinsam, was soll ich hier mit einer Klasse für Vorschriften machen? Besser ein Interface verwenden, da ist wenigstens jedem klar welche Methoden implementiert werden müssen. Und vor komischen Nebeneffekten wenn man irgendeine Methode verwendet, muss man sich auch nicht fürchten.

Übrigens hab ich einen grossen Teil des Compilers später umgeschrieben (Optimierungen halt, auch Dinge die das Lesen/Schreiben betrifft), ohne an den "Environments" was ändern zu müssen.

> Eigentlich sind wir uns da auch ziemlich einig, ich verwende nur eine andere Formulierung.
"Benutz den Verstand wenn du programmierst?", "Folge nicht blind allen Regeln?", Ja, ich denke da sind wir uns einig :wink:


----------



## Tellerrand (13. Jul 2007)

> "Nunja, deine Kernaussage ist "weniger ist mehr". Und ich behaupte, dass das so nicht richtig ist :bae: Meine Kernaussage ist "eine Trennung/Ordnung ist wichtiger"."

Ich stimme beidem zu und akzeptiere nicht, dass diese im Gegensatz zueinander stehen 


> "Ich bezweifle nicht, dass es möglich ist, ohne ein einziges Interface auszukommen. Nur bezweifle ich, dass das Projekt dadurch übersichtlicher wird. Also es geht mir keinesfalls um die rein technischen Möglichkeiten."

Ich habe nicht gesagt, dass es übersichtlich wäre auf Interfaces zu verzichten.
Das was ich gesagt habe ist: Wenn Mehrfachvererbung existieren würde, dann bräuchte man keine Interfaces.


> Das Einzige was ich dafür benötige ist deine Einwilligung abstrakte Klasse ohne eine einzige konkrete Methode auch als Interface zu betrachten.

Die bekommst du nicht, meine Aussage basiert doch auf dem Unterschied.  :shock: 


> Compilerbeispiel ...

Und auch hier ist es doch das gleiche ... warum verwendest du Interfaces und keine abstrakten Klassen?
Die Antwort darauf ist wieder "Mehrfachvererbung" und ich sage doch, dass ein Interface genau dann Sinn macht.
Meine Begründung ist nur eine andere 


Interessant ist es auch, wenn man ein Projekt, z.B. in UML, mit Mehrfachvererbung plant und ganz zum Schluss diese durch Interfaces ersetzt. Was da rauskommt ist oft ein sehr schönes Design.


----------



## Beni (13. Jul 2007)

Nun dann kann ich dir nicht widersprechen.

(Ich finde Interfaces trotzdem eine schöne Sache, würde sie auch einsetzen, wenn es Mehrfachvererbung gäbe.)


----------



## Philip (18. Jul 2007)

Tellerrand hat gesagt.:
			
		

> > "Nunja, deine Kernaussage ist "weniger ist mehr". Und ich behaupte, dass das so nicht richtig ist :bae: Meine Kernaussage ist "eine Trennung/Ordnung ist wichtiger"."
> 
> Ich stimme beidem zu und akzeptiere nicht, dass diese im Gegensatz zueinander stehen



Naja, sie stehen nicht im Gegensatz, aber es besteht zumindest ein Konflikt, das ist ja wohl klar. Und da würde ich im Zweifelsfall auch eher zu einer sauberen Trennung tendieren, als die lines of code krampfhaft klein halten zu wollen.
Das macht für mich auch die Eleganz von Java aus, dass die Sprache von Grund auf nicht den Anspruch hat, alles in einer Zeile programmieren zu können, sondern dass sinnvolle Strukturen zugrunde gelegt werden.



			
				Tellerrand hat gesagt.:
			
		

> Und auch hier ist es doch das gleiche ... warum verwendest du Interfaces und keine abstrakten Klassen?
> Die Antwort darauf ist wieder "Mehrfachvererbung" und ich sage doch, dass ein Interface genau dann Sinn macht.
> Meine Begründung ist nur eine andere



Naja, aber weißt du das immer vorher schon, wie alles aussehen wird, oder kommen vielleicht nicht doch öfters überraschende Veränderungen?

Meine Philosophie ist halt eher, dass die Spezifikation (Interfaces) getrennt betrachtet wird und zuerst modelliert wird. Und zwar genau so, wie es von dem Benutzer dieser Interfaces gebraucht wird. 
Danach fängt man an, sich über die Implementierung Gedanken zu machen. Dann hat man auch immer noch die Freiheit, mehrere Interfaces durch die selbe Klasse implementieren zu können.
Was ich sagen will: die Aufteilung, die für Benutzer der Schnittstelle sinnvoll ist, muss für den Implementierer der Schnittstelle nicht zwangsläufig genauso sein. Und die sauberste Möglichkeit, die Belange zu trennen sind eben Interfaces. (Ja, man braucht natürlich mindestens eine abstrakte Klasse oder Frameworkunterstützung  )
Vielleicht hat man dann mal ein Interface, auf das man verzichten hätte können, aber ich finde, der Ansatz erleichtert das Denken.

Neben dem Aspekt "keine Mehrfachvererbung von Klassen" kommt für mich also noch der Aspekt "separation of concerns" hinzu, der für Interfaces spricht. Eine (abstrakte) Klasse trennt nicht so gut, da hier schon Teile der Implementierung einfließen. Und durch diesen Aspekt werden Interfaces für mich eher zur Regel als zur Ausnahme.


----------

