Ankündigung

Einklappen
Keine Ankündigung bisher.

DI - Lazy

Einklappen

Neue Werbung 2019

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

  • DI - Lazy

    PHP unterstützt ja keinerlei Möglichkeit Variablen Lazy nachzuladen. Insbesondere bei vielen Abhänigkeiten im DiC kann dies problematisch sein, da alle Services von denen ein Service abhängig ist, vorher initialisiert werden müssen. Eine Möglichkeit dieses zu umgehen wäre:

    PHP-Code:
    class service implements iService {

      
    /**
         * @var \de\iMailer
         * @inject
         * @lazy
         */
        
    private $mailService;

        function 
    doStomething() {
            
    $this->mailService()->sendMail();
        }


    in diesem Fall würde man von dem DiC anstatt des Services eine anonyme Funktion bekommen welche beim Aufruf die korrekte Instanz zurückgibt. Dies hat jedoch den gewaltigen Nachteil, dass die @var Annotation nur noch bedingt stimmt, die CodeCompletion funktioniert nicht mehr und womöglich sind einige Entwickler schnell verwirrt.


    Vorteile:
    + Lazy

    Nachteile
    - "falsche" @var Annotation
    - Verwirrung
    - keine CodeCompletion

    was sagt ihr zu einer solchen Implementierung?

  • #2
    Ich sehe ehrlich gesagt gar nicht, warum es ein Problem sein sollte dass die Abhängigkeiten im Voraus initialisiert werden. Wenn eine Klasse von vielen Services abhängt und davon evtl. nur einen Teil braucht, würde ich mir erstmal überlegen ob sie nicht zu viele Aufgaben übernimmt und in mehrere Klassen gesplittet werden könnte.

    Wenn du aber diesen Weg gehen willst, was spricht dagegen, das über getter zu machen (ggf. auch magische)? Du musst ohnehin einen Umweg gehen, denn $this->mailService() wird nicht funktionieren (versucht, die Methode mailService aufzurufen und nicht das Attribut als Closure!)

    Hier mal ein erster Versuch mit magischem Getter (@method sorgt für korrekte Code Completion)

    PHP-Code:
    /**
     * @method \de\iMailer getMailService()
     */
    class service implements iService {

      
    /**
         * @var Closure
         * @inject
         * @lazy
         */
        
    private $_getMailService;

        public function 
    __call($method$args)
        {
            if (
    substr($method(0,3) === 'get')
            {
                return 
    call_user_func_array($this->{'_' $method}, $args);
            }
            
    // Exception
        
    }

        function 
    doSomething() {
            
    $this->getMailService()->sendMail();
        }


    [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


    • #3
      Ich würde mich fab anschließen. Wenn bei jedem Aufruf einer Klasse immer nur ein kleiner Teil der injecteten Services wirklich benötigt wird, dann wird wahrscheinlich SRP verletzt.

      Kommentar


      • #4
        Wie wärs die Services als Closures bereitzustellen, so dass sie erst initialisiert werden wenn sie auch tatsächlich angefordert werden.
        Beispiel:
        PHP-Code:

        class arbitEnvironmentDIC extends arbitDependencyInjectionContainer {
            public function 
        initialize() {
                
        $this->cache = function($dic) {
                    return new 
        arbitFilesystemCache($dic->request->controller);
                }
            }

        Das Beispiel ist geklaut aus Folie 21: http://qafoo.com/talks/11_02_phpuk_a...o_patterns.pdf
        Da geht es genau um die von dir angesprochene Problematik.
        Ein Video dazu gibts auch: http://ontwik.com/php/advanced-oo-patterns-in-php/
        Und die komplette Klasse arbitDependencyInjectionContainer:
        http://tracker.arbitracker.org/arbit..._container.php

        Kommentar


        • #5
          Zitat von SinnlosS Beitrag anzeigen
          Wie wärs die Services als Closures bereitzustellen
          hab ich dich in meinem beispiel gemacht?

          PHP-Code:
          $this->mailService() 
          ...

          Kommentar

          Lädt...
          X