Ankündigung

Einklappen
Keine Ankündigung bisher.

Service Locator ein Anti Pattern

Einklappen

Neue Werbung 2019

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

  • #16
    Zitat von BlackScorp Beitrag anzeigen

    Alles, wenn ich meine Einstellungen sehe, habe ich in 95% der Fälle eine 1:1 beziehung, wirklich selten gibt es mal mehr als eine Implementierung, dafür muss ich aber die Controller auch in DI injezieren und die Objekte aufbereiten. Es ist am Anfang umständlich.
    Klar, aber woher soll PHP-DI wissen dass es nur diese eine Implementierung gibt und wo diese sich überhaupt befindet? Das musst du so oder so manuell festlegen, außer du denkst dir irgendwelche Konventionen aus.

    Kommentar


    • #17
      Hey danke euch bieden vielmal für Eure Hilfe.

      Zitat von strub Beitrag anzeigen
      Deshalb wird bei meinem Container erst bei ->get('Mailer') die Konfiguration erstellt ohne vorher eine Defintion zu definieren, diese wird automatisch je nach Namespace path und container konigfuration gesucht



      Was ist der Vorteil?
      Der Vorteil ist das meine Services vorkonfuriert sind in einem ServiceProvider:
      PHP-Code:
      class ServiceProvider extends Service {

          
      /**
           * @return array|Service\DependencyInjection\Setter
           */    
          
      public function logger() {

              
      $fileHandler = new FileHandler();
              
      $fileHandler->setFileName('default');

              return [
                  
      'method' => [
                      [
      'addHandler''FileHandler'$fileHandler]
                  ]
              ];
          }

          public function 
      loggerAnother() {

              
      $fileHandler = new FileHandler();
              
      $fileHandler->setFileName('another');

              
      $setter diSetter();
              
      $setter->method('addHandler'$fileHandler);
              return 
      $setter;        
          }
      }


      $this->container->get('Logger');

      $this->container->get('LoggerAnother'); 

      So wenn ich z.b. eine neue Applikation schreibe oder nur ein Teil eines Service benutze, haben ich schon mal eine Standartkonifuration.

      Oder z.B habe ich eine Konfiguration für das Backend und eine für das Frontend. Aber das lässt sich warscheinlich auch mit dem php-di bewerkstelligen.

      Frontend/Config/Service/Logger
      Frontend/Config/Service/Session

      Backend/Config/Service/Logger
      Backend/Config/Service/Session

      Kommentar


      • #18
        Zitat von strub Beitrag anzeigen
        Der Vorteil ist das meine Services vorkonfuriert sind in einem ServiceProvider: (..)
        Du kannst deine Abhängigkeiten auch mit PHP-DI vorkonfigurieren bzw. die Erzeugung gänzlich selbst übernehmen. Hier ein paar Beispiel-Definitionen die PHP-DI unterstützt:

        PHP-Code:
        return[
          
        #1 - map interface to class
          
        \My\App\LoggerInterface::class => \My\App\Logger::class,

          
        #2 - use a lazy factory for creation
          
        \My\App\Logger::class => \DI\factory([\My\App\ComplexLoggerFactory::class, 'make']),

          
        #3 - defintion based on an arbitrary name
          
        'anotherLogger' => function(){
            return new \
        My\App\AnotherLogger();
          },

          
        #4 - override a constructor parameter
          
        \My\App\SomeService::class => \DI\object()
            ->
        constructorParameter('logger', \DI\object(\My\App\VerySpecialLogger::class)),

          
        #5 - map multiple interfaces to multiple implementations automagically
          
        'My\App\*RepositoryInterface' => DI\object('My\App\*DoctrineRepository'),
        ]; 
        Verwendung:

        PHP-Code:
        $loggerA $container->get(\My\App\LoggerInterface::class);
        $loggerB $contianer->get(\My\App\Logger::class);
        $loggerC $contianer->get('anotherLogger'); 
        Bei den (Lazy) Factories hast du sogar den Vorteil, dass sie auch vom Autowiring profitieren und somit selbst beliebige Abhängigkeiten anfordern können:

        PHP-Code:
        namespace My\App;

        use \
        My\App\{ConfigLoggerInterface};

        class 
        ComplexLoggerFactory{

          private 
        $config;

          public function 
        __construct(Config $config){
            
        $this->config $config;
          }

          public function 
        make(): LoggerInterface{
            
        $logger = new \My\App\ComplexLogger();
            
        $logger->setFile($config->getErrorLogPath());
            
        // configuration ..
            
        return $logger;
          }



        Zitat von strub Beitrag anzeigen
        So wenn ich z.b. eine neue Applikation schreibe oder nur ein Teil eines Service benutze, haben ich schon mal eine Standar d konifuration.
        ..die du ja selbst angelegt hast.

        Zitat von strub Beitrag anzeigen
        Oder z.B habe ich eine Konfiguration für das Backend und eine für das Frontend. Aber das lässt sich warscheinlich auch mit dem php-di bewerkstelligen.
        Na klar. Du könntest mit unterschiedlichen Environments arbeiten oder einfach zwei verschiedene Container erzeugen, die nichts miteinander zu tun haben. Das kommt ganz darauf an wie klar die Trennung zwischen Frontend und Backend bei dir ist. Ob eine Trennung der Container letztlich sinnvoll ist, hängt von der Anwendung.

        Zitat von strub Beitrag anzeigen
        Frontend/Config/Service/Logger
        Frontend/Config/Service/Session

        Backend/Config/Service/Logger
        Backend/Config/Service/Session
        Mir gefällt diese Konvention nicht. Ich persönlich will volle Kontrolle darüber haben wie und wo meine Objekte erzeugt werden. Dabei will ich aber nicht immer eine neue Klasse aufziehen müssen, denn oft hält sich die Erzeugung in Grenzen (siehe Beispiel #3).


        Mein Vorgehen mit PHP-DI:
        - Klassen die keine Konfiguration brauchen werden nicht in der Konfiguration aufgeführt (die löst der Autoloader auf)
        - Interfaces werden konkreten Implementierungen zugeordnet (teilweise abhängig vom Environment dev/prod)
        - Die Erzeugung von komplexen Objekten, die vorher konfiguriert werden müssen, wird an Lazy Factories delegiert
        - Wenn eine Klasse eine Implementierung für ein Interface braucht die von der Standardeinstellung abweicht, wird das konfiguriert (siehe #4 im Beispiel)

        Damit fahre ich unheimlich gut, denn ich kann zu 100% Autowiring nutzen, die Konfiguration ist sehr schlank, der Footprint ist bei dem gebotenen Featureset minimal und der Einfluss auf die Performance kaum messbar. Mit PHP-DI Version 6 wird es da noch viele Optimierungen geben (u.A. einen pre-compiled container für den Produktivbetrieb).

        Letztlich kannst du nutzen was du willst, solange es für dich passt. Ich verbringe ungerne Zeit damit Probleme zu lösen die bereits sehr gut gelöst wurden. Hauptsache du lässt die Finger vom Service Locator

        Kommentar


        • #19
          PHP-Code:
           public function make(): LoggerInterface{ } 
          das make(): hab ich noch nie gesehen, was heisst denn das lottikarotti ?

          Kommentar


          • #20
            Zitat von tomBuilder Beitrag anzeigen
            PHP-Code:
             public function make(): LoggerInterface{ } 
            das make(): hab ich noch nie gesehen, was heisst denn das lottikarotti ?
            Öhm, das ist ein beliebiger Methodenname. Du könntest sie auch ebenso create() oder newLoggerInstance() nennen. Ich bevorzuge die Bezeichnung make() wenn ich Factories nutze.

            Falls du den ":" meinst: das ist Teil einer Return type declaration

            Kommentar


            • #21
              Zitat von lottikarotti Beitrag anzeigen
              Falls du den ":" meinst: das ist Teil einer Return type declaration
              meinte ich, danke!

              Kommentar


              • #22
                Hey vielen dank Lottikarotti für die tolle Erklärung mit Beispielen. Nun scheint mir alles klarer

                Letztlich kannst du nutzen was du willst, solange es für dich passt. Ich verbringe ungerne Zeit damit Probleme zu lösen die bereits sehr gut gelöst wurden.
                Ich schreibe gerade einen neuen Container, mit autowiring etc. für mein Framework. Ich könnte natürlich auch PHP-DI verwenden, aber ich lerne einfach so immer sehr viel dazu, das ist eigentlich der Hauptgrund, warum ich immer alles selber programmiere.

                PHP-Code:
                Hauptsache du lässt die Finger vom Service Locator 
                Das nehme ich mir sehr zu herzen, darum schreibe ich vieles wieder um Aber die Vorteile überwiegen eben

                Kommentar


                • #23
                  Die Diskussion ist offensichtlich ein wenig von der ursprünglichen Fragestellung abgedriftet und verliert sich nun in irgendwelchen Details zu DiC. Aber weder PHP-DI noch ein anderer DiC werden eine saubere Lösung ermöglichen, wenn das Basisdesign schon nicht sauber ist.

                  PHP-Code:
                  Article extends Action {} 
                  Ist ein Article eine Action? Wohl kaum?

                  Bei Vererbung soll die abgeleitete Klasse in einer IST-EIN-BEZIEHUNG zu der Basisklasse stehen.
                  Die Vererbung dient nicht der Erweiterung einer Klasse, sondern der Spezialisierung.

                  Du setzt Vererbung falsch ein (konzeptionell) und bringst damit Sachen zusammen, die nicht zusammengehören. Das bringt ganz automatisch weitere Probleme mit sich.

                  Das ist der Punkt an dem du – meiner Ansicht nach - zuerst ansetzen solltest.

                  vg
                  jack














                  -

                  Kommentar


                  • #24
                    Hey danke dir Jack88. Da hast du natürlich recht. Mein Beispiel Code war schlecht.

                    Kommentar

                    Lädt...
                    X