# Unabhängige Auslieferung bei Vererbung



## langhaar! (26. Okt 2012)

Hallo,

in unserem Unternehmen gibt es auf hoher Ebene starke Ressentiments gegen Vererbung.
Argumentiert wird damit, dass eine Vererbung 
- im Gegensatz zu einer losen Kopplung durch Methoden - 
eine starke Bindung von Vater- und Kindklassen herstellt.

"bei der Vererbung gibt es eine undefinierte  aber sehr  starke Bindung zischen Oberklasse und erbender Klasse.
 Bekannt ist in diesem Zusammenhang das Kopieren von Konstanten von der oberen Klasse in die erbende Kasse."

Aufgrunddessen sollen Änderungen an Oberklassen ohne Kentnisse der Unterklassen kaum möglich sein. 
Umgekehrt ebenso. Bei einer Änderung der Oberklasse müssten auch alle Kindklassen erneut getestet werden.

Um die obigen Ausführungen zu verstehen, ist zu ergänzen, 
dass die Auslieferung des Codes Klassenweise erfolgt. 
Der Kunde bekommt genau die Klassen, die für ihn geändert wurden
 (Oft ist dies zu einem Bereich nur eine, in der monolithisch mehrere Tausend Zeilen Code stehen).


Was ist zu beachten, wenn Vater und Kindklasse bei Bedarf separat ausgeliefert werden sollen?
D.h., beide Klassen sind evtl. schon Jahre im Einsatz und es soll eine der beiden ausgetauscht werden.
Dass sich die Schnittstellen nicht verringern dürfen, ist klar. Was gilt für Erweiterungen? 
Bei welchen Änderungen der Vaterklasse muss die Kindklasse zwingend neu kompiliert werden?


----------



## maki (26. Okt 2012)

Hi,



> in unserem Unternehmen gibt es auf hoher Ebene starke Ressentiments gegen Vererbung.
> Argumentiert wird damit, dass eine Vererbung
> - im Gegensatz zu einer losen Kopplung durch Methoden -
> eine starke Bindung von Vater- und Kindklassen herstellt.
> ...


klingt nach "Favour Composition over  Inhertiance" und ist erstmal richtig.



> Um die obigen Ausführungen zu verstehen, ist zu ergänzen,
> dass die Auslieferung des Codes Klassenweise erfolgt.
> Der Kunde bekommt genau die Klassen, die für ihn geändert wurden
> (Oft ist dies zu einem Bereich nur eine, in der monolithisch mehrere Tausend Zeilen Code stehen).


Klingt sehr schräg..

Wie dem auch sei, sowas lässt sich mit vernünftigem Configmanagement in den Griff bekommen.



> Was ist zu beachten, wenn Vater und Kindklasse bei Bedarf separat ausgeliefert werden sollen?
> D.h., beide Klassen sind evtl. schon Jahre im Einsatz und es soll eine der beiden ausgetauscht werden.
> Dass sich die Schnittstellen nicht verringern dürfen, ist klar. Was gilt für Erweiterungen?
> Bei welchen Änderungen der Vaterklasse muss die Kindklasse zwingend neu kompiliert werden?


Bei allen Änderungen der Vaterklasse müssen die Kindklassen neu kompiliert werden.


----------



## langhaar! (29. Okt 2012)

maki hat gesagt.:


> Bei allen Änderungen der Vaterklasse müssen die Kindklassen neu kompiliert werden.



Tests von mir und Kollegen haben gezeigt, dass das nicht stimmt. :autsch:
So kann z.B. problemlos die Vaterklasse um eine neue Methode ergänzt werden und die class-Files der neuen Vater- und der alten Kindklasse arbeiten wie gewohnt zusammen.


----------



## SlaterB (29. Okt 2012)

das war wohl eher ein allgemeiner Hinweis/ Vorschlag als die absolute technische Klärung,
wenn du schon selber testest, wozu die Frage, hast du eine bestimmte Absicht?

man kann ja von Java-API-Klassen wie ArrayList usw. erben, letztlich muss man immer von Object erben,
und diese kompliliert man auch nicht neu..,

die grundsätzlichen Regeln dürfte doch überschaubar sein, du nennst sie selber,
Schnittstellen nicht ändern, alles was auch bei normalen Neukompilieren zweier Klassen in einem Projekt entweder zu Fehler führt oder eben in der Subklasse mitgeändert werden muss,

andersrum gibt es gar nichts, was sich auf die Super-Klasse auswirkt,
wenn man natürlich neuen Konstruktor/ Methode mit super() aufrufen will..


----------



## Lowpass (29. Okt 2012)

Eine starke Meinung zum Thema Composition vs. Inheritance zu haben und gleichzeitig Klassen mit unüberschaubarem Umfang zuzlassen (_mehrere *tausend* Zeilen Code_) finde ich komplett schräg.. ebenso, .class-Files einzeln auszuliefern/auszutauschen. 
Was verspricht man sich von dieser einzelnen, stückchenhaften Auslieferung?


----------



## langhaar! (29. Okt 2012)

SlaterB hat gesagt.:


> wenn du schon selber testest, wozu die Frage, hast du eine bestimmte Absicht?


Steht oben. Ich erläuter es noch man näher. Es werden einzelne Class-Dateien ausgeliefert. Das kann ich auch nicht ändern und ist hauptsächlich dadurch begründet, dass ein validiertes Umfeld vorliegt (Pharma) und die Kunden alles, was sie bekommen, testen müssen. Da kann für eine Anpassung oder Korrektur keine Gesamtauslieferung gemacht werden.

Es gibt Kollegen, die lehnen die Vererbung grundsätzlich ab, da die Abhängigkeit von Vater und Kindklassen nicht genau definiert sei; also eine geänderte Vaterklasse nicht auslieferbar sei (ohne Vater und Kindklasse neu zu kompilieren und beide zu testen).




> die grundsätzlichen Regeln dürfte doch überschaubar sein, du nennst sie selber,
> Schnittstellen nicht ändern, alles was auch bei normalen Neukompilieren zweier Klassen in einem Projekt entweder zu Fehler führt oder eben in der Subklasse mitgeändert werden muss,


Wie gesagt, meine Meinung steht gegen andere und selber testen gibt Hinweise, ich hätte es aber gern genauer oder noch besser irgendwo dokumentiert.



Lowpass hat gesagt.:


> Eine starke Meinung zum Thema Composition vs. Inheritance zu haben und gleichzeitig Klassen mit unüberschaubarem Umfang zuzlassen (_mehrere *tausend* Zeilen Code_) finde ich komplett schräg.. ebenso, .class-Files einzeln auszuliefern/auszutauschen.
> Was verspricht man sich von dieser einzelnen, stückchenhaften Auslieferung?


Sollte jetzt hoffentlich ein bisschen klarer sein. Die Größe der Klassen resultiert aus den prozeduralen Programmiergewohnheiten der Entwickler...


----------



## SlaterB (29. Okt 2012)

ich weiß nicht genau ob es deine Frage betrifft, 
aber neben dem technischen Teil des Kompilierens ist die inhaltliche Durchmischung ein Thema, 
welches das fachliche Testen (eben über das reine Kompilieren als Syntax-Test hinaus) erfordert

wenn eine Super-Klasse in der Methode X seine Attribute anders bearbeitet als zuvor (um mal völlig vage zu bleiben..)
dann dürften die Sub-Klassen, die X verwenden und die Attribute auslesen, anders ablaufen

wie sich das schon liest hat das aber nicht unbedingt mit Vererbung zu tun, auch bei Komposition unabhängiger Klassen
tritt dasselbe auf, wenn sie sich gegenseitig nutzen,
geänderte Konstanten aus anderen Klassen sind nicht schlimmer als geerbte geänderte Konstanten,
jede Änderung im relevanten Bereich erfordert Neutesten von Allem


falls soweit schon richtige Gedanken, dann ist deine Frage womöglich, 
ob speziell Vererbung statt Komposition besondere weitere Probleme macht?
hmm


----------



## langhaar! (29. Okt 2012)

SlaterB hat gesagt.:


> falls soweit schon richtige Gedanken, dann ist deine Frage womöglich,
> ob speziell Vererbung statt Komposition besondere weitere Probleme macht?
> hmm



Richtig.


----------



## faetzminator (29. Okt 2012)

Habt ihr da denn keine (J)Unit-Tests, welche ihr laufen lassen könnt :bahnhof: ?


----------



## langhaar! (29. Okt 2012)

Nein. Vom Umfang her kaum machbar. Zumindest die Einsicht, dass es schön wär, welche zu haben, ist da.


----------



## faetzminator (29. Okt 2012)

Irgendwann muss man beginnen. Ich verstehe, dass es schwer und mühsam ist. Aber warum nicht einfach ab den aktuellen Änderungen Tests schreiben? Ist anfänglich vielleicht nur 1% des Codes (teste es mit EclEmma, Coverclipse o.ä.), wird aber nach und nach mehr


----------



## langhaar! (29. Okt 2012)

Ist in Planung und in Teilen auch vorhanden, möchte ich an dieser Stelle aber nicht vertiefen.


----------



## faetzminator (29. Okt 2012)

Ich verstehe dich, aber eine andere Antwort kannst du nicht erwarten, da dies lediglich eine Symptombekämpfung ist und nicht das Problem bei der Wurzel packt... Keine Vererbung verwenden, weil die Klassen einzeln reinschneien...


----------



## SlaterB (29. Okt 2012)

langhaar! hat gesagt.:


> Richtig.



maki hat ja 'Favour Composition over Inheritance' genannt,
wenn man dazu nachliest kommen schon paar Ideen

beim ersten Link
Favour Composition over Inheritance (FCoI) - Clean Code Developer

"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) 

-> eine Klasse könnte in einer Revision intern Attribute/ verstecktes Verhalten verändern und trotzdem nach außen unverändert bleiben,
eine erbende Klasse hat vielleicht stärkeren Zugriff auf Zwischenergebnisse statt allein public-Zustand 
und ist von den Änderungen doch betroffen

-------

neues Verhalten:
eine List-Subklasse kontrolliert add(), remove() usw., lädt/ löscht entsprechende Objekte aus dem DB-Cache

nun wird in der Super-Klasse eine neue Methode clear() eingefügt, die es bisher (angenommen) nicht gab,
ohne remove() & Co. zu benutzen werden die Daten entfernt, die Sub-Klasse ist aber nicht mit geändert worden, verschläft ihre nötigen Aktionen

mit Komposition wäre das nicht möglich, dann könnte niemand an der Cache-Liste clear() aufrufen,
sofern nicht auch diese Methode unterstützt wird, an die interne richtige Liste sollte niemand rankommen


----------



## langhaar! (29. Okt 2012)

Den Link hatte ich mir auch angesehen 
und die Stelle 'inheritance breaks encapsulation' hat mich ins Grübeln gebracht.

Sollte meines Erachtens mit 'sauberen' Schnittstellen zu lösen sein und ist kein Grund, Vererbung komplett zu verdammen.

Werd' ich noch mal drüber meditieren.
Ich denke genau das ist die Stelle, an der es zu argumentieren gilt.

Technisch scheint es ja beim Austausch von Class-Files und Vererbung keine anderen Probleme zu geben, als bei Komposition. Dann ist zumindest der Punkt, dass die Bindung von Vater- und Kindklasse 'undefiniert' sei, hinfällig. ???:L


----------



## Aiwendil (29. Okt 2012)

Nur um mal die Sprache auf die eigentliche Frage zu bringen (nachdem wir den "warum willst du das überhaupt" und denn "aber das ist schlecht und du bist böse wenn du das so machst" Teil hoffentlich endlich hinter uns haben):

Wann du Kindklassen oft neu kompilieren musst: wenn sich statische Methoden oder statische/finale Konstanten ändern, da diese teilweise (wann genau weiß ich auch nicht) inline mit in ander Kompilate wandern.


----------



## langhaar! (29. Okt 2012)

Aiwendil hat gesagt.:


> Wann du Kindklassen oft neu kompilieren musst: wenn sich statische Methoden oder statische/finale Konstanten ändern, da diese teilweise (wann genau weiß ich auch nicht) inline mit in ander Kompilate wandern.



Mist. Genau so etwas habe ich gerüchteweise gehört (steht auch direkt schon im Eingangsbeitrag, 7. Zeile), konnte oder wollte es aber nicht so ganz glauben.


----------



## Ark (29. Okt 2012)

Ich hab's gerade mal ausprobiert: Das Inlining von solchen Konstanten passiert nicht nur bei einer Vererbungsbeziehung, sondern generell. D.h., wenn eine Konstante in einer Klasse geändert wird, müssen alle Klassen, die diese Konstante benutzen, ebenfalls neu kompiliert werden.


```
public static final double TESTTESTTEST = Math.PI;
```


```
// Field descriptor #6 D
  public static final double TESTTESTTEST = 3.141592653589793;
```
Ark


----------



## langhaar! (29. Okt 2012)

Cool! Danke! Dann hat die Vererbung vielleicht doch noch eine Chance...


----------



## Ark (29. Okt 2012)

langhaar! hat gesagt.:


> Mist. Genau so etwas habe ich gerüchteweise gehört (steht auch direkt schon im Eingangsbeitrag, 7. Zeile), konnte oder wollte es aber nicht so ganz glauben.





langhaar! hat gesagt.:


> Cool! Danke! Dann hat die Vererbung vielleicht doch noch eine Chance...


… Hä? xD

Ark


----------



## langhaar! (29. Okt 2012)

Bislang dienten die Konstanten als Argument für die undefinierte Bindung zwischen Vater- und Kindklasse.
Da dies aber genauso die Komposition betrifft, ist es kein Argument mehr, um keine Vererbung einzusetzen.


----------

