Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] OO Frage

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

  • [Erledigt] OO Frage

    Hallo an alle

    Ich habe eine relativ komplexe Datenbank, bei welcher ich die meisten Tabellen mit Objekten abbilde, also ActiveRecords mit ein paar für meine Zwecke nötigen Funktionen. Das funktioniert meistens ziemlich gut.

    Problem: Diese Objekte spiegeln natürlich nur ein Objekt der Datenbank wieder. Wie löse ich das jetzt am elegantesten, wenn ich beispielsweise alle Datensätze einer Tabelle haben möchte?

    Am Beispiel: Ich habe eine Tabelle Bücher und stelle einen Datensatz als Objekt Buch dar. Nun möchte ich meine Bibliothek füllen. Wie komme ich an all die Bücher?

    Meine Ansätze: Eine statische Methode zum Bücherobjekt hinzufügen welche mir alle Bücher zurückgibt. Ziemlich mies gelöst meiner Meinung nach.

    Zweite Möglichkeit: Eine neue Klasse, die mir alle Bücher auflisten kann. Hier hoffe ich aber das es noch eine bessere Möglichkeit gibt, da ich die Datenbankzugriffe soweit wie möglich in den AR lassen würde (also im Beispiel in der Klasse Buch).

    Ich bin mir ziemlich sicher das diese Art von Problem häufiger auftritt, also bin ich guter Dinge hier eine Lösung zu finden

    Danke euch schonmal


  • #2
    Hier hoffe ich aber das es noch eine bessere Möglichkeit gibt, da ich die Datenbankzugriffe soweit wie möglich in den AR lassen würde (also im Beispiel in der Klasse Buch).
    Ist aber durch nichts gerechtfertigt.
    a) Ein Einzelbuchaufruf dürfte i.a. mehr Detaildate abrufen als eine Liste
    b) Konsequenterweise müsstest Du dann eine Liste als Schleife aus Buchobjekten zusammenbauen. Das wäre aus Sicht der Performanz Wahnsinn.

    Bau Dir ein Objekt ListOfBooks und alles ist schön.
    --

    „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
    Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


    --

    Kommentar


    • #3
      Hm... schade. Aber war irgendwie zu erwarten. Danke dir

      Kommentar


      • #4
        wenn ich beispielsweise alle Datensätze einer Tabelle haben möchte?
        Das möchtest du nicht - for sure! Die Anzeige von "allen" Büchern ist bei 99% aller fachlichen Anforderungen immer mit einem Filter oder Paging belegt. Insofern kannst du schon eine Liste vom Typ Books liefern, jedoch mit einer Methode deren Signatur Filter und Paging zulässt.

        Beispiel:
        PHP-Code:
        interface BookStore {
           public function 
        getBooks(FilterCriterion $filterPagingDefinition $paging);

        Viele Grüße,
        Dr.E.

        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        1. Think about software design before you start to write code!
        2. Discuss and review it together with experts!
        3. Choose good tools (-> Adventure PHP Framework (APF))!
        4. Write clean and reusable software only!
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        Kommentar


        • #5
          Zitat von dr.e. Beitrag anzeigen
          Das möchtest du nicht - for sure!
          Selbstverständlich Aber das Prinzip ist damit ganz gut erklärt finde ich. Es ist halt die Frage womit man eher leben kann, einem leichten Bruch beim OO-Design oder weiter verstreuten Datenbankzugriffen.

          Kommentar


          • #6
            Ganz klar - letzterem. Denn ohne konsistentes OO-Design brauchst Du die DB-Schicht auch gleich gar nicht abstrahieren.
            --

            „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
            Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


            --

            Kommentar


            • #7
              Ein anderes Beispiel: Nimm an, Du führst in Deine Bibliothek neben Büchern noch Zeitschriften ein. Die haben jetzt keinen Autor mehr, sondern nur noch den Verlag als Herausgeber, Seitenzahl oder Auflage ist eher uninteressant, dafür gibts ne Nummer der Heftausgabe. Das Objekt Buch ist für eine Zeitschrift nicht mehr passend. Abder z.B. Bücher und Zeitschriften zu einem bestimmten Thema könnte eine typische verwandte Abfrage zu Deinem aktuellen Problem sein. Da würdest Du das gar nicht mehr in einem Objekt (BookClass oder JournalClass) einrichten können. Ergo kannst Du auch der Menge eines Objekttyps eine eigene Klasse gönnen.
              --

              „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
              Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“


              --

              Kommentar


              • #8
                Überzeugt. Ein erster Blick von mir macht den Eindruck als würde eine List-Klasse ganz gut zur bisherigen Anwendung passen. Nochmal danke an euch.

                Kommentar


                • #9
                  Ich würde mir in erster Linie auf alle Fälle Gedanken darüber machen was an Eigenschaften haben denn meine Leihangebote gemeinsam, also Bücher, Zeitschriften, CD's, DVD's, LP's und so weiter.

                  Du darfst nicht den Fehler machen und nur im Kriterium Buch denken, denn das macht keine Bibliothek aus.
                  Das steht dann gelich auch das DB Design mit im Haus, darüber solltest du dann auch noch mal nachdenken. Was kannst du vereinheitlicht in der DB abbilden und was muss getrennt werden. Stichwort Normalisierung.

                  Du kannst also eine Abstrakte Klassen erstellen die alle gemeinsamen Eigenschaften für Ausleihprodukte bereitstellt, dann kannst du für deine konkreten Produkte Klassene rstellen die diese spezialisieren und von der Abstrakten Klasse erben. Zusätzlich würde ich dann noch über ein Interface nachdenken, falls du diese Klassen bzw. daraus instanzierten Objekte irgendwo injizieren willst.

                  Denke auch mal über ein MVC nach. Ich habe immer ein Model was mir meine Datenstruktur abbildet und einen Mapper, welcher Methoden bereitstellt um die Daten zu holen oder zu speichern. Wichtig dabei, dein Model wie der Mapper sollten nichts über die Datenquelle wissen müssen.

                  Dann kannst du im Mapper Methoden bereit stellen wie insertBook, insertCd und so weiter.
                  Eine weitere Methode kann sein mediumList(Krititerium, Paging).
                  Im Controller bereitest du die Daten auf und gibst diese zur Ausgabe an die View weiter.

                  Vieleicht hilft dieser Ansatz auch noch ein wenig weiter.

                  Gruß der Litter
                  Aus dem Dynamo Lande kommen wir. Trinken immer reichlich kühles Bier. Und dann sind wir alle voll, die Stimmung ist so toll. Aus dem Dynamo Lande kommen wir.
                  http://www.lit-web.de

                  Kommentar


                  • #10
                    Theoretisch:
                    PHP-Code:
                    # the library
                    interface Library {
                       function 
                    setInventoryInventory $inventory );
                       function 
                    getInventoryInventoryInfo $inventoryInfo );
                       function 
                    lendInventoryInventory $inventory );
                    }

                    # the base: Inventory
                    interface Inventory extends Iterator {
                       function 
                    getTitle();
                       function 
                    getISBN();
                       function 
                    getLendState();
                       
                    /* ... */
                    }

                    # a book
                    interface Book extends Inventory {
                       function 
                    appendBookInfo $inventoryInfo );
                    }

                    # a CD
                    interface CompactDisc extends Inventory {
                       function 
                    appendCompactDiscInfo $inventoryInfo );
                    }

                    # a Magazine
                    interface Magazine extends Inventory {
                       function 
                    appendMagazineInfo $inventoryInfo );
                    }

                    # the base: InventoryInfo
                    interface InventoryInfo {
                       const 
                    INVENTORY_GROUP false;

                       function 
                    setTitle($title);
                       function 
                    setISBN($ISBN);
                       function 
                    setLendState($ISBN);

                       function 
                    getTitle();
                       function 
                    getISBN();
                       function 
                    getLendState();

                       function 
                    prepareToSearch$resultCountLimitpaginationInfo $paging null );
                       function 
                    prepareToStore();
                    }

                    # a book definition for append / search
                    interface BookInfo extends InventoryInfo {
                       const 
                    INVENTORY_GROUP 'book';
                       const 
                    LENDABLE true;
                    }

                    # a compact disc definition for append / search
                    interface CompactDiscInfo extends InventoryInfo {
                       const 
                    INVENTORY_GROUP 'CD';
                       const 
                    LENDABLE true;
                    }

                    # a magazine definition for append / search
                    interface MagazineInfo extends InventoryInfo {
                       const 
                    INVENTORY_GROUP 'Magazine';
                       const 
                    LENDABLE false;
                    }

                    # the Pagination Info
                    interface paginationInfo {
                       function 
                    setOffset();
                       function 
                    setItemsPerPage();
                       function 
                    getOffset();
                       function 
                    getItemsPerPage();

                    xxxInfo-Objekte dienen sowie als Suchanfrage-Objekt wie auch als Hinzufügbares Objekt. Zurück bekommt man bei Suchanfragen 1 Inventory-Objekt das als Iterator fungiert und geliehen werden kann.
                    [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

                    Kommentar


                    • #11
                      Mir ist nicht klar, wieso ein Buch oder eine CD ein iterierbares Inventar haben sollten, dem *Info-Objekte, die „als Suchanfrage-Objekt wie auch als Hinzufügbares Objekt“ (?) dienen, angehängt werden können.

                      Wenn das Collections sein sollen, ist „Book“ oder „CompactDisc“ meiner Ansicht nach ein sehr irreführender Name. Für mich ist aus dem Umriss insgesamt nicht erkennbar, welche Klasse dort was genau leisten soll.



                      @Ballamann:

                      Du könntest jedes Buch-Objekt einem übergeordneten Management-Objekt zuordnen (Repository, Store, …), in dem du die konkrete Datenbankinteraktion implementierst und das zur Generierung von Buch-Instanzen als Factory dienen kann. Ein Aufruf wie $book->save() würde dann beispielsweise im Methodenkörper zu $this->manager->save($this) weitergeschoben.

                      In dem Zusammenhang ist sicher auch ein fertiger ORM einen Blick wert.

                      - http://www.doctrine-project.org/proj...rm/2.0/docs/en
                      PHP-Wissenssammlung Composer Awesome Awesomeness PHP: The Right Way @mermshaus

                      Kommentar


                      • #12
                        Schon mal bücher gesehen die sich selbst ins Regal stellen ? :P

                        PHP-Code:
                        $library = new Library();

                        # buch einstellen
                        $addBook = new BookInfo();
                        $addBook->setTitle('1000 PHP Files unter der Harddisk');
                        $addBook->setAuthor('Jul Wayne');
                        $addBook->setISBN('110');
                        $addBook->prepareToStore();

                        $book = new Book();
                        $book->append($addBook);

                        $library->setInventory($book);

                        # buch suchen
                        $searchBook = new BookInfo();
                        $searchBook->setTitle('1000 PHP Files*');

                        $paginate = new PaginationInfo();
                        $paginate->setOffset(0);
                        $paginate->setItemsPerPage(10);

                        $searchBook->prepareSearch(100$paginate);

                        # suchergebnisse ausgeben
                        $result $library->getInventory($searchBook);

                        foreach ( 
                        $result as $foundBooks ) {
                            echo 
                        $foundBooks->getTitle();

                        Library = Storage Management
                        xxxInfo = Storage Management Information Object
                        Inventory extends = Storage Management Store / Result Object

                        Und bevor ihr jetzt denkt der kleine Tr0y hat ein Rad ab:
                        - Die von mir vorgetragene Interface Kette ist nichts anderes als ein generalisiertes Repository auf das Models zugreifen könnten. Der Witz an der ganzen Geschichte ist, ich hatte sowas schon zwischen den Fingern und musste darauf eine Anwendung aufsetzen. Alles in allem war die gesamte Logik hinter dem Repository einfach zu verstehen: Speichern und lesen kann nur die Bibliothek, um zu lesen benötigt sie Informationen was gelesen werden soll ( xxxInfo ). Wenn etwas gespeichert werden soll übergibt man nur eine Menge an Daten ( bspw. Book ) über die die Bibliothek Iteriert und sie Speichert. Ist irgendwo auch logisch denn wenn du bücher ausleihst, schleppst du die Bücher dem Bibliothekar hin, er iteriert darüber ( lendInventory ) und du gehst damit nach hause. Kriegt der Kerl neue Bücher, Iteriert er über sie und speichert sie.

                        Zugegebener Maßen ist "Book" relativ hart gewählt, es sollte eher BookCollection oder Books heißen.

                        Um den gesamten Bedienprozess noch etwas zu vereinfachen könnte man auch hingehen und ein Librarian-Object hinzufügen und den einzelnen Book-Klassen ein Observer-Interface schenken:
                        PHP-Code:
                        $dude = new Librarian();
                        $dude->setLibrary( new Library() );

                        $result $dude->bookSearch() # results new BookInfo
                           
                        ->setTitle('1000 PHP Files*'# results this
                           
                        ->prepareSearch(100PaginationInfo::getPage(0)->setItemsPerPage(10) );
                           
                        # results observer result, calls observer of librarian

                        foreach ( $result as $books ) {
                           echo 
                        $books->getTitle();

                        PHP-Code:
                        $dude = new Librarian();
                        $dude->setLibrary( new Library() );

                        $dude->addBook() # results new BookInfo
                           
                        ->setTitle('100 PHP Files unter der Harddisk'# results this
                           
                        ->setAuthor('Jul Wayne'# results this
                           
                        ->prepareToStorage(); # results observer result, calls observer of librarian 
                        PHP-Code:
                        $dude = new Librarian();
                        $dude->setLibrary( new Library() );
                        $dude->setCustomerID(1932378);

                        $dude->lendBook() # results BookInfo
                           
                        ->setISBN('110'# results this
                           
                        ->prepareSearch(1); # results observer result, calls librarian observer 
                        [URL="https://gitter.im/php-de/chat?utm_source=share-link&utm_medium=link&utm_campaign=share-link"]PHP.de Gitter.im Chat[/URL] - [URL="https://raindrop.io/user/32178"]Meine öffentlichen Bookmarks[/URL] ← Ich habe dir geholfen ? [B][URL="https://www.amazon.de/gp/wishlist/348FHGUZWTNL0"]Beschenk mich[/URL][/B].

                        Kommentar


                        • #13
                          Viele interessante Gedanken zu dem Thema, allerdings war Buch und Bücherei nur ein Beispiel, in meinem Fall müsste die Bücherei wirklich nur Bücher anzeigen (View) und die ISBN wissen (id mit der das eigentliche Buch wenn benötigt wieder erzeugt wird).

                          Zitat von litterauspirna Beitrag anzeigen
                          Du kannst also eine Abstrakte Klassen erstellen die alle gemeinsamen Eigenschaften für Ausleihprodukte bereitstellt, dann kannst du für deine konkreten Produkte Klassene rstellen die diese spezialisieren und von der Abstrakten Klasse erben. Zusätzlich würde ich dann noch über ein Interface nachdenken, falls du diese Klassen bzw. daraus instanzierten Objekte irgendwo injizieren willst.
                          Das ist in etwa die Lösung die ich jetzt implementiert habe, die Datenbank selbst ist schon ziemlich zufriedenstellend dargestellt.
                          Ich habe eine abstrakte Klasse, welche allgemeine Kriterien zur Auswahl der (um beim Beispiel zu bleiben) Bücherliste aufnimmt, eine Klasse BookList erbt dann und spezialisiert die Ausgabe (Quasi eine Factory). Spezialisierung weil ich von diesen Listen doch einige brauche, die aber im Grunde alle nur das Gleiche können müssen.

                          Denke auch mal über ein MVC nach. Ich habe immer ein Model was mir meine Datenstruktur abbildet und einen Mapper, welcher Methoden bereitstellt um die Daten zu holen oder zu speichern. Wichtig dabei, dein Model wie der Mapper sollten nichts über die Datenquelle wissen müssen.
                          Das ist genau der Punkt an dem ich stand als ich die Frage gestellt habe. Ich nutze MVC und wollte im View diverse Objekte anzeigen, jetzt war die Frage ob ich ein Extra-Model nehme oder die Klassen die meine Datenbank repräsentieren aufbohre. Wie gesagt, ich hab mich für ein abstraktes Extra-Model entschieden das spezialisiert wird.
                          Das ist mein erstes größeres Projekt, das ich auch alleine (privat) plane und umsetze, deswegen wollte ich hier lieber nachfragen ob es dafür Standardlösungen gibt.

                          Kommentar

                          Lädt...
                          X