Designfrage - komplexe vs. flache Klassenhierarchie

JanHH

Top Contributor
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

Top Contributor
Meinst du etwa siwas?

Java:
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)..
 

ARadauer

Top Contributor
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

Top Contributor
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.
 
J

JohannisderKaeufer

Gast
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

Top Contributor
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...
 
J

JohannisderKaeufer

Gast
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

Top Contributor
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

Top Contributor
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.
 
M

maki

Gast
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

Aktives Mitglied
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

Top Contributor
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

Aktives Mitglied
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.

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?
 
Zuletzt bearbeitet:
M

maki

Gast
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

Top Contributor
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.

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
 
M

maki

Gast
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

Aktives Mitglied
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

Top Contributor
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

Top Contributor
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

Aktives Mitglied
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?

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!
 
M

maki

Gast
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

Top Contributor
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.

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

Aktives Mitglied
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?
 
J

JohannisderKaeufer

Gast
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

Aktives Mitglied
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

Top Contributor
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

Top Contributor
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 :D

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) :
450px-Burj_Dubai_20100105.jpg

(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 :D : )

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 HashMap 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

Top Contributor
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.
 
Zuletzt bearbeitet:

Landei

Top Contributor
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

Top Contributor
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

Top Contributor
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

Top Contributor
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>
 

FArt

Top Contributor
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.
 

Bernd Hohmann

Top Contributor
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
 
S

Sym

Gast
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

Gesperrter Benutzer
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.
 
S

Sym

Gast
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

Gesperrter Benutzer
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

Aktives Mitglied
@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.
 
S

Sym

Gast
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.

[...]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

Aktives Mitglied
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

Gesperrter Benutzer
@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.
 

deetee

Aktives Mitglied
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

Top Contributor
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

Top Contributor
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
 
M

maki

Gast
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:
 
Zuletzt bearbeitet von einem Moderator:

Ähnliche Java Themen


Oben