Softwaredesign in C++ im Vergleich zu Softwaredesign in Java/C#
-
Die gute alte Zwiebel... Damit kann man es aber auch leicht übertreiben.
-
Wer sagt, dass Abstraktion schlecht ist? Trotzdem folge ich nicht dem Java-Stil. Natuerlich habe ich eine Socketklasse, eine fuer RS232 und ... trotzdem erben sie nicht von einem Interface obwohl sie alle ein wait_for_event() und read(...) haben. Warten bis Daten verfuegbar sind und dann lesen, natuerlich mit timeout.
-
knivil schrieb:
In C++ habe ich noch keine Factory verwendet und Singletons kommen seit langem nicht mehr vor. Und wenn ich Klassen als *Manager benennen wuerde, dann denke ich nochmals ueber mein Design nach, um das zu vermeiden.
kommt es mir nur so vor oder wird das was einige machen (einer macht) einfach mal als die Art wie man in C++ programmiert definiert.
-
volkard schrieb:
softwaredesign schrieb:
Wie immer gehst du auf nichts fachlich großartig ein sondern verbreitest recht spöttisch weiterhin irgendwelche Pauschalisierungen. Es scheint, als könntest du aus der eigenen Weltanschauung nur schwer ausbrechen und reagierst dementsprechend spottend oder belächelnd, wenn du mit etwas konfrontiert wirst, was du nicht kennst oder noch nicht verwendet hast...
Du bist nicht der erste (üblicherweise unregistrierte) Pinscher, der glaubt, sich beweisen zu müssen, indem er versucht, mir an Bein zu pinkeln.
Auf die Idee, dass du auch mal was falsches sagst, kommst du wohl garnicht.
volkard schrieb:
Man zerlegt nicht für die Wiederverwendung, sondern um den Überblick zu behalten.
Ist natürlich falsch. Man zerlegt für beides.
-
tntnet schrieb:
Beispiel: Lesen von Daten vom Socket. Manche Programme verwenden direkt den Systemaufruf read. Dabei wird zumindest mal vergessen, SIGINTR abzufangen. Eventuell sogar ganz auf Fehlerbehandlung verzichtet, weil es ja eigentlich nicht passieren darf. Packe ich das in eine Abstraktionsschicht, die alles implementiert und im Fehlerfall eine Exception wirft, eventuell sogar mit Timeoutüberwachung, dann habe ich eine einfache und robuste read-Funktion.
Das ist keine Abstraktion. Du transformierst den Fehler nur. Aus einem return value machst du ein Exception. Daran ist exakt gar nichts abstrakt. Nur deine Time-out Überwachung würde was bringen. Aber das ist keine Abstraktion, das ist eine Time-out Überwachung.
Ein mal in einen netten Wrapper (=Abstraktion)
Quatsch. Der Wrapper ist kein Abstraktion, sondern die abstrakten Konzepte die du mithilfe des Wrappers ausdrücken kannst. Eine 1:1 Darstellung eines C-Interfaces durch einen Wrapper ist keine Abstraktion. Ein fehlerhaftes Interface durch ein besseres auszutauschen ist die Korrektur eines Designfehlers, aber keine Abstraktion.
Wikipedia:
"'An abstraction' - a concept that acts as a super-categorical noun for all subordinate concepts, and connects any related concepts as a group, field, or category."Eventuell sogar mit einem Treiberinterface, wo ich Oracle durch eine andere Datenbank austauschen kann.
Nun reden wir von Abstraktion. Aber dein "eventuell" besagt, dass du das eventuell gar nicht implementiert hast?
Bislang sehe ich kein Beispiel dafür, wo du eine Gruppe von Dingen vereinheitlicht hast, sodass sich die Gesamtkomplexität verringert hat. Das geht auch nicht. Wenn du abstrahierst, musst du nicht nur die Objekte verstehen, die unter dieser Abstraktion zusammengefasst werden, sondern zusätzlich die Abstraktion selbst. Natürlich sorgt eine gute Abstraktion dafür, dass in einm konkreten Kontext die wahrgenommenee Komplexität verringert wird. Aber wenn sich jemand in das Projekt einarbeiten muss, muss er trotzdem die Abstraktion verstehen.
@wikileaks
Ich will auch kein Programm in Assembler schreiben. Es ändert aber nichts daran, dass ich wissen muss, welchen Code der compiler erzeugt, ob ich den prozssorcache ordentlich ausnutze(und überhaupt dass es einen gibt und was er macht) und ob der Code vektorisiert wird.
-
otze schrieb:
@wikileaks
Ich will auch kein Programm in Assembler schreiben. Es ändert aber nichts daran, dass ich wissen muss, welchen Code der compiler erzeugt, ob ich den prozssorcache ordentlich ausnutze(und überhaupt dass es einen gibt und was er macht) und ob der Code vektorisiert wird.Das trifft ja mal wohl für 90% der Softwareentwickler nicht zu. Also klingt mir der Absatz stark nach verallgemeinertem Quatsch.
MfG SideWinder
-
SideWinder schrieb:
Das trifft ja mal wohl für 90% der Softwareentwickler nicht zu. Also klingt mir der Absatz stark nach verallgemeinertem Quatsch.
Ich habe "ich" geschrieben. Aber du darfst auch ruhig Argumente zum Rest bringen.
-
otze schrieb:
SideWinder schrieb:
Das trifft ja mal wohl für 90% der Softwareentwickler nicht zu. Also klingt mir der Absatz stark nach verallgemeinertem Quatsch.
Ich habe "ich" geschrieben.
Hört sich wie ein "jeder" an wenn man liest
Beispiel bevor es ausratet: "Ich muss heutzutage studieren um einen guten Job zu bekommen.", heißt wohl nicht, dass ich damit unbedingt nur mich meine. Aber wenn du es so korrigierst, ok. Keine weitere Diskussion nötig.
MfG SideWinder
-
otze schrieb:
Eventuell sogar mit einem Treiberinterface, wo ich Oracle durch eine andere Datenbank austauschen kann.
Nun reden wir von Abstraktion. Aber dein "eventuell" besagt, dass du das eventuell gar nicht implementiert hast?
Warum so negativ? Das http://new.tntnet.org/howto/tntdb.html habe ich implementiert. Freut mich aber, dass Du mir dann doch noch Recht gibst.
Ach ja. Wie wäre es mit einem Abstraktionsinterface zu rpc? http://new.tntnet.org/howto/rpc-howto.html. Da kann man das verwendete RPC Protokoll ohne Codeänderungen austauschen.
Ich wollte nur ein paar einfache Beispiele bringen, um es leichter verständlich zu machen.
-
tntnet schrieb:
otze schrieb:
Eventuell sogar mit einem Treiberinterface, wo ich Oracle durch eine andere Datenbank austauschen kann.
Nun reden wir von Abstraktion. Aber dein "eventuell" besagt, dass du das eventuell gar nicht implementiert hast?
Warum so negativ? Das http://new.tntnet.org/howto/tntdb.html habe ich implementiert. Freut mich aber, dass Du mir dann doch noch Recht gibst.
conn.execute( "create table t1(col1 int not null primary key," " col2 int not null)");
Was zum Teufel soll denn das sein?
-
Ein SQL Statement?!
-
Kellerautomat schrieb:
Ein SQL Statement?!
Achso, gut.
Ich dachte schon..
-
wikileaks schrieb:
otze schrieb:
Es kann sein, dass die gefühlte Komplexität in einem bestimmten Anwendungsfall geringer wird, aber die Komplexität über das Gesamte Programm steigt an:
Nicht in meinem Verständnis vom Artikel.
Programmkomplexität = Aufgabenkomplexität - (1-Leakyness)*Abstraktion
Leakyness ist zwischen 0% (triviale Abstraktion), 20% (Normalfall), 50% (gutes grösseres Projekt) und >100% (absoluter Design-Fail).
Ich möchte kein Programm ohne Abstraktion (=strukturloser Assemblercode) schreiben, auch kein kleines.
Abstraktion:
Mehr Interfaces
Mehr Klassen
Weniger Code
Weniger Dinge zu lernen
Weniger mögliche FehlerquellenBeim Essen ist jedem klar, daß zu wenig schlecht ist und zu viel auch.
"Abstraktion" ist leider für die meisten viel zu abstrakt, um noch vernünftig zu bleiben.
-
Trotzdem folge ich nicht dem Java-Stil. Natuerlich habe ich eine Socketklasse, eine fuer RS232 und ... trotzdem erben sie nicht von einem Interface obwohl sie alle ein wait_for_event() und read(...) haben.
Zumindest teilweise ist das in C++ auch nicht nötig, weil Templates so stark sind. Es ist in Java immer nötig, dass man erbt, damit man irgendjemandem ein Interface-Objekt übergeben kann. In C++ kann man so was oft auch als Template-Parameter reinreichen und die Funktionen aufrufen, da braucht kein Mensch ein Interface.
Möchte man hingegen zur Laufzeit auswählen können, welche Art von Socket man nutzt, während der Anwendungsteil mit allen "Arten" von Sockets umgehen kann, finde ich solch ein Interface schon sinnvoll. Du hattest wohl einfach nicht den Anwendungsfall, dass das notwendig ist.
Um für den Fall zu wappnen, kann man halt ein Interface drüberschrauben. Erhalten Anwendungsklassen dann nur das Interface und nicht das Socket direkt, hat man abstrahiert. Würde man in Java dann direkt mit Factories verbinden und zack, hat man zig Klassen.
tntnet:
Na ja, dass der Anwendungscode kürzer wird, wenn Du Dinge rausziehst und in eine Toolbox/Library steckst, ist klar. Aber mit der Definition wäre ja z.B. bei einer Server/Client-Anwendung automatisch jede Implementierung mit einem Null-Client weniger komplex als mit einem Fat Client. Es geht schon um die gesamte Software.
-
Eisflamme schrieb:
Möchte man hingegen zur Laufzeit auswählen können, welche Art von Socket man nutzt, während der Anwendungsteil mit allen "Arten" von Sockets umgehen kann, finde ich solch ein Interface schon sinnvoll. Du hattest wohl einfach nicht den Anwendungsfall, dass das notwendig ist.
Könnte mich jetzt auch nicht an so flexible Sockets erinnern.
-
Ich bin nicht so tief in Netzwerkprogrammierung drin. Wenn man so etwas praktisch nicht braucht, würde ich da auch kein Interface drüberbasteln. Ob das der Java-Programmierer immer sofort macht, weiß ich nicht. Das würde ich als schlechten Stil abstempeln in C++ genau so wie in Java.
-
volkard schrieb:
Beim Essen ist jedem klar, daß zu wenig schlecht ist und zu viel auch.
"Abstraktion" ist leider für die meisten viel zu abstrakt, um noch vernünftig zu bleiben.
Sehe ich ähnlich, und laufe doch immer mal wieder in Gefahr zu viel zu abstrahieren. Anderseits gibt es durchaus auch Programmteile von denen ich sehr sicher bin, das diese in nicht allzu weiter Zukunft erweitert und verändert werden müssen - dort kann eine Abstraktion durchaus angebracht sein.
Abstraktion kann sinnvoll sein, sollte aber nicht als Selbstzweck dienen. Wenn man in einem Projekt nur einen Fall abbilden muss, so ist Abstraktion meist unnötiger Mehraufwand der nur die Projektkomplexität erhöht. Ebenso würde ich Abstraktionen zur Wiederverwertung nur dort betreiben wo ohnehin eine Abstraktion Sinn macht (Wir Entwickler schießen viel zu gerne mit Kanonen auf Spatzen, manchmal glaube ich, das wir einen Todesstern auf eine Stecknadel loslassen würden).
-
Und jetzt sind wir fern ab von Gut und Boese. In den Tiefen des Allgemeinen und Unkonkreten, wo weder wahr noch falsch existiert, gut oder schlecht, Java, C++, C#, ... Da bleibt mir nur noch zu sagen: ... .?!
-
asc schrieb:
Abstraktion kann sinnvoll sein, sollte aber nicht als Selbstzweck dienen.
Naja
Ich gebs zu, ich bau öfter mal deutlich komplexeren Code als nötig, weil mich eine straight forward Implementierung langweilen würde. Programmieren muss ja auch Spass machen. Selbst wenn ich ein kleineres Teilprojekt einfach runtertippen und vergessen könnte, bau ich das öfter so auf, wie ich ein größeres/komplexeres Projekt aufbauen würde.
-
Mechanics schrieb:
asc schrieb:
Abstraktion kann sinnvoll sein, sollte aber nicht als Selbstzweck dienen.
Naja
Ich gebs zu, ich bau öfter mal deutlich komplexeren Code als nötig, weil mich eine straight forward Implementierung langweilen würde. Programmieren muss ja auch Spass machen.
Privat ist da nichts gegen zu sagen, in einem bezahlten Projekt aber sollte man die Komplexität auch möglichst an den tatsächlichen Anforderungen und den wahrscheinlichsten Änderungen orientieren.
Es gibt Situationen wo es auch nicht verkehrt ist ein kleines Projekt wie ein größeres umzusetzen, wenn die Planung in die Richtung geht, dies über die Zeit entsprechend zu vergrößern - oder wo sich die Rahmenbedingungen schlicht und ergreifend geändert haben. Unser jetztiges Projekt soll z.B. nach C# portiert werden und war ursprünglich hauptsächlich für Einzelplätze oder zumindest nur wenige Benuzter ausgelegt.
Es ist bereits bekannt das die Planung dahin geht das wir größere Einrichtungen ansprechen wollen (und unsere größten Kunden geraten immer wieder an Grenzen der bisherigen Anwendung), und das der jetztige Teil langfristig nur noch einer von vielen Anwendungsbereichen sein soll. Das Projekt ist schon so groß und langlebig das sich hier Unittests mehr als auszahlen könnten, auch eine bessere Konfigurierbarkeit ist langfristig sinnvoll. Des weiteren sollte eine Mobilversion (die es bislang nicht gibt) möglichst viel Code mit der Clientanwendung teilen (Sprich Teile der Businesslogik sollten auf dem Server laufen).
Daher wird das Projekt definitiv komplexer als das bisherige.
Mechanics schrieb:
Selbst wenn ich ein kleineres Teilprojekt einfach runtertippen und vergessen könnte, bau ich das öfter so auf, wie ich ein größeres/komplexeres Projekt aufbauen würde.
Wenn nicht abzusehen ist das dies nötig wird, halte ich dies für falsch (sofern man es nicht gerade als Lernprojekt für größere Architekturen ausgelegt ist).