Ankündigung

Einklappen
Keine Ankündigung bisher.

Service-Locator

Einklappen

Neue Werbung 2019

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

  • Service-Locator

    Hi,

    ich habe bis jetzt - zumindest im PHP-Bereich - immer nur Service-Locator gesehen, die im Prinzip wie eine Factory aufgebaut waren, also generisch Objekte erzeugt haben.

    Was spräche denn dagegen, den ServiceLocator spezielle Methoden für die verschiedenen Objekte zu zur Verfügung zu stellen?


    EDIT: Im PAC-Thread gab es ja von Dr.e. die Anmerkung, dass Objekte, wie z. B. das Authentifizierungs-Objekt per Service-Locator verfügbar gemacht werden sollte. Jetzt ist es allerdings so, dass der Konstruktor ein Session-Objekt als Parameter erwartet. Wie sollte man so etwas jetzt in einem Service-Locator lösen? Über spezielle Methoden? Über Config-Dateien? Über optionale Parameter? Das hört sich alles etwas halb gewalkt an..

  • #2
    Hi xm22,

    Was spräche denn dagegen, den ServiceLocator spezielle Methoden für die verschiedenen Objekte zu zur Verfügung zu stellen?
    Es gibt auch hier verschiedene Ansätze: den generischen und den konkreten. Sofern du einen SL für einen konkreten Fall erstellst, ist es völlig legal, diesen mit konkreten Methoden auszustatten. Erstelle ich eine Komponente jedoch für ein Framework - wie dem APF - dann möchte ich dem Anwender eine möglichst breite Anwendbarkeit bieten. Hierzu sehe ich dann eine generische Komponente vor, die allen Anforderungen gewachsen ist. Diese einzusetzen ist dann sicher etwas mehr Aufwand, jedoch muss ich exakt keinen Code schreiben, was ich für eine dedizierte schon müsste.

    EDIT: Im PAC-Thread gab es ja von Dr.e. die Anmerkung, dass Objekte, wie z. B. das Authentifizierungs-Objekt per Service-Locator verfügbar gemacht werden sollte. Jetzt ist es allerdings so, dass der Konstruktor ein Session-Objekt als Parameter erwartet. Wie sollte man so etwas jetzt in einem Service-Locator lösen? Über spezielle Methoden? Über Config-Dateien? Über optionale Parameter? Das hört sich alles etwas halb gewalkt an..
    Für die Konstruktion von Services gibt es ebenfalls zwei Konzepte und eine Mischform der beiden: Konstruktor-Injection und Method-Injection. Beide werden sinnigerweise über Konfigurationen abgebildet, die dem ServiceLocator und Dependency Container (denn ein Locator ist nicht für die Konfiguration zuständig!) sagen, welche Abhängigkeiten injiziert werden sollen. Beide Arten sind auf generische und konkrete Weise abbildbar. Konstruktur-Injection hat den Vorteil, dass du einfacher nach dem Prinzip fail early and hard vorgehen kannst. Im APF setze ich ausschließlich auf Method-Injection, da APF-Objekte immer mit einer Factory erzeugt werden, die bestimmte Informationen per Method-Injection einimpfen. Hier ist die Initialisierung mit Hilfe des DIServiceManager deshalb auch so implementiert.
    Zusammengefasst: beide Möglichkeiten sind gegeben und können je nach Anwendungsfall Einsatz finden.
    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


    • #3
      Hm.. ok. Das werde ich mal näher betrachten.

      Kommentar


      • #4
        Ich tue mich immer noch etwas schwer damit. Ich habe jetzt mal einen Service Locator umgesetzt, allerdings kommt mir das mehr wie eine Factory vor:

        PHP-Code:
        <?php
            
        /**
             * ServiceLocator can be inherited to override methods
             */
            
        class Core_DI {
                
                protected static 
        $singletons    = array();
                
                private function 
        __construct() {
                    
                }
                
                public static function 
        getAuth($singleton true) {
                    if (
        $singleton) {
                        if (!isset(
        self::$singletons['auth'])) {
                            if (
        self::getConfig()->service->auth->namespace != '') {
                                
        self::$singletons['auth'] = new Core_Auth(Core_Session::getInstance(self::getConfig()->service->auth->namespace), self::getConfig()->applicationId);
                            } else {
                                throw new 
        Core_Exception('No auth namespace specified');
                            }
                        }
                        return 
        self::$singletons['auth'];
                    } else {
                        if (
        self::getConfig()->service->auth->namespace != '') {
                            return new 
        Core_Auth(Core_Session::getInstance(self::getConfig()->service->auth->namespace), self::getConfig()->applicationId);
                        } else {
                            throw new 
        Core_Exception('No auth namespace specified');
                        }
                    }
                }
                
                public static function 
        getConfig($singleton true$filename '') {
                    
        //config array in file must be named as $cArr
                    
        if ($singleton) {
                        if (!isset(
        self::$singletons['cfg'])) {
                            if (
        $filename != '' && file_exists($filename)) {
                                require(
        $filename);
                            } else {
                                if (
                                    !
        file_exists(_PROT_PATH.'/Config/'.$_SERVER['SERVER_NAME'].'.php') &&
                                    !
        file_exists(_PROT_PATH.'/Config/'.$_SERVER['SERVER_ADDR'].'.php')
                                ) {
                                    throw new 
        Exception('config file not found');
                                }
                                if (
        file_exists(_PROT_PATH.'/Config/'.$_SERVER['SERVER_NAME'].'.php')) {
                                    require_once(
        _PROT_PATH.'/Config/'.$_SERVER['SERVER_NAME'].'.php');
                                } else {
                                    require_once(
        _PROT_PATH.'/Config/'.$_SERVER['SERVER_ADDR'].'.php');
                                }
                            }
                            
        self::$singletons['cfg'] = new Core_Config($cArr);
                        }
                        return 
        self::$singletons['cfg'];
                    } else {
                        if (
        $filename != '' && file_exists($filename)) {
                            require(
        $filename);
                        } else {
                            if (
                                !
        file_exists(_PROT_PATH.'/Config/'.$_SERVER['SERVER_NAME'].'.php') &&
                                !
        file_exists(_PROT_PATH.'/Config/'.$_SERVER['SERVER_ADDR'].'.php')
                            ) {
                                throw new 
        Exception('config file not found');
                            }
                            if (
        file_exists(_PROT_PATH.'/Config/'.$_SERVER['SERVER_NAME'].'.php')) {
                                require_once(
        _PROT_PATH.'/Config/'.$_SERVER['SERVER_NAME'].'.php');
                            } else {
                                require_once(
        _PROT_PATH.'/Config/'.$_SERVER['SERVER_ADDR'].'.php');
                            }
                        }
                        new 
        Core_Config($cArr);
                    }
                }
                
                public static function 
        getTranslator($singleton true$language ''$type 'Array') {
                    
        $className 'Core_Translator_'.$type;
                    if (
        $language == '') {
                        
        $language self::getRequest()->getLanguage();
                    }
                    if (
        $singleton) {
                        if (!isset(
        self::$singletons['translator'][$language])) {
                            
        self::$singletons['translator'][$language] = new $className($language);
                        }
                        return 
        self::$singletons['translator'][$language];
                    } else {
                        return new 
        $className($language);
                    }
                }
                
                public static function 
        getRequest($type 'Http'$singleton true) {
                    
        $className 'Core_Request_'.$type;
                    if (
        $singleton) {
                        if (!isset(
        self::$singletons['request'][$type])) {
                            
        self::$singletons['request'][$type] = new $className($type);
                        }
                        return 
        self::$singletons['request'][$type];
                    } else {
                        return new 
        $className();
                    }
                }
                
                public static function 
        getResponse($type 'Http'$singleton true) {
                    
        $className 'Core_Response_'.$type;
                    if (
        $singleton) {
                        if (!isset(
        self::$singletons['response'][$type])) {
                            
        self::$singletons['response'][$type] = new $className($type);
                        }
                        return 
        self::$singletons['response'][$type];
                    } else {
                        return new 
        $className();
                    }
                }
                
                public static function 
        getAcl($roleId, array $rules = array(), $singleton true) {
                    if (
        $singleton) {
                        if (!isset(
        self::$singletons['acl'][$roleId])) {
                            
        $roles self::getConfig()->service->acl->roles->toArray();
                            if (isset(
        $roles['blacklist'][$roleId])) {
                                
        self::$singletons['acl'][$roleId] = new Core_Acl($role);
                                
        $role = new Core_Acl_Role($roleId$roles['blacklist'][$roleId]);
                                
        $role->setRuleArray($rules);
                                
        self::$singletons['acl'][$roleId]->addRole($role);
                            } else {
                                throw new 
        Core_Exception('no config for acl specified');
                            }
                        }
                        return 
        self::$singletons['acl'][$roleId];
                    } else {
                        
        $roles self::getConfig()->service->acl->roles->toArray();
                        if (isset(
        $roles['blacklist'][$roleId])) {
                            
        $acl = new Core_Acl($role);
                            
        $role = new Core_Acl_Role($roleId$roles['blacklist'][$roleId]);
                            
        $role->setRuleArray($rules);
                            
        $acl->addRole($role);
                            
                            return 
        $acl;
                        } else {
                            throw new 
        Core_Exception('no config for acl specified');
                        }
                    }
                }
                
                public static function 
        getUrl($singleton true$type 'Rewrite'$name ''$mode 'Http') {
                    if (
        $singleton) {
                        if (empty(
        self::$singletons['url'][$type][$name])) {
                            
        $className 'Core_Url_'.$type;
                            
        self::$singletons['url'][$type][$name] = new $className(self::getRequest());
                        }
                        return 
        self::$singletons['url'][$type][$name];
                    } else {
                        
        $className 'Core_Url_'.$type;
                        return new 
        $className(self::getRequest());
                    }
                }
                
                public static function 
        getLogger($singleton true) {
                    
                }
                
                
        /**
                 * Classes must implement the setOptions method
                 * @param string $class
                 * @param string $name        = ''
                 * @param bool $singleton    = true
                 * @param mixed $options    = null
                 * @return object
                 */
                
        public static function getGeneric($class$name ''$singleton true$options null) {
                    if (
        $singleton) {
                        if (!isset(
        self::$singletons[$class][$name])) {
                            
        self::$singletons[$class][$name] = new $class();
                            if (!empty(
        $options)) {
                                
        self::$singletons[$class][$name]->setOptions($options);
                            } else if (isset(
        self::getConfig()->$name)) {
                                
        self::$singletons[$class][$name]->setOptions(self::getConfig()->$name);
                            }
                        }
                        return 
        self::$singletons[$class][$name];
                    } else {
                        
        $obj $class();
                        if (!empty(
        $options)) {
                            
        $obj->setOptions($options);
                        } else if (isset(
        self::getConfig()->$name)) {
                            
        $obj->setOptions(self::getConfig()->$name);
                        }
                        return 
        $obj;
                    }
                }
            }
        Ist das als ServiceLocator zu bezeichnen?

        Kommentar


        • #5
          Hallo xm22,

          ServiceLocator != DI. Schau mal unter Core J2EE Patterns - Service Locator, dort findest du eine Beschreibung.

          Ich würde dir darüber hinaus empfehlen, mit deinem aktuellen Kenntnisstand auf fertige Lösungen zurückzugreifen, denn es fehlen dir aktuell IMHO einige Grundlagen um eine Implementierung zu verfassen, die für dich - und hinterher auch für andere - sauber verwendbar ist. Hast du das APF zu dieser Anforderung mal getestet? An sich erfüllt es meiner Meinung nach sowohl im Bereich SL als auch im Bereich DI deine Anforderungen vollständig.
          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
            ServiceLocator != DI
            Ok - Wobei mir der Unterschied nicht klar ist.

            Hast du das APF zu dieser Anforderung mal getestet?
            Habe ich - Aber auch dort erkenne ich nicht den konzeptionellen Unterschied zu meiner Klasse, außer, dass es generisch ist. Auch gefällt es mir nicht, dass die Instanziierung der Objekte zu statisch ist.

            Ein Dependency Injection Container hat, so wie ich es verstanden habe, die Aufgabe, den Aufruf von Objekten mit allen notwendigen Parametern zu kapseln.

            Richtig oder falsch?

            Und hier stellt sich mir jetzt die Frage, was ein Service-Locator anderes macht.

            Kommentar


            • #7
              Hi xm22,

              Ok - Wobei mir der Unterschied nicht klar ist.
              Der Unterschied ist an sich simpel:
              • Locator = Erzeuger/Store
              • DI = Konfigurator

              Die Kombination aus beidem ist dann eine Komponente, die sich sowohl mit der Beschaffung der Komponente als auch um die Konfiguration kümmert.

              Habe ich - Aber auch dort erkenne ich nicht den konzeptionellen Unterschied zu meiner Klasse, außer, dass es generisch ist.
              Exakt das ist der Unterschied, der meiner Ansicht nach auch der entscheidende ist. Sofern du einen Service-Locator - und dieser ist Gegenstand der Diskussion - zu statisch implementierst (=konkrete Services) so musst du jedes Mal eine neue Methode für einen neuen Service hinzufügen. Kombinierst du das mit einem DI-Mechanismus und möchtest das Projekt-übergreifend einsetzen, so baust du dir von Haus aus Stolper-Fallen ein. Konkret: du verbaust dir die Möglichkeit, die Services Projekt-spezifisch konfigurieren zu können. Dies wird beispielsweise bei Datenbank-Verbindungen sehr schnell klar.

              Auch gefällt es mir nicht, dass die Instanziierung der Objekte zu statisch ist.
              Was bedeutet das für dich? Wo findest du statische Elemente? So wie ich das Konzept definiert habe, hast du alle beliebigen Möglichkeiten. Du kannst Kaskaden von Services aufbauen und diese dynamisch oder statisch Konfigurieren.

              Ein Dependency Injection Container hat, so wie ich es verstanden habe, die Aufgabe, den Aufruf von Objekten mit allen notwendigen Parametern zu kapseln.

              Richtig oder falsch?
              Falsch. Die Aufgabe ist es, angeforderte Objekte (Services) zu konfigurieren. Den Aufruf des Services selbst wird weiter deine Applikation tun. Nur ist eben mit dem DI-Konzept die Konfiguration des Service abstrahiert. Im APF wird das noch über die generische Konfiguration (Namespace + Context + Environment) so gegliedert, dass du für jede beliebige Applikation in der du deine Software betreibst und jede Umgebung eine eigene Konfiguration ohne Software-Änderung anlegen kannst.
              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
                Ah - Es wird schon klarer

                Die Kombination aus beidem ist dann eine Komponente, die sich sowohl mit der Beschaffung der Komponente als auch um die Konfiguration kümmert.
                Achso - Ich bin bis dahin davon ausgegangen, dass es sich um getrennte Dinge handelt.

                Was bedeutet das für dich? Wo findest du statische Elemente?
                Dein Service-Locator hat bei Dir zwei Möglichkeiten, ein Objekt zu erzeugen:
                1. Ohne Parameter
                2. Mit einem Parameter (Der, schätze ich mal, beliebig ausgeprägt sein kann.)
                Ansonsten unterstützt das APF die Konfiguration mittels Setter bzw. über DI mittels Config-Datei.
                Das meine ich mit zu statisch. Was würde denn passieren, wenn eine Klasse beim Instanziieren mehrere Instanzen anderer Klassen benötigt?

                Die Aufgabe ist es, angeforderte Objekte (Services) zu konfigurieren. Den Aufruf des Services selbst wird weiter deine Applikation tun. Nur ist eben mit dem DI-Konzept die Konfiguration des Service abstrahiert.
                ? Aber die Instanziierung erfolgt doch trotzdem im DI-Container, oder nicht?

                Kommentar


                • #9
                  Hi xm22,

                  Dein Service-Locator hat bei Dir zwei Möglichkeiten, ein Objekt zu erzeugen:
                  Das ist kein SL, sondern ein DIServiceManager - eine Komponente, die sich um beide Themen (SL + DI) kümmert. Ich möchte das deshalb nochmal aufgreifen, da es mir in der Diskussion notwendig erscheint, die Unterschiede sauber zu definieren.

                  Grundsätzlich verstehe ich jedoch immer noch nicht, welche zwei Varianten du meinst. Der DIServiceManager kennt genau eine Variante: eine Konfigurations-Datei mit statischen und dynamischen Definitionen. Beispiel:
                  Code:
                  [GuestbookMapper]
                  servicetype = "NORMAL"
                  namespace = "modules::guestbook2009::data"
                  class = "GuestbookMapper"
                  conf.db.method = "setConnectionName"
                  conf.db.value = "guestbook2009"
                  conf.orm.method = "setORMInitType"
                  conf.orm.value = "NORMAL"
                  1. Ohne Parameter
                  Die Instanzierung erfolgt grundsätzlich mittels setter-Injection. Streng genommen wird nach diesem Konzept kein APF-Objekt ohne Parameter erzeugt, denn diese erhalten immer Context und Sprache. Dabei spielt es keine Rolle, ob du als Entwickler den Service ohne Initialisierungs-Parameter anforderst oder nicht. Das wiederum ist jedoch Teil des APF-Context-Konzeptes, das es dadurch ermöglicht, generische Konfigurationen pro laufender Applikation oder sogar innerhalb dieser getrennt anzubieten.

                  2. Mit einem Parameter (Der, schätze ich mal, beliebig ausgeprägt sein kann.)
                  Ansonsten unterstützt das APF die Konfiguration mittels Setter bzw. über DI mittels Config-Datei.
                  Das meine ich mit zu statisch.
                  Das verstehe ich immer leider noch nicht - oder du das Konzept von DI nicht? Du hast mit den verschiedenen Ausprägungen der ServiceManager alle Möglichkeiten offen und kannst sogar deine Sevices in deiner Applikation nochmal konfigurieren (was zwar Blödsinn ist, aber vielleicht meinst du das mit dynamisch).

                  Was würde denn passieren, wenn eine Klasse beim Instanziieren mehrere Instanzen anderer Klassen benötigt?
                  Das ist eine Frage des Konzeptes (wie oben angesprochen)! Sofern du auf constructor injection setzt, kannst du die APF-ServiceManager nicht verwenden, da diese nach dem setter injection Prinzip arbeiten. Um es nochmal deutlich zu sagen: das ist kein Nachteil! Beide Prinzipien lassen sich natürlich kombinieren, jedoch setzt das APF bewusst auf letzteres, um das Thema Konfiguration einfacher behandeln zu können. Die Composite-Struktur des Page-Controller-DOM-Baumes genügt einer definierten Struktur und bietet daher dem Entwickler ein effizientes Interface für eigene Implementierungen von GUI-Komponenten und durch den Front-Controller auch Business-Komponenten, die nach dem selben Prinzip arbeiten.

                  Sofern du bei einem "APF-Service" mehrere Komponenten in einem Service benötigst, würdest du diese einfach in der Konfiguration anlegen und dem Service mitgeben. Beispiel:

                  [ServiceA]
                  servicetype = ""
                  namespace = ""
                  class = ""
                  init.foo.method = "setServiceB"
                  init.foo.namespace = ""
                  init.foo.name = "ServiceB"
                  init.bar.method = "setServiceC"
                  init.bar.namespace = ""
                  init.bar.name = "ServiceC"

                  [ServiceB]
                  servicetype = ""
                  namespace = ""
                  class = ""

                  [ServiceC]
                  servicetype = ""
                  namespace = ""
                  class = ""
                  Sofern irgendwann ServiceC noch weitere, abhängige Services benötigt, kann das auf die gleiche Art und Weise passieren, wie die Injizierung von ServiceB in ServiceA. Hier sind keine Grenzen gesetzt.
                  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


                  • #10
                    Grundsätzlich verstehe ich jedoch immer noch nicht, welche zwei Varianten du meinst.
                    ServiceManager.php:
                    PHP-Code:
                    function &getServiceObject
                    function &getAndInitServiceObject 
                    Beim DIServiceManager gibt es nur eine Variante.

                    Code:
                    wird nach diesem Konzept kein APF-Objekt ohne Parameter erzeugt, denn diese erhalten immer Context und Sprache.
                    Aber eben auch nur, wenn man den SL bzw. DI benutzt. Das stört mich halt.

                    kannst du die APF-ServiceManager nicht verwenden, da diese nach dem setter injection Prinzip arbeiten
                    Verstanden - das meinte ich mit "statisch". Eine etwas unglückliche Wortwahl.

                    Sofern du bei einem "APF-Service" mehrere Komponenten in einem Service benötigst, würdest du diese einfach in der Konfiguration anlegen und dem Service mitgeben.
                    Ok, das macht natürlich Sinn. Da ist das mit der Setter-Injection wahrscheinlich die beste Lösung. Allerdings ist das in meinen Augen doch recht Performance fressend, oder? Ansonsten gefällt mir das gut.

                    EDIT: Wenn man nun viele Service-Objekte hat, dann stelle ich mir vor, dass die Config-Datei ziemlich ausufert. Oder beschränkst Du den Aufruf auf bestimmte Objekt-Typen?

                    Kommentar


                    • #11
                      Hi,

                      Code:
                      Beim DIServiceManager gibt es nur eine Variante.
                      Das verstehe ich immer noch nicht. Du hast du in der Konfiguration die Möglichkeit, einen "uninitialisierten" Service (Variante: getServiceObject()) und einen dynamisch oder statisch initialisierten Service (Variante: getAndInitServiceObject()) zu erzeugen. Letztere bietet dabei den Vorteil, dass du statische und dynamische Konfiguration in beliebiger Komplexität abbilden kannst.

                      Aber eben auch nur, wenn man den SL bzw. DI benutzt. Das stört mich halt.
                      Nein, Context und Sprache werden auch von Factory-Methoden in die GUI-Objekte injiziert. Was dich daran stört lässt sich für mich auch noch nicht ganz nachvollziehen, denn wenn du in einer anderen Technologie ein Objekt erstellst, musst du dieses auch initialisieren, denn es kennt die Parameter der Applikation auch nicht durch die Glaskugel.

                      Ok, das macht natürlich Sinn. Da ist das mit der Setter-Injection wahrscheinlich die beste Lösung. Allerdings ist das in meinen Augen doch recht Performance fressend, oder? Ansonsten gefällt mir das gut.
                      Für das APF macht das definitiv so Sinn. Performance-intensiver ist das in der Tat nicht, denn es macht (nahezu) keinen Unterschied, ob ein Objekt mit den relevanten Informationen zur Konstruktions-Zeit oder anschließend befüllt wird. Sofern das gekapselt stattfindet ist es auch für den Aufrufer oder Anwender völlig transparent. Man muss sich - beim APF ist das in den GUI-Objekten (=Taglib-Instanzen) so - einfach mit dem Timing-Model/Objekt-Lifecycle auseinandersetzen, dann wird klar, wo du was aufrufen bzw. verwenden kannst.
                      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


                      • #12
                        DIServiceManager
                        Für mich sah das so aus, als ob man in der Konfiguration pro ServiceObjekt nur _eine_ Konfiguration anlegen kann.

                        musst du dieses auch initialisieren, denn es kennt die Parameter der Applikation auch nicht durch die Glaskugel.
                        Stimmt schon - Dann muss man sich halt selber drum kümmern..

                        Kommentar

                        Lädt...
                        X