Seite 1 von 1

Konzept Objekt-Instanzierung - Interfaces

Verfasst: 20. Dezember 2010 08:08
von pbeerle
Hallo Zusammen,

Unsere Firma startet mit einem umfangreichen Projekt, in welchem wir eine ca. 15 jährige GUI-Applikation basierend auf MFC mit Qt durch Refactoring ersetzen wollen. COM und die COM-Aggregation wird ebenfalls intensiv angewendet.

Derzeit haben wir noch kein Knowhow im Umgang mit Qt. Wir versuchen derzeit, uns die Grundlagen zum Umbau zu erarbeiten. Ein Thema des Umbaus ist die Klasseninstanzierung sowie die COM-Aggregation zu ersetzen. Ich habe mir einmal des Source-Code zum Qt-Creator angeschaut und habe dazu einige Feststellungen gemacht und es ergaben sich einige Fragen, auf die ich (noch9 keine Antworten habe.

Im Qt-Creator:
a) Warum hat jede Klasse immer genau (nur) 1 Basisklasse ?

b) die Objekt-Instanzierung basiert im Wesentlichen darauf, dass die Klasse, die ein Objekt erzeugt immer genau die Klasse kennt und weiss, bei welcher Klasse sie diese Instanz bekommt. Eine Instanz wird vom Objekt, welches das Objekt erzeugt auch wieder gelöscht. Bevor eine Instanz gelöscht werden kann muss damit klar bekannt sein, dass dieses Objekt und deren Daten und Slots von aussen nicht mehr benutz werden.

c) Qt bedient sich einem Aggregations-Objekt um Fähigkeiten ähnlich der COM-Aggregation zu erweitern. Diese Objekte und die Lebensdauer wird aber immer vom äusseren Objekt bestimmt.

Meine Fragen:
1.) zu a) bis c). gibt es Gründe, warum dies so ist ?

2.) bei der COM-Aggregation können Clients nur durch Kenntniss eines Interfaces Objekt erhalten, die dann im weiteren Verlauf durch Smartpointer gehalten werden. Die Lebensdauer der inneren Objekte ist von den äusseren Objekten unabhängig, d.h. das äussere Objekt stirbt nicht, wenn es darauf keine Referenz mehr gibt, solange es noch Referenzen auf die inneren Objekte gibt.

Unsere Applikation hält also alle (inneren und äusseren) Objekte duch Smaprtpoineter und für uns stellt sich nun die Frage, mit welchem Konzept man dies COM-Aggregation auflösen kann, wobei es zu berücksichtigen gilt, dass wir durch Refactoring zum Ziel gelangen müsen.

3.) Gibt es eine Empfehlung, wie man die Objektinstanzierung unter Qt anwenden soll.

4.) Warum wendet z.B. der Qt-Creator die Interface-Technik relativ wenig an ?

Besten Dank

Gruss

Peter

Verfasst: 20. Dezember 2010 09:01
von franzf
Kurze Antwort: Es gibt in C++ viele Konzepte, eine einzige Applikation als Programmier-Referenz heranzuziehen macht wenig Sinn.

a) weil man ohne virtual-Vererbung bei mehreren von QObject abgeleiteten (und nicht nur bei denen) Basisklassen Probleme bekommt.

b) den ersten Satz versteh ich nicht.

c) definierte Besitzverhältnisse eben. (und Qt != Qt Creator)

2) Ich kenn das COM Interface nicht. Aber findest du wirklich es macht Sinn, ein Objekt länger leben zu lassen als notwendig? Das ist doch Speicherverschwendung! Smartpointer kannst du auch in Qt verwenden (Q[Shared,Scoped,Weak]Pointer gibt es ja nicht nur zum Spaß). Man sollte aber wissen, wann welcher Sinn macht, und nicht einfach einen sinnlosen Referenzzähler einbauen ohne nachzudenken.

3) ? Was meinst du damit?

4) Du meinst Ableiten von einer Klasse mit nur pure-virtual-Funktionen? Ich hab mir den Code dahingehend noch nicht angesehen, aber wenn es so ist wird es keinen Sinn gemacht haben.


Ich denke ihr solltet nicht die Konzepte 1:1 von COM/MFC nach Qt portieren. Refatoring heißt ja eben gerade nicht direkte Übertragung - da darf sich auch mal ordentlich was ändern.

Verfasst: 20. Dezember 2010 09:04
von Giesbert
Hi,

auf die schnelle ein paar Antworten:

zu 1.)
a) Warum hat jede Klasse immer genau (nur) 1 Basisklasse ?
Das ist in C++ eigentlich üblich, wenn du keine Interfaces hin zunimmst. So ist es auch in MFC :-)
b) die Objekt-Instanzierung basiert im Wesentlichen darauf, dass die Klasse, die ein Objekt erzeugt immer genau die Klasse kennt und weiss, bei welcher Klasse sie diese Instanz bekommt. Eine Instanz wird vom Objekt, welches das Objekt erzeugt auch wieder gelöscht. Bevor eine Instanz gelöscht werden kann muss damit klar bekannt sein, dass dieses Objekt und deren Daten und Slots von aussen nicht mehr benutz werden.
Bei QObjects wird die Lebenszeit via parent/child gekoppelt. Wwenn du Objekte als Top Level Objekte erzeugst, bist du auch für das delete zuständig. Wenn ein QObject zerstört wird, benachrichtigt es objekte, die verbunden sind und die signal/slot verbindungen werden gekappt.

zu 2.)
Das mit den smart pointer hängt ein wenig davonb ab, wie man das ganze löst. prinzipiell ist Qt C++ und man kann alles tun, was C++ bietet.

Aber COM ist da schon was Eigenes, was nicht C++ standard ist. Die Mechanismen kann man in C++ schon abbilden. Aber Qt hat da einen Möglichkeit, der lebenszeitkopplung, so das keine Memory leaks entstehen sollten (durch parent/child).
Du könntest das z.B. dadurch erreichen, das du ein Top level Objekt (von QObjekt abgeleitet) hast, das Parent für die ganzen Datenobjekte / service objekte / awas auch immer ist. Nur im UI muss parent / child stimmen, sonst bekommst du Layout Probleme.

3.) Naja, so wie Qt das Vorschlägt. Nutze parent / child wenn möglich. Was sonst möchtest du hier hören?

4.) In Qt werden interfaces nur für plug-ins verwendet. Das wurde halt mal so entschieden. Lose Kopplung hat zwar ihre Vorteile, aber auch Nachteile. Z.B. kann man keine Klassen erweitern, die man nur via interfaces erreicht. Und ich kenne im Qt Framework keine Stelle, wo interfaces mir Vorteile bringen würden.

Hoffe etwas Klarheit geschafft zu haben :-)

Ciao

Gerolf

Verfasst: 20. Dezember 2010 09:30
von pbeerle
Hallo Zusammen,

Besten Dank für die Antworten.
Habe diese soweit auch verstanden.

Leider aber habe ich aber immer noch keine Vortstellung darüber, wie ich das Verhalten in unserer Anwendung durch Refactoring ändern kann.

In unserer Applikation holt man sich mit CreareInstance ein Objekt mit einem bestimmten Interface. Mit QueryInterface und irgend einem anderen Interface kriegt man so z.B. Zugriff auf Fähigkeiten innerer Objekte (Clients wissen gar nicht, dass es innerer Objekte sind). Alle Objekte werden mit Smartpointern gehalten, wobei es natürlich auf ein und dasselbe Objekte mehrere Clients gibt, die einen solchen Smartpointer haben. Objekte löschen sich erst, wenn es keine Referenzen mehr gibt, wobei eben ein äusseres Objekt nicht stirbt, solange ein inneres Objekt noch eine Referenz hat. Die Refeenzzählung ist (bei MFC) im Objekt und nicht wie in Qt im Smartpointer.

Danke

Peter

Verfasst: 20. Dezember 2010 09:54
von Giesbert
Hallo pbeerle,

eine Referenzzählung ist in MFC nicht drinnen.
Reference Counting mach COM, das ist ein riesen Unterschied. Wenn du In Qt COM verwendest, hast du auch RefCounting.

Verfasst: 20. Dezember 2010 10:30
von franzf
Die zentralen Fragen sind denke ich:
*) Was ist der Hintergrund der Portierung nach Qt? Soll das Ding dann auch auf Linux und Mac laufen?
*) Falls Lin +Mac: Wie habt ihr bisher COM eingesetzt?
- In-Process-Server: -> Qt Plugin
- Lokaler Server: -> Kommunikation mit QProcess, oder einen Wrapper um COM/DBUS anbieten.
- Remote Server: Ich glaub DBUS kann nur Lokal. Wenn ihr hier plattformunabhängig bleiben wollt, müsst ihr von COM weg und ein eigenes Protokoll zur Kommunikation zwischen Client/Server entwickeln.
*) Falls es weiterhin nur auf Win laufen soll, könnt ihr bei COM bleiben. Wenn ihr nur von MFC weg wollt, könnt ihr doch gleich WPF nehmen.

Verfasst: 20. Dezember 2010 10:52
von pbeerle
Hallo franzf
franzf hat geschrieben: Die zentralen Fragen sind denke ich:
*) Was ist der Hintergrund der Portierung nach Qt? Soll das Ding dann auch auf Linux und Mac laufen?
.
1.) Moderners Look als mit MFC, GUI-Programmierung mit MFC ist mühsam, ineffizient und veraltet, usw.
2.) Kein MUSS aber ein Wunsch der plattformunabhängigkeit, da die zum GUI gehörende Maschinen-SW schon mit Qt realisiert ist
franzf hat geschrieben:
*) Falls Lin +Mac: Wie habt ihr bisher COM eingesetzt?
- In-Process-Server: -> Qt Plugin
- Lokaler Server: -> Kommunikation mit QProcess, oder einen Wrapper um COM/DBUS anbieten.
- Remote Server: Ich glaub DBUS kann nur Lokal. Wenn ihr hier plattformunabhängig bleiben wollt, müsst ihr von COM weg und ein eigenes Protokoll zur Kommunikation zwischen Client/Server entwickeln.
.
Lokal- und In-Proc-Server
franzf hat geschrieben: *) Falls es weiterhin nur auf Win laufen soll, könnt ihr bei COM bleiben. Wenn ihr nur von MFC weg wollt, könnt ihr doch gleich WPF nehmen.
Ein Projekt mit 60 Mannjahren von C++/MFC nach WPF mit Refactoring ?
Ist das wirklich sinnvoller, erfolgreicher, einfacher als mit Qt ?