MB: Instanzstrukturen mit TraitsHelper oder HelperService Meinung

0 66

Instanzstrukturen mit TraitsHelper oder HelperService Meinung

MB
  • meinung
  • php
  • programmiertechnik
  1. 1
    pl
    1. 0
      MB
      1. 0
        pl
        1. 0
          MB
  2. 0
    MB
    1. 0
      pl
      1. 0
        MB
        1. -2
          pl
          1. 0
            MB
            1. 0
              pl
        2. -1
          pl
          1. 0
            MB
            1. 0
              pl
          2. 0
            dedlfix
            1. 0
              MB
              1. 1
                dedlfix
                1. 0
                  MB
              2. -1
                pl
  3. 2
    Rolf B
    1. 0
      MB
      1. 0
        Rolf B
        1. 0
          pl
          1. 0
            Rolf B
            1. 0
              pl
          2. -1
            pl
            1. 0
              dedlfix
              1. 0
                pl
  4. -1
    pl
    1. 0
      MB
      1. 0
        pl
        1. 0
          MB
          1. 0
            Rolf B
            1. 1
              pl
            2. 1
              dedlfix
              1. 1
                Rolf B
                1. 0
                  dedlfix
              2. 1
                pl
                1. 0
                  dedlfix
                  1. 0
                    Rolf B
                    1. 0
                      dedlfix
            3. 0
              MB
  5. 0
    pl
    1. 0
      MB
      1. 0
        pl
        1. 0
          Rolf B
          1. 0
            pl
      2. 0
        MB
        1. 0
          pl
          1. 0
            MB
  6. 0
    MB
    1. 3
      dedlfix
      1. 0
        MB
        1. 0
          Matthias Apsel
          1. 0
            MB
            1. 0
              Matthias Apsel
              1. 0
                Rolf B
                1. 0
                  Matthias Apsel
                  1. 0
                    Rolf B
                    1. 0
                      Matthias Apsel
            2. 1
              dedlfix
              1. 0
                MB
    2. -1
      pl
    3. 1
      Rolf B
      1. 0
        MB
        1. 0
          MB

moin,

ich habe ein Problem in einer Instanzstruktur. Für das Problem habe ich Concrete[Indentifier]Instance-Klassen, die für einen Output parameter sammelt. Dieses Problem habe ich, wie unten beschrieben, "schematisch" gelöst. Es ist für den SQLGenerator:

//// Abstracts ////

abstract class AbstractInstance {
  trait TraitHelper;

  private $_storage;
}

//// Concretes ////

class ConcreteFooInstance {
  public function __construct ( AbstractInterface $params ) {
    $this->_doSomeThing ( $params ); // TraitHelper
  }
}

class ConcreteBarInstance {
  public function __construct ( AbstractInterface $params ) {
    $this->_doSomeThing ( $params ); // TraitHelper
  }
}

class ConcreteQuzInstance {
  public function __construct ( AbstractInterface $params ) {
    $this->_doSomeThing ( $params ); // TraitHelper
  }
}

class ConcreteTokInstance {
  public function __construct ( AbstractInterface $params ) {
    $this->_doSomeThing ( $params ); // TraitHelper
  }
}

//// Traits ////

trait TraitHeper {
  protected function _doSomeThing ( AbstractInterface $params ) : void {
    $this->_storage[] = $params;
  }
}

Ich sehe da viele Vorteile:

Pros

  • direkter Zugriff von TraitHelper-Trait
  • Einsatz von protected-Methoden
  • Kapselung der privaten, abstrakten Instanz Eigenschaften $this->_storage
  • Concrete[Indentifier]Instance müssen keine Instanz Eigenschaften haben

Cons

  • Dieses TraitHelper muss zwingend in der AbstractClass enthalten sein.

Ich kann das auch anders lösen, indem ich die TraitHelper-Klasse in HelperService umforme. Jedoch dann müsste ich…

  • …alle Methoden public deklarieren und mindestens eine Methoden im z.B. parent::__construct() realisieren.
  • alle Concrete[Indentifier]Instance müssten zusätzlich im Konstructor den Abstracten Konstructor aufrufen, um die HelperService-Klasse zu instanziieren.

Ich könnte die HelperService-Klasse auch in der konkreten Klasse Concrete[Indentifier]Instance realisieren jedoch…

  • …die Parameterübergabe zur AbstractInstanz-Klasse "verdeckt" zur realisieren, ist nicht möglich, meiner auffassung nach.
  • …muss die HelperService-Klasse in der Concrete[Indentifier]Instance jeders mal instanziieren werden.

Ich möchte natürlich sehr verständlich programmieren aber auch struktrierter und organisierter. Eure Meinung bitte.

lgmb

--
Sprachstörung

akzeptierte Antworten

  1. Eure Meinung bitte.

    Gerne. Dein ganzes kompliziertes Gebilde weist $param an eine private Eigenschaft $_storage. Das kann man wesentlich einfacher haben indem man in jeder Subklasse ganz einfach den Vaterkonstruktor aufruft und $param übergibt.

    MFG

    1. moin,

      Eure Meinung bitte.

      Gerne. Dein ganzes kompliziertes Gebilde weist $param an eine private Eigenschaft $_storage. Das kann man wesentlich einfacher haben indem man in jeder Subklasse ganz einfach den Vaterkonstruktor aufruft und $param übergibt.

      Bitte entschuldige. Ich formuliere es klare. Es war nicht deutlich, fällt mir etzt auf 😕. Die Parameter sollen ja von der Signatur her unterschiedlich sein und sie nicht gleichen.

      lgmb

      --
      Sprachstörung
      1. die Parameter sollen ja sehr unterschiedlich sein von der signatur her unterschiedlich sein und sie nicht gleichen.

        Das ist mir schon klar. Deswegen benutzt Du ja auch diesen unsäglichen $this->_storage[] = $params; Syntax.

        Von meiner ersten Atwort, die unabhängig davon ist abgesehen, hier fände ich eine saubere Deklaration daß $_storage ein array ist und die Anwendungen von array_push() deutlich reproduzierbarer.

        Zum Verständnis meiner Antwort: Der Aufruf des Vaterkonstruktors ist immer dann erforderlich wenn Eigenschaften geerbt+initilisiert werden sollen.

        MFG

        1. moin,

          die Parameter sollen ja sehr unterschiedlich sein von der signatur her unterschiedlich sein und sie nicht gleichen.

          Das ist mir schon klar. Deswegen benutzt Du ja auch diesen unsäglichen $this->_storage[] = $params; Syntax.

          Bitte versteh das ich es "schematisch" dargestellt für euch habe. Ich hab nicht vor über 5BM hier im Forum darzustellen, die mein SQLGenerator mitlerweile umfast.

          lgmb

          --
          Sprachstörung
  2. moin,

    Nachtrag

    • Traits diesbezüglich sind mir suspekt aber zur ösung des Problems die einzige möglichkeit, in meinen Augen.
    • Die Konstruktor Parameter der Concrete[Indentifier]Instance-Klassen müssen unterschiedlich sein aber ein gemeinsames Interface haben z.B.
    class ConcreteFooInstance {
      public function __construct ( AbstractInterface $params ) {}
    }
    class ConcreteBarInstance {
      public function __construct ( string $foo, int $bar ) {}
    }
    class ConcreteQaxInstance {
      public function __construct ( array $container ) {}
    }
    class ConcreteTokInstance {
      public function __construct ( int $foo, AbstractInterface $params ) {}
    }
    

    Sry, ich habs vergessen zu Erwähnen und es nicht deutlich gemacht. Danke an @pl.

    lgmb

    --
    Sprachstörung
    1. Traits diesbezüglich sind mir suspekt aber zur ösung des Problems die einzige möglichkeit, in meinen Augen.

      Nein sind sie nicht. Hier gehts um die Vererbung einer Eigenschaft, das ist OOP pur.

      MFG

      1. moin,

        Traits diesbezüglich sind mir suspekt aber zur ösung des Problems die einzige möglichkeit, in meinen Augen.

        Nein sind sie nicht. Hier gehts um die Vererbung einer Eigenschaft, das ist OOP pur.

        mach mal bitte n konretes Beispiel damit ich das nachvollziehen kann.

        lgmb

        --
        Sprachstörung
        1. moin,

          Traits diesbezüglich sind mir suspekt aber zur ösung des Problems die einzige möglichkeit, in meinen Augen.

          Nein sind sie nicht. Hier gehts um die Vererbung einer Eigenschaft, das ist OOP pur.

          mach mal bitte n konretes Beispiel damit ich das nachvollziehen kann.

          Steht auf meiner Webseite. Am besten spiel die ganze Vererbungsgeschichte mal selber durch mit einer Eigenschaft.

          MFG

          1. moin,

            moin,

            Traits diesbezüglich sind mir suspekt aber zur ösung des Problems die einzige möglichkeit, in meinen Augen.

            Nein sind sie nicht. Hier gehts um die Vererbung einer Eigenschaft, das ist OOP pur.

            mach mal bitte n konretes Beispiel damit ich das nachvollziehen kann.

            Steht auf meiner Webseite. Am besten spiel die ganze Vererbungsgeschichte mal selber durch mit einer Eigenschaft.

            ich glaube du verstehts mein "spezielles" Problem und eine von vielen Lösung des "speziellen" Problemes nicht. Ich wär nicht hier, wenn es um ein "spezielles" Problem der Vererbung geht. Und "Vaterkonstrukt" ist Nicht verständlich, habe ich dir schonmal gesagt.

            lgmb

            --
            Sprachstörung
            1. moin,

              moin,

              Traits diesbezüglich sind mir suspekt aber zur ösung des Problems die einzige möglichkeit, in meinen Augen.

              Nein sind sie nicht. Hier gehts um die Vererbung einer Eigenschaft, das ist OOP pur.

              mach mal bitte n konretes Beispiel damit ich das nachvollziehen kann.

              Steht auf meiner Webseite. Am besten spiel die ganze Vererbungsgeschichte mal selber durch mit einer Eigenschaft.

              ich glaube du verstehts mein "spezielles" Problem und eine von vielen Lösung des "speziellen" Problemes nicht. Ich wär nicht hier, wenn es um ein "spezielles" Problem der Vererbung geht. Und "Vaterkonstrukt" ist Nicht verständlich, habe ich dir schonmal gesagt.

              Also meine Antwort mal etwas konkreter, Du hast hier den Fall der Vererbung einer Eigenschaft und das löst man ganz einfach mit pure OOP und nicht mit Traits.

              MFG

        2. moin,

          Traits diesbezüglich sind mir suspekt aber zur ösung des Problems die einzige möglichkeit, in meinen Augen.

          Nein sind sie nicht. Hier gehts um die Vererbung einer Eigenschaft, das ist OOP pur.

          mach mal bitte n konretes Beispiel damit ich das nachvollziehen kann.

          OOP Grundwissen!

          abstract class AbstractInstance {
              private $_storage = array();
              function __construct($params){
                  array_push($this->_storage, $params);
              }
          }
          
          
          class ConcreteFooInstance extends AbstractInstance{
            public function __construct ( $params ) {
              parent::__construct( $params );
            }
          }
          
          
          $f = new ConcreteFooInstance( 123 );
          
          print_r($f);
          

          MFG

          1. moin,

            moin,

            Traits diesbezüglich sind mir suspekt aber zur ösung des Problems die einzige möglichkeit, in meinen Augen.

            Nein sind sie nicht. Hier gehts um die Vererbung einer Eigenschaft, das ist OOP pur.

            mach mal bitte n konretes Beispiel damit ich das nachvollziehen kann.

            OOP Grundwissen!

            Sry, wenn ich OOP Grundwissen benötige, wäre ich nicht hier. Das weist du, du kennst mich gut genug um zu wissen, dass ich das schon weis

            PHP Grundwissen

            array_push($this->_storage, $params); Geht auch ist aber umständlich

            $this->_storage[] = $params Geht, ist simpler, frisst weniger resourcen

            lgmb

            --
            Sprachstörung
            1. moin,

              Traits diesbezüglich sind mir suspekt aber zur ösung des Problems die einzige möglichkeit, in meinen Augen.

              Nein sind sie nicht. Hier gehts um die Vererbung einer Eigenschaft, das ist OOP pur.

              mach mal bitte n konretes Beispiel damit ich das nachvollziehen kann.

              OOP Grundwissen!

              Sry, wenn ich OOP Grundwissen benötige, wäre ich nicht hier.

              Du hast danach gefragt! Und ja, Vererbung ist OOP-Grundwissen!

              MFG

          2. Tach!

            OOP Grundwissen!

            abstract class AbstractInstance {
                private $_storage = array();
                function __construct($params){
                    array_push($this->_storage, $params);
                }
            }
            
            
            class ConcreteFooInstance extends AbstractInstance{
              public function __construct ( $params ) {
                parent::__construct( $params );
              }
            }
            

            Eine Constructor-Methode, die nur 1:1 die Constructor-Methode der geerbten Klasse aufruft, ist überflüssig. Die geerbte Constructor-Methode wird sowieso aufgerufen, wenn sie nicht überschrieben wurde. Es sei denn, sie wäre protected oder private.

            dedlfix.

            1. moin,

              Eine Constructor-Methode, die nur 1:1 die Constructor-Methode der geerbten Klasse aufruft, ist überflüssig. Die geerbte Constructor-Methode wird sowieso aufgerufen, wenn sie nicht überschrieben wurde. Es sei denn, sie wäre protected oder private.

              Ich denke - hoffe - das @pl diese Konstrukt schematisch meinte. Ich bezweifel jedoch die Sinnhaftigkeit oder den Zweck @pl s Konstrukt. Hardgecodet ist Hardgecodet. Mängel die all von absehen, denke ich mal.

              lgmb

              --
              Sprachstörung
              1. Tach!

                Ich denke - hoffe - das @pl diese Konstrukt schematisch meinte. Ich bezweifel jedoch die Sinnhaftigkeit oder den Zweck @pl s Konstrukt. Hardgecodet ist Hardgecodet.

                Warum sollte das nicht im Allgemeinen sinnvoll sein? Ich bezweifle eher denn Sinn des Traits in deinem Fall. Das hat ja Rolf B schon gut begründet. Da nicht genau hervorgeht, was du letztlich möchtest, kann ich mir dazu aber keine konkrete Meinung bilden. In der jetzigen Form sieht es mir jedenfalls over engineered aus.

                dedlfix.

                1. moin,

                  Ich denke - hoffe - das @pl diese Konstrukt schematisch meinte. Ich bezweifel jedoch die Sinnhaftigkeit oder den Zweck @pl s Konstrukt. Hardgecodet ist Hardgecodet.

                  Ich bezweifle eher denn Sinn des Traits in deinem Fall. Das hat ja Rolf B schon gut begründet.

                  Deswegen habe ich es ja hier vorgetragen ud begründet warum ich dieses trait verwende.

                  Da nicht genau hervorgeht, was du letztlich möchtest, kann ich mir dazu aber keine konkrete Meinung bilden.

                  Alles gut. Zugegebenermaßen hätte ich das Beispiel genauer entwickeln sollen, wie mir auf fällt. @pl hat mich ja auf den trichter gebracht, dass mein schaubildhaftes Konstrukt fehler enthält.

                  In der jetzigen Form sieht es mir jedenfalls over engineered aus.

                  ich entwickle ja weiter

                  lgmb

                  --
                  Sprachstörung
              2. moin,

                Eine Constructor-Methode, die nur 1:1 die Constructor-Methode der geerbten Klasse aufruft, ist überflüssig. Die geerbte Constructor-Methode wird sowieso aufgerufen, wenn sie nicht überschrieben wurde. Es sei denn, sie wäre protected oder private.

                Ich denke - hoffe - das @pl diese Konstrukt schematisch meinte. Ich bezweifel jedoch die Sinnhaftigkeit oder den Zweck @pl s Konstrukt.

                Der Sinn von OOP besteht darin Vererbung sinnvoll einzusetzen. Und wie hier mehrfach erwähnt, nicht mit Traits denn deren Zweckbstimmung ist nämlich eine ganz andere.

                Und ja, wenn die Argumente auf den Vaterkonstruktor passen muss man den auch nicht einmal überschreiben.

                MFG

  3. Hallo MB,

    TraitHelper und AbstractInstance sind zu eng gekoppelt. Der Trait liefert einen Setter für eine private Eigenschaft von AbstractInstance. Vermutlich liefert er noch mehr und du zeigst nur beispielhaft eine Methode - aber bei dem, was Du zeigst, lautet die Aussage: Entweder gehört _doSomething nach AbstractInstance, oder $_storage gehört in den TraitHelper. Methode und Property gehören jedenfalls zusammen, nicht auseinander. Es zu trennen ist ein Unfall, der darauf wartet, zu passieren.

    Einsatzzweck von Traits ist das wiederverwendbare Anflanschen von Methoden an Klassen, die keine gemeinsame Elternklasse haben. Traits sollten meiner Meinung nach auch niemals direkt auf Properties des Objekts zugreifen, in dem sie geUSEt werden, und sie sollten alle Methoden USEenden Objekts, die sie verwenden, per abstract-Deklaration anmelden, so dass es nicht möglich ist, einen Trait dort zu verwenden wo er nicht funktionieren kann.

    Also - gibt es mehrere Klassenhierarchien (oder Klassen), die keine gemeinsame Wurzel haben, und die diesen Trait benötigen? Dann hat er Existenzberechtigung. Andernfalls solltest Du ihn nach AbstractInstance integrieren. FALLS es irgendwann noch AbstractInstance2 gibt, das logisch so weit von AbstractInstance entfernt ist, dass eine gemeinsame Elternklasse nicht sinnvoll ist, DANN kannst Du den StorageTrait immer noch aus AbstractInstance herausfaktoriesieren.

    Vor Overengineering habe ich dich schon mehrfach gewarnt. Baue nicht zu viel Abstrakta für "zukünftige Erweiterungen". Zum einen weißt Du heute nicht, ob sie wirklich kommen. Zum anderen ist das Problem von Voraussagen, dass sie immer dann schwierig werden, wenn sie sich auf die Zukunft beziehen. Deine zukünftige Erweiterung mag ganz anders werden als Du heute glaubst, und deine gelegten Fundamente könnten sich als falsch platziert erweisen. Baue heute, was Du heute brauchst. Und wenn Du mehr brauchst, refaktoriere und erweitere.

    Baue für das, was Du heute baust, Unittests. Damit kannst Du sicherstellen, dass dein Code nach dem refaktorieren immer noch funktioniert.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. moin,

      TraitHelper und AbstractInstance sind zu eng gekoppelt.

      Ja ich habs befürchtet 😕.

      Entweder gehört _doSomething nach AbstractInstance, oder $_storage gehört in den TraitHelper.

      _doSomething ist im TraitHelper enthalten und wird von AbstractInstance imlementiert. Insofern keine einwände finde ich 😀.

      Methode und Property gehören jedenfalls zusammen, nicht auseinander. Es zu trennen ist ein Unfall, der darauf wartet, zu passieren.

      Ja wie gesagt ich hab es gelöst aber unglücklich 😕

      Traits sollten meiner Meinung nach auch niemals direkt auf Properties des Objekts zugreifen, in dem sie geUSEt werden, und sie sollten alle Methoden USEenden Objekts, die sie verwenden, per abstract-Deklaration anmelden, so dass es nicht möglich ist, einen Trait dort zu verwenden wo er nicht funktionieren kann.

      ach ja jetzt wo du es sagst…

      trait TraitHelper {
        
        abstract private function _addStorage( InterfaceAbstract $params )  void;
      
        /* CODE */
      }
      

      besser? Ich fühle mich auf jedenfall wohlerer 😀.

      Also - gibt es mehrere Klassenhierarchien (oder Klassen), die keine gemeinsame Wurzel haben, und die diesen Trait benötigen? Dann hat er Existenzberechtigung.

      Nein gibt es nicht. Werde Ich anders lösen so wie du es empfohlen hast

      Vor Overengineering habe ich dich schon mehrfach gewarnt.

      Ja ich weis. Und ich halte mich an deinen Rat. Aber fals nicht, klage ich wieder mein Leid hier im Forum 😉.

      […] Baue heute, was Du heute brauchst. Und wenn Du mehr brauchst, refaktoriere und erweitere.

      Jo danke. Werde ich beherzigen.

      Baue für das, was Du heute baust, Unittests. Damit kannst Du sicherstellen, dass dein Code nach dem refaktorieren immer noch funktioniert.

      Danke. Werde ich machen. Zu den UnitTests habe ich noch zukünftig Fragen.

      P.S.: Sry wegen der vielen Auszeichnungen von mir. Ich kann es besser lesen eben weil es abhehoben und ausgezeichnet ist. So passieren mir weniger fehler.

      lgmb

      --
      Sprachstörung
      1. Hallo MB,

        _doSomething ist im TraitHelper enthalten und wird von AbstractInstance imlementiert. Insofern keine einwände finde ich 😀.

        Hä? Das ist zumindest im gezeigten Code des Eingangspostings nicht so. Da wird _doSomething von Traithelper implementiert, und nutzt $_storage von AbstractInstance. Wären die beiden beisammen gewesen, hätte ich das ja nicht kritisiert.

        abstract private function _addStorage( InterfaceAbstract $params ) void;

        Willst Du damit jetzt den Zugriff auf private $_storage von AbstractInstance kapseln? Das ist dann sinnvoll, wenn AbstractInstance eine Menge Dinge mit $_storage anstellen muss, unabhängig vom Trait.

        Da Du nur symbolischen Code gepostet hast, kann ich nicht einschätzen was für deinen Fall am Besten ist. Ist die Idee erwägenswert, $_storage als Property des Trait zu deklarieren und das Management des $_storage komplett vom Trait erledigen zu lassen?

        Rolf

        --
        sumpsi - posui - obstruxi
        1. $_storage als Property des Trait zu deklarieren und das Management des $_storage komplett vom Trait erledigen zu lassen?

          Vermutlich will er das. Dazu müsste man aber den Unterschied zwischen Klassenvariablen und Instanzvariablen kennen.

          Auf jeden Fall würde dann auch ein _storage[]=$param einen Sinn machen wenn sich diese Variable statisch verhält.

          Ein $this->_storage[]=$param ergibt jedenfalls keinen Sinn.

          MFG

          1. Hallo pl,

            doch, das kann schon Sinn ergeben wenn es außerhalb des Konstruktors noch weitere Adds zu diesem Array gibt. Oder manche Konstruktoren mehrere Werte in $_storage eintragen. Aber das ist Speck-Ulation, dafür müsste man den vollständigen Sourcecode sehen.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. hi

              doch, das kann schon Sinn ergeben wenn es außerhalb des Konstruktors noch weitere Adds zu diesem Array gibt.

              Zweifelhaft ob das dann noch sinnvoll ist. Es ist ja der Sinn eines Konstruktors, Properties zu initialisieren. Also genau einmal wenn die Instanz erstellt wird.

              Daten die später hinzukommen wurde ich jedenfalls nicht in derselben Eigenschaft ablegen.

              MFG

          2. $_storage als Property des Trait zu deklarieren und das Management des $_storage komplett vom Trait erledigen zu lassen?

            Vermutlich will er das. Dazu müsste man aber den Unterschied zwischen Klassenvariablen und Instanzvariablen kennen.

            Auf jeden Fall würde dann auch ein _storage[]=$param einen Sinn machen wenn sich diese Variable statisch verhält.

            Ein $this->_storage[]=$param ergibt jedenfalls keinen Sinn.

            MFG

            Also statt

            abstract class AbstractInstance {
              trait TraitHelper;
            
              private $_storage;
            }
            
            abstract class AbstractInstance {
             static public $_storage = array(); # = []
            }
            
            

            als Klassenvariable anlegen. Was natürlich weitere Konsequenzen hat.

            MFG

            1. Tach!

              Ein $this->_storage[]=$param ergibt jedenfalls keinen Sinn.

              Also statt[dessen] [...] als Klassenvariable anlegen. Was natürlich weitere Konsequenzen hat.

              Da wir den genauen Anwendungsfall nicht kennen, ergibt diese Empfehlung gleich gar keinen Sinn. Warum sollte das, was vorher zur Instanz gehörte, plötzlich global werden? Dazu kannst du keine sinnvolle Begründung liefern, aus dem erstgenannten Grund.

              Ein $this->_storage[] = $param; ist im Grunde genommen nur semantisch fragwürdig. Funktional ist es jedenfalls im gezeigten Code gleich zu $this->_storage = [$param];

              dedlfix.

              1. Natürlich ist es immer sinnvoll bei der Kapselung zu bleiben wenn man OOP konsequent nutzen will. Das ist aber genau das was ich hier nicht im Geringsten erkennen kann: Eine sinnvolle Nutzung von OOP!

                Idealerweise würde man hier ein Interface bauen, nur eine Instanz erstellen und mit dieser Instanz die Methoden des Interface in einer ganz bestimmten Reihenfolge aufrufen. Diesen Vorschlag machte ich bereits vor Wochen!

                MFG

  4. Es gibt noch in anderes Problem. Deine Subklassen füllen in private $_storage; ein Array. D.h., jedesmal wenn eine Instanz der Subklasse erstellt wird, gibt es einen Eintrag in diesem Array. Nun ist das eine private Eigenschaft die nur solange existiert solange es eine Instanz gibt.

    D.h., jede Instanz bekommt bei der Erstellung genau ein Arrayelement. Worin besteht der Sinn eines Array's mit genau einem Element?

    MFG

    1. moin,

      Es gibt noch in anderes Problem. […]

      Und hier ist die AW

      lgmb

      --
      Sprachstörung
      1. moin,

        Es gibt noch in anderes Problem. […]

        Und hier ist die AW

        lgmb

        Nein dass ist keine Antwort auf meine Frage. Meine Frage noch einmal: Warum ein Array wenn es nur einen Eintrag gibt?

        MFG

        1. moin,

          moin,

          Es gibt noch in anderes Problem. […]

          Und hier ist die AW

          lgmb

          Nein dass ist keine Antwort auf meine Frage. Meine Frage noch einmal: Warum ein Array wenn es nur einen Eintrag gibt?

          Das Problem ist "schemahaft" erläutert worden und @Rolf B hats beantwortet! Bei meinem real existierenden Code, ist das ganze Komplex, eben 5MB groß und wächst weiter.

          lgmb

          --
          Sprachstörung
          1. Hallo MB,

            uppala, dieses Detail hatte ich total übersehen. Das erklärt zumindest mal, warum Du $_storage nicht über parent::__construct befüllst.

            Es ist aber eine Unsauberkeit. PHP verzeiht Dir hier einen Fehler, den Du nicht machen solltest.

            Ein Miniprogramm zur Demonstration:

            <?php
            var_dump($a);
            $a[] = 7;
            echo "---\n";
            var_dump($a);
            

            Ausgaben:

            <b>Notice</b>:  Undefined variable: a in <b>[...][...]</b> on line <b>3</b>
            NULL
            ---
            array(1) {
              [0]=>
              int(7)
            }
            

            Die Notice ignorieren wir mal, das ist bei einem private nicht so, aber der Wert darin ist interessant: NULL. PHP erlaubt Dir, den [] (Array Append) Operator auf NULL anzuwenden und wandelt den Inhalt von $a stillschweigend in ein Array um.

            Das ist typisch PHP, gemacht für Leute, die sich ihre Webseiten aus diversen Vorlagen zusammenkopieren und keine Ahnung vom Programmieren haben (was eine Breitseite gegen PHP ist, NICHT gegen Dich!). Es ist vor allem extrem unsauber.

            PHP hat seit Version 4 viele Unsauberkeiten deprecated und irgendwann entfernt. Möglicherweise passiert das auch hier einmal. Du solltest eine Variable, die Du als Array nutzen willst, DEFINITIV mit einem leeren Array initialisieren.

            So ist's sauberer:

            class Foo
            {
               private $_storage = [];
            
               public function __construct($bar) 
               {
                  $this->_storage[] = $bar;
               }
            }
            

            Diese Form der Initialisierung eignet sich vor allem für Traits, weil die keine Konstruktoren kennen. Initializer laufen vor dem Konstruktor.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. Du solltest eine Variable, die Du als Array nutzen willst, DEFINITIV mit einem leeren Array initialisieren.

              Hab ich auch schon empfohlen. MFG

            2. Tach!

              Ein Miniprogramm zur Demonstration:

              <?php
              var_dump($a);
              $a[] = 7;
              echo "---\n";
              var_dump($a);
              

              Ausgaben:

              <b>Notice</b>:  Undefined variable: a in <b>[...][...]</b> on line <b>3</b>
              NULL
              ---
              array(1) {
                [0]=>
                int(7)
              }
              

              Die Notice ignorieren wir mal, das ist bei einem private nicht so, aber der Wert darin ist interessant: NULL.

              Du kannst das so nicht nachstellen. Wenn du in einer Klasse eine Variable deklarierst, wird sie beim Instantiieren eines Objekts angelegt. Sie hat zwar den Wert NULL als Default-Wert bekommen, weil nichts anderes festgelegt war.

              Eine einfache Variable allerdings ist nicht angelegt. Das NULL bei ihr ist das Ergebnis des Ausdrucks, mit dem du auf sie zuzugreifen versuchst. Sie existiert nicht, also gibt PHP den Wert NULL zurück.

              PHP erlaubt Dir, den [] (Array Append) Operator auf NULL anzuwenden und wandelt den Inhalt von $a stillschweigend in ein Array um.

              Das ist in beiden Fällen so. Ob die Variable den Inhalt NULL hat, oder PHP ein NULL beim misslungenen Lesevorgang liefert, bleibt sich gleich.

              Das ist typisch PHP, gemacht für Leute, die sich ihre Webseiten aus diversen Vorlagen zusammenkopieren und keine Ahnung vom Programmieren haben (was eine Breitseite gegen PHP ist, NICHT gegen Dich!). Es ist vor allem extrem unsauber.

              Ja, aber das hat hier keine weiteren Auswirkungen, weil sich hier kein Schreibvorgang davorschmuggeln kann. Die Instanzvariable existiert ja nicht, bevor das Objekt instantiiert wird. Globale Variablen hingegen könnten an anderen Stellen des Programms bereits beschrieben worden sein.

              dedlfix.

              1. Hallo dedlfix,

                Die Notice ignorieren wir mal, das ist bei einem private nicht so

                Warum reitest Du dann so drauf rum? Das Verhalten, worum es mir geht, ist bei Property und Variable gleich: sind sie nicht initialisiert, steht NULL drin, und PHP schießt den Wert in ein Array um. Bei einer Variablen legt es sie auch noch an.

                Und das ist der typische "ich korrigiere mal deine Fehler für Dich" Mist in PHP.

                Rolf

                --
                sumpsi - posui - obstruxi
                1. Tach!

                  Hallo dedlfix,

                  Die Notice ignorieren wir mal, das ist bei einem private nicht so

                  Warum reitest Du dann so drauf rum?

                  Ich habe genau einmal deine Aussage korrigiert. "Darauf rumreiten" fängt bei mir erst später an.

                  Das Verhalten, worum es mir geht, ist bei Property und Variable gleich: sind sie nicht initialisiert, steht NULL drin, und PHP schießt den Wert in ein Array um. Bei einer Variablen legt es sie auch noch an.

                  Das ist immer noch widersprüchlich, aber ich will da jetzt nicht weiter darauf rumreiten.

                  Und das ist der typische "ich korrigiere mal deine Fehler für Dich" Mist in PHP.

                  Ja, PHP erlaubt sich hier einen impliziten Schritt beim Anlegen des Arrays. Es ist aber nur dann Mist, wenn der Mist weiteren Mist verursacht. Natürlich ist es semantisch sauberer, das zu schreiben, was man tatsächlich will. Aber wenn sich etwas aus dem Kontext ergibt, kann man es auch so nutzen, solange es - wie hier - keine Nebenwirkungen gibt.

                  Das ist in etwa wie beim schließenden ?> am Ende einer PHP-Datei. Auch da ist es eigentlich "sauberer" den geöffneten Code-Bereich auch wieder zu schließen. Aber es ist nicht notwendig, wenn sowieso das Dateiende dem Bereich ein implizites Ende setzt. (Dass das Weglassen noch einen Vorteil bezüglich ungewolltem Whitespace hat, ist ein anderes Thema.)

                  dedlfix.

              2. hallo @dedlfix

                Deine Reaktion ist mir unverständlich. Gerade hier in einem Fachforum sollte es auch um einen sauberen Programmirstil gehen!

                Insofern gibt es an der Empfehlung on @Rolf B das Array sauber zu initialisieren nicht das Geringste auszusetzen und auch nicht hinzuzufügen.

                Selbst wenn es ohne Initialiserung funktioniert heißt das doch noch lange nicht daß man es so machen kann.

                MFG

                1. Tach!

                  Deine Reaktion ist mir unverständlich. Gerade hier in einem Fachforum sollte es auch um einen sauberen Programmirstil gehen!

                  Insofern gibt es an der Empfehlung on @Rolf B das Array sauber zu initialisieren nicht das Geringste auszusetzen und auch nicht hinzuzufügen.

                  Das Array wird ordnungsgemäß initialisiert. Nur nicht explizit, sondern implizit.

                  Selbst wenn es ohne Initialiserung funktioniert heißt das doch noch lange nicht daß man es so machen kann.

                  Warum nicht? Wo ist das konkrete Problem für den vorliegenden Fall, wenn das Ergebnis dasselbe ist?

                  dedlfix.

                  1. Hallo dedlfix,

                    wie geschrieben: das konkrete Problem kommt in dem Moment, wo PHP das als Altlast deprecated. Es wäre nicht das erste Mal, dass solche Deprecations ganze Codebasen ruinieren, weil Dinge auf einmal nicht mehr implizit funktionieren (und man sie nicht einfach heraussuchen kann, weil sie eben implizit sind).

                    Ich habe sowas zweimal bei Carcassonne Online erlebt. Beim ersten Mal haben wir PHPBB2 weggeworfen, beim zweiten Mal konnte ich die freie Version Orion BB mühsam am Laufen halten, aber das waren ein paar Tage Try and Crash.

                    Rolf

                    --
                    sumpsi - posui - obstruxi
                    1. Tach!

                      wie geschrieben: das konkrete Problem kommt in dem Moment, wo PHP das als Altlast deprecated.

                      Ich sehe das gelassen. Zum einen wird sowas lange angekündigt, zum anderen meine ich, dass es unwahrscheinlich ist, dass genau dieses Feature rausgepatcht wird. Und außerdem kann es jedes Feature treffen, auch die, an denen es bisher nichts auszusetzen oder keine Alternative gab. Also wenn das Argument lautet, dass etwas in Zukunft geändert werden könnte, dürfte man gar nicht erst anfangen.

                      dedlfix.

            3. moin,

              uppala, dieses Detail hatte ich total übersehen. […].

              ach verdammt ich auch 😟. Sorry dafür. Natürlich sollte so sein, wie du kritik übst eben private $_storage = [];. Meine ganzen Klassen habe ich so per default inizialisiert. Und: Bitte, bitte, bitte, kritisiert mich! Aus fehlern Lernt man bekanntlich 😉.

              lgmb

              --
              Sprachstörung
  5. moin,

    ich habe ein Problem in einer Instanzstruktur.

    Und hier könnte Ihre Problembeschreibung stehen!

    Also: Welches Problem hat Du mit der Struktur?

    MFG

    1. moin,

      ich habe ein Problem in einer Instanzstruktur.

      Und hier könnte Ihre Problembeschreibung stehen!

      Also: Welches Problem hat Du mit der Struktur?

      Ich habe gehofft, das mein Beispiel Code, den ich durch deine Anmerkung richtig gestellt habe, die Sachlage klar ist . In deinem Fall nicht. Ok, macht ja nix. Wie erwähnt hat @Rolf B seine Meinung dazu gesagt, die ich sehr schätze.

      lgmb

      --
      Sprachstörung
      1. Dein Beispielcode macht Dein Problem nicht deutlich. Dein Beispielcode zeigt jedoch, daß Dir OOP-Grundwissen fehlt und Du es demzufolge nicht anwenden kannst.

        MFG

        1. Hallo pl,

          Dein Beispielcode zeigt jedoch, daß Dir OOP-Grundwissen fehlt

          das sehe ich auch so, darum fragt er hier. Aber wir arbeiten ja dran :)

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Autoimmunisierung kann tödlich sein ;)

      2. moin,

        ich habe ein Problem in einer Instanzstruktur.

        Und hier könnte Ihre Problembeschreibung stehen!

        Also: Welches Problem hat Du mit der Struktur?

        Ich habe gehofft, das mein Beispiel Code, den ich durch deine Anmerkung richtig gestellt habe, die Sachlage klar ist . In deinem Fall nicht. Ok, macht ja nix. Wie erwähnt hat @Rolf B seine Meinung dazu gesagt, die ich sehr schätze.

        Ich muss zugeben, das mein Beispiel Code nicht treffend gewählt ist 😕. Sorry. Ihr müsst verstehen, das mein Code so sehr gewachsen ist, sodas es mir unmöglich ist, ein wirklich konkretes Beispiel anzuführen. Daher habe ich alls runtergebochen was ruterzubrechen war und eben den Code "schematisch" vongeführt. Mir ist jetzt klar geworden, dass die Resonanz der Community dem entsprechen ausfällt.

        lgmb

        --
        Sprachstörung
        1. Dein Code zeigt, wie man es nicht machen soll: Die Initialisierung einer Instanz, was in OOP zweifelsfrei eine Angelegenheit des Konstruktors ist, über einen Tait zu schleifen.

          Und genau das hat Dir auch @Rolf B geschrieben, nämlich daß die Methoden eines Trait in diesem Fall auf private Eigenschaften der Instanz zugreifen.

          MFG

          1. moin,

            Dein Code zeigt, wie man es nicht machen soll: Die Initialisierung einer Instanz, was in OOP zweifelsfrei eine Angelegenheit des Konstruktors ist, über einen Tait zu schleifen.

            Und genau das hat Dir auch @Rolf B geschrieben, nämlich daß die Methoden eines Trait in diesem Fall auf private Eigenschaften der Instanz zugreifen.

            Ok. 2ter Versuch

            lgmb

            --
            Sprachstörung
  6. moin,

    • gegeben sind n konkrete Child-Class(es) mit der Benennung ConcreteConstruct die nur einer __construkt()-Methode enthält.
    • in der __construct()-Methode der ConcreteConstruct-Klasse können weitere ConcreteConstruct-Klassen per ConstructorInjection als Parameter enthalten sein.
    • Jeder Construct-Klasse ist Child-Class von Parent-Class AbstractConstruct.
    class ConcreteConstruct extends AbstractConstruct {
      public function __construct ( ConstructInterface $construct ) {
        // ...
      }
    }
    
    • Die __construct-Parameter werden in der Initialisierung der ConcreteConstructor-Klasse verarbeitet.
    • Jede Construct-Klasse befüllen, nach der Verarbeitung, über die protected Methode, private Instance-Property Arrays der AbstractConstruct-Klasse.
    • Ist eine ConcreteConstruct-Klasse ein Initialisierungsparameter von einer weitere ConcreteConstruct-Klasse, so nimmt der ConcreteConstruct-Klasse als Parameter, seine schon befülten Instance-Property Arrays von der AbstractConstruct-Klasse und übergibt sie der ConcreteConstruct-Klasse in seiner __construct-Methode vor der Weiterverarbeitung.
      $this->_receiveArray ( $construct->sendArray ( ) );
    
    • Die Weiterverarbeitung soll eine Helper-Klasse erledigen, da die Verarbeitung der ConcreteConstruct gleich oder ähnliche ist und man es gut auslagern kann.

    Wenn ich die Helper Klasse in einer der Beiden Klassen - ConcreteConstruct oder AbstractConstruct - implementiere, kann ich die Daten des ConcreteConstruct schon weiterverarbeiten, aber nicht als Daten zur AbstractConstruct-Klasse zurückgeben, sie verstauen und als ConstructInjection weiter an den nächsten fremeden ConcreteConstruct reichen.

    deswegen habe ich das mit Traits gelöst.

    Ich habe Überlegt ob man die Daten die die Helper-Klasse annimmt, nicht in eine extra Klasse Data schreiben könnte die die Klasse AbstractConstruct als Instance Property hätte. So könnte man die weiterverarbeiteten Parameter der Helper-Klasse, in der Data-Klasse verstauen, gekapselt und isoliert weitergeben an die AbstractConstruct.

    abstractclass AbstractConstruct {
      public function sendData ( ) : Data
      {
        return $this->_help->getData ( );
      }
    }
    
    class Helper {
      
      private $_data;
      
      private function _addData ( ) : void { /* ... */ }
    
      public function getData ( ) : Data
      {
        return $this->data;
      }
    }
    

    lgmb

    --
    Sprachstörung
    1. Tach!

      • gegeben sind n konkrete Child-Class(es) mit der Benennung ConcreteConstruct die nur einer __construkt()-Methode enthält.

      Eigentlich ist ein konkretes Problem gegeben, aber das ist in deinem Konstrukt nicht zu erkennen. Es sieht nach wie vor so aus, als ob du dich mit der Architektur von mit sich selbst beschäftigtem Code befasst, statt mit Programmieren von Code für den Anwendungsfall. Es fällt deshalb schwer zu beurteilen, ob das was du machst zielführend ist oder es bessere Lösungswege gibt.

      dedlfix.

      1. moin,

        Tach!

        • gegeben sind n konkrete Child-Class(es) mit der Benennung ConcreteConstruct die nur einer __construkt()-Methode enthält.

        Eigentlich ist ein konkretes Problem gegeben, aber das ist in deinem Konstrukt nicht zu erkennen.

        ok. Ist nachvollziehbar.

        Es sieht nach wie vor so aus, als ob du dich mit der Architektur von mit sich selbst beschäftigtem Code befasst, statt mit Programmieren von Code für den Anwendungsfall.

        Das checke ich von hinten und vorn nicht.

        Es fällt deshalb schwer zu beurteilen, ob das was du machst zielführend ist oder es bessere Lösungswege gibt.

        Einleuchtend. Danke für deine Beurteilung. Das war für mich sehr hilfreich.

        lgmb

        --
        Sprachstörung
        1. Hallo MB,

          Es sieht nach wie vor so aus, als ob du dich mit der Architektur von mit sich selbst beschäftigtem Code befasst, statt mit Programmieren von Code für den Anwendungsfall.

          Das checke ich von hinten und vorn nicht.

          Was soll dein Programm später einmal können?

          Warum programmierst du es?

          Für dich zum Lernen?

          Für die Praxis?

          Bis demnächst
          Matthias

          --
          Du kannst das Projekt SELFHTML unterstützen,
          indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
          1. moin,

            Es sieht nach wie vor so aus, als ob du dich mit der Architektur von mit sich selbst beschäftigtem Code befasst, statt mit Programmieren von Code für den Anwendungsfall.

            Das checke ich von hinten und vorn nicht.

            Was soll dein Programm später einmal können?

            SQL generieren

            Warum programmierst du es?

            Meine Einleitungfrage+AWs und Ergänzung von @Rolf B

            Für dich zum Lernen?

            jepp, sowohl als Projekt und zum SQL Lernen.

            Für die Praxis?

            jepp, um mich zu profilieren

            lgmb

            --
            Sprachstörung
            1. Hallo MB,

              Für die Praxis?

              jepp, um mich zu profilieren

              Wenn ich @Rolf B und @dedlfix richtig verstehe, ist das für die Praxis nicht wirklich sinnvoll. Praxis heißt hier Webentwicklung.

              Bis demnächst
              Matthias

              --
              Du kannst das Projekt SELFHTML unterstützen,
              indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
              1. Hallo Matthias,

                möchtest Du damit sagen, dass der Thread für dieses Forum off-topic ist?

                Rolf

                --
                sumpsi - posui - obstruxi
                1. Hallo Rolf B,

                  möchtest Du damit sagen, dass der Thread für dieses Forum off-topic ist?

                  Nicht zwingend. Programmiertechnik gehört unbedingt dazu.

                  Ich vergleiche das mit der bei null beginnenden Neuentwicklung eines Programms wie PHP-MyAdmin, nur ohne My, sondern für alle möglichen DBMS.

                  Bis demnächst
                  Matthias

                  --
                  Du kannst das Projekt SELFHTML unterstützen,
                  indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
                  1. Hallo Matthias,

                    Nicht zwingend

                    Dann verstehe ich diesen Satz von Dir nicht:

                    Praxis heißt hier Webentwicklung.

                    Was willst Du uns damit sagen?

                    Rolf

                    --
                    sumpsi - posui - obstruxi
                    1. Hallo Rolf B,

                      Dann verstehe ich diesen Satz von Dir nicht:

                      Praxis heißt hier Webentwicklung.

                      Was willst Du uns damit sagen?

                      Ich schrieb

                      Wenn ich @Rolf B und @dedlfix richtig verstehe, ist das für die Praxis nicht wirklich sinnvoll. Praxis heißt hier Webentwicklung.

                      zu lesen als:

                      Wenn ich @Rolf B und @dedlfix richtig verstehe, ist das für die Webentwicklung nicht wirklich sinnvoll (weil es den Anwendungsfall nicht gibt).

                      nicht zu lesen als:

                      In diesem Forum beschäftigen wir uns ausschließlich mit Webentwicklung.

                      Beachte auch, dass da noch ein if dranhängt.

                      Bis demnächst
                      Matthias

                      --
                      Du kannst das Projekt SELFHTML unterstützen,
                      indem du bei Amazon-Einkäufen Amazon smile (Was ist das?) nutzt.
            2. Tach!

              Für die Praxis?

              jepp, um mich zu profilieren

              Für die Praxis braucht man Code, der einfach zu verstehen und damit auch einfach zu warten ist. Wenn du nur zeigen möchtest, dass du Patterns aufsetzen kannst, gehst du falsch an praxistaugliche Lösungen heran. Zudem sind Pattern kein Selbstzweck. Das Verwenden von Pattern-Namen in Bezeichnern ist auch nicht die beste Vorgehensweise. Der Leser muss erkennen, was der Code für die fachliche Aufgabenstellung bewirken soll, nicht welches Pattern da eingebaut ist. Du musst deinem Auftraggeber am Ende sagen können: "Ich habe das Problem gelöst" und nicht "Ich habe dieses und jenes Pattern eingesetzt." Von mir bekommst du für solchen Code keine Anerkennung, sondern nur ein Kopfschütteln, warum der so überaus komplex aufgebaut ist.

              dedlfix.

              1. moin,

                Für die Praxis?

                jepp, um mich zu profilieren

                Für die Praxis braucht man Code, der einfach zu verstehen und damit auch einfach zu warten ist.

                Das is mein Ziel

                Wenn du nur zeigen möchtest, dass du Patterns aufsetzen kannst, gehst du falsch an praxistaugliche Lösungen heran.

                Das will ich vermeiden

                Das Verwenden von Pattern-Namen in Bezeichnern ist auch nicht die beste Vorgehensweise. Der Leser muss erkennen, was der Code für die fachliche Aufgabenstellung bewirken soll, nicht welches Pattern da eingebaut ist.

                Das ist meine Absicht.

                Und es ist, denke ich, noch sinnvoller, wenn man das Pattern mit der Aufgabe der Klasse zusäzlich in den Klassennamen schreibt, wenn man ein Pattern realisieren möchten, weil es gerade sinnvoll, ist ein Pattern zu implementieren z.B. SQLSnippetMemento aus der Luft gegriffen. Wenn es für die Praxis - rein empirisch - eher hinderlich ist, lass ich es mit verwundetem Gesicht weg, eben weil ein anderer Programmierer, der GoF versiert ist, durch diese Klassenbezeichnung, weis, was am Bach ist, wenn er meinen Code analysiert.

                Von mir bekommst du für solchen Code keine Anerkennung, sondern nur ein Kopfschütteln, warum der so überaus komplex aufgebaut ist.

                Ok gut. Aber bedenke bitte, dass meine Arbeitsgedächtnis von Naturaus sehr begrenzt und es durch meinen Unfall, noch eingeschränkter ist. Ich bin auf Strukturen angewiesen. Wenn ich total "normal" (im Gemeinsinn) wäre, dann ist dein Kopfschüttel berechtigt. Nur ist das nicht der Fall.

                lgmb

                --
                Sprachstörung
    2. Die __construct-Parameter werden in der Initialisierung der ConcreteConstructor-Klasse verarbeitet.

      Du hast es immer noch nicht verstanden was ein Konstruktor macht.

      MFG

    3. Hallo MB,

      ich habe mir das jetzt fünfmal durchgelesen, aber es kommt mir doch arg verknotet vor, was Du da schreibst. Das meiste verstehe ich nicht.

      Abstraktion ist kein Selbstzweck, man muss schon etwas dadurch gewinnen. Da Du nur symbolischen Code zeigst, ist der Nutzen schwer zu erkennen und ich muss Dir einfach glauben, dass du ihn hast.

      Ich nehme an, dass deine ConcreteConstruct Klassen SQL Fragmente konstruieren. Vermutlich gibt's einen QueryConstruct, SelectConstruct, ein FromConstruct, ein TableReferenceConstruct, und vieles mehr. Diese Klassen solltest Du aber nicht zu sehr abstrahieren. Ein QueryConstruct braucht mehrere Abteilungen: Select, From, Where, GroupBy, Having und OrderBy. Ein Select besteht aus dem Keyword SELECT und einer Column-Liste. Im Falle von MS SQL Server auch noch aus einer TOP Klausel (welche bei MYSQL LIMIT heißt und nicht Teil der SELECT Klausel ist!). Eine Column-Liste besteht aus mehreren Column-Angaben, eine Column-Angabe besteht aus Inhalt und Alias, der Inhalt ist ein Spaltenname, eine Konstante oder eine Expression, etc etc.

      All das bildet einen Baum (Syntax-Tree) und ein Baum besteht grundsätzlich aus zwei Dingen: Knoten und Blätter. Ein Knoten hat Kinder (andere Knoten oder Blätter), ein Blatt nicht.

      Knoten kannst Du so implementieren, dass sie ganz einfach die SQL Fragmente ihrer Blätter verketten. Das wäre eine Funktionalität, die man im AbstractConstruct implementieren kann. Bei Blättern ist es anders, da muss jedes Blatt seine eigene Logik haben, wie es sein SQL Fragment erzeugt. Und diese Logik solltest Du in der Construct-Klasse des Blattes implementieren.

      Es gibt grundsätzlich zwei Ansätze. Einmal kann der Konstruktor die ganze Arbeit machen und das SQL Fragment des Knotens komplett zusammensetzen. Aber dann brauchst Du keine Klassen, das ist ein rein funktionaler Ansatz. Nachteil ist, dass Du die Generierung nicht validieren kannst. Die Teile eines SQL Statements haben Abhängigkeiten, z.B. Table Aliase, und bei einem funktionalen Ansatz kann das SELECT Statement nicht validieren, ob die Alias-Angaben der Columns in den Tables überhaupt vorkommen.

      Ein Objektorientierter Ansatz würde im ersten Schritt einen vollständigen Syntaxbaum konstruieren und die SQL Generierung als zweiten Schritt machen.

      Die Idee hier lautet Polymorphie; es gibt eine getSQL Methode (oder wie Du das nennst) in AbstractConstruct, die von Knotenklassen überschrieben werden kann, aber nicht muss. Blattklassen sollten sie überschreiben, weil sie nicht andere SQL Fragmente aggregieren, sondern aus dem Nichts erzeugen.

      Wenn man den Generator so baut, dann könnten sich einige deiner Probleme in Luft auflösen. Wenn Du ihn schon so gebaut hast und die Probleme trotzdem hast, dann übersehe ich sie bei meiner abstrakten Überlegung möglicherweise...

      Rolf

      --
      sumpsi - posui - obstruxi
      1. moin,

        ich habe mir das jetzt fünfmal durchgelesen, aber es kommt mir doch arg verknotet vor, was Du da schreibst. Das meiste verstehe ich nicht.

        Tu mir leid 😟.

        Abstraktion ist kein Selbstzweck, […] ich muss Dir einfach glauben, dass du ihn hast.

        Kannst du 😉

        Ich nehme an, dass deine ConcreteConstruct Klassen SQL Fragmente konstruieren. […] Blattklassen sollten sie überschreiben, weil sie nicht andere SQL Fragmente aggregieren, sondern aus dem Nichts erzeugen.

        Die Baumstruktur mit Blättern und Knoten habe ich schon entwickelt, und alles drum und drann und es ist so wie du vermutet hast.

        […]. Wenn man den Generator so baut, dann könnten sich einige deiner Probleme in Luft auflösen.

        Bin seit vorgestern dabei die Traits auszulösen durch deinen & euren Antrieb 😀. Danke Dir bzw. euch.

        Und ich bin echt Kleinkarriert, ich weis 😕. Teilweise ist das auch gut so aber es kann auch schaden.

        lgmb

        --
        Sprachstörung
        1. moin,

          Bin seit vorgestern dabei die Traits auszulösen durch deinen & euren Antrieb 😀.

          ups, ich meinte Traits durch Klassen intern einer Klasse aufzulösen.

          lgmb

          --
          Sprachstörung