Problem mit Klassendesign
-
Ich finde der Entwurf ist "verkehrt herum". Kommunikationssysteme sind das klassische Beispiel für Schichtenarchitekturen. Das heißt, die Connection-Klasse sollte die Protokollklasse garnicht kennen. Eine Protokollklasse sollte die Connection besitzen, nicht umgekehrt. Dadurch zwingst Du auch nicht Deine Protokolle auf ein gemeinsames Interface. Das ist nämlich nicht besonders sinnig. Schließlich muß http ganz andere Anfragen erstellen und verarbeiten als z.B. telnet oder ftp.
MfG Jester
-
Hallo DJohn,
uff, danke , eine Antwort. Beobachte den Thread schon 3 Stunden oder so.
Ja, Der Code stellt genau das dar, was ich haben möchte.Wenn nun ein Projekt kompiliert werden soll für ein bestimmtes Protokoll, soll einfach nur die gewünschte abgeleitete Protokollklasse mitkompiliert werden, und wenn dann die Connectionklasse die richtigen virtuellen Funktionen referenziert, ohne dass ich extra nochmal irgendwas an ihrem Code ändern muss,
isses optimal.Ich kann mir nicht vorstellen, dass der Basisklassenzeiger dann das komplette Objekt hat, ich meine inclusive abgeleitete Klasse?
Funzt das so einfach? Das käme mir wie Zauberei vor.Wie kann man das erklären, das dass funktioniert?
Danje arniOOps, habe den unteren Teil nicht gesehen, genau das ist es, was ich vermeiden will, die ConnectionKlasse müsste so immer an das gewünschte Prorokoll angepasst werden.
-
Hai Jester,
dieses Gefühl werde ich auch nicht los, das da noch etwas fundamentales im Design nicht stimmig ist.Was du sagst, die Connectionklasse sollte das Protokoll gar nicht kennen, das isses, genau so stell ich es mir vor..
Wie meinst du das mit dem gemeinsamen Interface, kannst du bitte noch ein bisschen mehr ins Detail gehen ? ich habe deinen Punkt noch nicht richtig.
mfg
arniNachtrag:
habe beim schreiben die Nachrichten erst nach und nach mitbekommen, sorry, wirkt jetzt vielleicht etwas unkoordiniert.
-
Ich finde folgenden Code deutlich eingängier:
HttpProtokoll http(connection); http.get("blablabla");
etc. Die Connection bietet Dir eine gewisse Schnittstelle und die benutzt Du um die höheren Protokolle zu implementieren. Übrigens ist auch der Rest Deine Kommunikation so gebaut:
Du hast ne physikalische Leitung, dadrauf kannste irgendwie Bits übertragen, mehr nicht. Dann bauste ne Schicht drauf, die versucht Fehler zu erkennen und einfach bescheid sagt, wenn was nicht klappt. Dadrauf setzt ne Schicht auf, die den Zugriff auf das Übertragungsmedium regelt, zum Beispiel CSMA/CD bei Ethernet. Das ist die Ebene, auf der MAC-Adressen zum Einsatz kommen. Die Schicht drunter, die die Bits überträgt hat keine Ahnung von MAC-Adressen. Das braucht sie nämlich auch nicht. Dadrüber liegt die nächste Schicht, mit einem Routing-Protokoll, z.B. IP. Die Schicht untendran kann nämlich nur direkt verbundene Kommunikationspartner miteinander kommunizieren lassen. IP sorgt dafür, daß man auch mit jemandem kommunizieren kann, der irgendwo anders sitzt. Das ganze ist wiederum transparent für die unterliegenden Schichten. Dadrauf kommen dann schließlich Protokolle wie TCP etc.
Der Vorteil von sowas, ist daß man statt was komplexem wie TCP (mit Verbindungsauf- und abbau) auch was einfacheres, z.B. UDP drauflegen kann, ohne daß die unten dran was mitkriegen.
Wenn's Dich interessiert, dann such mal nach ISO-OSI Referenzmodell.MfG Jester
-
@Jester
Ja, osi ist mir ziemlich klar, mir wird auch die Logik klar, die du versuchst rüberzubringen.
Da habe ich mich wohl richtig verfranzelt in der Objektmodellierung. Ist nach meiner Erfahrung meistens so, wenn man das Gefühl hat, jetzt musst du C++ 'verbiegen und verbeulen', um etwas darzustellen. Dann ist meist im Ansatz, sprich in der Abbildung der realen WElt, der Wurm drin. Ich werde mich jetzt an die Tafel machen, Selbstgespräche führen (kann ich so wunderbar bei denken), und das jetzt noch mal neu aufrollen. Bei Gelegenheit kann ich ja mal berichten, was bei rausgekommen ist.
Danke
arni
-
@arni
Die Connection-Klasse musst Du nicht ändern! Sie muss wie gesagt auch nicht die konkrete Protokollklasse kennen. Aber irgendwann musst Du Dich entscheiden welches Protokoll Du verwendest. Und an dieser Stelle (und nur an dieser Stelle) musst Du dann bestimmten welches konkrete Objekt dem Zeiger auf das abstrakte Protokoll zugewiesen wird. Du kannst dazu z.B. auch eine Fabrikmethode verwenden:AbstraktProtokoll* createProtokoll(){ cout << "Bitte Protokoll angeben:"; char p; cin >> p; switch (p){ case 'A':return new ProtokollA; case 'B':return new ProtokollB; } }
@jester
Ja über das Design als solchs kann man sicher auch einiges anmerken. Ich hatte die Frage eher so verstanden, dass arni Polymorphy verwenden wollte, aber nicht richtig wußte, wie das funktioniert.DJohn
-
@DJohn
Doch, Polymorphie ist schon klar, ich versuche ein gutes Design zu entwickeln für eine Server-Client Anwendung, die wiederverwendbar und portabel (Weitgehend, WSAstartup()ist halt nun mal nicht portabel, aber da kommt man halt unter w2k nicht drumrum) sein soll. Habe mir so vorgestellt eine Modularisierung des Protokolls, ein Modul das z.B. Client-Kommandozeilen interpretiert (z.B für die Remotewartung verschiedener Netzwerkknoten-Geräte), die Socket als Modul (Kann ja morgen UDP für eine Anwendung nötig sein)Ein Server, der 0-64 Clients handelt, anpassbar durch Verwendung von *.ini-Files und noch so ein paar Kleinigkeiten.
Ist für mich durchaus eine Anforderung, bin kein Profi, der das schon Jahre macht, sondern arbeite mich z.B. gerade durch Markus Baeckmanns 'OOP für Dummies' durch. (Ist das nicht der Marc++us (Admin) hier im Forum?). Deswegen, da muss ich mich schon ebbes bemühen und manchmal renne ich einfach in die falsche Richtung. Da haben wir uns schon oft in der Schule die Köpfe heiss geredet nach dem Motto : besitzt nun die Connection das Protokoll oder das Protokoll die Connection ?. Meiner Meinung nach oft Fragen, die nicht ganz trivial zu beantworten sind.
Und Da finde ich im Moment Jesters Argument sehr einleuchtend: Die Connection wird mir hier im Fall durch TCP/IP geliefert, also meine hier Socket und die Connection, während z.B. Telnet als Schicht 5 dann obenauf kommt, und das isses ja was er sagt, 'Das Protokoll sollte die Connection besitzen'. Is schon cool hier das Forum, es gibt nicht so viele Leute, find ich, mit denen man sowas diskutieren kann.
@DJohn
Das nächste mal fasse ich das auch in ein Stück Code, deinen Beitrag konnte man sofort verstehen, und meinen Roman musste man sich erstmal reindrücken.
Danke
arni
-
Doch, Polymorphie ist schon klar, ich versuche ein gutes Design zu entwickeln für eine Server-Client Anwendung,
Naja, so klar isses nu auch wieder nich
Polymorphie = Du willst deine Typen zur Laufzeit festlegen (Beispielsweisse der User stellt in nem Config dialog ein, ob er TCP per socket nutzt, oder http mittels nen textparser wrappt, oder was weiss ich was es da noch gibt ...)
WIllst du dagegen deinen code nur wiederverwendbar machen, also dein code fuer alle moeglichkeiten offen lassen, aber noch mit dem compilen entscheiden, welches protokoll du nutzt, solltest du Polymorphie vermeiden und Templates in betracht ziehen .... (polymorphie kann dir unter umstaenden viel ressourcen kosten)
Ideal waere ne mischung aus beiden .....
Ciao ...
-
@RHBaum
hast natürlich Recht : wissen was Polymorphie ist und sie immer optimal ( oder auch nicht´) anwenden sind zwei Paar Schuhe.
Genau darüber lasse ich mir seit einigen Tagen den Kopf rauchen. Habe heute auch schon über die Verwendung von templates nachgedacht und bin auf einen Beitrag gestoßen, der hatte ne ähnlich gelagerte Frage, glaube war in den FAQ's, über den Gebrauch von Basisklassen, virtuellen Funktionen und Templates. Wenn ich die Antwort richtig interpretiert habe, ist das alles Standard-konform, man darf aber in den Templates nicht mit virtuellen Funktionen hantieren, die dürfen wohl nur in der Basisklasse stehen.
Schade, dass man hier keine einfache Form von UML machen kann. Dann könnte man das Problem noch besser darstellen und diskutieren.Bisher habe ich das Gefühl, ich denke immer im Kreis herum, wie würdest du das Problem angehen, wenn ein Server TCP-socket-connections mit unterschiedlichen,
modular einzuhängenden Protokollen handeln sollte?
Danke
arni
-
Du solltest vor allem aufpassen, nicht zu modular sein zu wollen. Es hat keinen großen Sinn, die höhreren Klassen auch von den unteren stark zu entkoppeln. http setzt nunmal auf TCP auf, warum sollte man sich also die Mühe machen ein http-Protokoll zu implementieren, das vom unterliegenden Protokoll unabhängig ist? Um so anwendungsspezifischer Du wirst um so spezieller wird Dein Code.
Bau Dir ne ordentliche TCP-Klasse und implementier dann Deine anderen Protokolle auf dieser Schnittstelle. So einfach ist das. Polymorphie scheint mir an dieser Stelle hauptsächlich Sinn zu machen, um auch "Fake-Klassen" reinstecken zu können. Quasi ne TCP-Instanz, die in ne Datei schreibt und Infos aus ner Datei liest, damit Du die höheren Schichten automatisch testen kannst und sowas.
Diese Konstruktion ist erstmal einfach, leicht zu implementieren, ohne daß Du Dich zu sehr einschränkst. Wenn Du mehr Flexibilität brauchst, dann kannste das später leicht hinzufügen, aber ich vermute fast, daß das vollkommen genügen wird.
MfG Jester