Allgemeine Frage zum Doc/View Modell


  • Administrator

    Grüsse zusammen,

    Ich habe schon lange ein wenig das Problem bei diesem Modell, dass ich mich nicht so recht entscheiden kann was nun wo reinkommt. Bzw. vor allem in der Kommunikation ist bei mir hier ein Problem, wer von beiden den Code für die Kommunikation übernimmt.

    Also nehmen wir mal ein Beispiel. Wir haben eine ListView und ein Document mit verschiedenen Listen. Wie passiert nun die Kommunikation?

    1. Möglichkeit:
    Der User klickt auf etwas, was in der View registriert wird, dann wird das ListCtrl der View entsprechend für die neuen Angaben angepasst und dann einer Funktion aus der Document Klasse übergeben zum Füllen. Also

    C...View::OnIrgendwas(...)
    {
        CListCtrl& refListCtrl = GetListCtrl();
        /* refListCtrl mit Kolonnen und Co anpassen */
    
        C...Doc* pDoc = (C...Doc*)GetDocument();
        pDoc->FillListWithUselessThings(refListCtrl);
    }
    

    2. Möglichkeit:
    In der View wird registriert was passiert und es werden die Daten aus der Doc geholt und dann in die Liste gesetzt. Also

    C...View::OnIrgendwas(...)
    {
        CListCtrl& refListCtrl = GetListCtrl();
        /* refListCtrl mit Kolonnen und Co anpassen */
    
        C...Doc* pDoc = (C...Doc*)GetDocument();
        for(int i = 0; i < pDoc->GetIrgendwasCount(); ++i)
        {
            CIrgendwas/** oder & oder gar nix*/ Objekt = pDoc->GetIrgendwasAt(i);
            /* Und dann das refListCtrl damit füllen. */
        }
    }
    

    Also ich tendiere mehr zur 1. Möglichkeit. Da ich so in meiner Doc mit den privaten Membern frei hantieren kann. Zudem muss ich auch nicht so Funktionen wie GetCount usw. einführen. Aber dann erscheint mir langsam am Ende die View überflüssig, da es eigentlich schlussendlich nur noch ein weitergeben von Objekten ist. Also bei jedem Schritt, welcher der User macht, wird irgend eine Funktion aus der Doc aufgerufen. Deshalb meine Frage: Was ist "richtiger"?
    Bzw. gibt es noch andere Möglichkeiten?

    Grüssli und danke im voraus!



  • Ich habe für mich Möglichkeit 2 gewählt.
    Sobald was mit Controls (ich habe Formviews) dabei ist, gehört es in den View.
    Reine Recordsetaktionen werden im Doc erledigt.

    Aber Möglichkeit 1 ist auch nicht schlecht, ich bin nur nicht drauf gekommen. 😉


  • Administrator

    Hmmm tjo und was ist nun richtig? Gibt es das denn überhaupt? Und was sagen da noch andere dazu? ^^

    Grüssli



  • Also ich arbeite eigentlich auch immer mit Möglichkeit 2. Das entspricht mehr meinem Verständnis des Doc/View-Modells: Das Document verwaltet nur die Daten und stellt für diese Getter und Setter zur Verfügung. Die Steuerung der Aus- und Eingabe übernimmt der View.

    Ich denke aber dass es dazu kein wirkliches richtig oder falsch gibt, ist eher eine Stilfrage. 🙂

    Gruß Brainiac

    PS: :schland: 👍 🕶





  • ..



  • DOC soll garnicht wissen das es eine Klasse CListCtrl gibt.
    Bei V1 muss es dies aber.
    DOC soll nur Daten bereithalten und dem Frager übergeben.
    Die View soll damit machen was sie will.
    Es könnte ja sein das man eine weitere View braucht und die Daten nicht in ein CListCtrl kommen. Dann müsste man wieder DOC umschreiben weil man eine weitere Funktion braucht.

    Bei V2 braucht man aber nru eine weitere VIEW.


  • Mod

    Ich sehe auch 2 eher als korrekt an. Wie Unix-Tom es schon schrieb. Man erzeugte eine Abhängigkeite zwischen Doc und View. Beide müssen Details von einander wissen was ich gar nicht für gut halte.



  • ich beschäftige mich gerade mit diesem Thema und erstelle eine kleine Testapp,
    die Objekte in eine Listenklasse (Studentenliste) aufnimmt und in der man in einem SDI Formview durch die Datensätze blättern kann.
    Ähnlich des Beispieles Inside Visuall C++ 6.0 (Kruglinski S347ff):

    http://flylib.com/books/en/1.562.1.150/1/

    Die große Frage ist nun, wohin denn die Funktionen zum Bewegen und Bearbeiten der Studentenliste genau implementiert werden sollen.

    Soweit ich es verstanden habe, werden im Doc die Daten abgelegt und im View die Funktionen die die Daten darstellen.

    Da hätten wir (A.) die Navigationsfunktionen: Next, Prev, First, Last
    die Funktionen zum (B.) Anzeigen der Daten im Formular
    und die Funktionen zum (C.) Bearbeiten der Daten: Neue Datensatz, Datensatz löschen, alle Datensätze löschen.

    Im Buchbsp. wird A, B und C fast komplett im View implementiert.

    (A.) + (B.) in den View zu legen, leuchtet mir ein und ist logisch
    aber müsste (C.) nicht in das Doc,
    gerade wenn später ggf. noch andere Views implementiert werden sollen,
    dann kann man mittels UpdateAllViews gleich die anderen Views aktualisieren, wenn Daten gelöscht wurden. Oder geht das so nicht?

    Wäre nett, wenn mir dort jemand auf die Sprünge helfen könnte.

    Gruß Thomas


  • Mod

    Auch ein neuer Datensatz hat eine visuelle Aktion notwendig. Auch diese Funktion kann in den View gehören. 😉

    Wenn das Dokument auch die Positon bestimmt, und immer nur über einen Datensatz zum editieren verfügt, dann kann auch die Navigations Befehle in den View. 😉

    Es gibt viele Wege nach Rom.



  • Ich übergebe keine GUI Objekte in irgendwelche Datenhaltungsklassen.. Daher verwende ich oftmals einen Mischansatz aus 1 und 2. Lieber lasse ich mir eine typisierte Liste (std::vector/list<Objekt*> füllen (wie in Ansatz 1) und kopiere dann die Items aus der Liste (wie in Ansatz 2) selber in die GUI Objekte (CListCtrl).

    Bedingt zwar den Overhead 2x über die Objektmenge zu iterieren, aber das nehme ich in Kauf.

    Wenn es absolut performant sein soll, man es ganz elegant haben will und Templates liebt, kann man im View einen Functor erstellen der ein Element in das GUI Object (CListCtrl) kopiert, und diesen dann seiner Datenhaltungsklasse übergeben. Anstelle die oben beschriebene Liste zu füllen, ruft die Datenhaltungsklasse dann halt jedesmal den Functor auf an der Stelle wo vorher ein Objekt der Liste hinzugefügt worden wäre.



  • Danke für die Hinweise, ich habe es schlussendlich so wie im Buch Bsp gemacht.

    Dabei trat aber folgende Fragestellung auf:

    In der View-Klasse CEx16aView habe ich einen Diagnoseroutine CEx16aView::DsDiag()
    geschrieben, die TRACE Infos ausgibt. Auf diese Routine möchte ich auch von der Document Klasse aus zugreifen.

    Das bekomme ich leider nur so hin, was ja vollkommen verkorkst ist:

    void CEx16aDoc::OnEditClearAll() 
    {
        //Dump vor dem Loeschen
    	POSITION pos = GetFirstViewPosition(); 
    	CEx16aView* pView = (CEx16aView*) GetNextView(pos); 
    	pView->DsDiag(); 
       //..
    }
    

    Wie kann ich vernünftig zugreifen?

    Danke ..



  • Also unter
    http://www.codeguru.com/forum/showthread.php?t=282338&goto=nextoldest
    findest du allgemein ne Anleitung, wie man zwischen den Klassen auf irgendwelche Dinge zugreifen kann.



  • AndyDD schrieb:

    Also unter
    http://www.codeguru.com/forum/showthread.php?t=282338&goto=nextoldest
    findest du allgemein ne Anleitung, wie man zwischen den Klassen auf irgendwelche Dinge zugreifen kann.

    ja, nach dieser Anleitung bin ich auch vorgegangen:

    POSITION pos = GetFirstViewPosition();
    CEx16aView* pView = (CEx16aView*) GetNextView(pos);
    pView->DsDiag();
    

    Mein Gefühl sagt mir aber, das dies nicht besonders elegant ist
    und ich vermute mal, dass es einen besseren Weg gibt



  • Was meinste denn mit

    ThomasC schrieb:

    Mein Gefühl sagt mir aber, das dies nicht besonders elegant ist
    und ich vermute mal, dass es einen besseren Weg gibt

    Du holst dir einen Zeiger auf deine Viewklasse uns kannst alle public-Elemente ansprechen. Was spricht dagegen? Oft muss die View-Klasse auf Daten des Doc zugreifen, deshalb gibts ja auch GetDocument(). Wenn es andersrum genauso wichtig wäre, dann hätte die Doc-Klasse automatisch auch gleich eine Get-Methode aufs View. Du könntest ja auch vom Doc aus ne Message an das View schicken um damit noch Informationen zu übertragen. Ansonsten gibts ja noch UpdateAllViews oder UpdateWindow.


  • Mod

    ThomasC schrieb:

    AndyDD schrieb:

    Also unter
    http://www.codeguru.com/forum/showthread.php?t=282338&goto=nextoldest
    findest du allgemein ne Anleitung, wie man zwischen den Klassen auf irgendwelche Dinge zugreifen kann.

    ja, nach dieser Anleitung bin ich auch vorgegangen:

    POSITION pos = GetFirstViewPosition();
    CEx16aView* pView = (CEx16aView*) GetNextView(pos);
    pView->DsDiag();
    

    Mein Gefühl sagt mir aber, das dies nicht besonders elegant ist
    und ich vermute mal, dass es einen besseren Weg gibt

    Das ist auch nicht elegant. Damit muss das CDocument wissen wie die Views ticken.

    Für so etwas gibt es UpdateAllViews. Damit wird die OnUpdate Methode in jedem View aufgerufen.
    Man kann sogar ein CObject als weitere Infor mitliefern oder ein DWORD als Hint.



  • Hallo Martin,

    ich benutze UpdateViews natürlich aus dem aktuellen View heraus und aus dem Doc, aber nur wenn sich Daten geändert haben.

    Die Diagnosefunktion möchte ich davon unabhängig nutzen. Ich müsste Sie dann in die überschriebene virtuelle Methode des betreffenden Views einfügen und sie würde dann ständig aufgerufen werden, wenn Daten geändert werden.

    Gruß Thomas


  • Mod

    Warum benutzt Du nicht grundsätzlich UpdateAlViews aber eben mit unterschieldichen Hints?



  • Martin Richter schrieb:

    Warum benutzt Du nicht grundsätzlich UpdateAlViews aber eben mit unterschieldichen Hints?

    OK, habe es geschnallt.


Anmelden zum Antworten