Ankündigung

Einklappen
Keine Ankündigung bisher.

DI-Container Key

Einklappen

Neue Werbung 2019

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

  • #16
    Zitat von xm22 Beitrag anzeigen
    Du kannst genauso wenig davon ausgehen, dass das Interface ilogger auch die Methode log implementiert.
    wenn ich meinem system einen di container spendiere dann ja nicht ohne hintergrund. die interfaces für den container werden vom entwickler des systems geschrieben, damit ist davon auszugehen, dass das interface die methode implementiert. wenn nicht ist es schlichtweg ein fehler.

    dadurch ist aber gewährleistet, dass jemand der meinen service ersetzt auch die nötige API für den service implementiert.

    wenn ich eine setter / getter injection habe und ein interface mit angebe habe ich identische vorteile, muss mir jedoch neben dem interface zusätzlich auch den schlüssel für den zugriff auf den service merken.

    Kommentar


    • #17
      Ich verstehe schon. Aber das Problem, das bleibt, ist, dass Du in einer großen Applikation einen Haufen Interfaces hast, die nur zur Identifikation dienen. Aber das ist halt Geschmacksfrage.


      EDIT: Es gibt einen eklatanten Nachteil: Jeder Service muss ein passendes Interface implementieren. Was machst Du bei Drittanbietern? Deren Klassen ableiten, damit die das Interface implementieren können?

      Kommentar


      • #18
        Zitat von notyyy Beitrag anzeigen
        wenn ich meinem system einen di container spendiere dann ja nicht ohne hintergrund. die interfaces für den container werden vom entwickler des systems geschrieben, damit ist davon auszugehen, dass das interface die methode implementiert. wenn nicht ist es schlichtweg ein fehler.
        Wer schreibt denn das System?
        Dann kannst du genauso gut davon ausgehen, dass bei einem simplen Namen einfach davon auszugehen ist, dass alles passend ist.

        Für mich klingt die ganze Diskussion nach absoluter Korinthen... und vollkommen überflüssig.
        Wenn du dich auf nichts verlassen willst, lass dich miniaturisieren und setzt dich selbst an die Bits, um sie zu schubsen.
        Alles mit unnötigen Interfaces zuzupflastern hilft weder der Performance, noch der Verständlichkeit geschweige denn der Wartbarkeit.
        K.I.S.S. for the win!
        actra.development - Zend Certified Engineer for PHP5 - actra-oss @ github

        Kommentar


        • #19
          wenn allerdings 2 datenbankverbindungen existieren, dann muss eine davon eine andere aufgabe erfüllen als die andere. im Klartext bedeutet das für mich wir haben unterschiedliche services. beiden services impementieren demnach ein eigenes interface.
          Das ist doch - mit Verlaub gesagt - Unsinn. Ein Datenbanktreiber ist sowas wie ein Adapter, die eben die eigentlichen Implementierungsunterschiede durch eine einheitliche Schnittstelle versteckt. Nur so kann er austauschbar sein - Deine Anwendung merkt im Idealfalle nichts davon, ob Du vor DBS x oder DBS y sitzt. So wäre eine denkbare Interfacemethode "connect()". Die Implementierung dieser Methode ist für jeden Datenbanktreiber pflicht - Design by Contract.

          So kann ich mir jederzeit bspw. eine DB-Connection vom Typ mysql holen, diese aber leicht durch einen anderen Typ tauschen, ohne dass ich die restliche Anwendung, die dadrauf zugreifen muss, zu ändern gezwungen bin. Hätte jeder Adapter seine eigene Schnittstelle, hättest Du überhaupt nichts gewonnen!

          Ich kann Dir nur empfehlen, Dir mal einen real existierenden DI zu schnappen und Dir ein paar Services zusammenzukonfigurieren, dann werden der Sinn und Zweck, die Vor- und Nachteile des Ganze viel deutlicher sichtbar, als man das hier erklären könnte. Dann würdest Du garantiert auch feststellen, auf was für einem falschen Dampfer Du dich gerade befindest

          Kommentar


          • #20
            Zitat von joshiausdemall Beitrag anzeigen
            Das ist doch - mit Verlaub gesagt - Unsinn.
            ich sehe ein, dass interfaces hier aus verschiedenen gründen fehl am platze sind. ich denke dennoch du hast meine aussage falsch verstanden.

            wenn 2 datenbanktreiber zur selben zeit benötigt werden, haben diese meiner meinung nach unterschiedliche aufgaben. es macht keinen sinn 2 identisch konfigurierte datenbanktreiber der selben klasse zu besitzen.


            Dann kannst du genauso gut davon ausgehen, dass bei einem simplen Namen einfach davon auszugehen ist
            dann hast du meine aussage falsch verstanden. wenn ich für ein service ein interface erzwinge kann mir keiner ein service unterschieben der dieses interface nicht unterstützt. wenn ich einfach ein object zurück bekomme kann ich nie sicher sein, dass nicht ein unsauberer plugin entwickler meine stabilität damit gefährdet, dass er halb implementierte services registriert.


            Für mich klingt die ganze Diskussion nach absoluter Korinthen...
            deswegen befinden wir uns in der kategorie software design, einfach machen halte ich hier für unangebracht, es sollte schon überlegt sein.

            Kommentar


            • #21
              ich bin glücklich zu sehen, dass google auf meiner seite ist bzw. diesen weg nicht völig ausschließt.

              http://code.google.com/p/google-guic...GettingStarted

              PHP-Code:
              /*
                    * This tells Guice that whenever it sees a dependency on a TransactionLog,
                    * it should satisfy the dependency using a DatabaseTransactionLog.
                    */
                  
              bind(TransactionLog.class).to(DatabaseTransactionLog.class);

                   
              /*
                    * Similarly, this binding tells Guice that when CreditCardProcessor is used in
                    * a dependency, that should be satisfied with a PaypalCreditCardProcessor.
                    */
                  
              bind(CreditCardProcessor.class).to(PaypalCreditCardProcessor.class); 
              here is another example:

              https://github.com/sarnowski/pinjector

              Kommentar


              • #22
                Wenn Dich das glücklich macht, kannst Du ja ein Konstrukt wie

                $foo = DIContainer::get ($name , $interface);

                Und die Prüfung mit instanceof in der Methode des Containers umsetzen. Aber ehrlich gesagt finde ich die Diskussion ziemlichen Quark. So sauber ist ein DI-Container Pattern ohnehin nicht, ist eben ein Kompromiss zwischen übermäßigem Setup und Objektabhängigkeiten.
                --

                „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


                • #23
                  Zitat von nikosch Beitrag anzeigen
                  $foo = DIContainer::get ($name , $interface);
                  dies ist für die get funktion doch völlig irrelevant. wichtig ist, dass man keinen service injizieren kann welcher vom interface her nicht passt.

                  ich finde es existieren große konzeptionelle unterschiede zwischen z.b. google guice und dem pico container (oder Zend DI, Symfony DI, ...).

                  ich spiele mal ein wenig mit dem konzept von google guice rum und implementiere testweise mal ähnliches in php. der weg ist halt etwas anders und umfangreicher zu implementieren, dennoch halte ich ihn für den besser.

                  ich glaube das thema sollte man nicht unterschätzten, der di container ist dank der vielen anhängigkeiten für die grundstabilität (mit-)verantwortlich. abhängigkeiten lassen sich halt nur durch verträge auflösen, alles andere grenzt bei großen systemen an anarchie.

                  Auf die Probleme, auf die ich bei der implementierung gestossen bin, habe ich lösungen in der google guice dokumentation gefunden, nun muss ich diese noch auf php adaptieren und für mich in den nächsten projekten austesten, bei welchem di container für mich die vorteile überwiegen.

                  Kommentar


                  • #24
                    dies ist für die get funktion doch völlig irrelevant. wichtig ist, dass man keinen service injizieren kann welcher vom interface her nicht passt.
                    Wieso ist das irrelevant? Das war Deine Kritik:
                    $di->get('service.logger');

                    hier wird anhand des strings service.logger der logger geholt. dabei ist völlig unklar was der logger für ein objekt ist und welche methoden dieser implementiert.
                    Und Deine „Einsicht“
                    durch eine contructor oder einer setter injection ist ja wieder typensicherheit gewährleistet.
                    ist insofern auch Quark, weil
                    Für die Setter Injection im DI Container sich an der Grundproblematik nichts ändert (anfordernder Klasse hat keine Garantie, was sich im Container befindet)
                    Für die Setter Injection im nutzenden Objekt sich überhaupt kein Mehrwert von DIC bietet. DIC ist doch gerade dafür, dass Du im Objekt Instanzen anfordern kannst. Sonst kannst Du auch einfach normales DI und irgendeine globale Verwaltung (Registry) verwenden.
                    --

                    „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


                    • #25
                      OT: @Nikosch: Samstag früh halb fünf treibst Du Dich hier rum?!

                      Kommentar


                      • #26
                        OT: Wie man sieht.
                        --

                        „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


                        • #27
                          Zitat von nikosch Beitrag anzeigen
                          Wieso ist das irrelevant? Das war Deine Kritik:
                          so war meine aussage nicht gemeint.

                          $di->get('service.logger', 'iLogger');

                          hier müsste jede klasse die den logger nutzt, verifizieren das das interface stimmt. identisch dazu wäre

                          $di->get('service.logger') instanceof iLogger

                          das ist in meinen augen unnötig und behandelt die problematik falsch, sinniger wäre es, zu verifizieren dass $di->set('logger', 'stdClass') eine exception wirft weil stdClass kein logger ist.

                          um dies zu verifizieren muss es einen vertrag für einen validen logger geben, verträge sind in der OOP welt interfaces.

                          daraus könnte dieses konstrukt resultieren.

                          // dem di beibringen das service.logger immer ein interface implementieren muss.
                          $di->get('service.logger').implements('ilogger');

                          $di->set('service.logger', 'stdObj'); // Exception!

                          $di->set('service.logger', 'loggerImpl'): // works


                          nun kann man via $di->get('service.logger') einen validen logger bekommen.


                          warum mir dies wichtig ist:

                          ich möchte benutzern gerne die möglichkeit geben teile eines systems auszutauschen, also dazu animieren die Konfiguration des DI Containers zu verändern. da ich wenig mit klassen von 3. Anbietern zutun habe möchte ich möglichst viel sicherheit. sicherheit schafft man nur durch verträge.


                          Zitat von nikosch Beitrag anzeigen
                          Für die Setter Injection im DI Container sich an der Grundproblematik nichts ändert (anfordernder Klasse hat keine Garantie, was sich im Container befindet)
                          das sehe ich anders, $di->get('service.logger')->log('hallo welt');

                          und

                          /** @inject */
                          function getLogger(iLogger $logger)

                          haben große unterschiede. es ist verifiziert, dass das interface stimmt.
                          dummerweise würde ich lieber gerne der konfiguration überlassen, welches interface für welchen service bereitstehen muss.

                          Zitat von nikosch Beitrag anzeigen
                          globale Verwaltung (Registry) verwenden.
                          global ist böse, ich tendiere dazu, den di container mit zu injizieren. so wird jeder klasse die instanz des di containers injiziert.

                          ich bin der meinung, dass alles was man tauschen kann in irgendeiner form vertraglich geregelt sein muss. in der echten welt kann ich auch nicht auf mein auto einfach lkw reifen schrauben, diese müssen eine gewisse norm (interface) erfüllen damit ich diesen "service" dafür nutzen kann.

                          wenn man abhängigkeiten nur lose definiert ohne diese auch zu regeln mag das alles ganz toll funktionieren bis man eine größere community hat und nurnoch auf fehler wie call to undefined method stösst oder services an stellen nutzt an denen diese nichts zu suchen haben.

                          einen nicht zu unterschätzendes problem bringt es jedoch services interfaces zuzuweisen.
                          das interface müsste abhängig von der tätigkeit des services definiert werden, ein service selber sollte aber abstrakt sein. ein abstrakter service sollte nicht einfach ein interface für definierte belange implementieren. an dieser stelle muss ich noch etwas über einen gangbaren weg nachdenken, eine möglichkeit wäre eine den abstrakten service von einer klasse erben zu lassen, die sich um die konkreten belange des service kümmert, wie das interface, welches der DIC nutzt, zu implementieren.

                          Kommentar


                          • #28
                            global ist böse, ich tendiere dazu, den di container mit zu injizieren. so wird jeder klasse die instanz des di containers injiziert.
                            kannst auch genauso die geholte Instanz injizieren. Dann haste auch nen Vertrag. Und wer sagt eigentlich, dass die Registry nicht gegen einen Typ geprüft werden kann.

                            Also ich finde das ganze Problem Hupe. Wenn Du bei set ein Type-Binding machst, verlagerst Du die Problematik auf den Stringschlüssel, über den Du den Service anfragst. Wenn Du das falsche Serviceobjekt anfragst, hast Du genauso wenig Kontrolle darüber, ob das Inerface stimmt. Einen Weg habe ich oben gezeigt - bei der Anfrage ein Interface/abstrakte Basisklasse als String mitgeben.

                            einen nicht zu unterschätzendes problem bringt es jedoch services interfaces zuzuweisen.
                            das interface müsste abhängig von der tätigkeit des services definiert werden, ein service selber sollte aber abstrakt sein. ein abstrakter service sollte nicht einfach ein interface für definierte belange implementieren. an dieser stelle muss ich noch etwas über einen gangbaren weg nachdenken, eine möglichkeit wäre eine den abstrakten service von einer klasse erben zu lassen, die sich um die konkreten belange des service kümmert, wie das interface, welches der DIC nutzt, zu implementieren.
                            Sorry, das ist doch nur noch Gefasel.
                            --

                            „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


                            • #29
                              Zitat von nikosch Beitrag anzeigen
                              Sorry, das ist doch nur noch Gefasel.
                              vielleicht hab ichs auch einfach tot geredet, wenn mir ein ein Konzept gefällt jedoch die nachteile in meinen Augen untragbar sind versuche ich immer zu verstehen warum diese existieren und ob man diese nicht vielleicht umgehen kann. insbesondere bei konzepten bin ich sehr detailverliebt. oft ist es notwendig Kompromisse einzugehen um einfachere api's zu schaffen und nicht vor lauter korrektheit ein gigantischen overhead zu überzeugen. ich denke jedoch das es wichtig ist, dass einem bewusst ist warum und an welchen stellen "sinnvoll" gespart wurde.

                              ich werde mich weiter und intensiver mit der problematik vertraut machen und wenn ihr möchtet meinen favorisieren Ansatz vorstellen, wenn ich mir sicher bin welchen weg ich gehen möchte.

                              Kommentar


                              • #30
                                Hast du dir mal die Implementierung von bereits vorhandenen Produkten angesehen? Kannst du dies nicht einfach verwenden?
                                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

                                Lädt...
                                X