Ankündigung

Einklappen
Keine Ankündigung bisher.

Video Diskussion: Wieso man extends vermeiden sollte und was gibt es als alternative?

Einklappen

Neue Werbung 2019

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

  • #61
    Zitat von BlackScorp Beitrag anzeigen
    Ja nur das mit Team, es war halt aus dem Team heraus eine Erfahrung. Final soll auch mir selbst auf die Finger hauen und mich dazu zwingen zwei mal zu überlegen ob eine Vererbung notwendig ist.
    Für mich hat die Lesbarkeit & Wartbarkeit von Code einen sehr hohen Stellenwert. Traits stellen eine weitere Quelle an Funktionalität dar die ausschließlich von Klassen nutzbar ist. Ich als Entwickler muss diese beim Lesen von Code erfassen, verstehen und nachvollziehen. Bei Namenskollisionen muss ich Aliase anlegen, welche beim Lesen ebenfalls erfasst und zugeordnet werden müssen. Methoden die durch einen Trait importiert werden können zudem versehentlich überschrieben werden, was eine weitere Fehlerquelle darstellt oder zu unerwartetem Fehlverhalten führen kann. Auch Traits kann man falsch verwenden indem man gegen übliche Prinzipien verstößt. Sie schützen uns im Grunde also vor nichts, bringen aber eine eigene Funktionsweise, Komplexität und Risiken mit.

    Man kann Traits natürlich nutzen, sie sind schließlich Teil der Sprache, aber auch hier sollte man wissen was man tut.

    Zitat von BlackScorp Beitrag anzeigen
    Und der Letzte Punkt, ja mit Final nutze ich traits, wenn es gerade nicht anders geht, normalweise wird aber ein Objekt injeziert.
    Wenn Composition der übliche Weg ist den du gehst dann verstehe ich nicht so ganz wieso das Video final & traits so stark in den Mittelpunkt rückt. Composition statt Inheritance wäre als Kernaussage noch irgendwie nachvollziehbar, vor allem weil es auch für Einsteiger verständlich ist. Anfängern rate ich grundsätzlich erstmal von Vererbung ab, da man sie sehr leicht völlig falsch verwenden kann (User is a Database is a Controller is a Clown).

    Zitat von BlackScorp Beitrag anzeigen
    Im Team sieht man in einer meiner Klasse eine Methode X, diese Methode möchte man wiederverwenden, diese Kopiere ich dann in ein Trait und gebe das Trait weiter.
    Klingt für mich irgendwie konstruiert. Mich würden ganz konkrete Beispiele interessieren. Wenn eine Klasse eine Methode X beinhaltet die einfach so entnehmbar ist, dann braucht es diese Methode in der Klasse nicht (SRP). Wenn man also bereits Refactorting betreibt kann man diese Funktionalität direkt in eine eigene Klasse oder gar Funktion auslagern.

    Zitat von BlackScorp Beitrag anzeigen
    Ursprünglich sind meine Klassen ganz normal mit Final und Public/Private Methoden versehen, wenn etwas gebraucht wird, soll es nicht still und heimlich geschehen, sondern so dass ich das auch sehe/mitkriege.
    Als Entwickler bin *ich* dafür verantwortlich ob und wie ich eine Klasse ableite, insbesondere wenn ich dabei auf Implementierungsdetails zurückgreife. Du kehrst das quasi um und übernimmst die Verantwortung für alle Klassen die von deiner Klasse abgeleitet werden. Das mag zwar in eurem Team so notwendig sein, meiner Meinung nach sollte man aber genau hier ansetzen und das Team bei der Verwendung von Vererbung stärker schulen, klare Standards und Verantwortungen festlegen. Wenn man von einer Klasse nur die Public-API benötigt ist Composition ein gutes Werkzeug. Vererbung ist in den meisten Fällen auch überhaupt nicht notwendig.
    [SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]

    Kommentar


    • #62
      Zitat von lottikarotti Beitrag anzeigen
      Für mich hat die Lesbarkeit & Wartbarkeit von Code einen sehr hohen Stellenwert.
      Und für mich nicht? Ich schreibe lieber den Quellcode so, dass nur ich ihn verstehe um mein Arbeitsplatz zu sichern
      Zitat von lottikarotti Beitrag anzeigen
      Traits stellen eine weitere Quelle an Funktionalität dar die ausschließlich von Klassen nutzbar ist. Ich als Entwickler muss diese beim Lesen von Code erfassen, verstehen und nachvollziehen.
      Noch mal. ICH bereite eine Final Klasse vor, eine Methode aus der Klasse soll wiederverwendet werden, ICH will nicht dass meine Klasse abgeleitet wird, also "extrahiere" ich die notwendige Methode in ein Trait und gebe es dem Entwickler. ABER nur dann wenn die Ableitung kein Sinn macht.

      Zitat von lottikarotti Beitrag anzeigen
      Bei Namenskollisionen muss ich Aliase anlegen, welche beim Lesen ebenfalls erfasst und zugeordnet werden müssen.
      Ja, ist noch nicht vorgekommen
      Zitat von lottikarotti Beitrag anzeigen
      Methoden die durch einen Trait importiert werden können zudem versehentlich überschrieben werden, was eine weitere Fehlerquelle darstellt oder zu unerwartetem Fehlverhalten führen kann.
      Ja hat aber auc den vorteil dass man den Trait bei Bedarf überschreiben kann.

      Zitat von lottikarotti Beitrag anzeigen
      Auch Traits kann man falsch verwenden indem man gegen übliche Prinzipien verstößt. Sie schützen uns im Grunde also vor nichts, bringen aber eine eigene Funktionsweise, Komplexität und Risiken mit.
      Traits bringen eine Art "archivierung". Wenn du in einem Kleinen Team arbeitest, ein Feature X muss jetzt released werden, das Feature Y kann aber NOCH nicht jetzt released werden, da kannst du ein Fallback mit einem Trait erstellen um sicher zu stellen dass beides VORERST funktioniert und später kann man das Trait entfernen.


      Zitat von lottikarotti Beitrag anzeigen
      Wenn Composition der übliche Weg ist den du gehst dann verstehe ich nicht so ganz wieso das Video final & traits so stark in den Mittelpunkt rückt.
      weil du mit Final eben Inheritance unterdrücks und mit Traits eben doch Methoden zur Nutung anbietest. Es gibt nun mal Methoden die man wiederverwenden soll aber ohne Ableitung.


      Zitat von lottikarotti Beitrag anzeigen
      Composition statt Inheritance wäre als Kernaussage noch irgendwie nachvollziehbar, vor allem weil es auch für Einsteiger verständlich ist. Anfängern rate ich grundsätzlich erstmal von Vererbung ab, da man sie sehr leicht völlig falsch verwenden kann (User is a Database is a Controller is a Clown).
      Genau, wobei das nicht nur auf Anfänger zutrifft siehe Silex/PayPal Beispiele, desswegen gehe ich soweit und sage: "Egal ob Afänger oder nicht, lase die Vererung erstmal komplett weg und setze dir ein Riegel mit dem final ober drauf"

      Zitat von lottikarotti Beitrag anzeigen
      Klingt für mich irgendwie konstruiert. Mich würden ganz konkrete Beispiele interessieren. Wenn eine Klasse eine Methode X beinhaltet die einfach so entnehmbar ist, dann braucht es diese Methode in der Klasse nicht (SRP). Wenn man also bereits Refactorting betreibt kann man diese Funktionalität direkt in eine eigene Klasse oder gar Funktion auslagern.
      Einfach so war das nicht, ich musste schon mit der Methode noch weitere Eigenschaften "extahieren". In meinem Teil der Software habe ich auch einiges Refactored nur konnte ich nicht einfach Teile von einem Microservice von meinen Kollegen refactorend weil ich den Quellcode garnicht kenne und nicht weiß welche Auswirkungen meine Veränderung hätte.

      Zitat von lottikarotti Beitrag anzeigen
      Als Entwickler bin *ich* dafür verantwortlich ob und wie ich eine Klasse ableite, insbesondere wenn ich dabei auf Implementierungsdetails zurückgreife.
      Ja, aber dafür musst du die Zeit finden, und das ganze irgendwie in den Scrum implementieren.

      Zitat von lottikarotti Beitrag anzeigen
      Du kehrst das quasi um und übernimmst die Verantwortung für alle Klassen die von deiner Klasse abgeleitet werden.
      Im Gegenteil, ich unterbinde Vererbung meiner klassen und habe somit keine Verantwortung. Sobald ich sehe, dass eine Klasse bei mir final hat, kann ich die Anpassen wie es mir passt. Wenn ich sehe dass die klasse kein final hat, dann weiß ich dass diese Abgeleitet wird und ich kann dann vorher plannen und dann gucken ob ich die Klasse verändern kann und welche Auswirkung könnte es haben.

      Zitat von lottikarotti Beitrag anzeigen
      Das mag zwar in eurem Team so notwendig sein, meiner Meinung nach sollte man aber genau hier ansetzen und das Team bei der Verwendung von Vererbung stärker schulen,
      Oder man unterbindet Vererbung komplett.

      Zitat von lottikarotti Beitrag anzeigen
      klare Standards und Verantwortungen festlegen. Wenn man von einer Klasse nur die Public-API benötigt ist Composition ein gutes Werkzeug. Vererbung ist in den meisten Fällen auch überhaupt nicht notwendig.
      Ja da sind wir uns Einig.

      Es gab halt Vorfälle in der Vergangenheit, daraus habe ich Schlussfolgerung gezogen und Regeln aufstellt, diese habe ich in dem Video versucht zusammen zu fasst. Es muss halt was einfaches und simples sein. Ich habe zb in Storm mein Klassen Template umgeschrieben, jede Klasse wird direkt mit strict_types und final erstellt.

      Wenn ich eine Vorhandene Klasse anpassen muss, dann gucke ich ob da final drin steht, wenn ja, dann ist alles gut und ich muss nur auf public methoden achten.
      Wenn KEIN final drin ist, schaue ich nach in welchen Projekten die meine Klasse abgeleitet wird und frage dann den Zuständigen ob ich einfach so die Methode verändern kann.

      Sagt er "Ich habe keine Zeit" dann kommt Trait ins Spiel und ein TODO damit er es anpasst sobald ich Zeit habe.

      Ich nutze halt die Möglichkeiten von PHP damit eine Kommunikation zwischen Entwicklern entsteht, denn trotzt den Standup meetings werden Dinge "im Tunnel" schnell umgesetzt und keiner kriegt irgendwas mit

      apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

      Kommentar


      • #63
        Zitat von BlackScorp Beitrag anzeigen
        Und für mich nicht? Ich schreibe lieber den Quellcode so, dass nur ich ihn verstehe um mein Arbeitsplatz zu sichern
        Also findest du dass Traits die Lesbarkeit / Nachvollziehbarkeit von Code nicht negativ beeinflussen können oder gar zu einer Verbesserung führen?

        Hinweis: ich spreche in meinem Beitrag ja nur über mich und meinen persönlichen Eindruck bzw. versuche die Brücke zwischen meinen Motiven und meiner Kritik an Traits zu schlagen. Ich wollte dir da nichts unterstellen, sondern meine Kritik in Bezug auf das Video und die getroffenen Aussagen (so wie ich das verstanden und interpretiert habe) ausführlich äußern.

        Zitat von BlackScorp Beitrag anzeigen
        Noch mal. ICH bereite eine Final Klasse vor, eine Methode aus der Klasse soll wiederverwendet werden, ICH will nicht dass meine Klasse abgeleitet wird, also "extrahiere" ich die notwendige Methode in ein Trait und gebe es dem Entwickler. ABER nur dann wenn die Ableitung kein Sinn macht.
        Genau hier würde mich mal ein ganz konkretes Beispiel interessieren. Wenn einer meiner Entwickler eine Teilfunktion aus einer vorhandenen Klasse (die das SRP bricht) benötigt dann wird diese in eine eigene Klasse oder Funktion ausgelagert. Ob Vererbung möglich ist oder nicht hat mit dieser Entscheidung überhaupt nichts zu tun.

        Zitat von BlackScorp Beitrag anzeigen
        Ja, ist noch nicht vorgekommen
        Kann aber

        Zitat von BlackScorp Beitrag anzeigen
        Ja hat aber auc den vorteil dass man den Trait bei Bedarf überschreiben kann.
        Man muss also wissen was man tut?

        Zitat von BlackScorp Beitrag anzeigen
        Traits bringen eine Art "archivierung". Wenn du in einem Kleinen Team arbeitest, ein Feature X muss jetzt released werden, das Feature Y kann aber NOCH nicht jetzt released werden, da kannst du ein Fallback mit einem Trait erstellen um sicher zu stellen dass beides VORERST funktioniert und später kann man das Trait entfernen.
        Dieses Argument verstehe ich ehrlich gesagt nicht. Kannst du hierfür mal ein konkretes Beispiel liefern? Code ist ja grundsätzlich änderbar. Features vorbereiten oder entfernen kann ich ja nicht nur mit Traits.

        Zitat von BlackScorp Beitrag anzeigen
        weil du mit Final eben Inheritance unterdrücks und mit Traits eben doch Methoden zur Nutung anbietest. Es gibt nun mal Methoden die man wiederverwenden soll aber ohne Ableitung.
        Und das geht doch auch ganz gut mit Composition. Zudem lässt sich das Prinzip von Composition auch auf Sprachen übertragen die nicht über Traits verfügen.

        Zitat von BlackScorp Beitrag anzeigen
        Genau, wobei das nicht nur auf Anfänger zutrifft siehe Silex/PayPal Beispiele, desswegen gehe ich soweit und sage: "Egal ob Afänger oder nicht, lase die Vererung erstmal komplett weg und setze dir ein Riegel mit dem final ober drauf"
        Ich habe mich mit der Implementierung von Silex oder Paypal nicht weiter beschäftigt und kann diese daher auch nicht beurteilen. Deiner Empfehlung kann ich mich allerdings anschließen. final zur technischen Durchsetzung kann man machen, da habe ich prinzipiell kein Problem damit.

        Zitat von BlackScorp Beitrag anzeigen
        Einfach so war das nicht, ich musste schon mit der Methode noch weitere Eigenschaften "extahieren". In meinem Teil der Software habe ich auch einiges Refactored nur konnte ich nicht einfach Teile von einem Microservice von meinen Kollegen refactorend weil ich den Quellcode garnicht kenne und nicht weiß welche Auswirkungen meine Veränderung hätte.
        Du sprichst in deinen Beispielen immer von einer Methode. Jetzt kommen Eigenschaften dazu. Bietet sich eine eigenständige Klasse nicht genau dafür an?

        Zitat von BlackScorp Beitrag anzeigen
        Ja, aber dafür musst du die Zeit finden, und das ganze irgendwie in den Scrum implementieren.
        Ja, und?

        Zitat von BlackScorp Beitrag anzeigen
        Im Gegenteil, ich unterbinde Vererbung meiner klassen und habe somit keine Verantwortung. Sobald ich sehe, dass eine Klasse bei mir final hat, kann ich die Anpassen wie es mir passt. Wenn ich sehe dass die klasse kein final hat, dann weiß ich dass diese Abgeleitet wird und ich kann dann vorher plannen und dann gucken ob ich die Klasse verändern kann und welche Auswirkung könnte es haben.
        Der Lerneffekt ist doch deutlich einprägsamer wenn jemand schmerzlich erfährt dass man sich nicht auf Implementierungsdetails stützen sollte

        Zitat von BlackScorp Beitrag anzeigen
        Oder man unterbindet Vererbung komplett.
        Das tun wir bspw. indem wir Composition pauschal bevorzugen. Wenn sich irgendwo abzeichnet dass Vererbung sinnvoller sein könnte, dann wird darüber gesprochen.


        Zitat von BlackScorp Beitrag anzeigen
        Es gab halt Vorfälle in der Vergangenheit, daraus habe ich Schlussfolgerung gezogen und Regeln aufstellt, diese habe ich in dem Video versucht zusammen zu fasst. Es muss halt was einfaches und simples sein. Ich habe zb in Storm mein Klassen Template umgeschrieben, jede Klasse wird direkt mit strict_types und final erstellt.

        Wenn ich eine Vorhandene Klasse anpassen muss, dann gucke ich ob da final drin steht, wenn ja, dann ist alles gut und ich muss nur auf public methoden achten.
        Wenn KEIN final drin ist, schaue ich nach in welchen Projekten die meine Klasse abgeleitet wird und frage dann den Zuständigen ob ich einfach so die Methode verändern kann.

        Sagt er "Ich habe keine Zeit" dann kommt Trait ins Spiel und ein TODO damit er es anpasst sobald ich Zeit habe.

        Ich nutze halt die Möglichkeiten von PHP damit eine Kommunikation zwischen Entwicklern entsteht, denn trotzt den Standup meetings werden Dinge "im Tunnel" schnell umgesetzt und keiner kriegt irgendwas mit
        Das ist halt alles sehr subjektiv und spezifisch für deine Situation. Ob das nun ausreicht um daraus ein allgemein gültiges Argument für Traits zu drehen weiß ich nicht.
        [SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]

        Kommentar


        • #64
          Also ich finde dass Trait die Lesbarkeit teilweise verbessert. Ich habe zum Beispiel den LoggerAwareTrait von PSR ziemlich oft im Einsatz denn ich will nicht jedes Mal eine Logger Eigenschaft definieren und eine setLogger (außerdem ist es einfach nur eine Art Rauschen wenn man sich die Klasse dann anschaut mit setLogger). Man muss halt schon wissen was man für ein Trait implementiert.

          Zu meinen Konkreten Beispiel.

          Ich hatte eine Hydrator Klasse die ich einem Repository genutzt habe. Diese hat Werte aus der Datenbank erhalten um daraus dann ein Entity zu erzeugen.

          Mein Kollege hatte eine Join mit meiner Tabelle und nutzte da mein Hydrator Klasse, bzw leitete den Hydrator ab und nutzte dann Teile der Logik.

          Irgendwann bekam ich ein Feature und musste meine Tabelle erweitern und dementsprechend auch die Hydrator Klasse anpassen. Habe in meinem Projekt nachgeschaut wo ich die Klasse nutze und alles angepasst.
          Natürlich wusste ich nicht dass diese Klasse abgeleitet wurde. Die Anpasung führte zum Problem.

          Ich wusste nicht dass meine Klasse anderweitig Verwendet wurde, er wusste nicht dass ich die Klasse eventuell verändere. Im ersten Moment haben wir dann ein Trait verwendet damit die Methode zur Verfügung steht und wir erstmal so weiter machen können. Später haben wir das dann aber abgeändert durch einen "Service" also eine extra Klasse die nur diese eine Methode hat (und einige Eigenschaften).


          Ja und passt lässt sich das nicht einfach so sagen, man hat deadlines einzuhalten und nur wegen einer Methode hällt man jetzt kein Meeting ab, da wird schnell irgendwas gemacht und gelaunched.

          In meinem Video wollte ich den Trait als eine art "hack" bzw "zwischenlösung" anbieten, egal was hauptsache NICHT extends. Es ist halt vom Programmieraufwand, einfacher ein Trait zu schreiben und diesen via use Einzubinden als dann eine Klasse zu erzeugen, gegebenfalls in DI Container zu pushen dann die Stellen anpassen wo man die neue Klasse verwenden möchte damit das autowiring funktioniert.
          apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

          Kommentar


          • #65
            Nur eins noch, am Beispiel von Silex :
            Genau, wobei das nicht nur auf Anfänger zutrifft siehe Silex/PayPal Beispiele, desswegen gehe ich soweit und sage: "Egal ob Afänger oder nicht, lase die Vererung erstmal komplett weg und setze dir ein Riegel mit dem final ober drauf"
            Ich halte es für vermessen einem Entwicklern wie den Machern von Silex Ratschläge in Bezug auf Grundlagen zu geben.
            Bedenke bitte, erst wenn alle Reglen in Fleisch u nd Blut übergegangen sind, hat man die Reife diese zu brechen -- irgendwie so geht wohl das zitat.

            Kommentar


            • #66
              Zitat von BlackScorp Beitrag anzeigen
              Also ich finde dass Trait die Lesbarkeit teilweise verbessert. Ich habe zum Beispiel den LoggerAwareTrait von PSR ziemlich oft im Einsatz denn ich will nicht jedes Mal eine Logger Eigenschaft definieren und eine setLogger (außerdem ist es einfach nur eine Art Rauschen wenn man sich die Klasse dann anschaut mit setLogger). Man muss halt schon wissen was man für ein Trait implementiert.
              Ich persönlich nutze Setter-Injection nicht. Der LoggerAwareTrait zeigt ganz gut warum: wenn ich diesen nun in einer Klasse nutze muss ich vor der Verwendung von $logger prüfen ob auch ein Logger gesetzt wurde:

              PHP-Code:
              ...
              public function 
              foo(){
                if(
              $this->logger){
                  
              $this->logger->log(..);
                }

                ..

                if(
              $this->logger){
                  
              $this->logger->log(..);
                }
              }
              .. 
              Das könnte man natürlich alles in den Trait verfrachten aber dann ist der Trait nur ein Wrapper um den Logger und Composition somit deutlich simpler. Bei Setter-Injection (ist zwar ein ganz anderes Thema) muss man außerdem mit dem Fall umgehen dass sich das Objekt in einem nicht vertrauenswürdigen Zustand befinden kann weil bspw. Abhängigkeiten nicht injiziert wurden, was das Fehlerpotential erhöht und zu zusätzlichen Prüfungen zwingt.

              Das Beispiel überzeugt mich persönlich nicht.

              Zitat von BlackScorp Beitrag anzeigen
              Ich wusste nicht dass meine Klasse anderweitig Verwendet wurde, er wusste nicht dass ich die Klasse eventuell verändere. Im ersten Moment haben wir dann ein Trait verwendet damit die Methode zur Verfügung steht und wir erstmal so weiter machen können. Später haben wir das dann aber abgeändert durch einen "Service" also eine extra Klasse die nur diese eine Methode hat (und einige Eigenschaften).
              Klingt schon sehr speziell aber letztlich war die Lösung eine eigene Klasse. Der Trait war hier nur eine temporäre Notlösung wie ich das verstanden habe. Da fehlt mir einfach die sinnvolle Rechtfertigung für die Aussage "nutze traits statt extends". Und "hauptsache nicht extends" ist für mich eben kein Grund pauschal Traits zu empfehlen. Ansonsten müsste man schon auf die Details von Traits eingehen und erläutern wie diese funktionieren und worauf man achten muss.

              Zitat von BlackScorp Beitrag anzeigen
              Ja und passt lässt sich das nicht einfach so sagen, man hat deadlines einzuhalten und nur wegen einer Methode hällt man jetzt kein Meeting ab, da wird schnell irgendwas gemacht und gelaunched.
              Ein gesondertes Meeting muss ja nicht unbedingt sein. Man kann ja frei miteinander kommunizieren

              Zitat von BlackScorp Beitrag anzeigen
              In meinem Video wollte ich den Trait als eine art "hack" bzw "zwischenlösung" anbieten, egal was hauptsache NICHT extends. Es ist halt vom Programmieraufwand, einfacher ein Trait zu schreiben und diesen via use Einzubinden als dann eine Klasse zu erzeugen, gegebenfalls in DI Container zu pushen dann die Stellen anpassen wo man die neue Klasse verwenden möchte damit das autowiring funktioniert.
              Der Schreibaufwand scheint zwar geringer, meines Erachtens nach leidet am Ende aber die Lesbarkeit / Nachvollziehbarkeit, wenn auch nicht massiv. Wer Autowiring nutzt hat sowieso kein Problem mehr mit DI und kann einfach Constructor-Injection nutzen.
              [SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]

              Kommentar


              • #67
                Zitat von lottikarotti Beitrag anzeigen
                Ich persönlich nutze Setter-Injection nicht. Der LoggerAwareTrait zeigt ganz gut warum: wenn ich diesen nun in einer Klasse nutze muss ich vor der Verwendung von $logger prüfen ob auch ein Logger gesetzt wurde:

                PHP-Code:
                ...
                public function 
                foo(){
                if(
                $this->logger){
                $this->logger->log(..);
                }

                ..

                if(
                $this->logger){
                $this->logger->log(..);
                }
                }
                .. 
                Ja dafür gibt es den Nulllogger https://github.com/php-fig/log/blob/...NullLogger.php den setzt du einfach in deinem Konstruktor per Default. Dann brauchst du kein If. Es geht darum dass man in siner Klasse nicht explizit setLogger Methode schreibt, die ist dann schön ausgelagert. Du hast halt dann nicht mehr "Rauschen" in einer Klasse. Du weißt dass du loggen must, das siehst du an LoggerAwareInterface eine wietere Methode nerft da einfach nur rum

                Zitat von lottikarotti Beitrag anzeigen
                Das könnte man natürlich alles in den Trait verfrachten aber dann ist der Trait nur ein Wrapper um den Logger und Composition somit deutlich simpler. Bei Setter-Injection (ist zwar ein ganz anderes Thema) muss man außerdem mit dem Fall umgehen dass sich das Objekt in einem nicht vertrauenswürdigen Zustand befinden kann weil bspw. Abhängigkeiten nicht injiziert wurden, was das Fehlerpotential erhöht und zu zusätzlichen Prüfungen zwingt.

                Das Beispiel überzeugt mich persönlich nicht.
                NullObject pattern löst auch einige If statements auf


                Zitat von lottikarotti Beitrag anzeigen
                Klingt schon sehr speziell aber letztlich war die Lösung eine eigene Klasse. Der Trait war hier nur eine temporäre Notlösung wie ich das verstanden habe.
                Korrekt
                Zitat von lottikarotti Beitrag anzeigen
                Da fehlt mir einfach die sinnvolle Rechtfertigung für die Aussage "nutze traits statt extends". Und "hauptsache nicht extends" ist für mich eben kein Grund pauschal Traits zu empfehlen. Ansonsten müsste man schon auf die Details von Traits eingehen und erläutern wie diese funktionieren und worauf man achten muss.
                Naja die Rechfertigung ist: extends ist kompliziert und hat viele Nebenwirkungen, mit einem Trait hat man einen Quickfix den man im Zweifel nutzen sollte.

                Zitat von lottikarotti Beitrag anzeigen
                Ein gesondertes Meeting muss ja nicht unbedingt sein. Man kann ja frei miteinander kommunizieren
                Ja, ist nicht passiert, wenn man im "flow" ist, dann geht man den einfachsten Weg, man sieht eine Logik in der Klasse, denkt sich nichts dabei und schon hat man eine Ableitung drin.

                Zitat von lottikarotti Beitrag anzeigen
                Der Schreibaufwand scheint zwar geringer, meines Erachtens nach leidet am Ende aber die Lesbarkeit / Nachvollziehbarkeit, wenn auch nicht massiv.
                In Storm tippst du use und TraitNamen ein dann ALT+ Einfügen > Create class und copy paste von notwendigen Methoden/EIgenschaften whatever. Autoloading handled das dann. In einer Minute habe ich meine Logik publik gemacht und es kann benutzt werden.

                Zitat von lottikarotti Beitrag anzeigen
                Wer Autowiring nutzt hat sowieso kein Problem mehr mit DI und kann einfach Constructor-Injection nutzen.
                Autowire funktioniert auch nur bedingt und nicht immer. Da muss du dann in der COnfig Sachen eintellen etc. Wir nutzen auch PHP-DI und alles magisch und von alleine läuft da auch nicht
                apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

                Kommentar


                • #68
                  Zitat von BlackScorp Beitrag anzeigen
                  Ja dafür gibt es den Nulllogger https://github.com/php-fig/log/blob/...NullLogger.php den setzt du einfach in deinem Konstruktor per Default. Dann brauchst du kein If. Es geht darum dass man in siner Klasse nicht explizit setLogger Methode schreibt, die ist dann schön ausgelagert. Du hast halt dann nicht mehr "Rauschen" in einer Klasse. Du weißt dass du loggen must, das siehst du an LoggerAwareInterface eine wietere Methode nerft da einfach nur rum
                  Das sind Probleme die ich nicht in einer Klasse haben möchte. Wenn ich einen Logger im Konstruktor fordere dann brauche ich mir keine weiteren Gedanken darüber machen und auch keinen NullLogger erzeugen:

                  PHP-Code:
                  class Example{

                    public function 
                  __construct(LoggerInterface $logger){
                      
                  $this->logger $logger;
                    }

                    public function 
                  action(){
                      
                  $this->logger->log(..);
                      
                  // ..
                      
                  $this->logger->log(..);
                    }


                  Der Fall dass $logger null sein könnte existiert hier gar nicht, was die Klasse wiederum vereinfacht. Mehr "Rauschen" hast du damit auch nicht.

                  Zitat von BlackScorp Beitrag anzeigen
                  NullObject pattern löst auch einige If statements auf
                  Klar, aber die Lösung des Problems bzw. die Verantwortung mit diesem Fall umzugehen wird der Klasse aufs Auge gedrückt und muss auch bei jeder Klasse die so aufgebaut ist immer wieder berücksichtigt und umgesetzt werden.

                  Zitat von BlackScorp Beitrag anzeigen
                  Naja die Rechfertigung ist: extends ist kompliziert und hat viele Nebenwirkungen, mit einem Trait hat man einen Quickfix den man im Zweifel nutzen sollte.
                  Ich halte Vererbung mit extends nicht für sonderlich komplizierter als Traits, insbesondere wenn ich mir die Pitfalls ansehe die auch durch die Verwendung von Traits auftreten können (versehentliche overrides bspw.).

                  Zitat von BlackScorp Beitrag anzeigen
                  In Storm tippst du use und TraitNamen ein dann ALT+ Einfügen > Create class und copy paste von notwendigen Methoden/EIgenschaften whatever. Autoloading handled das dann. In einer Minute habe ich meine Logik publik gemacht und es kann benutzt werden.
                  Ist ja auch vollkommen ok. Aber das ist einfach eine spezifische Arbeitsweise die mit dem für oder gegen Vererbung erstmal gar nichts zu tun hat (da Vererbung mit extends ja auch nicht immer automatisch sinnvoll ist wenn Traits ggf. sinnvoll wären und umgekehrt).

                  Zitat von BlackScorp Beitrag anzeigen
                  Autowire funktioniert auch nur bedingt und nicht immer. Da muss du dann in der COnfig Sachen eintellen etc. Wir nutzen auch PHP-DI und alles magisch und von alleine läuft da auch nicht
                  Autowiring mit PHP-DI ist doch sehr explizit konfigurierbar. "Magic" ist daran eigentlich nichts. Klassen werden, sofern möglich automatisch (=basierend auf Autoloading) instanziiert. Wenn das nicht klappt dann liegt es daran dass PHP-DI weitere Informationen benötigt um die Klasse zu erzeugen. Wir halten uns sehr strikt an "Constructor-Injetion" und hatten bisher noch nie Probleme mit Autowiring. Nie.
                  [SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]

                  Kommentar


                  • #69
                    Versehentliche Overwrites lassen sich einfach beheben, einfach methode umändern. Habe ich aber aus Gründen meine Klasse bearbeitet und diese wird abgeleitet und ich weiß nichts davon ist das schon ein größeres Risiko.

                    versehentliche Overwrites sind bekannte unbekannte. Sobald du eine Methode erstellst, siehst du dass es zu konflikt führt.

                    Wenn ich meine Klasse aber verändere, kann es ja in sonst irgend einem Projekt via Composer installiert worden sein und eventuell sogar abgeleitet. Es ist eine Unbekannte Unbekannte, vieleicht wird auch die Klasse nirgends benutzt, ich weiß es zu dem Zeitpunkt wo ich die Klasse anpasse noch nicht.

                    Ist die Klasse aber mit final versehen, kann ich mir sicher sein dass da nichts gemacht wurde.

                    Ich sehe bei Traits halt keine Pitfalls.

                    Vor allem seit dem wir unseren Monolithen aufgeteilt haben in packages und jeder kann ein package via Composer nachinstallieren, hat man keinen Überglick mehr.


                    Ich lese halt hier immer wieder von erfahrenen entwicklern "So soll das sein" und dann gucke ich meine Projekte an und frage mich, bin ich hier der Blöde? Überall wo ich bisher dran gearbeitet habe wurden alle Projekte über Jahre hin irgendwie aufgebaut, irgendwas wurde drauf gepackt, irgendwas weggerissen, Teile sind historisch gewachsen, komplett wurde da nichts verändert. keine 100%ige Testabdeckung. Jede Veränderung tut weh und ist total kompliziert.

                    Ich kann mir halt beim besten willen nicht vorstellen dass nur ich das Problem haben.

                    Dann hätte ich mal am Anfang von meinem Video sagen sollen. "Habt ihr ein scheiß Code wo jede klasse von allem möglichen ableitet? Dann habe ich da ein Trick, macht alles Final und wenn jemand eure Methoden benötigt, gibt ihm ein Trait".

                    Hoffe jetzt verstehst du die Motivation hinter dem ganzen?


                    Klar kann man jetzt sagen "Korrekt wäre es, wenn man sich hinsetzt und überlegt wie soll die Architektur aussehen und dann arbeitet man schritt für schritt alles ab und macht alles schön" . Ich arbeite seit 2011 als PHP Entwickler, so ein Szenario hat es nie gegeben. Davor habe ich eine Ausbildung als C++ Entwickler gemacht, da wurden auch einfach eine weitere dll gebaut, diese in den Ordner Kompeliert und in die GUI eingebaut.


                    Desswegen war das eher an Anfängern gerichtiet, diese müssen meistens den Code ausbaden, besonders Junior devs, da kommst du in eine Agentur rein und kriegst dine Projekt zugeordnet mit einem Legacy code.

                    Fazit: Aus Erfahrung kann ich sagen, dass Vererbung dir Probleme bereitet weil du nie weißt wer was mit deinen Klassen anstellt. Traits hingegen lassen sich schnell erstellen ohne zu viel Config und Einstellungen und man kann diese bei Bedarf sogar überschreiben, außerdem können immer wiederkehrende methoden in ein Trait ausgelagert werden.

                    Wenn deine Codebasis es zulässt dass man alles schön machen kann mit eigenen Klassen und das auch noch schnell dann brauchst du nur wenige bis kaum Traits.

                    Ich bin hier im Forum seit Jahren aktiv und neben diesem Forum auch noch in Russisch sprachigen Forum unterwegs und ich sehe hier und dort Fragen mit Codeschnipsel und ich sehe dass diese nicht schön sind und keiner will es aufräumen, man möchte nur sein Problem schnell fixen mit möglichst wenig Pitfalls.


                    Desswegen bin ich halt so verwirrt über die gesammte Diskussionen hier im Forum, habt ihr Tatsächlich so eine Perfekte Codebasis wo es sofort klar ist, wenn ihr was verändert, welche Auswirkungen es hat? Seht ihr sofort die Probleme die in der Software dann auftauchen? Habt ihr keine Hacks drin wo es heißt "Später räumen wir auf"?

                    apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

                    Kommentar


                    • #70
                      Zitat von BlackScorp Beitrag anzeigen
                      Versehentliche Overwrites lassen sich einfach beheben, einfach methode umändern.
                      Und wenn ich ein Interface implementieren muss, welches diese Methode so vorgibt? Ist natürlich auch ein konstruiertes Beispiel, kann aber potentiell auftreten. Mit Composition nicht.

                      Zitat von BlackScorp Beitrag anzeigen
                      Habe ich aber aus Gründen meine Klasse bearbeitet und diese wird abgeleitet und ich weiß nichts davon ist das schon ein größeres Risiko.
                      Als Ersteller einer Klasse hat man meiner Meinung nach nur Verantwortung für die Public-API zu tragen. Änderungen an der Public-API sollten rückwärts-kompatibel sein oder unter einer neuen Major-Version released werden. Dass andere Entwickler Unfug treiben lässt sich ja nicht grundsätzlich vermeiden.

                      Zitat von BlackScorp Beitrag anzeigen
                      Wenn ich meine Klasse aber verändere, kann es ja in sonst irgend einem Projekt via Composer installiert worden sein und eventuell sogar abgeleitet. Es ist eine Unbekannte Unbekannte, vieleicht wird auch die Klasse nirgends benutzt, ich weiß es zu dem Zeitpunkt wo ich die Klasse anpasse noch nicht.
                      Als Maintainer eines Pakets garantiere ich dafür dass sich die Public-API im Rahmen einer Major-Version nicht verändert. Implementierungsdetails sind eben was sie sind: Implementierungsdetails. Wenn sich jemand auf diese stützt, dann geht er ganz bewusst ein Risiko ein. Wenn er nicht weiß dass er ein Risiko eingeht, dann sehe ich hier Schulungsbedarf.

                      Zitat von BlackScorp Beitrag anzeigen
                      Ist die Klasse aber mit final versehen, kann ich mir sicher sein dass da nichts gemacht wurde.
                      Frage zu final und phpunit: lassen sich mit final deklarierte Klassen einfach mocken?

                      Zitat von BlackScorp Beitrag anzeigen
                      Ich sehe bei Traits halt keine Pitfalls.
                      Unterm Strich sind die Mechaniken ähnlich wie bei Vererbung, dementsprechend sind die Probleme ähnlich. Es kann ja auch jemand deinen Trait in seine Klasse hängen und sich ebenfalls auf Implementierungsdetails stützen. Eine Änderung des Traits wird diese Klasse nun auch nicht überleben.

                      Zitat von BlackScorp Beitrag anzeigen
                      Vor allem seit dem wir unseren Monolithen aufgeteilt haben in packages und jeder kann ein package via Composer nachinstallieren, hat man keinen Überglick mehr.
                      Damit eine Codebase gut skaliert benötigt es Standards die konsequent umgesetzt und durchgesetzt werden. Wir machen dafür viele Code-Reviews und diskutieren regelmäßig über die Architektur unseres Systems und unserer Softwareprodukte. Eine stetige Entwicklung, zumindest mental, trägt schon viel zur Verbesserung bei.

                      Zitat von BlackScorp Beitrag anzeigen
                      Ich lese halt hier immer wieder von erfahrenen entwicklern "So soll das sein" und dann gucke ich meine Projekte an und frage mich, bin ich hier der Blöde? Überall wo ich bisher dran gearbeitet habe wurden alle Projekte über Jahre hin irgendwie aufgebaut, irgendwas wurde drauf gepackt, irgendwas weggerissen, Teile sind historisch gewachsen, komplett wurde da nichts verändert. keine 100%ige Testabdeckung. Jede Veränderung tut weh und ist total kompliziert.

                      Ich kann mir halt beim besten willen nicht vorstellen dass nur ich das Problem haben.
                      Solche Probleme haben sicherlich alle größeren Projekte. Die Frage ist nur wie man damit umgeht. Wir gehen gerne den direkten Weg und versuchen solche Probleme durch simple Standards zu lösen und durch regelmäßiges Refactoring durchzusetzen.

                      Zitat von BlackScorp Beitrag anzeigen
                      Dann hätte ich mal am Anfang von meinem Video sagen sollen. "Habt ihr ein scheiß Code wo jede klasse von allem möglichen ableitet? Dann habe ich da ein Trick, macht alles Final und wenn jemand eure Methoden benötigt, gibt ihm ein Trait".
                      Du machst das alles zu sehr an deiner Situation fest, es klingt manchmal sogar ein wenig emotional. Ich, und eventuell andere Forenmitglieder, betrachten das ganz sachlich aus der fachlichen Sicht. Mich interessiert eigentlich weniger wieso du das so handhabst sondern nur der rein fachliche Aspekt.

                      Zitat von BlackScorp Beitrag anzeigen
                      Desswegen war das eher an Anfängern gerichtiet, diese müssen meistens den Code ausbaden, besonders Junior devs, da kommst du in eine Agentur rein und kriegst dine Projekt zugeordnet mit einem Legacy code.
                      Das ist schon eine sehr konkrete Form von Anfängern.

                      Zitat von BlackScorp Beitrag anzeigen
                      Fazit: Aus Erfahrung kann ich sagen, dass Vererbung dir Probleme bereitet weil du nie weißt wer was mit deinen Klassen anstellt.
                      Das halte ich nicht für "mein" Problem sofern sich die Public-API nicht geändert hat. Wenn ein Entwickler meine Internals benötigt um sein Problem zu lösen dann ist meine Klasse eventuell problematisch.

                      Zitat von BlackScorp Beitrag anzeigen
                      Traits hingegen lassen sich schnell erstellen ohne zu viel Config und Einstellungen und man kann diese bei Bedarf sogar überschreiben, außerdem können immer wiederkehrende methoden in ein Trait ausgelagert werden.
                      Wenn wir hier mal beim Beispiel mit dem LoggerAwareTrait bleiben dann "konfigurierst" du den Trait doch auch indem du setLogger(..) im Konstruktor aufrufst. Die Konfiguration wird nur verlagert oder versteckt und ist im schlimmsten Fall sogar von außen unerreichbar.

                      Zitat von BlackScorp Beitrag anzeigen
                      Wenn deine Codebasis es zulässt dass man alles schön machen kann mit eigenen Klassen und das auch noch schnell dann brauchst du nur wenige bis kaum Traits.
                      Das klingt so als müsste die Codebase besondere Anforderungen erfüllen um mit Composition umgehen zu können. Im Softwarebereich ist Composition doch völlig normal. Mit "schön machen" hat das noch gar nichts zu tun.

                      Zitat von BlackScorp Beitrag anzeigen
                      Ich bin hier im Forum seit Jahren aktiv und neben diesem Forum auch noch in Russisch sprachigen Forum unterwegs und ich sehe hier und dort Fragen mit Codeschnipsel und ich sehe dass diese nicht schön sind und keiner will es aufräumen, man möchte nur sein Problem schnell fixen mit möglichst wenig Pitfalls.
                      Dann bietet sich doch die simple Lösung an wie in meinem Beispiel oben gezeigt

                      Zitat von BlackScorp Beitrag anzeigen
                      Desswegen bin ich halt so verwirrt über die gesammte Diskussionen hier im Forum, habt ihr Tatsächlich so eine Perfekte Codebasis wo es sofort klar ist, wenn ihr was verändert, welche Auswirkungen es hat? Seht ihr sofort die Probleme die in der Software dann auftauchen? Habt ihr keine Hacks drin wo es heißt "Später räumen wir auf"?
                      Klar hat jeder Leichen im Keller. Aber wir wollen ja nicht noch mehr Leichen anhäufen.

                      Da die Beiträge nun immer länger werden gehe ich weiter nur noch auf Punkte ein zu denen ich noch nichts gesagt habe. Ich denke im Großen und Ganzen habe ich meine Sichtweise recht ausführlich dargelegt. Wir müssen ja nicht einer Meinung sein
                      [SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]

                      Kommentar


                      • #71
                        Zitat von lottikarotti Beitrag anzeigen
                        Und wenn ich ein Interface implementieren muss, welches diese Methode so vorgibt? Ist natürlich auch ein konstruiertes Beispiel, kann aber potentiell auftreten. Mit Composition nicht.
                        Trait ist ja auch Composition


                        Zitat von lottikarotti Beitrag anzeigen
                        Als Maintainer eines Pakets garantiere ich dafür dass sich die Public-API im Rahmen einer Major-Version nicht verändert. Implementierungsdetails sind eben was sie sind: Implementierungsdetails. Wenn sich jemand auf diese stützt, dann geht er ganz bewusst ein Risiko ein. Wenn er nicht weiß dass er ein Risiko eingeht, dann sehe ich hier Schulungsbedarf.
                        Und die Schulung macht wer? und wer soll diese Bezahlen? Und macht eine Schulung nur dann Sinn wenn jemand auch was lernen will?

                        Zitat von lottikarotti Beitrag anzeigen
                        Frage zu final und phpunit: lassen sich mit final deklarierte Klassen einfach mocken?
                        Ja, ich nutze keine Mocking frameworks, phpunit lässt sich auch wunderbar ohne mockery ausführen

                        Zitat von lottikarotti Beitrag anzeigen
                        Unterm Strich sind die Mechaniken ähnlich wie bei Vererbung, dementsprechend sind die Probleme ähnlich. Es kann ja auch jemand deinen Trait in seine Klasse hängen und sich ebenfalls auf Implementierungsdetails stützen. Eine Änderung des Traits wird diese Klasse nun auch nicht überleben.
                        Ja, aber ein Trait lässt sich leicher Kopieren und als Temporär abspeichern quasi ein fallback bis man die Zeit hat das Problem richtig anzugehen

                        Zitat von lottikarotti Beitrag anzeigen
                        Damit eine Codebase gut skaliert benötigt es Standards die konsequent umgesetzt und durchgesetzt werden. Wir machen dafür viele Code-Reviews und diskutieren regelmäßig über die Architektur unseres Systems und unserer Softwareprodukte. Eine stetige Entwicklung, zumindest mental, trägt schon viel zur Verbesserung bei.
                        Ja das weiß ich, in der Theorie, habe noch nie sowas erleben dürfen.


                        Zitat von lottikarotti Beitrag anzeigen
                        Solche Probleme haben sicherlich alle größeren Projekte. Die Frage ist nur wie man damit umgeht. Wir gehen gerne den direkten Weg und versuchen solche Probleme durch simple Standards zu lösen und durch regelmäßiges Refactoring durchzusetzen.
                        Bisher bin ich sehr gut damit gelaufen dass ich einfach alles als final definiert habe.

                        Zitat von lottikarotti Beitrag anzeigen
                        Du machst das alles zu sehr an deiner Situation fest, es klingt manchmal sogar ein wenig emotional. Ich, und eventuell andere Forenmitglieder, betrachten das ganz sachlich aus der fachlichen Sicht. Mich interessiert eigentlich weniger wieso du das so handhabst sondern nur der rein fachliche Aspekt.
                        Naja ich muss es doch schon an meinen Erfahrung anknüpfen, ich kann ja auch nicht sagen "Das wäre schön wenn ihr das so und so macht". Ich sage es eher im Sinne "Wollt ihr probleme vermeiden, dann macht es so" sicherlich treffen diese Probleme nicht auf jeden zu, doch ich bin mir sicher, dass die Anzahl die der Entwickler auch signifikant ist.


                        Zitat von lottikarotti Beitrag anzeigen
                        Das halte ich nicht für "mein" Problem sofern sich die Public-API nicht geändert hat. Wenn ein Entwickler meine Internals benötigt um sein Problem zu lösen dann ist meine Klasse eventuell problematisch.
                        Jain, meistens kommt es ja aus dem Fall "ach ja der und der hat es mal so gemacht, guck mal nach, wir brauchen diese logik auch an der neuen Stelle". Klar ist es im ersten Moment mein Problem, sobald meine änderung jemanden betrifft, wird auch sein problem zu meinem.


                        Zitat von lottikarotti Beitrag anzeigen
                        Wenn wir hier mal beim Beispiel mit dem LoggerAwareTrait bleiben dann "konfigurierst" du den Trait doch auch indem du setLogger(..) im Konstruktor aufrufst. Die Konfiguration wird nur verlagert oder versteckt und ist im schlimmsten Fall sogar von außen unerreichbar.
                        Ne beim LoggerAwareTraits gehts wirklich nur darum, nicht jedes Mal setLogger Methode zu schreiben, der Trait ist eine Aushilfe für den LoggerAwareInterface

                        Zitat von lottikarotti Beitrag anzeigen
                        Das klingt so als müsste die Codebase besondere Anforderungen erfüllen um mit Composition umgehen zu können. Im Softwarebereich ist Composition doch völlig normal. Mit "schön machen" hat das noch gar nichts zu tun.
                        Naja doch, also erstmal grundlegend muss immer Autoloading da sein, dann brauchst du vernüftigen DI. Wenn du ein Mischmasch aus beiden hast, manchmal ohne DI manchmal mit dann ist es nicht mehr so einfach mal eine Klasse anzulegen und diese zu erzeugen usw..

                        Zitat von lottikarotti Beitrag anzeigen
                        Dann bietet sich doch die simple Lösung an wie in meinem Beispiel oben gezeigt
                        Ich kann halt auch nicht immer einfach den Constructor überschreiben, es gibt Klassen die ohne DI manuell erzeugt wurden (kleinere Code schnipsel die nichts direkt mit der Applikation zu tun haben), da ist es einfacher via Setter zu arbeiten oder eben LoggerInterface optional zu setzen und wenn logger null ist dann NUllLogger nutzen. Außerdem ist es wieder eine Änderung der Public API und wieder die diskussion wieso wurde der Constructor geändert.


                        Zitat von lottikarotti Beitrag anzeigen
                        Da die Beiträge nun immer länger werden gehe ich weiter nur noch auf Punkte ein zu denen ich noch nichts gesagt habe. Ich denke im Großen und Ganzen habe ich meine Sichtweise recht ausführlich dargelegt. Wir müssen ja nicht einer Meinung sein
                        Genau, ich bin eher auf der Seite wo man alles auf Final stellen sollte und alles von außen injezieren um sich sein Objekt zusammen zu setzen. Wenn man aber dennoch eine Quick und Dirty Lösung braucht, kann man Traits nutzen. Man sollte es temporär machen aber wir haben dennoch solche Traits seit mehreren Jahren im Code liegen. Ein Trait als Quick und Dirty Lösung ist besser als ein extends.

                        apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

                        Kommentar


                        • #72
                          Zitat von BlackScorp Beitrag anzeigen
                          Trait ist ja auch Composition
                          Auf Grund der Art und Weise wie Traits eine Klasse intern erweitern zählen sie für mich weniger zur klassischen Komposition. Für mich sind Traits das Türchen zur Mehrfachvererbung.

                          Zitat von BlackScorp Beitrag anzeigen
                          Naja ich muss es doch schon an meinen Erfahrung anknüpfen, ich kann ja auch nicht sagen "Das wäre schön wenn ihr das so und so macht". Ich sage es eher im Sinne "Wollt ihr probleme vermeiden, dann macht es so" sicherlich treffen diese Probleme nicht auf jeden zu, doch ich bin mir sicher, dass die Anzahl die der Entwickler auch signifikant ist.
                          Mir geht es im Grunde darum dass ich eine fachlich fundierte Argumentation bevorzuge. Ob irgendjemand irgendwas machen muss weil es bei ihm nicht anders geht ist für mich aus technischer Sicht vollkommen irrelevant.

                          Zitat von BlackScorp Beitrag anzeigen
                          Ich kann halt auch nicht immer einfach den Constructor überschreiben, es gibt Klassen die ohne DI manuell erzeugt wurden (kleinere Code schnipsel die nichts direkt mit der Applikation zu tun haben), da ist es einfacher via Setter zu arbeiten oder eben LoggerInterface optional zu setzen und wenn logger null ist dann NUllLogger nutzen. Außerdem ist es wieder eine Änderung der Public API und wieder die diskussion wieso wurde der Constructor geändert.
                          Das sind Kompromisse die der Situation geschuldet sind. In dieser Situation können Traits durchaus ein gangbarer Weg für euch sein. Es lassen sich aber auch viele andere Dinge situationsbedingt rechtfertigen, daher gilt das Argument für mich einfach nicht
                          [SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]

                          Kommentar


                          • #73
                            Zitat von lottikarotti Beitrag anzeigen
                            Auf Grund der Art und Weise wie Traits eine Klasse intern erweitern zählen sie für mich weniger zur klassischen Komposition. Für mich sind Traits das Türchen zur Mehrfachvererbung.
                            Würde ich nicht sagen, bei Mehrfachvererbung hast du das Problem das die Unterklassen noch weiter vererbt werden können und dann hast du eine große Hierarchie, bei Traits ist es nicht so, ein Trait ist eher eine Art Auslagerung des Codes. Als ob du einfach Bestandteile aus einer Klasse rausschneidest und in eine Externe Datei ablegst und diese Datei dann verwendest. Macht eventuell deine Klasse sogar schlanker. Zum Beispiel https://github.com/php-fig/log/blob/...oggerTrait.php damit kannst du deinen eigenen Logger implementieren mit NUR einer log methode, und weil das Interface ja von dir weitere Methoden verlangt, hast du die Wahl. Entweder alle Methoden in der Klasse selber anlegen oder eben den Trait nutzen.

                            Zitat von lottikarotti Beitrag anzeigen
                            Mir geht es im Grunde darum dass ich eine fachlich fundierte Argumentation bevorzuge. Ob irgendjemand irgendwas machen muss weil es bei ihm nicht anders geht ist für mich aus technischer Sicht vollkommen irrelevant.
                            Naja ich habe mehrere Blogs in dem Beitrag verlinkt wo viele Erfahrene Entwickler auch der meinung sind, man sollte Final per Default einstellen und ableitung vermeiden so weit es geht. In Programmiersprachen wie etwa Kotlin sind alle Klasse per default final und man muss extra diese zur Ableitung definieren.

                            Diese "Sperre" könnte aber dazu führen, dass einige Methoden einfach als Statisch definiert um diese aufzurufen. Da nutze ich lieber ein Trait.

                            Zitat von lottikarotti Beitrag anzeigen
                            Das sind Kompromisse die der Situation geschuldet sind. In dieser Situation können Traits durchaus ein gangbarer Weg für euch sein. Es lassen sich aber auch viele andere Dinge situationsbedingt rechtfertigen, daher gilt das Argument für mich einfach nicht
                            Ja aber du hast auch nicht die verlinken Artikel dir durchgelesen und mal die Erklärung von anderen dir durchgelesen und du hast dir da auch nicht gedanken gemacht dass es durchaus viele Fälle geben kann man wo zwischendurch eine Quick und Dirty Lösung bereitstellen muss. Ich kann auch nicht deine Meinung Teilen weil ich eben nicht mit einer durchgängig sauberer Codebasis gearbeitet habe mit einem Codereview und 80% Testcoverage. Ich kenne halt nur das zusammengesetzte Monster der aus vielen einzelteilen über Jahre zusammengesetzt wurde. Ich glaube auch nicht dass die Anfänger Gruppe sehr spezielle ist. In php ist es oft so, dass jemand ein Projekt startet mit wenig erfahrung, anschließend läuft das Projekt gut und es generiert Einnahmen für die Firma, dann werden die ersten Entwickler eingestellt, eventuell nur Junior und die müssen sich jetzt damit auch außeinander setzen.

                            Ich vermute in 20 Jahren wenn wir in unserem Schulsystem Informatik eingeführt haben, so dass man nach dem Abi schon alles das Kann was ein Anwendungsentwickler nach 3 Jahren gelernt hat, wird es noch mehr Entwickler geben die sich auf solche Projekte losgelassen werden. Und hier wird dann so eine Quick und Dirty Lösung durchaus hilfreich sein.
                            apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

                            Kommentar

                            Lädt...
                            X