# Designfrage - komplexe vs. flache Klassenhierarchie



## JanHH (21. Dez 2012)

Hallo,

habe damals (1997) an der FH gelernt, das man schöne saubere Klassenstrukturen bauen soll... lieber Vererbung und Unterklassen, als Schalter und viele if(...)-Abfragen, um das Verhalten eines Objektes zu steuern.

Ist auch naheliegend, allerdings kommt mir in der modernen java-Welt, speziell JEE, eine flachere Klassenstruktur (wo man durchaus mal mehrere Unterklassen in eine gemeinsame Oberklasse "reinpackt" und mit if-Sachen arbeitet) einfacher vor, vor allem was Persistenz (JPA) und automatische (De-)Serialisierer (XML, JSon) angeht.

Ist es also "in Mode" oder zeitgemäß, die reine Lehre ein wenig pragmatisch aufzuweichen, oder wie geht ihr damit um?

Gruß+Danke
Jan


----------



## KSG9|sebastian (21. Dez 2012)

Meinst du etwa siwas?


```
class Tier{

 public Tier(boolean katze){

 }
  void fo() {
     System.out.println("Ich bin ein " + (katze ? "Kater" : "Hund"));
  }

}
```

Falls ja: Mieses Design!

Ich wüsste auch nicht warum XML/JSON/Hessian-Serialisierung etwas damit zu tun hat.

Mach einfach ein sauberes Design, achte auf das Übliche (KIS, DRY, Singe Responsibility, Co,position over Inheritance)..


----------



## Marco13 (21. Dez 2012)

Ein bißchen darüber philosophiert hatte ich mal in http://www.java-forum.org/softwareentwicklung/76479-tief-darf-vererbungshierarchie.html - aber speziell zur Persistenzfrage kann ich nicht viel sagen, deswegen halte ich mich ansonsten erstmal zurück.


----------



## ARadauer (21. Dez 2012)

Ja auf jeden Fall, also aus Gründen von Performanze und Klarheit kann man sicher die Verberung etwas abflachen.
Auch im Bereich Datenbank Normalisierung, da wird bewusst Redundanz aus Performanze Gründen rein gepackt.

das Beispiel von KSG9 ist natürlich etwas krass, aber wenns konkret um sowas geht, bzw bei einer Entität, ist sicher ein Tier mit der Eigenschaft der Bezeichnung besser, als 3 Subklassen mit Hund, Katze, Maus.
Und wenn wir uns über Services bzw Logik unterhalten würd ich auch Komposition der Vererbung vorziehen.



> die reine Lehre ein wenig pragmatisch aufzuweichen


ja, bin ich absolut dafür!


----------



## Landei (21. Dez 2012)

Vererbung hat auch ihre Schattenseiten (und ich meine nicht nur Unterhaltszahlungen). Besonders kritisch wird es, wenn man Vererbung da einsetzt, wo eigentlich Komposition angesagt wäre. Ich versuche immer zu hinterfragen, welches _Problem_ ich mit einer bestimmten Vererbungsbeziehung zu lösen versucht. Und oft stellt sich selbiges nur als Scheinproblem heraus - dann wird die betreffende Hierarchie-Ebene halt gestrichen.


----------



## JohannisderKaeufer (21. Dez 2012)

Ich beziehe mich einmal auf das Buch:

Enterprise JavaBeans 3.1: Das EJB-Praxisbuch für Ein- und Umsteiger 
von Jan Leßner und Werner Eberling
Allerdings die erste Ausgabe über EJB 3.0

Dort beschreiben sie ein Szenario, bei dem Sie in einer Versicherung, 20 verschiedene Stateless Session Beans hatten, die mehr oder weniger das gleiche gemacht haben. Also die Berechnung eines bestimmten Versicherungstyps. Der Session-Pool für jedes dieser EJB's war auf 1 gesetzt worden.
Das hatte dann zur Folge dass es immer wieder zu wartenden Client-Anfragen kam, wenn das entsprechende Bean bereits rechnete.

Das hatte man dann dahin umgebaut, dass es nur noch ein Session Bean gab, dass alle Versicherungstypen berechnen konnte, je nachdem was in der Anfrage stand.

Den Session-Pool hat man dann auf 20 Instanzen für dieses EJB gesetzt und im Endeffekt eine bessere Performance bekommen.
Vorher konnten nur 20 verschieden Requests parallel verarbeitet werden, nacher waren es 20 Requests die parallel verarbeitet werden konnten.

Ersteres war einfacher zu warten und einfacher strukturiert. Vererbung hätte hier mit Sicherheit gut reingepasst.

Letzteres komplexer, dafür leistungsfähiger. Wird aber doch das ein oder ander if und den ein oder anderen Schalter gebraucht haben.


----------



## ARadauer (21. Dez 2012)

versteh ich nicht...


> Der Session-Pool für jedes dieser EJB's war auf 1 gesetzt worden.


warum, wenn sie stateless sind? 
nur weil ich nicht weiß wie ich mit ejbs umgehe (was ich wirklich nicht weiß ;-)...) muss ich nicht alles in eine klasse stopfen...


----------



## JohannisderKaeufer (21. Dez 2012)

Eine stateless Session Bean hat auch ihren State.

Der Unterschied zu einer Statefull Session Bean besteht darin, daß ein Client hier immer mit der gleichen statefull Session Bean spricht, wohin bei einer stateless Session Bean jeder request von einer anderen beantwortet werden kann.

Und das was eine stateless Session Bean bereithält, kann unter Umständen auch eine kostbare Resource sein. Datenbankverbindungen, Drucker oder andere physische WTFs.

Und die Firma wollte, aus welchen Gründen auch immer sichergehen, daß höchstens 20 Beans, also Objektinstanzen bereitgehalten werden. D.h. dass man den Sessionpool für jedes von 20 Beans auf 1 beschränkt.


Klar, muß nicht alles in eine Klasse gestopft werden, aber es kann auch Vorteile haben.


So ein ejb, kannst du dir wie einen Thread vorstellen, der auf einem Applicationserver läuft.
So ein Thread soll eine Aufgabe erledigen, aber du möchtest nicht für jedes erledigen so einer Aufgabe einen neuen Thread erstellen. Also legst du dir Threadpools an.
Jetzt kannst du dir entweder 20 Verschiedene Threads erstellen, bei der jeder eine bestimmte Aufgabe super kann und legst davon eine Instanz in den Pool.
Oder du baust einen Thread der es schafft alle Aufgaben unter einen Hut zu bekommen und legst 20 Instanzen davon in einen Pool.

Die Begrenzung von 20 Instanzen könntest, du dir mit 20 Rechenkernen


----------



## Bernd Hohmann (21. Dez 2012)

JanHH hat gesagt.:


> Ist es also "in Mode" oder zeitgemäß, die reine Lehre ein wenig pragmatisch aufzuweichen, oder wie geht ihr damit um?



Kommt darauf an.

Die üblichen "Katze extends Tier"-Beispiele sind leider untauglich: der Neuling fragt sich "warum der Umstand?", wird aber in ein Schema gepresst und meint, dass nur so die kommenden Probleme zu lösen sind. Damit arten diese Strukturen eher in das Messie-Syndrom aus ("ich mache das sauber über Vererbung, Interfaces und Factories - es könnte ja mal irgendjemand die Ausgabe nicht ins Web sondern in die Gartenlaube haben wollen").

OOP wird halt erst bei komplexeren Aufgaben spannend und daher bin ich bei Vererbung, Factories und Interfaces immer ganz knauserig und setze es erst ein, wenn es wirklich Sinn macht. Mag auch daran liegen, dass ich 70% meiner Zeit in prozeduralen Sprachen unterwegs bin.

Bernd


----------



## JanHH (24. Dez 2012)

Ich hab mal bei einem Projekt gemäß dem was ich damals gelernt hab eine  relativ komplexe, sehr saubere Klassenhierarchie gebaut (waren alles JPA-Entities), der Projektleiter meinte, meine Güte, und hat alles zusammengestrichen in eine einzige Klasse rein (!), was inhaltlich sogar halbwegs vertretbar war; die redundanten Felder hielten sich in Grenzen. Er meinte, theoretisch wäre mein Ansatz natürlich perfekt, aber in der Praxis handelt man sich bei JPA da so grosse Probleme hinsichtlich Komplexität, Wartbarkeit und Performance ein, das man das einfach nicht mehr so macht.

Und bei Objektserialisierung mit json kommts mir auch einfacher vor. Irgendwie wir die gesamte Anwendung doch deutlich einfacher wenn man die Klassenhierarchie etwas "aufweicht".

Vielleicht reicht es auch aus, zu wissen, wie man es richtig macht. Wie in "der pragmatische Programmierer" steht.. man darf durchaus gegen "die reine Lehre" verstossen beim Softwaredesign, aber nur wenn man weiss, wie es eigentlich korrekt wäre, und die Entscheidung dagegen ganz bewusst, aus pragmatischen Gründen, punktuell trifft, und dies auch entsprechend im Quellcode kommentiert. So finde ich das eigentlich auch vertretbar.


----------



## maki (24. Dez 2012)

JanHH hat gesagt.:


> habe damals (1997) an der FH gelernt, das man schöne saubere Klassenstrukturen bauen soll... lieber Vererbung und Unterklassen, als Schalter und viele if(...)-Abfragen, um das Verhalten eines Objektes zu steuern.


Vermute mal ganz stark, dass sie dir wie allen anderen auch in den 90er Jahren hauptsächlich Quatsch über OOD/OOP erzählt haben 

Die "reine Lehre" ist eben was anderes als das was man uns in den 90er Jahren erzählte.

Von daher kannst du dich schon ruhig an die "reine Lehre" halten, denn diese sagt klar aus dass komplexe & tiefe Vererbungshierarchien ein Problem darstellen, Komposition über Vererbung, vererben von Schnittstellen um Gemeinsamkeiten auszudrücken, nicht vererben vom Implementierungen um Code wiederzuverwenden, usw. usf.

Das J2EE/JEE Programmiermodell hat traditionell starke Tendenzen zur prozeduralen Programmierung, eben dumme Beans als Datenhaltung/Datenstruktur und SessionBeans für die Logik, eben so ziemlich das Gegenteil von OO.
Mittlerweile wäre sauberes OOD möglich in JEE, wird IMHO aber eher selten praktiziert, vor allem wennm so viele Bücher darüber immer noch die prozedurale Sichweise propagieren.

Bei ORM muss man eben verstehen was es für Konsequenzen hat wenn man bestimmte OO strukturieren auf eine Relationale DB abbilden will.


----------



## deetee (24. Dez 2012)

Es gibt seit einigen Jahren bereits ein Design Paradigma "Composition over inheritance". Sehr gut erklärt von CCD: Favour Composition over Inheritance (FCoI) - Clean Code Developer

Alles in eine Klasse zu packen ist auf keinen Fall ratsam, wenn man auf bestimmte Qualitätsrichtlinien und Prinzipien achten möchte. Jeder möchte pragmatisch sein, nur versteht jeder etwas anderes darunter. Ich bezeichne die meisten solcher vermeintlich pragmatischen Lösungen eher als quick & dirty Programmierung. Hin und wieder sind solche Lösungen in der Realität vorzuziehen, aber das macht die Qualität der Lösung ansich nicht besser, dessen sollte man sich bewusst sein.


----------



## Bernd Hohmann (24. Dez 2012)

deetee hat gesagt.:


> Es gibt seit einigen Jahren bereits ein Design Paradigma "Composition over inheritance". Sehr gut erklärt von CCD: Favour Composition over Inheritance (FCoI) - Clean Code Developer



Mir wird bei Aussagen wie _"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."_ immer ganz blümerant.

Anscheinend bin ich der einzige Entwickler auf der Welt, der nur ganz ganz selten mal zur Laufzeit irgendwelche Funktionalität austauschen muss. Wenn ich jede Klassen auf Wiederverwertbarkeit, Flexibilität und Funktionsaustauschbarkeit hin trimmen würde, wäre mein Code ein aufgeblähter Komposthaufen ungenutzter Interfaces.

Bernd


----------



## deetee (24. Dez 2012)

Bernd Hohmann hat gesagt.:


> Mir wird bei Aussagen wie _"...und erschwert das Austauschen von Funktionalität zur Laufzeit."_ immer ganz blümerant.
> 
> Anscheinend bin ich der einzige Entwickler auf der Welt, der nur ganz ganz selten mal zur Laufzeit irgendwelche Funktionalität austauschen muss.
> 
> Bernd



Fällt dir was auf? 

Gerade der Einsatz von Interfaces unterstützt das Austauschen von Verhalten/Funktionalität zur Laufzeit. Desweiteren gibt es genau für solche Anwendungsfälle das ein oder andere Design Pattern, welche wiederum meist mittels OOP implementiert werden, und nicht durch prozedurale Programmierung.

PS:
Oh ich merke gerade, dass du das wahrscheinlich nicht ironisch gemeint hast. Dann kann ich dazu nur sagen, wenn man solche Anforderungen nicht hat, die den Einsatz von Interfaces rechtfertigen würden, dann braucht man natürlich auch keine einsetzen.



Bernd Hohmann hat gesagt.:


> Wenn ich jede Klassen auf Wiederverwertbarkeit, Flexibilität und Funktionsaustauschbarkeit hin trimmen würde, wäre mein Code ein aufgeblähter Komposthaufen ungenutzter Interfaces.



Ich würde es dann eher ein gut sortiertes Werkzeugregal nennen, wo man sich je Anwendungsfall daraus bedienen kann.
Sicher kann man auch die ein oder andere Funktion bei prozeduraler Programmierung wiederverwenden, aber womit würdest du oder deine Kollegen wohl lieber arbeiten, mit einem Werkzeugkasten, wo alles durcheinander geworfen willkürlich herumliegt oder einem Werkzeugregal, wo alles übersichtlich und sortiert an seinem Platz ist?


----------



## maki (24. Dez 2012)

> Sehr gut erklärt von CCD


Das sehe ich anders 



> Mir wird bei Aussagen wie "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." immer ganz blümerant.


Finde ich keine so gute Erklärung, "austauschen von Funktionalität zur Laufzeit" kann viel heissen, vom StrategyPattern bis zu einem Plugin-System.
Meistens heisst "austauschen von Funktionalität zur Laufzeit" dass da jemand Bullshitbingo spielt 

Ganz unten im Link ist dann doch noch eine bessere Erklärung:


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


----------



## Bernd Hohmann (24. Dez 2012)

maki hat gesagt.:


> Finde ich keine so gute Erklärung, "austauschen von Funktionalität zur Laufzeit" kann viel heissen, vom StrategyPattern bis zu einem Plugin-System.
> Meistens heisst "austauschen von Funktionalität zur Laufzeit" dass da jemand Bullshitbingo spielt



Vermutlich geht es um solche Sachen wie "HashMap m = new HashMap()" wo mir dann immer hier im Forum gesagt wird "Map m = new HashMap()" ist besser weil man dann die HashMap problemlos durch was anderes austauschen kann.

Wobei ich mir dabei denke "Momentmal - warum soll ich an dieser Stelle verbergen, dass ich mit einer HashMap arbeite wo ich doch explizit die Funktionalität einer HashMap haben will und das an keiner Stelle zb. durch bernd.util.HeadBanger zu ersetzen ist. Letzteres implementiert zwar auch java.util.Map, hat aber eine ganz andere Funktionalität als die HashMap.



maki hat gesagt.:


> Ganz unten im Link ist dann doch noch eine bessere Erklärung: _"Because inheritance exposes a subclass to details of its parent's implementation, it's often said that 'inheritance breaks encapsulation"_



Da sehe ich eigentlich kein Problem. Ich stelle mir gerade AWT, Swing und SWT ohne diese Klassenhierarchie vor. Auf der anderen Seite: Wenn ich mir einen Stacktrace von Catalina etc. anschaue frag ich mich, ob da wirklich eine solche Vererbungshierarchie notwendig ist.

Bernd


----------



## maki (24. Dez 2012)

> Da sehe ich eigentlich kein Problem. Ich stelle mir gerade AWT, Swing und SWT ohne diese Klassenhierarchie vor. Auf der anderen Seite: Wenn ich mir einen Stacktrace von Catalina etc. anschaue frag ich mich, ob da wirklich eine solche Vererbungshierarchie notwendig ist.


Speziell GUI Frameworks haben oft eine sehr tiefe Hierarchie:
[JavaSpecialists 121] - How Deep is Your Hierarchy?

Generell ist aber die starke Kopplung and die interna der Elternklassen aber DAS Problem bei der Vererbung


----------



## deetee (24. Dez 2012)

Bernd Hohmann hat gesagt.:


> Da sehe ich eigentlich kein Problem. Ich stelle mir gerade AWT, Swing und SWT ohne diese Klassenhierarchie vor. Auf der anderen Seite: Wenn ich mir einen Stacktrace von Catalina etc. anschaue frag ich mich, ob da wirklich eine solche Vererbungshierarchie notwendig ist.
> 
> Bernd



Speziell Swing, bei SWT weiß ich es nicht, implementiert u.a. das Composite und Decorator Pattern, diese basieren zum Großteil auf Vererbung. Vererbung ansich ist nichts schlechtes, das behauptet hier glaube ich niemand.

Der Vorteil beim Einsatz dieser objekt-orientierten Patterns ist nun, dass jeder der das Pattern kennt weniger Probleme hat mit dem Verständnis von Swing bzw. der Architektur und der Anwendung.


----------



## Bernd Hohmann (24. Dez 2012)

maki hat gesagt.:


> Generell ist aber die starke Kopplung an die Interna der Elternklassen aber DAS Problem bei der Vererbung



Danke für den Link!

Ich sehe in der starken Kopplung nicht so sehr das Problem. Wer eine SWT-Anwendung schreibt will die GUI nicht gegen Swing oder AWT austauschen und ich habe viele "Muttertierklassen" die ganz bewusst sehr viel Funktionalität offenlegen.

Bernd


----------



## Bernd Hohmann (24. Dez 2012)

deetee hat gesagt.:


> Der Vorteil beim Einsatz dieser objekt-orientierten Patterns ist nun, dass jeder der das Pattern kennt weniger Probleme hat mit dem Verständnis von Swing bzw. der Architektur und der Anwendung.



Frei nach Schimanski: "Ich hör' immer nur Patterns! Patterns! Patterns! Gibt's in diesem S*****land überhauot keine anständigen Programmierer mehr?" 

Wenn Du mir bei Gelegenheit mal erzählst, was Du in Java programmierst, kann ich diese Aussage vielleicht etwas besser einschätzen. Klingt für mich so, als ob Du ständig Deine Vorgehensweise überprüfst und an Dir selber zweifelst (nicht böse gemeint, wirklich!).

Bernd


----------



## deetee (24. Dez 2012)

Bernd Hohmann hat gesagt.:


> Ich sehe in der starken Kopplung nicht so sehr das Problem.



Du scheinst alle modernen und anerkannte Prinzipien für unnötig zu halten, kann das sein? Der Eindruck entsteht zumindest, da ich auch Kollegen kenne, die ähnlich argumentieren. Allerdings weiß ich bei denen, warum sie so argumentieren. Sie möchten nichts neues lernen und weigern sich Veränderungen zu akzeptieren. Ganz ehrlich, das geht früher oder später wohl jedem mal so, dass neue Dinge plötzlich alte Muster ablösen sollen. Mir geht es selbst oft so, allerdings eher mit kompletten Technologien/Frameworks, statt mit so abstrakten Dingen wie Prinzipien und Praktiken. Ich habe z.B. lange den Vorteil von MAven nicht gesehen oder vielleicht nicht sehen wollen. Mittlerweile wundere ich mich, warum ich so lange an ANT festgehalten habe. Und ja, ich weiß, dass Maven kein vollständiger Ersatz für ANT ist.

Jedenfalls zurück zur Kopplung. Eine starke Kopplung ist gerade das was man vermeiden sollte, stattdessen auf eine lose Kopplung hinarbeiten. Das ist eigentlich schon seit Jahren so anerkannt, aber gerade durch die aktuelle Welle von Dependency Injection, IoC, etc. müsste das doch nochmal jedem bewusst gemacht worden sein, oder?



Bernd Hohmann hat gesagt.:


> Frei nach Schimanski: "Ich hör' immer nur Patterns! Patterns! Patterns! Gibt's in diesem S*****land überhauot keine anständigen Programmierer mehr?"
> 
> Wenn Du mir bei Gelegenheit mal erzählst, was Du in Java programmierst, kann ich diese Aussage vielleicht etwas besser einschätzen. Klingt für mich so, als ob Du ständig Deine Vorgehensweise überprüfst und an Dir selber zweifelst (nicht böse gemeint, wirklich!).
> 
> Bernd



Natürlich überprüfe ich mich regelmäßig selbst, man nennt das reflektieren. Ich meine das auch nicht böse, aber wie alt bist du? Ich bin 33 Jahre, und denke mal du bist mind. 50, deinen Ansichten nach zu urteilen. Wirklich nicht böse gemeint!


----------



## maki (24. Dez 2012)

Bernd Hohmann hat gesagt.:


> Ich sehe in der starken Kopplung nicht so sehr das Problem. Wer eine SWT-Anwendung schreibt will die GUI nicht gegen Swing oder AWT austauschen und ich habe viele "Muttertierklassen" die ganz bewusst sehr viel Funktionalität offenlegen.


GUI scheinen wirklich eine Ausnahme zu sein.

Dein Beispiel mit den Muttertierklassen finde ich sehr gut, wird oft als Negativ-Besipiel für Vererbung genutzt 

Arten (Säugetiere, Vögel, etc. pp.) scheinen auf den erten Blick Ideal als Beispiel für Vererbung gedacht, allerdings merkt man das es schwierig wird, wenn man zB. versucht eine Fledermaus zu modellieren.
Ein Platypus (Schwimmhäute, Schnabel, Giftstachel an den Hinterbeinen, legt Eier, säugt seine Jungen) aber sprengt jede solche Vererbungshierarchie, nimmt man da Interfaces, wird es einfacher.

"hat ein"(Komposition), "kann"(Interfaces) und "ist ein"(Vererbung) sind semantisch sehr unterschiedlich.

Die starke Kopplung bei der Vererbung führt dazu, dass Änderungen an einer Stelle (zB. an einer Methode in der Basisklasse) sehr große Auswirkungen haben die anderen Code "brechen" können, das ganze ist fragil was Änderungen betrifft. Manchmal ist sie sehr nützlich und genau richtig, man muss halt immer abwägen und die Alternativen vergleichen


----------



## Bernd Hohmann (24. Dez 2012)

deetee hat gesagt.:


> Du scheinst alle modernen und anerkannte Prinzipien für unnötig zu halten, kann das sein? Der Eindruck entsteht zumindest, da ich auch Kollegen kenne, die ähnlich argumentieren. Allerdings weiß ich bei denen, warum sie so argumentieren. Sie möchten nichts neues lernen und weigern sich Veränderungen zu akzeptieren.



Es ist erstaunlich, was "nur" 46-33 = 13 Jahre Altersunterschied ausmachen.

Mit 33 sass ich mit Frau und Kind als Angestellter in einer Mietwohnung und bin jeder Sau nachgerannt, die durchs Dorf getrieben wurde.

Mit 46 sitze ich auf einem Pool von Applikationen, die richtig gross sind. Die Kunden wickeln im Monat darüber Umsätze in Millionen/Milliardenhöhe ab. Das geht von Auftragserfassung, Lagerverwaltung, RMA, Greiflisten, Projekte, Zugabeartikel. Ablaufende SBOs? Kein Thema - ab Montag bekommen die Kunden eine E-Mail. In welchem Paket steckt der Artikel xyz mit folgender Seriennummer? Wurde am Freitag, 2 Oktober 1998 mit UPS versendet, am Samstag um 11:40 an Frau Mustermann zugestellt, Garantie ist erloschen. Bringt der Wartungsvertrag 1232 überhaupt einen Gewinn? Welchen Lagerbestand haben wir von ABC? 3 in Lagerort 01 und 4 Stück hat der Techniker mit im Auto. SMS an Techniker 2 Stück ans Lager zurückzugeben.

Ich bin jeder Neuigkeit aufgeschlossen, aber mit dem Ballast auf dem Buckel und der Verantwortung prüfe ich schon ob es einen wirtschaftlichen Vorteil bringt. In den meissten Fällen ist es bereits schon so implementiert, in anderen Fällen wirds als "untauglich für *diese* Praxis" verworfen.



deetee hat gesagt.:


> Jedenfalls zurück zur Kopplung. Eine starke Kopplung ist gerade das was man vermeiden sollte, stattdessen auf eine lose Kopplung hinarbeiten. Das ist eigentlich schon seit Jahren so anerkannt, aber gerade durch die aktuelle Welle von Dependency Injection, IoC, etc. müsste das doch nochmal jedem bewusst gemacht worden sein, oder?



Also mir irgendwie nicht. Ich denke schon immer über die Zukunft der Programme nach. Und je mehr ich darüber nachdenke, um so mehr versuche ich Funktionalität in die Mutterklasse zu verlagern um bei (zb) der Erzeugung eines neuen Stammdatenfensters so wenig wie möglich Arbeit zu haben (und das sind richtig harte Mütter welche die Eingeweide ihrer Kinder erstmal durch den Wolf drehen und dann fein säuberlich in irgendwelche Listen eintüten).

Es macht bei dieser Grössenordnung der Projekte hier IMHO keinen Sinn mehr, eine lose Kopplung zu erreichen. Solche Spiele finden (wenn überhaupt) in der Toolbox statt und selbst da muss man einfach abwägen "Aufwand jetzt gegenüber eventuellen Erleichterungen in den Änderungen später inclusive Einarbeitung in die API".

Meine 5ct

Bernd


----------



## deetee (25. Dez 2012)

Bernd Hohmann hat gesagt.:


> Es macht bei dieser Grössenordnung der Projekte hier IMHO keinen Sinn mehr, eine lose Kopplung zu erreichen. Solche Spiele finden (wenn überhaupt) in der Toolbox statt und selbst da muss man einfach abwägen "Aufwand jetzt gegenüber eventuellen Erleichterungen in den Änderungen später inclusive Einarbeitung in die API".



Je größer eine Anwendung, desto mehr lohnt sich eine durchdachte Architektur/Konzeption u.a. durch lose Kopplung, um beim Thema zu bleiben.

Das Prinzip lautet "Teile und Herrsche", kommt aus der theoretischen Informatik und lässt sich wunderbar auch auf die moderne Softwareentwicklung anwenden. Statt einer Gott-Klasse sollte man die Verantwortlichkeiten identifizieren und in Komponenten auslagern. Diese Trennung bringt Vorteile wie Testbarkeit, Robustheit, Erweiterbarkeit, uvm, die bei einer Gott-Klasse weniger gegeben sind.

Dein Verantwortungsbereich klingt mir danach, dass du es mit s.g. historisch gewachsenen Systemen zu tun hast. Dafür schonmal mein Beileid. Solche Systeme tun ihren Dienst und fertig. Niemand möchte daran ein Refactoring vornehmen, falls es wirtschaftlich überhaupt vertretbar wäre, was meistens sowieso nicht der Fall ist.

Ich verstehe dich also, wenn du bei deinen bestehenden Systemen keinen Sinn siehst Design Pattern, etc. einzuführen. Das kostet meist auch wesentlich mehr Zeit, u.a. weil keine Unit Tests existieren.
Ich habe auch schon solche alten Systeme vor mir gehabt, die auch heute noch laufen. Ich dachte mir, es wäre lediglich ein Tropfen auf dem heissen Stein, wenn ich jetzt mit sauberer Entwicklung anfange, stattdessen habe ich "quick & dirty" die Erweiterungen reingehackt. Das Ziel war, es sollte alles weiterhin funktionieren! Das ist eine große Herausforderung bei solchen Systemen, da die Seiteneffekte unüberschaubar sind. Allerdings ist das kein zufriedenstellendes Ziel, weder für Entwickler, noch für den Kunden! Der Kunde geht natürlich davon aus, dass das System nach einer Erweiterung weiterhin funktioniert, und ein Entwickler sollte schon etwas höhere Ziele haben, als ein funktionierendes System, z.B. robuste, sichere, verständliche und schnelle Anwendungen. Doch solche Ziele kann man bei historisch gewachsenen Systemen nur sekundär beachten, wenn überhaupt.

Was ich gerne wissen würde ist, ob du auf der berühmten "grüne Wiese" auch die Ansicht vertrittst, dass Interfaces, Design Patterns, etc. unnötig sind?


----------



## JohannisderKaeufer (25. Dez 2012)

deetee hat gesagt.:


> Das Prinzip lautet "Teile und Herrsche", kommt aus der theoretischen Informatik und lässt sich wunderbar auch auf die moderne Softwareentwicklung anwenden. Statt einer Gott-Klasse sollte man die Verantwortlichkeiten identifizieren und in Komponenten auslagern. Diese Trennung bringt Vorteile wie Testbarkeit, Robustheit, Erweiterbarkeit, uvm, die bei einer Gott-Klasse weniger gegeben sind.



Wer soll das bezahlen?

Entscheidend ist ob der Kunde damit zufrieden ist.

Und die genannten Vorteile bringen erstmal nur Kosten, die dafür sorgen, daß jemand anders den Zuschlag erhält.


----------



## deetee (25. Dez 2012)

JohannisderKaeufer hat gesagt.:


> Wer soll das bezahlen?
> 
> Entscheidend ist ob der Kunde damit zufrieden ist.
> 
> Und die genannten Vorteile bringen erstmal nur Kosten, die dafür sorgen, daß jemand anders den Zuschlag erhält.



Es ist durchaus kostspieliger Qualität zu produzieren, aber darin unterscheiden sich eben die Firmen auf dem Markt. Einige betreiben sogar ganze QA Abteilungen, Test Teams, Release Management , etc. um die gewünschte Qualität zu erreichen und letztlich zu verkaufen.

Kosten entstehen auch bei einer Quick & Dirty Lösung. Der Unterschied ist, dass die versteckten Kosten weitaus höher sind, z.B. Fehlerbehebungskosten, bis hin zum Imageverlust und damit auch Kundenverlust.

Außerdem ist es ein Irrtum zu denken eine Quick & Dirty Lösung wäre soviel schneller und damit kostengünstiger in der Entwicklung. Erfahrene Entwickler bringen die nötige Routine mit, um auch ein sauberes System in akzeptabler Zeit hochzuziehen. Sicher nicht in der gleichen Zeit, aber wie gesagt, die Folgekosten sind bei einem sauberen System viel geringer, darin besteht der eigentliche Nutzen und Kostenvorteil. Es kostet nunmal weniger 10 Fehler zu beheben, als 2 oder 3. Außerdem fällt die Einarbeitung neuer Entwickler günstiger aus und die Erweiterung der Systeme kann in der Regel effizienter bei konstanter oder höherer Qualität durchgeführt werden.

Es kommt immer darauf an, wie man sich entscheidet bzw. sich als Firma positionieren möchte. Sicher gibt es solche und solche auf dem Markt. Ich arbeite jedenfalls lieber bei einer die auf Qualität wert legt.

Vergleiche mit dem Automarkt, Smartphone-Markt oder sonstigen Märkten, wo Qualität eine Rolle spielt überlasse ich jedem selbst.


----------



## Bernd Hohmann (25. Dez 2012)

deetee hat gesagt.:


> Es ist durchaus kostspieliger Qualität zu produzieren, aber darin unterscheiden sich eben die Firmen auf dem Markt. Einige betreiben sogar ganze QA Abteilungen, Test Teams, Release Management , etc. um die gewünschte Qualität zu erreichen und letztlich zu verkaufen.



Also wer vorne eine QA Abteilung braucht hat hinten was falsch gemacht.

Ich klinke mich hier aus weil bei mir Qualität durch die jahrelange Erfahrung der Entwickler sichergestellt wird wärend Du versuchst das Problem über Interfaces (oder sonst was) strammzuziehen. Das passt einfach nicht in der Denke, in 10 Jahren wirst Du auch anders an die Probleme herangehen.

Bernd


----------



## Marco13 (25. Dez 2012)

Soooo, das Thema ist dann wohl weit genug von Hierarchien und Persistenz weg und hin zu allgemeinen Flamew^C^C^C Diskussionen abgedriftet, dass ich mich mal wieder einklinken kann  



Bernd Hohmann hat gesagt.:


> Klingt für mich so, als ob Du ständig Deine Vorgehensweise überprüfst und an Dir selber zweifelst (nicht böse gemeint, wirklich!).



Wer das nicht macht, macht IMHO was falsch. Oder wie ich es schonmal gesagt hatte: Programmieren ist schwer. IMMER. Wer meint, Programmieren sei leicht, sollte so sehr versuchen, es _besser_ zu machen, dass es wieder schwer ist. 

Zum allgemeinen Thema "Codequalität" etc. wurde hier schon öfter diskutiert. Ich fand den Artikel aus http://www.java-forum.org/softwareentwicklung/144463-codequalitaet-funktioniert-genug.html lesenswert. Nicht wirklich etwas neues, aber zumindest mal einige wichtige Punkte auf selbigen gebracht. 

Um ein bißchen zu vermitteln: Man kann Code schreiben, der aus vielen Interfaces und Design Patterns besteht, und der trotzdem so grottensch... ist, dass man ihn praktisch nur durch das Drücken einer einzelnen Taste noch "verbessern" kann. Man kann auch ... "hacken", oder, weniger böswillig formuliert: "sehr pragmatisch zielorientiert" arbeiten, und da kann etwas rauskommen, was sich über viele Jahre hinweg bewährt. 

Wie leicht das eine passiert oder das andere zu erreichen ist, hängt IMHO sehr stark vom Umfeld und dem Ziel ab. Eine "Standardsoftware" die 100000 Nutzer haben wird und von Fach(IT)-fremden Personen verwendet werden soll, wird sicher anders geschrieben als eine Spezialsoftware die 10 Nutzer hat und bei jedem Nutzer von 10 Experten administriert wird. Und die Frage, ob es um ein TicTacToe-Applet oder eine Atomkraftwerksnotabschaltung ist, spielt vielleicht auch eine Rolle.  

Analogien sind so eine Sache, aber ich fand die recht bedenkenswert, die uns auf einer Folie im 1. Semester mal präsentiert wurde: 
- Eine Holzhütte kann praktisch jeder bauen. Der eine gut, der andere weniger, die eine ist stabiler, die andere hat keine Fenster... Das ist das, was jeder einzelne zuhause an Programmen schreiben kann. 
- Wenn man ein richtiges Haus bauen will, kommt man alleine schon nicht weit: Da braucht's Planung und viele Leute aus verschiedenen Fachgebieten, und wenn das Haus fertig ist, und man DANN erst denkt: "Ach, Strom bräucht' man auch noch" und dann anfängt, Kabel an die Wände zu tackern, dann funktioniert das vielleicht, ist aber nicht das, was man will. Das sind "Business-Applikationen", die man nicht mehr alleine schreibt, und wo man sich vorher schonmal über die Interfaces (aka Steckdosen) Gedanken machen sollte, bevor mal loslegt. 
- Das letzte Bild war dann ... etwas, was ich hier mal in einer noch deutlicheren Version poste (weil es genau DAS damals noch gar nicht gab) : 





(Zugegeben, der Prof war ein Software-Engineering-Verfechter, aber die Message mag schon stimmen). Was für das Programmiererische Analogon dessen notwendig ist, ist IMHO noch nicht entwickelt worden, aber man kann sich ja ausmalen, wo die Reise hingeht. 

Tatsache ist aber, dass einige (und vermutlich mehr, als man denkt) Programme in bezug auf diese Analogie Potjemkin'sche Dörfer sind: Mit offiziellen und für viel Geld ausgearbeiteten Styleguides ist festgelegt, dass das fancy grüne Glühen, das erscheint, wenn man mit der Maus über einen Button fährt, einen Radius von 8.6 Pixeln haben soll, aber wenn man den Button drückt, erscheint der Stacktrace einer NullPointerException auf der Konsole. 

[ot]
[ot]
(Also SO OT, dass es schon fast wieder OT ist  : )



Bernd Hohmann hat gesagt.:


> Vermutlich geht es um solche Sachen wie "HashMap m = new HashMap()" wo mir dann immer hier im Forum gesagt wird "Map m = new HashMap()" ist besser weil man dann die HashMap problemlos durch was anderes austauschen kann.



Bei privaten Variablen ist das sogar noch der "am wenigsten schlimme" Fall - die sieht man ja sowieso nicht - auch wenn das angedeutete Argument, dass du dich irgendwie darauf verlassen würdest, dass das eine _Hash_Map ist, befremdlich klingt: Map ist Map. 
Aber wenn jemand so ein Wort wie "ArrayList" oder "HashMap" in der Signatur einer public-Methode verwendet, läuft's mir schon immer ein bißchen kalt den Rücken runter... :noe:

[/ot]
[/ot]


----------



## JanHH (25. Dez 2012)

Also wenn ich, aus welchen Gründen auch immer, explizit eine HashMap brauche, sage ich HashMap m = ..., ansonsten halt Map m = ...? Der Fall ist doch nun relativ einfach zu klären. Wobei das letztere eher der Normalfall sein dürfte.

Hab übrigens grad in der Firma die Situation, das ein Kollege sich nicht um Designrichtlinien schert, die ich entworfen habe, meine sauber durchdachten Strukturen durch "pragmatische quick&dirty"-Sachen torpediert, und die Vorgesetzten scherts nicht.. die sehen eher seinen schnellen Erfolg und meine Kritik als "prinzipienreiterisches Genörgel". Ich kann so nicht arbeiten. Kollegen, falls ihr das liest, ich kündige zu Ende Januar. Wenn Kritik am Festhalten an Konzepten der sauberen Softwareentwicklung leichte Mobbingtendenzen annimmt, ists genug.


----------



## Landei (25. Dez 2012)

Ein Punkt, der noch nicht angesprochen wirde:

Ich denke, dass sich die Auffassungen zum Design von Klassenhierarchien mit Java 8 entscheidend verändern werden. Insbesondere Extension-Methoden (aber in geringerem Umfang auch Closures) werden Alternativen zur Klassen-Vererbung bieten. Ich stelle gerade beim Experimentieren mit meiner highJ - Bibliothek fest, wie stark die neuen Möglichkeiten ein bestehendes Design umkrempeln, verbessern und - in meinem Fall - überhaupt erst praktikabel machen können.


----------



## Marco13 (25. Dez 2012)

Bestimmte Konzepte und Prinzipien werden sich wohl nicht direkt _verändern_. Aber ich könnte mir vorstellen, dass es eine Entlastung bringt: Heute muss man sich bei jeder Methode, die man NICHT in ein Interface aufnimmt, überlegen, wie man eine ggf. später auftretende Notwendigkeit für diese Methode behandeln will. Mit den extension methods schreibt man sie später einfach dazu.


----------



## Sanix (26. Dez 2012)

Bernd Hohmann hat gesagt.:


> Also wer vorne eine QA Abteilung braucht hat hinten was falsch gemacht.
> 
> Ich klinke mich hier aus weil bei mir Qualität durch die jahrelange Erfahrung der Entwickler sichergestellt wird wärend Du versuchst das Problem über Interfaces (oder sonst was) strammzuziehen. Das passt einfach nicht in der Denke, in 10 Jahren wirst Du auch anders an die Probleme herangehen.
> 
> Bernd



Deine Aussage ist schon ziemlich nah an "Gute Programmierer machen keinen Fehler". Derzeit entwickle ich an einem System, dass noch 40 andere angebunden hat. Da brauchst du einfach noch irgendwo ein Testing um zu sehen, ob das ganze irgendwie integriert funktioniert. Vor allem wenn die Entwicklung parallel läuft, kann man nicht bereits mit den anderen Systemen testen.


----------



## Bernd Hohmann (26. Dez 2012)

Sanix hat gesagt.:


> Deine Aussage ist schon ziemlich nah an "Gute Programmierer machen keinen Fehler". Derzeit entwickle ich an einem System, dass noch 40 andere angebunden hat. Da brauchst du einfach noch irgendwo ein Testing um zu sehen, ob das ganze irgendwie integriert funktioniert. Vor allem wenn die Entwicklung parallel läuft, kann man nicht bereits mit den anderen Systemen testen.



<diabolisches grinsen>Unit-Tests?</diabolisches grinsen>


----------



## Sanix (7. Jan 2013)

Bernd Hohmann hat gesagt.:


> <diabolisches grinsen>Unit-Tests?</diabolisches grinsen>



Nicht wirklich testbar mit Unit Tests. Vor allem wenn noch von div. Systemen Mails verschickt werden.


----------



## FArt (7. Jan 2013)

Sanix hat gesagt.:


> Nicht wirklich testbar mit Unit Tests. Vor allem wenn noch von div. Systemen Mails verschickt werden.


Doch. Unittests macht man ja erst mal im Kleinen. Da werden in der Regel keine Mails verschickt. Da Unittests aber auch für größer angelegte Tests verwendet werden, gibt es heutzutage gut Möglichkeiten des Mocking.


----------



## Timothy Truckle (7. Jan 2013)

FArt hat gesagt.:


> Doch. Unittests macht man ja erst mal im Kleinen. Da werden in der Regel keine Mails verschickt. Da Unittests aber auch für größer angelegte Tests verwendet werden, gibt es heutzutage gut Möglichkeiten des Mocking.


genau:Mock Net Services 4 Java

bye
TT


----------



## Bernd Hohmann (7. Jan 2013)

FArt hat gesagt.:


> Doch. Unittests macht man ja erst mal im Kleinen. Da werden in der Regel keine Mails verschickt. Da Unittests aber auch für größer angelegte Tests verwendet werden, gibt es heutzutage gut Möglichkeiten des Mocking.



Der Haken bei automatisierten, grösseren Unittests ist, dass deren Erzeugung, Pflege und Wartung im Ernstfall 50%+1 der Kapazitäten binden. Und da man auch nicht alle "******" des Teams an die Entwicklung der Tests dransetzen kann muss gut aufgeteilt werden. Das +1 ist der Projektleiter den man im Idealfall dafür neu einstellt.

Dieser "worst case" kommt zb. bei der Implementation von Schnittstellen zum Tragen. De jure muss man als "source" einen kompletten Unittest für den "drain" haben um das komplett testen zu können. Schon aufgrund der Interpretationsmöglichkeiten des Vorgabedokuments nicht sinnvoll und rationell zu implementieren.

Normalerweise hat man als Entwickler die Testszenarien im Kopf und wenn nicht, soll sich die Fachabteilung darum kümmern dass die entsprechenden Szenarien erstellt werden. Daraus nun einen maschinellen Test zu machen rentiert imho nicht immer (je weniger desto grösser das Projekt wird).

Bernd


----------



## Sym (8. Jan 2013)

Größere Integrationstest der wichtigen Pfade machen auch später automatisiert noch Sinn. Wichtig dabei ist nur, je integrativer der Test, desto größer der Wartungsaufwand. Deshalb sollte man stark überlegen, wo man einen Test benötigt, und wo nicht.

Die Frage ist natürlich, ob man solche Tests als Unit-Tests implementiert oder vielleicht andere Tools wie Selenium verwendet.


----------



## schlingel (8. Jan 2013)

Ich bin jetzt etwas länger als 4 Jahre im Geschäft und hatte noch nie das Glück in eine Firma zu kommen wo von Anfang an Unit-Tests geschrieben wurden - eher so im Nachhinein für einzelne Teile dazu gepackt. Ich kann also nicht beurteilen ob in der Praxis die Wirtschaftlichkeit tatsächlich nicht gegeben ist wenn man eine hohe Testabdeckung anstrebt.

Ich kenne die Argumentation für Tests aus Vorlesungen und Büchern, mich würde interessieren ob hier jemand schon Erfahrung gemacht hat mit großen Projekten.

PS: Gerade bei sehr großen Projekten würde man sich, zumindest als "Neuer", Tests wünschen. Eine bessere Beispielsammlung gibt es selten.


----------



## Sym (8. Jan 2013)

Ich bin in einem Projekt tätig, an dem seit knapp 4 Jahren entwickelt wird. Zunächst mit wenig Tests. Mittlerweile sind wir soweit, dass immer Tests geschrieben werden. Teilweise wird sogar test-first entwickelt. 

Anfangs war ganz klar das Problem, wie Tests geschrieben werden. Durch die EE-Entwicklung waren es ganz schnell integrative Tests, was den Aufwand stark in die Höhe getrieben hat. Nun werden stark Mocks genutzt, um Abhängigkeiten zu anderen Beans zu minimieren. Dadurch sind die Tests auch wirklich UNIT-Tests. Das funktioniert sehr gut.

Man fühlt sich dadurch sicherer, wenn man Code anfasst.


----------



## schlingel (8. Jan 2013)

Klar. Und wie sieht es mit dem Zeitaufwand bzw. den Kosten aus? (Das war ja auch das Argument von Bernd.) Seid ihr jetzt schneller als vor den Tests, langsamer oder gleich schnell? Habt ihr da vielleicht Zahlen? Bugs/Monat gemeldet oder so sowas?


----------



## deetee (8. Jan 2013)

@Schlingel
Je mehr Routine man im Schreiben von Tests bekommt, desto höher ist der Nutzen. Und je besser man sich als neuer Entwickler in diesem Bereich auskennt, desto effizienter wird man sich in neue Projekte einarbeiten können.
Grundsätzlich sind Unit Tests förderlich für die Software. Man muss allerdings einige Voraussetzungen mitbringen, wie KnowHow aufbauen und Routine sammeln, damit dieser Nutzen sich auch positiv auswirken kann. Andernsfalls wird man nur die negativen Aspekte sehen, das ist die Gefahr.

Also wenn sich keiner mit Unit Testing, Mocking, etc. professionell auskennt sind die Chancen auf eine erfolgreiche Etablierung natürlich gering. Das ist wie mit allem anderen auch. Letztlich ist die Testinfrastruktur ein eigenständiges Projekt, welches man mit den selben Standards und Konventionen entwickeln und warten muss, wie alle anderen Projekte auch. Ansonsten...wie gesagt, macht man sich eher unglücklich auf Dauer gesehen.


----------



## Sym (8. Jan 2013)

schlingel hat gesagt.:


> Klar. Und wie sieht es mit dem Zeitaufwand bzw. den Kosten aus? (Das war ja auch das Argument von Bernd.) Seid ihr jetzt schneller als vor den Tests, langsamer oder gleich schnell? Habt ihr da vielleicht Zahlen? Bugs/Monat gemeldet oder so sowas?


Bei Neuentwicklungen sind wir etwas langsamer. Durch die Tests wird einem schneller bewusst, was man wirklich möchte. Dadurch ist die eigentliche Entwicklung schneller als ohne Test. Allerdings kostet ein Unittest Zeit.

Bei Änderungen am Code habe ich das Gefühl, dass es schneller geht als ohne Test, weil man sich durch den bereits existierenden Test Sicherheit erkauft. 

Anfangs sah es so aus: Entwicklung des Codes, Deployment der Änderung, Test der Änderung und häufiger auch mal zurück in die Entwicklung.

Durch eine hohe Testabdeckung ist die Sicherheit bei der Entwicklung bereits wesentlich höher. Dadurch werden direkt weniger Fehler deployed und Änderungen gehen vom Test weniger häufig zurück in die Entwicklung.

Wir sind generell schneller geworden. Ob das nur an den Tests liegt, wage ich zu bezweifeln. Fakt ist aber, dass man sich sicherer durch den Code bewegt und weniger kaputt geht. Dadurch hat man prinzipiell weniger Wartungs- und manuellen Testaufwand.



deetee hat gesagt.:


> [...]Also wenn sich keiner mit Unit Testing, Mocking, etc. professionell auskennt sind die Chancen auf eine erfolgreiche Etablierung natürlich gering. [...]


Das sehe ich auch so. In diesem Projekt musste der Umgang mit Unittests auch lange gelernt werden.


----------



## deetee (8. Jan 2013)

Nur damit kein einseitiger Eindruck entsteht: Man sollte als primäres Ziel nicht die Performance/Schnelligkeit haben, wenn man Unit Testing beginnt. Es geht eher um Robustheit, was nichts anderes bedeutet als geringere Fehleranfälligkeit.

Die Chancen aus diesem Ziel weiteren Nutzen zu ziehen, wie schnellere Entwicklung, sinkende Kosten durch Fehlerbehebungen, Imagegewinn durch stabilere Software, etc. muss man sich auch hart erarbeiten, was ein paar Jahre andauern kann.

Und ganz wichtig: Man führt Standards und Automatisierung ein, was immer bedeuten sollte, dass man nicht nur selbst, sondern auch alle anderen die selben Arbeitsprozesse in der selben Zeit bei konstanter Qualität durchführen können sollten. Das Fachwissen vorausgesetzt!

Es ist also kein reiner Egotripp von einzelnen technikverliebten Entwicklern, vielmehr eine taktische bis strategische Unternehmensentscheidung.


----------



## schlingel (8. Jan 2013)

@deetee Das ist mir schon alles klar. Ich hätte mir allerdings Zahlen gewünscht  Ich bin ein Freund von hard facts und so etwas wie "weniger Bugs" kann man ja zB schön anhand der Bugs/Monat messen. Im Normalfall hat man diese Daten ja, auch wenn sie unaufbereitet im Bug-Tracker vor sich hin schlummern.


----------



## Bernd Hohmann (8. Jan 2013)

Sym hat gesagt.:


> Bei Änderungen am Code habe ich das Gefühl, dass es schneller geht als ohne Test, weil man sich durch den bereits existierenden Test Sicherheit erkauft.



Kann natürlich auch bedeuten, dass das Risikobewusstsein schrumpft nach dem Motto "der Unittest wird schon meckern wenn ich was vergurkt habe".

Bernd


----------



## deetee (8. Jan 2013)

Bernd Hohmann hat gesagt.:


> Kann natürlich auch bedeuten, dass das Risikobewusstsein schrumpft nach dem Motto "der Unittest wird schon meckern wenn ich was vergurkt habe".
> 
> Bernd



Dafür sind Unit Tests da, damit Fehler schneller erkannt werden. Es gibt keine Fehlerfreie Software, wenn man sich das klargemacht hat, weiß man Unit Tests umso mehr zu schätzen, denn die helfen einem die unnötigsten Fehler VOR dem Release zu beheben. Wer fehlerfreie Software anstrebt hat vermutlich zuviel Zeit. Nichtmal die NASA bekommt das hin.

Und wenn du längere Entwicklungszeiten bei Änderungen durch Risikobewusstsein rechtfertigst, dann ist das eher ein Zeichen von fehlendem Qualitätsbewusstsein. Funktioniert ist nicht genug


----------



## Landei (8. Jan 2013)

Bernd Hohmann hat gesagt.:


> Kann natürlich auch bedeuten, dass das Risikobewusstsein schrumpft nach dem Motto "der Unittest wird schon meckern wenn ich was vergurkt habe".
> 
> Bernd



Wenn ein Fehler trotz eines Unittests durchrutscht, sollte erst der Unittest um den entsprechenden Fall erweitert werden, bevor man den Fehler korrigiert. Wenn man sich konsequent daran hält, wird das Risiko _tatsächlich_ immer geringer, und eine entsprechend "sorglose" Geisteshaltung damit gerechtfertigt. 

Was du "Risikobewusstsein" nennst, wird leider allzu oft vorgeschoben, um dringend nötige Refactorings auf die lange Bank zu schieben.


----------



## Bernd Hohmann (8. Jan 2013)

Landei hat gesagt.:


> Wenn man sich konsequent daran hält, wird das Risiko _tatsächlich_ immer geringer, und eine entsprechend "sorglose" Geisteshaltung damit gerechtfertigt.



Das ist der Grund, warum die moderne Assistenzsysteme im Auto (ABS, ESP) nicht die erwartete Wirkung gezeigt haben: sie werden durch die erhöhte Risikobereitschaft der Fahrer in Teilen wegkompensiert.

Überspitzt gesagt: würde man den Sicherheitsgurt weglassen und statt Lenkrad-Airbag paar spitze Pfeile verbauen wird die Anzahl der Verkehrsunfälle schlagartig sinken weil jeder wie auf rohen Eiern fährt.

Ich sag ja nix gegen (halb)automatisierte Unittests (setze sie ja selber gerne ein), bin mir aber ihrer Schwächen bewusst.

Bernd


----------



## maki (8. Jan 2013)

Unittests haben automatisiert zu sein, alles andere ist IME nur Augenwischerei/Zeitverschwendung.



> Überspitzt gesagt: würde man den Sicherheitsgurt weglassen und statt Lenkrad-Airbag paar spitze Pfeile verbauen wird die Anzahl der Verkehrsunfälle schlagartig sinken weil jeder wie auf rohen Eiern fährt.


Ja nee, am besten also nur Blind Proggen und dann ausliefern, weil Tests schlecht fürs Qualitätsbewusstsein sind? :joke:


----------



## deetee (8. Jan 2013)

Unit Testing hat Schwächen, allerdings ist es kein Vergleich zur Entwicklung ohne Unit Tests. So wie es fahrlässig ist ohne Gurt zu fahren, ist es auch fahrlässig ohne Unit Tests zu entwickeln. Auch das Fahren mit Gurt hat Nachteile, trotzdem weiß man im Profirennsport den Gurt zu schätzen. Genauso wie ein profesioneller Entwickler Unit Testing zu schätzen weiß.



Bernd Hohmann hat gesagt.:


> Ich sag ja nix gegen (halb)automatisierte Unittests (setze sie ja selber gerne ein), bin mir aber ihrer Schwächen bewusst.
> 
> Bernd



Aber wohl nicht ihrer Stärken...


----------



## Sym (8. Jan 2013)

Bernd Hohmann hat gesagt.:


> Kann natürlich auch bedeuten, dass das Risikobewusstsein schrumpft nach dem Motto "der Unittest wird schon meckern wenn ich was vergurkt habe".
> 
> Bernd


Das ist quatsch.


----------



## Bernd Hohmann (8. Jan 2013)

maki hat gesagt.:


> Ja nee, am besten also nur Blind Proggen und dann ausliefern, weil Tests schlecht fürs Qualitätsbewusstsein sind? :joke:



Ich habe eine geringe Fehlerquote bei Auslieferung - ich glaube nicht dass das ohne eine sorgfältige QA wärend der Entwicklung machbar ist. Und unter QA verstehe ich schon etwas mehr, als auf alten Code automatisierte Tests loszulassen nur weil Grün so beruhigend ist 

Aber kaufmännische Programmierung mit seinen vielen Eingaben ist eh so ein Sonderfall, andere Branchen lassen sich bestimmt besser automatisch testen.

Bernd


----------



## deetee (8. Jan 2013)

Bernd Hohmann hat gesagt.:


> Aber kaufmännische Programmierung mit seinen vielen Eingaben ist eh so ein Sonderfall, andere Branchen lassen sich bestimmt besser automatisch testen.
> 
> Bernd



Ja, so wird es sein


----------



## maki (8. Jan 2013)

Bernd Hohmann hat gesagt.:


> Ich habe eine geringe Fehlerquote bei Auslieferung - ich glaube nicht dass das ohne eine sorgfältige QA wärend der Entwicklung machbar ist. Und unter QA verstehe ich schon etwas mehr, als auf alten Code automatisierte Tests loszulassen nur weil Grün so beruhigend ist


Die Qualität der Tests entscheidet ob "grün" aussagekräftig ist oder nicht.



Bernd Hohmann hat gesagt.:


> Aber kaufmännische Programmierung mit seinen vielen Eingaben ist eh so ein Sonderfall, andere Branchen lassen sich bestimmt besser automatisch testen.


Sehe da kein Problem, weder für Unittests noch für Integrationstests.
Ist IMHO alles eine Frage der Struktur, sowhl des Codes, als auch der Tests.

Der Punkt ist doch der:
Jeder Entwickler testet, autom. Tests haben Vorteile.

Automatische Integrationstests sind in der Entwicklung erstmal aufwändig, isolierte Unittests nicht, wenn die Strukturen es zulassen, bei SW die testgetrieben geschrieben wurde, hat der Code immer die passende Struktur, geht ja gar nicht anders.

Wenn man natürlich versucht einen isolierten Unittest zu schreiben nachdem der ProdCode schon "fertig" ist, kann es sehr schwer und aufwändig werden.

Tests für bestehenden Code zu schreiben ist am schwierigsten, viele Entwickler tappen in diese Falle und haben danach eine Abneigung gegen Unittests.
Speziell die Wartbarkeit von autom. Unittests zeigt einem recht schnell ob die Struktur/Tests passen, ober eben nicht.

Zum Thema zahlen:
Wenn ein "normaler" Entwickler mehr als 10-15% der Zeit isol. Unittests braucht die er braucht um den Prod. Code zu schrieben, dann ist was falsch.
Ja, klingt erstmal extrem, soll aber deutlich machen das isol. Unittests meist falsch geschrieben werden, meist weil die Strukturen es nicht besser zulassen.

Mit "normaler" Entwickler meine ich damit den Entwickler, der bestehende Test- APIs/Utils/Frameworks nutzt um seine Tests zu schreiben, dass irgendwer diese Test- APIs/Utils/Frameworks schreiben muss ist klar.

Was mit schlechtwartbaren Test passiert wissen wir ja alle: 
Dieser Klotz am Bein wird irgendwann weggeworfen...


----------



## Bernd Hohmann (8. Jan 2013)

maki hat gesagt.:


> Die Qualität der Tests entscheidet ob "grün" aussagekräftig ist oder nicht.



Du hast meinen milden Spott nicht durchschaut: Wenn ich per Modul 10 Tests habe und 100 Module habe werden 1000 Tests durchgeführt. Falle ich durch einen Test durch, habe ich immer noch eine saugute Fehlerquote von 1 Promille die ich nach oben reporten kann.



maki hat gesagt.:


> [...] bei SW die testgetrieben geschrieben wurde, hat der Code immer die passende Struktur, geht ja gar nicht anders.



Ja, "test driven".. da will ich mich mal dran versuchen. Aber mein aktuelles Java-Hobby-Projekt ist 99% GUI da fehlt es im Moment noch an allem. Mache dazu gelegentlich mal ein Thema auf.



maki hat gesagt.:


> Tests für bestehenden Code zu schreiben ist am schwierigsten, viele Entwickler tappen in diese Falle und haben danach eine Abneigung gegen Unittests.



Das mag auch daran liegen, dass der bestehende Code auf andere Testverfahren ausgelegt ist. Es ist ja nicht so, dass automatisierte Unittests (im Sinne von zb. JUnit) die einzigen Verfahren sind. Lohn&Gehalt hab ich früher so getestet dass es einen entsprechenden Datenbestand gab und ein großes Tastaturmacro wärend der Mittagspause alle Abrechnungen über einen definierten Datenbestand ausgeführt hat. Danach die Ausdrucke prüfen (goto 1)

Speziell die Wartbarkeit von autom. Unittests zeigt einem recht schnell ob die Struktur/Tests passen, ober eben nicht.



maki hat gesagt.:


> Wenn ein "normaler" Entwickler mehr als 10-15% der Zeit isol. Unittests braucht die er braucht um den Prod. Code zu schrieben, dann ist was falsch.



Das verstehe ich jetzt nicht. Meinst Du Gesamtaufwand = 100%, 10%-15% für Unittests, Rest für Produktivsystem? 10-15% erscheint mir etwas wenig. Gib mal ein ungefähres Beispiel was da getestet wird. 

So.. jetzt mal die Bedienungsanleitung der neuen Küche lesen. Vielleicht finde ich die Taste um dieses dämliche Piepen abzuschalten :autsch:

Bernd


----------



## deetee (8. Jan 2013)

Bernd Hohmann hat gesagt.:


> Du hast meinen milden Spott nicht durchschaut: Wenn ich per Modul 10 Tests habe und 100 Module habe werden 1000 Tests durchgeführt. Falle ich durch einen Test durch, habe ich immer noch eine saugute Fehlerquote von 1 Promille die ich nach oben reporten kann.



Mit Testdurchführungen (nicht nur Unit Tests) kann man lediglich die Existenz von Fehlern beweisen, niemals die Nicht-Existenz.
Wenn du also deinem Chef erzählst, dass du nur 1 Fehler in deinem Programm hast, dann ist das...ich sag mal sehr optimistisch gedacht.

Das was du durch rote unit tests reporten kannst sind die bekannten Fehler. Unit Tests und Integrationstests helfen dir nach einer Änderung (Bugfix, Refactoring, Change Request) die Sicherheit/Gewissheit zu haben, dass durch deine Änderung keine kritischen Seiteneffekte entstanden sind. Ohne solche Tests wäre so eine Aussage viel zu teuer, weil man erstmal alles manuell testen müsste.

Außerdem ist nicht die Anzahl der Tests alleine wichtig, sondern auch die Code Coverage. Unit Testing ohne Code Coverage Analyse macht überhaupt keinen Sinn. Wenn es also blöd läuft fragt dich deine QA oder Führungskraft, warum denn da noch soviele rote Zeilen markiert sind.

Und der eigentliche Gewinn durch solche autom. Tests und einer hohen Testabdeckung ist der, dass sie jeder zur Verfügung hat. Ein neuer Entwickler kann einen ersten Beitrag zum Projekt leisten und man hat schon mal eine erste Gewissheit, dass seine Arbeit ok ist, wenn alle Tests weiterhin durchlaufen. Das spart Zeit und Geld. Ein Entwickler ist schneller produktiv einsetzbar und seine Arbeit kann effizienter kontrolliert werden. Nicht selten benötigen Entwickler weitaus weniger Einarbeitungszeit, wenn Unit Tests und Integrationstest existieren. Schließlich zählt das auch zur Code Dokumentation.


----------



## maki (8. Jan 2013)

> Du hast meinen milden Spott nicht durchschaut: Wenn ich per Modul 10 Tests habe und 100 Module habe werden 1000 Tests durchgeführt. Falle ich durch einen Test durch, habe ich immer noch eine saugute Fehlerquote von 1 Promille die ich nach oben reporten kann.


Ach, wenn es nur um das reporten geht kann man sehr einfach an den Zahlen drehen.
These: Man kann zB. 100% Coverage durch die Tests haben, ohne eine einzige Assertion/Expectation 



> Ja, "test driven".. da will ich mich mal dran versuchen. Aber mein aktuelles Java-Hobby-Projekt ist 99% GUI da fehlt es im Moment noch an allem. Mache dazu gelegentlich mal ein Thema auf.


GUI & isol. Unittests ist so eine Sache, TDD is da sehr schwer, aber MVP/Passive View/Presenter First  bieten eine einfacher zu testende Struktur, verglichen zB. mit "MVC".
Würde dir nicht empfehlen TDD an einem prod. Projekt oder GUI auszuprobieren, Spiel-Projekte (zB. nur die Domäne einer Zeiterfassung mit TDD zu erstellen, ohne GUI etc. pp.) eignen sich IMHO am besten um was ganz neues zu lernen.

Das größte Schwierigkeit an TDD IMHO: Den eigenen Schweinehund überwinden 
Die Gewohnheit Dinge auf eine bestimmte Art anzugehen muss erstmal überwunden werden...



> Das mag auch daran liegen, dass der bestehende Code auf andere Testverfahren ausgelegt ist. Es ist ja nicht so, dass automatisierte Unittests (im Sinne von zb. JUnit) die einzigen Verfahren sind. Lohn&Gehalt hab ich früher so getestet dass es einen entsprechenden Datenbestand gab und ein großes Tastaturmacro wärend der Mittagspause alle Abrechnungen über einen definierten Datenbestand ausgeführt hat. Danach die Ausdrucke prüfen (goto 1)


"Halbautomatische" Tests sind manchmal zwingend notwendig, je nachdem was getestet wird (zB. das Layout), aber wenn sich etwas automatisieren lässt ist das ja eine Gute Sache 



> Das verstehe ich jetzt nicht. Meinst Du Gesamtaufwand = 100%, 10%-15% für Unittests, Rest für Produktivsystem? 10-15% erscheint mir etwas wenig. Gib mal ein ungefähres Beispiel was da getestet wird.


So war das gemeint.. wenn auch ein bisschen überspitzt ausgedrückt 
Isolierte Unittests sind bei TDD Whitebox tests, d.h. der Test kennt über den inneren Aufbau der zu testenden Klasse und prüft eben "ob der Code so funktioniert wie er sollte", also das verhalten, nicht nur das Ergebnis. 
Mit "isoliert" ist gemeint dass man wirklich nur eine Klasse bzw. Methode prüft, alles andere (bis auf die Java API) wird gemockt, die Mocks prüfen dann ob bestimmte Methoden aufgerufen wurden.

Mocks Aren't Stubs

Dadurch dass man "sehr wenig" Code pro einzelnem Test prüft (kurze Klassen & Methoden!), bleiben die Tests recht einfach und man vermeidet vielleicht einfacher das redundante abdecken von Prod Code durch verschiedene Tests und hat eine bessere "defect localisation".
Selbst dafür sind 10-15% der Zeit wenig und als Ziel gedacht, Anfangs 30% zu brauchen oder mehr ist üblich, man muss sich ja erst die Frameworks zusammensuchen und ein paar utils etc. bauen.. wichtig ist eben dass die Tests wartbar bleiben, den Änderungen am Prod. Code sollten Tests brechen, diese müssen "einfach" zu reparieren sein.
Ständiges refactoring gehört natürlich auch dazu, werden aber nicht in die "10-15%" reingerechnet 

Unittests prüfen natürlich nicht ob das Gesamtsystem funktioniert 
Integrationstests wie zB. End to End Tests etc. sind immer noch wichtig.
Für Integrationstests zB. kann man DBUnit nutzen um Daten in die DB zu klopfen bzw. zu prüfen.


----------



## JohannisderKaeufer (8. Jan 2013)

Bernd Hohmann hat gesagt.:


> So.. jetzt mal die Bedienungsanleitung der neuen Küche lesen. Vielleicht finde ich die Taste um dieses dämliche Piepen abzuschalten :autsch:
> Bernd



[OT]
Wenn ich das meine was es ist, dann kannst du dass per Mobiltelefon steuern. 
Einfach 1 1 2 und Anruftaste tippen. 
Dann per Sprachsteuerung weiter
- Rauchmelder piept
- Küche brennt
- ADRESSE angeben

15 Minuten warten und dann kommt ein Servicetechniker der das erledigt.

Hier ein Video zur besseren Veranschaulichung
The IT Crowd - Series 1 - Episode 2: Fire! - YouTube
[/OT]


----------



## Bernd Hohmann (9. Jan 2013)

JohannisderKaeufer hat gesagt.:


> Wenn ich das meine was es ist, dann kannst du dass per Mobiltelefon steuern.



Es war der Alarmpiepser des Kühlschranks weil die Temparatur noch > 10° war :toll:

Spülmaschine ist jetzt eingestellt, die zeigt per Projektor auf dem Boden an was sie gerade macht und wie lange es noch dauert.

Der Backofen wäre was für unseren Kollegen FArt: das Ding stellt eine riesen API in Form eines riesen Menues und einer 48seitigigen Bedienungsanleitung zur Verfügung. Der Unterschied zwischen "Dampfgaren, Intervalldampfaren, Biodampfgaren, feuchte Heissluft und heisse Feuchtluft" wird allerdings nirgends erklärt. Hätte ich die Firmware selber programmiert wüsste ich jetzt wenigstens was da abläuft. Hm... Vielleicht mal schauen was da für eine CPU drin? :idea:

Bernd


----------



## Bernd Hohmann (10. Jan 2013)

deetee hat gesagt.:


> Und der eigentliche Gewinn durch solche autom. Tests und einer hohen Testabdeckung ist der, dass sie jeder zur Verfügung hat. Ein neuer Entwickler kann einen ersten Beitrag zum Projekt leisten und man hat schon mal eine erste Gewissheit, dass seine Arbeit ok ist, wenn alle Tests weiterhin durchlaufen. Das spart Zeit und Geld. Ein Entwickler ist schneller produktiv einsetzbar und seine Arbeit kann effizienter kontrolliert werden. Nicht selten benötigen Entwickler weitaus weniger Einarbeitungszeit, wenn Unit Tests und Integrationstest existieren.



Ich bekomme da ein gedankliches Problem bei großen Anwendungen.

Wenn in einem Produktivsystem massiv Refactoring bzw. Aufräumarbeiten betrieben werden sind Unittests prima, blöderweise ändern sich auch die ganzen Schnittstellen und Testvoraussetzungen sodass man diejenigen Entwickler in die Änderung der Tests stecken muss welche mit dem Gesamtsystem am besten vertraut sind.

Umgekehrt könnte man jetzt sagen: würden die fähigsten Entwickler die Änderungen selber durchführen statt Tests zur Überwachung der weniger fähigen Entwickler zu schreiben wäre man fertig (natürlich unter der Voraussetzung, dass die fähigen Entwickler sich selber eine Testsuite bauen um ihr Ergebnis zu überprüfen - diese Testsuite fällt aber wesentlich knapper aus als ein vollkommener Test).

Schauen wir mal, was bei Programmerweiterungen passiert...

Eigentlich das gleiche Problem: Um einen unerfahrenen Entwickler an die Sache heranlassen zu können, müssen erst die Tests aufgebohrt werden. Das können aber nur diejenigen Entwickler, die wissen wo wie was geändert werden muss und welche Fallstricke sich daraus ergeben. Ergo könnten die das auch gleich selber ordentlich machen.

Da kommen wir schnell zum Computer-Inder, nämlich die Umgebung so vorzubereiten dass auch der Kollege "irgendwo draussen" nichts falsch machen kann - mit dem Overhead, dass sich die kompetenten Leute darum kümmern müssen.

Naja - auf der anderen Seite: in der heutigen Zeit gibt es kaum Entwickler die sich ordentlich einarbeiten wollen/können weil die Projekte zu kurzfristig angelegt sind. Vielleicht ist das übliche "Fire & Hire"-Geschäft die Keimzelle für das überbordende Testen statt alle Kraft in die Weiterenticklung zu stecken.

Meine 5ct.

Bernd


----------



## Sym (10. Jan 2013)

Ich glaube, wenn Du so argumentierst, dann bekommt ihr nie neue Entwickler ins Boot, oder? 

Die Probleme, die Du beschrieben hast, hat man doch auch ohne Unit-Tests. Der Vorteil bei Unit-Tests ist ja ebenfalls, dass solche Tests die Funktionalität dokumentieren. Sprich, wenn eine neue Person im Projekt den Code anfasst und dazu einen Test findet, weiß sie ungefähr, was bisher dort passieren sollte. Dementsprechend kann der Test auch von unerfahrenen Entwicklern angepasst werden. Ohne den Test hätte die Person auf jeden Fall weniger Wissen, oder nicht?

Und natürlich sind größere Refactorings nicht unbedingt etwas für Frischlinge.

Ich finde übrigens, dass Unit-Tests zu einem ordentlichen Arbeiten dazu gehören. Sie dokumentieren, wie das Verhalten von Methoden sein soll. Sie stellen sicher, dass sich das erwartete Verhalten auch nach Änderungen nicht ändert. Und wenn man die Tests bei Bugs immer schön nachzieht, erhöht dies immens die Stabilität der Software, weil mit großer Wahrscheinlichkeit dieser Defekt nicht wieder auftritt.


----------



## deetee (10. Jan 2013)

Bernd Hohmann hat gesagt.:


> Wenn in einem Produktivsystem massiv Refactoring bzw. Aufräumarbeiten betrieben werden sind Unittests prima, blöderweise ändern sich auch die ganzen Schnittstellen und Testvoraussetzungen sodass man diejenigen Entwickler in die Änderung der Tests stecken muss welche mit dem Gesamtsystem am besten vertraut sind.


Bei einem Refactoring ändern sich selten Schnittstellen, vorallem keine öffentlichen. Auch die Testvoraussetzungen bleiben die selben, weil ja das Ziel von Refactoring keine neue Funktionaliät ist, sondern das Programm soll nachher genauso funktionieren, wie es vor dem Refactoring lief.



Bernd Hohmann hat gesagt.:


> Umgekehrt könnte man jetzt sagen: würden die fähigsten Entwickler die Änderungen selber durchführen statt Tests zur Überwachung der weniger fähigen Entwickler zu schreiben wäre man fertig (natürlich unter der Voraussetzung, dass die fähigen Entwickler sich selber eine Testsuite bauen um ihr Ergebnis zu überprüfen - diese Testsuite fällt aber wesentlich knapper aus als ein vollkommener Test).


Da hast du mich falsch verstanden oder ich mich falsch ausgedrückt, denn man schreibt niemals Tests, um andere Entwickler besser überwachen zu können, sondern zwecks Wartbarkeit und Änderbarkeit. Natürlich auch wegen weiteren Gründen, aber Wartung und Anpassung werden i.d.R. auch von anderen Entwicklern übernommen, als derjenige der es entwickelt hat. Und Unit/Integrationstests helfen dabei sehr...wenn man sich damit auskennt. Das ist eigentlich auch der größte Nachteil den ich an Unit Testing bzw. Testen mit einem Unit Test Framework sehe, es ist eine eigenständige Disziplin und muss erlernt werden, um wirklich effizient zu sein.
Das was du jetzt mit "Testsuite der fähigen Entwickler" bezeichnest, sollten IMHO die Unit- und Integrationstests sein, denn genau das ist es, was ich von fähigen Entwickler heutzutage erwarte.
Was du unter einem "vollkommenen Test" verstehst, weiß ich nicht, scheint mir aber nichts mit Unit Testing zu tun zu haben.



Bernd Hohmann hat gesagt.:


> Eigentlich das gleiche Problem: Um einen unerfahrenen Entwickler an die Sache heranlassen zu können, müssen erst die Tests aufgebohrt werden. Das können aber nur diejenigen Entwickler, die wissen wo wie was geändert werden muss und welche Fallstricke sich daraus ergeben. Ergo könnten die das auch gleich selber ordentlich machen.


Selber machen setzt voraus, dass der Entwickler auch noch zur Verfügung steht, also noch im Unternhemen sein muss und auch für die Änderung zeitlich abgestellt werden kann.
Das "Aufbohren" von Tests kann durchaus notwendig werden. Aber warum traust du das nur den Entwicklern zu, die die Tests geschrieben haben? Anders gesagt, wenn die Entwickler schon vorher ordentlich geabeitet haben, dann sollten es andere Entwickler auch leichter haben ordentlich weiter zu entwickeln.
Natürlich muss man die Anforderungen kennen, damit der Test auch nach der Änderung noch genau das macht, was er machen soll. Das bedeutet nichts anderes als Einarbeitung. Es kann schließlich nicht im Sinne der Firma sein, dass Programme an bestimmte Entwickler gebunden sind. Das mag für dne Entwickler toll sein, ich finde so eine Einstellung mehr als gefährlich und zeugt von wenig Qualitätsbewusstsein und Kundenorientierung.



Bernd Hohmann hat gesagt.:


> Naja - auf der anderen Seite: in der heutigen Zeit gibt es kaum Entwickler die sich ordentlich einarbeiten wollen/können weil die Projekte zu kurzfristig angelegt sind. Vielleicht ist das übliche "Fire & Hire"-Geschäft die Keimzelle für das überbordende Testen statt alle Kraft in die Weiterenticklung zu stecken.


Da ist auf jedenfall was dran. Die Budgets und Deadlines geben oft nicht den Raum für große qualitätsfördernde Maßnahmen. Deswegen ist es so wichtig, dass Entwickler in der selben Zeit besseren Code schreiben lernen. Unit Testing ist dafür ein guter Weg, allerdings benötigt man einige Jahre um wirklich auf ein gutes Niveau zu kommen. Ich beschäftige mich seit gut 3 Jahren mit Unit Testing, ca. 60% davon privat, weil es in den Firmen noch extremen Nachholbedarf gibt. Meinen Kenntnissstand würde ich als fortgeschritten bezeichnen, auf keinen Fall bin ich ein Routinier/Profi in diesem Bereich. In der Theorie kenne ich 90% der Möglichkeiten, in der Praxis bringt das leider wenig, wenn es darum geht Deadlines einzuhalten! Da hilft mir nur am Ball bleiben und Routine sammeln.


----------



## DerFeivel (10. Jan 2013)

Grundsätzlich stimme ich dir zu deetee.
Allerdings habe ich hierzu noch eine Anmerkung:



deetee hat gesagt.:


> Bei einem Refactoring ändern sich selten Schnittstellen, vorallem keine öffentlichen. Auch die Testvoraussetzungen bleiben die selben, weil ja das Ziel von Refactoring keine neue Funktionaliät ist, sondern das Programm soll nachher genauso funktionieren, wie es vor dem Refactoring lief.



Ich bin mir nicht sicher, aber ich glaube, er bezog auch die Schnittstellen zwischen den einzelnen Units mit ein.
Hier kann es bei einem Refactoring ja durchaus auch zu Änderungen kommen (habe ich selbst gerade durch). Beispielsweise wenn man eine Klasse refactored die in ihrer alten Version mehrere Responsibilities erfüllt in mehrere Klassen aufteilt.
Aber selbst dann ändert sich das getestete Verhalten nicht, so dass sich in der Regel der Aufwand hier oftmals auch in Grenzen hält.  


Unabhängig davon:

Gerade bei großen, komplexen Programmen spielen Unit-Test ihre eigentliche Stärke erst aus. Selbst der fähigste Entwickler verliert bei mehren Dutzend Klassen irgendwann den Überblick.
Unit-Tests helfen hier dem Entwickler das nach außen "sichtbare" Verhalten der Unit (i.d.R. also der Klasse/Komponente) stabil zu halten. 
Die Test sind also sozusagen eine FSK der Entwickler. 

Für die neuen Entwickler heisst es halt:
Wenn ich ein neues Feature einbaue, verhält sich die Komponente/die Features der Komponente danach immernoch genauso wie vorher. Es sollte also somit auch im eigenen Interesse eines jeden Entwicklers sein, Unit-Tests zu schreiben um nicht permanent an dem selbstentwickelten Feature herumdoktern zu müssen.


----------



## maki (10. Jan 2013)

> Naja - auf der anderen Seite: in der heutigen Zeit gibt es kaum Entwickler die sich ordentlich einarbeiten wollen/können weil die Projekte zu kurzfristig angelegt sind. Vielleicht ist das übliche "Fire & Hire"-Geschäft die Keimzelle für das überbordende Testen statt alle Kraft in die Weiterenticklung zu stecken.


Die Keimzelle für "überbohrtes Testen" war das streben nach Qualität.
Selbst erfahrene Enwickler machen Fehler, auch die müssen Testen, automatisieren spart einem viel Arbeit während es die Qualität in bestimmten Bereichen sicherstellt, nämlich den getesteten Bereichen.

Ohne ständiges Refactoring "vergammelt" Code bzw. die ganze Software,  Refactoring ohne Tests ist ein Spiel mit dem Feuer -> Teufelskreis

Das alles funktioniert IME übrigens nicht wenn man nur ein paar Monate in einem Projekt bzw. bei einem Kunden ist, wozu denn auch? "Nach mir die Sinnflut..."


----------



## Bernd Hohmann (10. Jan 2013)

Sym hat gesagt.:


> Die Probleme, die Du beschrieben hast, hat man doch auch ohne Unit-Tests. Der Vorteil bei Unit-Tests ist ja ebenfalls, dass solche Tests die Funktionalität dokumentieren. Sprich, wenn eine neue Person im Projekt den Code anfasst und dazu einen Test findet, weiß sie ungefähr, was bisher dort passieren sollte. Dementsprechend kann der Test auch von unerfahrenen Entwicklern angepasst werden. Ohne den Test hätte die Person auf jeden Fall weniger Wissen, oder nicht?



Das ist natürlich ein schlagkräftiges Argument: in den Tests findet man ein recht isoliertes Muster wie die Funktion "anzufassen" ist. 

Bernd


----------



## Bernd Hohmann (11. Jan 2013)

deetee hat gesagt.:


> Die Budgets und Deadlines geben oft nicht den Raum für große qualitätsfördernde Maßnahmen. Deswegen ist es so wichtig, dass Entwickler in der selben Zeit besseren Code schreiben lernen. Unit Testing ist dafür ein guter Weg, allerdings benötigt man einige Jahre um wirklich auf ein gutes Niveau zu kommen. Ich beschäftige mich seit gut 3 Jahren mit Unit Testing, ca. 60% davon privat, weil es in den Firmen noch extremen Nachholbedarf gibt. Meinen Kenntnissstand würde ich als fortgeschritten bezeichnen, auf keinen Fall bin ich ein Routinier/Profi in diesem Bereich. In der Theorie kenne ich 90% der Möglichkeiten, in der Praxis bringt das leider wenig, wenn es darum geht Deadlines einzuhalten! Da hilft mir nur am Ball bleiben und Routine sammeln.



Das ist ein ehrliches Statement von jemanden der tief in der Materie drinsteckt - damit kann ich was anfangen.

Denn bislang hatte ich den Eindruck, dass man mit leichter Hand einen Unittest schreibt um auch komplexe Themen abzuwickeln - da hat sich meine Erfahrung gesperrt.

Aber wenn Unittests bedeuten, dass man auch mal viel Sch**sse fressen muss (in der Firma wie auch Privat) um das ordentlich zu machen - da bin ich schon wieder dabei!

Danke für die Auflösung meines gedanklichen Knotens, unter diesen Voraussetzungen full ACK für den Rest Deines Textes.

Bernd


----------



## deetee (11. Jan 2013)

Das freut mich, dass du wieder "auf" gemacht hast. Ich glaube ich muss mir da auch ein Beispiel nehmen, weil ich eine ähnliche Haltung habe was eine momentan gehypte Praktik angeht: Scrum! Ich finde Scrum eigentlich gut, verstehe aber nicht, warum alles alte nun schlecht sein soll und mit Scrum alles besser. Aber das Thema ist mindestens 1 eigener Thread wert.

Gern würde ich hier jetzt noch auf angerissene Themen eingehen, z.B.

1. Wie "verkaufe" ich Unit Testing meinen Vorgesetzten?
2. Welche Maßnahmen sind notwendig, um Unit Testing professionell zu betreiben?
3. Wie denken Vorgesetzte über Unit Testing und andere QA Maßnahmen?

Das würde aber ebenfalls den Thread sprengen. Vielleicht mach ich mal einen neuen auf.


----------



## Sym (11. Jan 2013)

Das Thema Unit-Tests hat eigentlich auch diesen Thread schon gesprenkt...


----------



## DerFeivel (11. Jan 2013)

deetee hat gesagt.:


> 1. Wie "verkaufe" ich Unit Testing meinen Vorgesetzten?



Wenn deine Firma/Abteilung ein Ticket-System benutzt wäre ein mögliches Vorgehen der Weg über Statistiken (da sind leitende Angestellte meist ganz verrückt nach ).

Ein guter Indikator für Unit Tests wären dann Komponenten/Features an denen immer wieder herumgedoktort wird/werden muss, weil neue Anpassungen ältere Anpassungen sprengen.
Wäre ja sowas wie DER Fall für Unit-Tesging.


Eventuell kann dir bei der Argumentation auch sowas hier helfen:

http://research.microsoft.com/en-us/groups/ese/nagappan_tdd.pdf (Hab das Paper jetzt nicht nochmal durchgelesen, aber hier sollte es um den Vergleich der Fehlerdichte in TDD und Non-TDD Entwicklerteams gehen)




deetee hat gesagt.:


> 2. Welche Maßnahmen sind notwendig, um Unit Testing professionell zu betreiben?



Know your tools.

Best Practices, wie bspw. einen bestimmten Aufbau der Tests (Given / When / Then fällt mir da gerade ein)

1-2 TDD-erfahrene Entwickler (wir hatten das Glück ein TDD-erfahrenes Team zu bekommen)


Und, ach ja:

Ganz wichtig:

 Vorgesetzte die Unit-Testing akzeptieren .




deetee hat gesagt.:


> 3. Wie denken Vorgesetzte über Unit Testing und andere QA Maßnahmen?



Einzelfallbasiert. 

Aufgrund Ihrer Funktion als Team- /Projektleiter würde ich aber vermuten eher wenig. Kostet auf den ersten Blick ja nur Zeit und die ist ja bekanntlich Geld


----------



## Bernd Hohmann (11. Jan 2013)

deetee hat gesagt.:


> Ich finde Scrum eigentlich gut, verstehe aber nicht, warum alles alte nun schlecht sein soll und mit Scrum alles besser.



Wie ich paar Postings vorher zu Dir gesagt hat: "warts ab, in 10 Jahren wird eine neue Sau durchs Dorf getrieben und dann schreibst Du hier 'warum soll ich das machen, das alte läuft doch so gut'.

Mein langjähriger Kollege und ich betreiben Scrum und Extreme Programming im Grunde genommen schon seit .. 1995 oder so (also noch bevor es "erfunden" wurde).

Das ergab sich bei uns einfach aus der Tatsache, dass wir a) eine recht gereifte, aber krude API b) keine Debugger oder IDEs mit Syntaxhighlighting hatten. Da kommt man schnell auf Methoden die heute zb. unter Pair-Programming und Test-Driven-Development bekannt sind.

Bei solchen Sachen wie Scrum, agile Softwareentwicklung etc. sollte man immer im Hinterkopf behalten dass es sich nicht um Entwicklungsmethoden der Sorte 1+1=2 sondern um Entwicklungs_kultur_ handelt die im Kontext der Autoren entstanden ist und nicht unbedingt 1:1 auf die (Entwicklungs)Kultur der Deutschen adaptierbar ist.

Mal überspitzt gesagt: Wärend der Deutsche noch sorgenvoll in die Zukunft schaut, ist der Amerikaner schon auf der nächsten Party. Sowas wie Scrum wird in anderen Ländern als neue Idee aufgegriffen, in DE eher als Dogma aufgefasst was die Adaption sehr schwierig macht weil eine Abweichung von der reinen Lehre ein Sakrileg ist.

Nimm von Scrum was zum Unternehmen passt, sind ja genügend Bausteine vorhanden.

Bernd


----------



## maki (11. Jan 2013)

> Mein langjähriger Kollege und ich betreiben Scrum und Extreme Programming im Grunde genommen schon seit .. 1995 oder so (also noch bevor es "erfunden" wurde).


Wirklich?
So mit TDD, Pair Programming, CI (inkl. Server), etc. pp.?
Glaub ich nicht, zumindest was xP betrifft 

Scrum dagegen, also agile vorgehensweisen, das glaube ich gerne.


----------



## Bernd Hohmann (11. Jan 2013)

maki hat gesagt.:


> Wirklich?
> So mit TDD, Pair Programming, CI (inkl. Server), etc. pp.?
> Glaub ich nicht, zumindest was xP betrifft



Doch doch.

Was es nicht gab waren automatisierte Tests - dafür hatten wir eine Vorgehensweise die man heute als "Pen & Paper Testunit" beschreiben würde. Dh. ehe man das Programm (meisstens eine Faktura oder FiBu) erweitert hat, wurden auf einem Blatt Papier sämtliche Eingabeparameter und Ausgabeparameter aufgeschrieben und dann nachgedacht "Für diese Eingabewerte erwarte ich folgende Ausgabewerte, wie komme ich da hin, welche Fallstricke sind zu erwarten". Am Ende wird das dann mit anderen Testwerten überprüft und wegprogrammiert. Das ganze so, dass immer ein lauffähiger Stand beibehalten wird und der Zyklus "Entwurf, Programmierung, Test" recht kurz bleibt.

Und natürlich meisstens zu zweit. Oft etwas anstrengend (der "passive" Entwickler entwickelt dabei meisst eine Technik für einen erholsamen Sekundenschlaf - wärend der Kollege die Doku erweitert kann man mal 30sek wegpennen. Nach 4 Stunden ist man kaputter als nach 2 Tagen Schlammschippen).

Was halt damals zu Diskettenzeiten auch nicht ging war die starke Integration des Kunden. Da blieb es bei regelmässigen Telefonaten und es sind ständig Faxe mit Mustermasken oder Probedrucken herumgegangen und wenn ein Zwischenstand erreicht war, wurde der zum herumspielen ausgeliefert.  Aber lieber bin ich mal paar Stunden (oder auch Tage) in den Betrieb gefahren um zu sehen, wie die Anwender dort ticken und wie die Arbeitsabläufe sind.

Heute ist das dank Telefon/Internetflatrate und VPN alles kein Thema mehr. Ich hab eben eine Änderung auf einen Rechner 300km entfernt eingespielt und via Telefon und VNC mit dem Kunden darüber diskutiert ob das so seinen Vorstellungen entspricht.

Ja, wir konnten das schon vor den Amis und war immer verblüfft, wie verstaubt andere Betriebe waren 

Bernd


----------



## deetee (11. Jan 2013)

Bernd Hohmann hat gesagt.:


> Doch doch.
> 
> Was es nicht gab waren automatisierte Tests - dafür hatten wir eine Vorgehensweise die man heute als "Pen & Paper Testunit" beschreiben würde. Dh. ehe man das Programm (meisstens eine Faktura oder FiBu) erweitert hat, wurden auf einem Blatt Papier sämtliche Eingabeparameter und Ausgabeparameter aufgeschrieben und dann nachgedacht "Für diese Eingabewerte erwarte ich folgende Ausgabewerte, wie komme ich da hin, welche Fallstricke sind zu erwarten".



Das wird auch hier und da heute noch so gemacht und ich kenne es als CTE.

Es gibt auch Editoren dafür, aber einen guten kostenlosen konnte ich noch nicht finden. Leider ist es auch sonst digital per Wiki Syntax o.ä. etwas kompliziert zu zeichnen, daher geht es per Hand meist schneller. Allerdings ist es auf dem Papier schlecht für nachhaltige Dokumentation, daher spar ich mir das immer mehr. Außerdem kennt es kein Mensch mehr, leider. Auch Entscheidungstabellen sind eigentlich extrem praktisch, aber leider auch am aussterben.


----------



## maki (11. Jan 2013)

> Was es nicht gab waren automatisierte Tests - dafür hatten wir eine Vorgehensweise die man heute als "Pen & Paper Testunit" beschreiben würde. Dh. ehe man das Programm (meisstens eine Faktura oder FiBu) erweitert hat, wurden auf einem Blatt Papier sämtliche Eingabeparameter und Ausgabeparameter aufgeschrieben und dann nachgedacht "Für diese Eingabewerte erwarte ich folgende Ausgabewerte, wie komme ich da hin, welche Fallstricke sind zu erwarten". Am Ende wird das dann mit anderen Testwerten überprüft und wegprogrammiert. Das ganze so, dass immer ein lauffähiger Stand beibehalten wird und der Zyklus "Entwurf, Programmierung, Test" recht kurz bleibt.


Ne, das ist kein xP.
Auf Papier kommt im xP erstmal *gar nix*, nur Code zählt.
Keine Kopfgeburten, sondern echte Lösungen die aus der Praxis kommen und erstmal funktionieren, vor allem aber getestet sind, bevor sie geschrieben wurden 
Zuklus in xP ist eher der aus TDD:
Test schreiben, Prod Code anpassen bis der Test durchgeht, dann Refactoring.
Also umgeklehrt zu dem was du beschrieben hast.


----------



## FArt (11. Jan 2013)

Bernd Hohmann hat gesagt.:


> Nimm von Scrum was zum Unternehmen passt, sind ja genügend Bausteine vorhanden.
> Bernd



Das ist Scrumbut und oft ein Grund, warum Scrum nicht funktioniert. Scrum ist nun mal (absichtlich) relativ dogmatisch ausgelegt.

Wenn man es etwas freier haben möchte, sollte man es eher mit Kanban versuchen und dies mit anderen Techniken kombinieren.


----------



## Bernd Hohmann (11. Jan 2013)

FArt hat gesagt.:


> Das ist Scrumbut und oft ein Grund, warum Scrum nicht funktioniert.



Ich dachte, Scrum-but wurde mittlerweile durch Scrum-and ersetzt?

Bernd


----------



## Kratzer (11. Jan 2013)

Ich kann dir nur raten, ganz old-school wie du es gelernt hast mit den hierarchischen Klassenstruukturen zu arbeiten. Spätestens, wenn du im Team arbeitest, werden dich dein Kollegen sonst verfluchen.:autsch:


----------



## FArt (14. Jan 2013)

Bernd Hohmann hat gesagt.:


> Ich dachte, Scrum-but wurde mittlerweile durch Scrum-and ersetzt?
> Bernd



Scrum-and hört sich positiver an und ist eher ein Anpassungsprozess, dem oft zu strikten Scrum geschuldet... Scrum-but ist eher eine eigenmächtige Anpassung zur Verwässerung von Scrum, oft mit dem Ergebnis, dass Scrum nicht funktioniert, da hier oft nicht das Ziel existiert (oder zumindest nicht erreicht wird), den Prozess auf Scrum im Laufe der Zeit umzustellen.


----------

