Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] Model-View Konzeption

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] Model-View Konzeption

    Ich stehe im Moment vor dem Problem, wie ich mein Model und meine View miteinander verbinden kann. Ich will versuchen, es an einem einfach gehaltenem Beispiel deutlich zu machen:

    Das Domain-Model:
    PHP-Code:
    class Member implements User
    {
        
    //...
    }

    class 
    Guest implements User
    {
        
    //...
    }

    interface 
    User
    {
        public function 
    getId();
        public function 
    getName();
        public function 
    getEmailAddress();
    }

    class 
    Thread
    {
        public function 
    getAuthor();
        public function 
    getName();
    }

    class 
    ImportantThread extends Thread
    {

    Der View übergebe ich nun die jeweiligen Objekte. Dort möchte ich nun auf die verschiedenen Arten von Objekten reagieren:
    • Ein ImportantThread soll ein anderes Bild als ein Thread bekommen.
    • Ein Member soll verlinkt werden, ein Guest nicht.


    Wie komme ich nun darum herum, in meiner View ständig if-else- oder switch-Konstrukte verwenden zu müssen? Ein paar Ansätze habe ich, aber so wirklich gefallen tun sie mir alle nicht.

    Entscheidung ins Model verlagern
    Eine Möglichkeit wäre es, der Klasse Thread z.B. eine getImageSource-Methode zu verpassen, die dann von dem ImportantThread überschrieben werden könnte. Allerdings ist dies ein Wissen, welches das Model gar nicht haben sollte (je nach View mag es verschiedene Bilder geben). Von daher klingt dieser Ansatz für mich nicht sehr klug.

    Eine extra Klasse aus der View für jedes Domänenobjekt
    Ein anderer Ansatz wäre, für jedes Domänenobjekt noch ein Objekt aus der View zu nutzen.
    Das könnte z.B. so aussehen:
    PHP-Code:
    class MemberView extends UserView
    {
        public function 
    hasLink()
        {
            return 
    true;
        }
        
    //...
    }

    class 
    GuestView extends UserView
    {
        public function 
    hasLink()
        {
            return 
    false;
        }
        
    //...
    }

    abstract class 
    UserView
    {
        public static 
    factory(User $user)
        {
            if (
    $user instanceOf Member) {
                return new 
    MemberView($user);
            } else {
                return new 
    GuestView($user);
            }
        }

        abstract function 
    hasLink();
        abstract function 
    getLink();
        
    //...

    Das Positive:
    • Die if-else- bzw. switch-Konstrukte werden auf ein Minimum reduziert.
    • Das Model kennt keine Daten der View


    Das Negative:
    • Parallele Vererbungshierarchien
    • Sehr starke Kopplung der View-Klassen an das Model, Änderungen müssten oft doppelt erfolgen.



    Wirklich gefallen tut mir auch diese Möglichkeit nicht. Gibt es für mein Problem ein Möglichkeit, die ich übersehen habe? Irgendeine BestChoice vielleicht?
    Programming PHP

  • #2
    Sehe ich jetzt nicht dramatisch. Wenn die Modellogik unterschiedlich ist und die Viewlogik unterschiedlich, braucht man halt jeweils mehrere Objekte. Ist die Viewlogik sehr ähnlich, könnte man mehrere Models mit einer gemeinsamen View abfeiern (Templatelogik o.ä.). Aber irgendwo muss die Logik ja stecken.
    [COLOR="#F5F5FF"]--[/COLOR]
    [COLOR="Gray"][SIZE="6"][FONT="Georgia"][B]^^ O.O[/B][/FONT] [/SIZE]
    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
    [URL="http://www.php.de/javascript-ajax-und-mehr/107400-draggable-sorttable-setattribute.html#post788799"][B]Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“[/B][/URL][/COLOR]
    [COLOR="#F5F5FF"]
    --[/COLOR]

    Kommentar


    • #3
      Ins Model sollte die Darstellungslogik mit Sicherheit nicht.
      Ich würde auch nicht für wichtige Threads eine weitere Klasse implementieren. Was ist, wenn es noch andere Thread-Typen gibt? Noch mehr Klassen? Nee - lieber als Attribut.
      Definier doch im Template anhand eines Attributs des Threads eine CSS-Klasse. Z. B.
      PHP-Code:
      <div class="thread thread-<?php echo $thread->getType(); ?>">
      ...
      </div>
      ...

      Kommentar


      • #4
        Zitat von [-UFO-]Melkor Beitrag anzeigen
        Eine extra Klasse aus der View für jedes Domänenobjekt
        Ein anderer Ansatz wäre, für jedes Domänenobjekt noch ein Objekt aus der View zu nutzen.
        Das könnte z.B. so aussehen:
        PHP-Code:
        class MemberView extends UserView
        {
            public function 
        hasLink()
            {
                return 
        true;
            }
            
        //...
        }

        class 
        GuestView extends UserView
        {
            public function 
        hasLink()
            {
                return 
        false;
            }
            
        //...
        }

        abstract class 
        UserView
        {
            public static 
        factory(User $user)
            {
                if (
        $user instanceOf Member) {
                    return new 
        MemberView($user);
                } else {
                    return new 
        GuestView($user);
                }
            }

            abstract function 
        hasLink();
            abstract function 
        getLink();
            
        //...

        Im Prinzip würde ich es diesen Ansatz verfolgen aber so hast du deine if-else Konstrukte nur verlagert. Du fragst jetzt halt hasLink() ab anstatt die Klasse, ist damit wirklich etwas gewonnen?

        Wie wäre es damit:

        PHP-Code:

        abstract class UserView
        {
            
        // ...

            
        public static factory(User $user)
            {
                if (
        $user instanceOf Member) {
                    return new 
        MemberView($user);
                } else {
                    return new 
        GuestView($user);
                }
            }

            abstract function 
        renderName();
        }

        class 
        MemberView extends UserView
        {
            public function 
        renderName()
            {
                
        // Name mit Link
            
        }
            
        //...
        }

        class 
        GuestView extends UserView
        {
            public function 
        renderName()
            {
                
        // Name ohne Link
            
        }
            
        //...

        [IMG]https://g.twimg.com/twitter-bird-16x16.png[/IMG][URL="https://twitter.com/fschmengler"]@fschmengler[/URL] - [IMG]https://i.stack.imgur.com/qh235.png[/IMG][URL="https://stackoverflow.com/users/664108/fschmengler"]@fschmengler[/URL] - [IMG]http://i.imgur.com/ZEqflLv.png[/IMG] [URL="https://github.com/schmengler/"]@schmengler[/URL]
        [URL="http://www.schmengler-se.de/"]PHP Blog[/URL] - [URL="http://www.schmengler-se.de/magento-entwicklung/"]Magento Entwicklung[/URL] - [URL="http://www.css3d.net/"]CSS Ribbon Generator[/URL]

        Kommentar


        • #5
          Entscheidung ins Model verlagern
          Eine Möglichkeit wäre es, der Klasse Thread z.B. eine getImageSource-Methode zu verpassen, die dann von dem ImportantThread überschrieben werden könnte. Allerdings ist dies ein Wissen, welches das Model gar nicht haben sollte (je nach View mag es verschiedene Bilder geben). Von daher klingt dieser Ansatz für mich nicht sehr klug.
          Warum nicht? MVC einzusetzen bedeutet nicht, sein OOP-Verständnis beiseite legen zu dürfen. Was du hier hast sind keine Models im klassischen Sinn von MVC, sondern Domänen-Objekte. Wenn du so willst, ist dein Model eine DSomänen-Objekt-Sammlung bzw. -Struktur.

          Betrachtet man die einzelnen Typen, so ist das Icon/Bild eines solchen Threads definitiv ein Attribut eines Domänen-Objekts und hat nichts in der View-Logik zu suchen. Ein Important-Thread ist also ein ganz einfacher Thread, dessen Bild einfach anders ist. Wer diese Information in den Thread injiziert sei zunächst dahingestellt, kann aber sehr einfach an Hand des Typen ohne jegliches zusätzliche Mapping erfolgen (Icon hat den Typ-Bezeichner im Datei-Namen) oder durch explizites Mapping in einer Business-Schicht an Hand von diversen Informationen initialisiert werden.

          Fakt ist jedoch, dass der oben vorgestellte Ansatz definitiv Blödsinn ist, da du Funktions- und Struktur-Duplizierung betreibst.
          Viele Grüße,
          Dr.E.

          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          1. Think about software design [B]before[/B] you start to write code!
          2. Discuss and review it together with [B]experts[/B]!
          3. Choose [B]good[/B] tools (-> [URL="http://adventure-php-framework.org/Seite/088-Why-APF"]Adventure PHP Framework (APF)[/URL][URL="http://adventure-php-framework.org"][/URL])!
          4. Write [I][B]clean and reusable[/B][/I] software only!
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

          Kommentar


          • #6
            so ist das Icon/Bild eines solchen Threads definitiv ein Attribut eines Domänen-Objekts
            Ein Icon hat in meinen Augen nichts mit der Rolle des Threads in der Applikation zu tun. Das dient lediglich der Darstellung. Da würde ich eher für einen "Typ" plädieren. Diesen kann man dann noch für andere Dinge verwenden. Was wäre denn z. B., wenn dieser Thread-Typ nicht nur ein anderes Bild, sondern auch eine andere Hintergrundfarbe haben soll? Noch ein Attribut?

            Was anderes ist das z. B. bei einem User und dessen Avatar-Bild.

            Kommentar


            • #7
              Deswegen hatte ich ja auch

              Wer diese Information in den Thread injiziert sei zunächst dahingestellt, kann aber sehr einfach an Hand des Typen ohne jegliches zusätzliche Mapping erfolgen (Icon hat den Typ-Bezeichner im Datei-Namen)
              vorgeschlagen, was ich persönlich bevorzugen würde. Beides ist jedoch valide, denn ein Mapping in der Business-Schicht wiederspricht nicht dem Ansatz aus einem Thread einen ImportantThread zu machen, der das Interface einfach um GUI-relevante Attribute ergänzt. Fraglich ist dann allerdings, wie ich in der GUI mit den unterschiedlichen Instanzen umgehe. jedes mal instanceof zu nutzen halte ich für keine gute Idee.
              Viele Grüße,
              Dr.E.

              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
              1. Think about software design [B]before[/B] you start to write code!
              2. Discuss and review it together with [B]experts[/B]!
              3. Choose [B]good[/B] tools (-> [URL="http://adventure-php-framework.org/Seite/088-Why-APF"]Adventure PHP Framework (APF)[/URL][URL="http://adventure-php-framework.org"][/URL])!
              4. Write [I][B]clean and reusable[/B][/I] software only!
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

              Kommentar


              • #8
                vorgeschlagen, was ich persönlich bevorzugen würde.
                So meinte ich das Ist mir irgendwie entgangen..

                EDIT:
                jedes mal instanceof zu nutzen halte ich für keine gute Idee.
                Dem stimme ich zu - So lange sich ein Important-Thread von einem nur marginal unterscheidet (Anderer Typ), halte ich es für unsinnig, dafür eine eigene Klasse zu implementieren.

                Kommentar


                • #9
                  PHP-Code:
                      public static factory(User $user)
                      {
                          switch (
                  $user->getType ()) {
                            case 
                  'member':
                            case 
                  'admin':
                              return new 
                  MemberView($user);

                            case 
                  'supermember':
                              return new 
                  SuperMemberView($user);

                            default:
                              return new 
                  GuestView($user);
                          }
                      } 
                  Davon abgesehen würde ich statt Factory method eine echte Factory (als Objekt) benutzen. Das sind dann noch mehr Objekte, aber Du bleibst flexibler für Erweiterungen.
                  [COLOR="#F5F5FF"]--[/COLOR]
                  [COLOR="Gray"][SIZE="6"][FONT="Georgia"][B]^^ O.O[/B][/FONT] [/SIZE]
                  „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
                  [URL="http://www.php.de/javascript-ajax-und-mehr/107400-draggable-sorttable-setattribute.html#post788799"][B]Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“[/B][/URL][/COLOR]
                  [COLOR="#F5F5FF"]
                  --[/COLOR]

                  Kommentar


                  • #10
                    Ich versuche das mal zusammenzufassen, mal sehen ob ich alles richtig verstanden habe.

                    Einige Informationen lassen sich direkt im Domänen-Objekt unterbringen (z.B. der Avatar eines Users). Dementsprechend lässt sich auch die Unterscheidung verschiedener Typen bewirken, die sich z.B. nur in ihrer Darstellung unterscheiden.

                    Will ich komplexere View-Logik ausdrücken, arbeite ich aber lieber mit extra Klassen für die View-Logik.
                    Programming PHP

                    Kommentar


                    • #11
                      Eigentlich brauchst Du für die Views keine extra Klassen - Jedenfalls habe ich noch nie was erlebt, wo ich das gebraucht hätte.. Dann eher mit Templates für die einzelnen Bestandteile. Dann ist das auch einheitlich.

                      Kommentar


                      • #12
                        Ich stimme xm22 zu, für View-Logik ist im MVC-Pattern schon eher der Controller zuständig. Nach meinem Dafürhalten sollte dieser die Informationen so für die Anzeige aufbereiten, dass der View-Teil quasi Logik-frei ist. Andernfalls hast du massive Probleme mit Wiederverwendbarkeit und Testbarkeit.
                        Viele Grüße,
                        Dr.E.

                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                        1. Think about software design [B]before[/B] you start to write code!
                        2. Discuss and review it together with [B]experts[/B]!
                        3. Choose [B]good[/B] tools (-> [URL="http://adventure-php-framework.org/Seite/088-Why-APF"]Adventure PHP Framework (APF)[/URL][URL="http://adventure-php-framework.org"][/URL])!
                        4. Write [I][B]clean and reusable[/B][/I] software only!
                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                        Kommentar


                        • #13
                          Vielen Dank euch allen, das bringt mich ein gutes Stück weiter
                          Programming PHP

                          Kommentar

                          Lädt...
                          X