Ankündigung

Einklappen
Keine Ankündigung bisher.

Clean Code

Einklappen
Das ist ein wichtiges Thema.
X
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Clean Code

    Hallo leute,

    einige kennen mich noch sicherlich, war eine längere Zeit inaktiv. Habe mich mehr auf meine Probleme als auf die Probleme andere PHP Entwickler konzentriert und dadurch ist jetzt ein Artikel von mir auf Sitepoint erschienen. Vielleicht kennen einige diese Quelle nicht, deshalb dachte ich, ich verlinke es hier, könnte ja für den einen oder anderen interessant sein.

    http://www.sitepoint.com/clean-code-...opment-in-php/

    ein wenig vorweg:
    Wieso sollte clean code architektur interessant sein?

    Jedes Projekt fängt mit kleinen script schnipsel an und wird im Laufe der Zeit erweitert, dabei werden oft im Script dinge mit Copy&Paste übertragen, irgendwann tauchen bugs im Code auf die bisher ungesehen waren, um diese Bugs zu beheben, geht man alle stellen durch und einige können übersehen werden, spätestens ab diesen Zeitpunkt denkt man über das Refactoring nach, doch jedes Rafactoring führt zu weiteren Bugs und irgendwann lässt man es ganz sein.

    Die Lösung dafür sind gute und solide tests. Nun gibt es auch Projekte die mit Frameworks umgesetzt sind, diese sind i.d.r. nicht einfach zu Testen da man vieles vom Framework mit testen muss, obwohl es nicht notwendig ist. Es werden DI Container initialisiert, routen werden aufgerufen, in den Controllern dann ORM um daten zu laden und am ende überprüft man ob ein bestimmter text im HTML Code gegeben ist, sobald sich was an der HTML Struktur verändert, schlagen die Tests fehl, zu dem werden die tests auch langsamer, hat man langsame und/oder fragile tests lässt man es sein überhaupt den code automatisiert zu testen, hat man es sein gelassen, kann man den Quellcode nicht refactorisieren, kann man den Quellcode nicht refactorisieren versinkt man im Chaos. Um schnelle und stabile tests schreiben zu können, muss man seine logik komplett von allem Trennen, darum geht es bei der Clean Code Architektur.

    wenn jemand rückfragen hat, einfach hier fragen

    LG BlackScorp

    apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp


  • #2
    Sehr lesenswert. Toller Artikel!
    Standards - Best Practices - AwesomePHP - Guideline für WebApps

    Kommentar


    • #3
      danke war sogar in dem newsletter von jetbrains http://blog.jetbrains.com/phpstorm/2...february-2016/ muss wohl weitere teile jetzt schreiben
      apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp

      Kommentar


      • #4
        Gratuliere zum Artikel! So wie ich es sehe hat Dich der Clean-Code-Virus nicht mehr losgelassen – finde ich gut

        The image above shows the different layers of the application. The inner layers do not know anything about the outer layers and they all communicate via interfaces.
        Der Kern der Aussage ist, dass Kopplung zwischen den Schichten ausschließlich zu den weiter zur Mitte liegenden Schichten bestehen darf, aber niemals zu den äußeren Schichten. Das entspricht übrigens auch dem Prinzip der sogenannten Zwiebelarchitektur. Die Geschäftsdomäne, hier die Entity-Schicht hat demnach als einzige Schicht keine Abhängigkeiten zu anderen Schichten. Die darüber liegende, nächste äußere Schicht, hier die Use-Cases-Schicht darf demnach nur von der Entities-Schicht abhängig sein, aber nicht von z.B. Gateways oder UI usw.

        Dieses Prinzip sehe ich leider bereits in der ViewEntriesUseCase-Klasse verletzt. Die Klasse gehört zum UseCase-Layer und ist von der Repository-Klasse und der ViewFactory abhängig. Das darf laut dem oben beschriebenen Prinzip, nicht sein, weil beide Layer (Gateways, UI) weiter außen angesiedelt sind. Es entsteht also eine unschöne direkte (falsch gerichtete) Abhängigkeit zwischen der Geschäftsdomäne und den Storage- sowie UI-Komponenten.

        PHP-Code:
        class ViewEntriesUseCase
        {
            
        /**
             * @var EntryRepository
             */
            
        private $entryRepository;
            
        /**
             * @var EntryViewFactory
             */
            
        private $entryViewFactory;

            
        /**
             * ViewEntriesUseCase constructor.
             * @param EntryRepository $entryRepository
             * @param EntryViewFactory $entryViewFactory
             */
            
        public function __construct(EntryRepository $entryRepositoryEntryViewFactory $entryViewFactory)
            {
                
        $this->entryRepository $entryRepository;
                
        $this->entryViewFactory $entryViewFactory;
            } 
        Wie siehst Du das?

        VG
        Jack
        -

        Kommentar


        • #5
          [MOD: Verschoben von Off-Topic]
          Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
          PHP.de Wissenssammlung | Kein Support per PN

          Kommentar


          • #6
            würde ich so nicht sagen, das usecase hat eine abhängigkeit zum interface wichtig ist dass die Entitiy nicht nach außen zum Controller gegeben wird oder kann man das Bild irgendwie anders interpretieren?

            http://i.stack.imgur.com/UpCvB.png
            apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp

            Kommentar


            • #7
              The inner layers do not know anything about the outer layers
              Die Aussage bezieht sich doch auf das folgende Clean-Code-Architecture Bild?

              Wenn eine Komponente aus einem inneren Ring sich Komponenten aus einem der äußeren Ringen bedient, dann besitzt diese Komponente zwangsläufig Kenntnis von diesen Komponenten und ist von diesen somit abhängig. Damit wird in Deiner UseCase-Beispielklasse der oben genannten Ansatz, aus meiner Sicht, ganz klar verletzt. Ob die Abhängigkeit zu einem Interface besteht oder zu einer konkreten Klasse, sagt nur etwas über die Art der Kopplung aus. Viel wichtiger ist jedoch, dass es diese Abhängigkeit, nach dem beschriebenen Ansatz, gar nicht geben dürfte.

              wichtig ist dass die Entitiy nicht nach außen zum Controller gegeben wird
              Wichtig ist, dass die Entity nicht vom Controller abhängig wird, also dass die Geschäftsdomäne den Controller nicht kennt. Eine umgekehrte Abhängigkeit, also die Abhängigkeit des Controllers von der Entity bzw. im Allgemeinen von der Geschäftslogik ist dagegen unvermeidbar.

              Natürlich bedeutet das nicht automatisch, dass der Controller unmittelbar mit Entities arbeiten muss oder sollte, aber er wird irgendwie, zumindest über irgendeine andere Komponente, den Kontakt zur Geschäftsdomäne herstellen müssen. Mann könnte dann zwar nicht mehr sagen, dass der Controller die Geschäftsdomäne kennt, aber er bleibt von der Geschäftsdomäne IMMER direkt oder indirekt abhängig, sozusagen mit der Geschäftsdomäne verdrahtet.

              Wenn der Controller also mit Entities arbeiten würde, dann bliebe die Geschäftsdomäne weiterhin vom Controller vollständig unabhängig, ergo hätte dies nicht zwangsläufig eine Verletzung des o.g. Prinzips zur Folge.

              VG
              Jack

              p.s.
              ich frage mich wo der Thread jetzt gelandet ist, nach dem er verschoben wurde? In PHP-Fortgeschrittene erscheint er zumindest bei mir nicht?
              -

              Kommentar


              • #8
                Zitat von jack88 Beitrag anzeigen
                p.s.
                ich frage mich wo der Thread jetzt gelandet ist, nach dem er verschoben wurde? In PHP-Fortgeschrittene erscheint er zumindest bei mir nicht?
                Sorry, hier in der Verschiebe-Liste gibt es 2 x "PHP-Fortgeschrittene" .. Werd ich intern melden. Sorry, sollte jetzt passen.


                Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
                PHP.de Wissenssammlung | Kein Support per PN

                Kommentar


                • #9
                  Also der Grüne bereich das sind konkrete implementierungen diese werden an den inneren kreis übergeben. das usecase kennt nicht die konkrete implementierungen, also hat es nicht direkt eine abhängigkeit nach oben. während der controller aber zb nur das UseCase kennt und auch aufruft hat der Controller eine abhängigkeit zum UseCase. Ich sehe da keine Verletzung das UseCase kennt nur interfaces keine konkreten implementierungen es ist loose gekoppelt, die interfaces gehören zu keinem kreis.

                  Hier noch mal vom original blog eintrag von Uncle Bob

                  "For example, consider that the use case needs to call the presenter. However, this call must not be direct because that would violate The Dependency Rule: No name in an outer circle can be mentioned by an inner circle. So we have the use case call an interface (Shown here as Use Case Output Port) in the inner circle, and have the presenter in the outer circle implement it." https://blog.8thlight.com/uncle-bob/...hitecture.html

                  Sprich die abhängigkeit ist durch konkrete implementierung definiert, nicht durch interfaces


                  "Wichtig ist, dass die Entity nicht vom Controller abhängig wird, also dass die Geschäftsdomäne den Controller nicht kennt. Eine umgekehrte Abhängigkeit, also die Abhängigkeit des Controllers von der Entity bzw. im Allgemeinen von der Geschäftslogik ist dagegen unvermeidbar."

                  Die abhängigkeit zwischen controllern und entities ist auch nicht gegeben, controller kennt nur usecases, das usecase intern holt sich kurzfristig daten vom entity baut views und erzeugt ein ViewDto welches an den controller geliefert wird. der controller kennt keine Entities keine Repositories er kennt nur usecase und request/response objekte

                  ich sehe den thread auch nur durch die suche
                  apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp

                  Kommentar


                  • #10
                    Zitat von BlackScorp Beitrag anzeigen
                    Die abhängigkeit zwischen controllern und entities ist auch nicht gegeben, controller kennt nur usecases, das usecase intern holt sich kurzfristig daten vom entity baut views und erzeugt ein ViewDto welches an den controller geliefert wird. der controller kennt keine Entities keine Repositories er kennt nur usecase und request/response objekte
                    Das Routing über UseCases kann man machen. Ist aber kein Muss. Man kann in einem Controller auch direkt mit einem DAO sprechen. Kommt auf die Anwendung an. Gerade in kleineren Anwendungen muss man Dinge nicht unnötig kompliziert machen. Genau so kann es aber sein, dass in einer größeren Anwendung die Schicht Usecases nicht mehr reicht und man kleinteilige UseCases wieder zu größeren Usecases zusammenfassen möchte. Irgendwo sind UseCases ja auch nur Controller.

                    Wozu sollte ich etwas über ein Request-Object routen, wenn eine Methode in PHP Parameter hat?
                    Wozu sollte ich etwas in ein Response-Object wrappen, wenn eine Methode in PHP ein return-Statement hat?

                    Was mich hier etwas stört, ist die Betrachung, dass alles über ein Request- und ein Response-Object gehen sollte.

                    Was ist der tiefere Sinn hinter der Unterschiedung zwischen diesen beiden Varianten?

                    PHP-Code:
                    /**
                     * @param AddCommentRequest $request
                     * @param AddCommentResponse $response
                     */
                    function addComment(AddCommentRequest $requestAddCommentResponse $response) {
                        
                    $comment $request->getComment();
                        
                    $user $request->getUser();
                        
                    $commentId $this->comments->add(
                            
                    $this->comments->create()
                            ->
                    setUserId($user->getId())
                            ->
                    setBody($comment->getText())
                        );
                        
                    $response->setCommentId($commentId);

                    PHP-Code:
                    /**
                     * @param Comment $comment
                     * @param User $user
                     * @return int Comment Id
                     */
                    function addComment(Comment $commentUser $user) {
                        return 
                    $this->comments->add(
                            
                    $this->comments->create()
                            ->
                    setUserId($user->getId())
                            ->
                    setBody($comment->getText())
                        );


                    Standards - Best Practices - AwesomePHP - Guideline für WebApps

                    Kommentar


                    • #11
                      Zitat von rkr Beitrag anzeigen

                      Das Routing über UseCases kann man machen. Ist aber kein Muss. Man kann in einem Controller auch direkt mit einem DAO sprechen. Kommt auf die Anwendung an. Gerade in kleineren Anwendungen muss man Dinge nicht unnötig kompliziert machen.
                      Ich sehe den Prozess als wichtig an, weil wenn du in einem Feature Meeting sitzt und dein Cheff/Kunde erklärt was er möchte, denkst du automatisch dann in den UseCase blöcken, ist egal wie groß/klein die Anwendung ist. Durch diese UseCase aufteilung hast du zusätlich schon Tasks für den Scrum Board, außerdem hast du nach einer weile eine Routine eingebaut, und Routinen kann man automatisieren. Ein netter nebeneffekt, weil man teilweise immer wieder neue UseCases erstellt, fühlen sich features wie Greenfield projects an, weil du immer in einer Eigenständigen sauberen klasse arbeitest. Wenn man außerdem die UseCases weglässt, wie will man dann tests schreiben? dann muss man ja beim Testen das Routing des Frameworks mit testen.


                      Zitat von rkr Beitrag anzeigen
                      Genau so kann es aber sein, dass in einer größeren Anwendung die Schicht Usecases nicht mehr reicht und man kleinteilige UseCases wieder zu größeren Usecases zusammenfassen möchte. Irgendwo sind UseCases ja auch nur Controller.
                      Die UseCases packt man nicht zusammen zu einem Großen, ich mach das eher mit dem Command Bus pattern, du hast quasi eine ansamlung an usecases und kannst steuern wann was ausgeführt wird und ob überhaupt.

                      Zitat von rkr Beitrag anzeigen
                      Wozu sollte ich etwas über ein Request-Object routen, wenn eine Methode in PHP Parameter hat?
                      die paremeter können aus unterschiedlichen quellen kommen, ich habe usecases die ich sowohl im CLI als auch im web prozess ausführe
                      Zitat von rkr Beitrag anzeigen
                      Wozu sollte ich etwas in ein Response-Object wrappen, wenn eine Methode in PHP ein return-Statement hat?
                      der response kann auch auf CLI anders dargestellt werden als im web


                      Zitat von rkr Beitrag anzeigen
                      Was mich hier etwas stört, ist die Betrachung, dass alles über ein Request- und ein Response-Object gehen sollte.

                      Was ist der tiefere Sinn hinter der Unterschiedung zwischen diesen beiden Varianten?

                      PHP-Code:
                      /**
                      * @param AddCommentRequest $request
                      * @param AddCommentResponse $response
                      */
                      function addComment(AddCommentRequest $requestAddCommentResponse $response) {
                      $comment $request->getComment();
                      $user $request->getUser();
                      $commentId $this->comments->add(
                      $this->comments->create()
                      ->
                      setUserId($user->getId())
                      ->
                      setBody($comment->getText())
                      );
                      $response->setCommentId($commentId);

                      PHP-Code:
                      /**
                      * @param Comment $comment
                      * @param User $user
                      * @return int Comment Id
                      */
                      function addComment(Comment $commentUser $user) {
                      return 
                      $this->comments->add(
                      $this->comments->create()
                      ->
                      setUserId($user->getId())
                      ->
                      setBody($comment->getText())
                      );

                      ja hier hast du nur ein return wert, wie willst du aber die commentId anzeigen? das usecase weis nicht ob es in CLI oder im Web aufgerufen wird, desswegen schreibst du response->setCommentId bei der konkrete implementierung des Requests würdest du dann schreiben

                      PHP-Code:
                      public function setCommentId($commentId){
                      $this->Symfony2OutputInterface->writeLn('<fg=green>'.$commentId.'</fg=green>');

                      mit nem return statement hättest du da schwierigkeiten, die Request und Response objekte sind auch interfaces


                      apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp

                      Kommentar


                      • #12
                        aber wie kommst du drauf, dass durch die definierten abhängigkeiten im construktor, das usecase irgendwas vom controller weis,
                        Du hast mich missverstanden. Das UseCase weiß nichts vom Controller. Du hast in dem zweiten Post Controller ins Spiel gebracht und geschrieben, dass es wichtig ist, dass eine Entity nicht nach außen zum Controller gegeben wird.

                        ...wichtig ist dass die Entitiy nicht nach außen zum Controller gegeben wird...
                        Nur darauf bezog sich alles was ich zum Controller geschrieben habe. Die Controller sind an dieser Stelle ehrlich gesagt auch nicht weiter wichtig.

                        Wir sprechen hier ja ganz konkret über die auf dem Bild vorgestellte Architektur und die Prinzipien dahinter. Meine Kritik gilt an dieser Stelle ausschliesslich der ViewEntriesUseCase-Klasse, weil ich der Ansicht bin, dass diese die vorgestellten Architekturprinzipien verletzt.

                        Die UseCases auf dem Bild sind direkt bei den Entities angesiedelt und dürfen demnach nur Kenntnis von Entities haben. Die Richtung der Abhängigkeiten ist entscheidend und wird durch die Pfeile auf dem Bild fest vorgegeben (von außen nach innen). Du hast es selbst richtig geschrieben:

                        The inner layers do not know anything about the outer layers
                        Das Problem ist, dass die ViewEntriesUseCase-Klasse das Prinzip verletzt, weil sie auf Komponenten (ViewFactory + Repository) aus weiter außen liegenden Ringen zurückgreift.

                        VG
                        Jack

                        p.s.
                        @blackscorp
                        ich sehe gerade, daß sich Dein Post auf den ich mich hier beziehe inzwischen verändert hat... das erste Zitat steht nicht mehr drin und das Zitat von Uncle Bob war davor - glaub ich - auch nicht da...
                        -

                        Kommentar


                        • #13
                          Zitat von jack88 Beitrag anzeigen

                          Das Problem ist, dass die ViewEntriesUseCase-Klasse das Prinzip verletzt, weil sie auf Komponenten (ViewFactory + Repository) aus weiter außen liegenden Ringen zurückgreift.
                          "For example, consider that the use case needs to call the presenter. However, this call must not be direct because that would violate The Dependency Rule: No name in an outer circle can be mentioned by an inner circle. So we have the use case call an interface (Shown here as Use Case Output Port) in the inner circle, and have the presenter in the outer circle implement it." https://blog.8thlight.com/uncle-bob/...hitecture.html

                          Die Pfeile zeigen konkrete implementierung an, die usecases nutzen schon die interfaces von außen nur wissen die usecases nicht konkret was im hintergrund passiert
                          apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp

                          Kommentar


                          • #14
                            Zitat von BlackScorp Beitrag anzeigen
                            Wenn man außerdem die UseCases weglässt, wie will man dann tests schreiben? dann muss man ja beim Testen das Routing des Frameworks mit testen.
                            Ich spreche erst mal nur vom Wording. Du nennst die Dinger UseCases. Du kannst sie auch Controller nennen. Was ich meinte war, dass es in größeren Anwendungen mehr Ringe geben kann.

                            Zitat von BlackScorp Beitrag anzeigen
                            Die UseCases packt man nicht zusammen zu einem Großen, ich mach das eher mit dem Command Bus pattern, du hast quasi eine ansamlung an usecases und kannst steuern wann was ausgeführt wird und ob überhaupt.
                            Wie du das Kind nennst, sei dir überlassen. Abstrakt Gedacht läuft alles immer auf die Zusammenfassung von Detail-Schritten zu allgemeineren Schritten hinaus. Ob du das mit einer Command-Chain, oder mit einer direkt zusammenfassenden Methode machst, hängt vom Fall ab. Ich sehe hier keine universell anwendbare Methode.

                            Nehmen wir an, wir synchronisieren eine Bestellung zwischen einem Marktplatz und einem Warenwirtschaftssystem. Der UseCase lautet "Hole eine Bestellung ab und schreibe Sie in ein Fremdsystem".

                            Dieser UseCase verbindet jetzt ein generisches Repository-Interface, dass generische Bestelldaten zurückgibt und diese an ein generisches Repository schreibt. Also quasi ein Input-Repository und ein Output-Repository. Nach erfolgreichem Transfer muss dem Input-Repository mitgeteilt werden, unter welcher Nummer die Warenwirtschaft diese Bestellung führt, wodurch die Bestellung als Übertragen gilt. Der UseCase hat hier die Aufgabe, eine Liste von irgendwas irgendwohin zu spielen. Der Input muss nur eine Liste von irgendwas zurückgeben und eine Stellvertreternummer entgegennehmen können. Der Output muss nur eine Bestellung entgegennehmen und bei erfolgreicher Verarbeitung einer Stellvertreternummer entgegennehmen.

                            Kann ich so machen. Ich kann aber einen weiteren UseCase dazwischenschalten: Nimm genau eine Bestellung auf einem Input und gebe diese an einen Output weiter. Wenn das geklappt hat... Details siehe oben.

                            Heißt, dass ich erster UseCase statt der Abhängigkeit zu einem Input-Repository und einem Output-Repository die Abhängigkeit zu einem Input-Repository und einem zweiten UseCase bekommt.

                            Zitat von BlackScorp Beitrag anzeigen
                            die paremeter können aus unterschiedlichen quellen kommen, ich habe usecases die ich sowohl im CLI als auch im web prozess ausführe
                            Ist gegeben. Warum brauche ich dafür ein dediziertes Request-Objekt?

                            Zitat von BlackScorp Beitrag anzeigen
                            der response kann auch auf CLI anders dargestellt werden als im web
                            Ist gegeben. Warum brauche ich dafür ein dediziertes Response-Objekt?

                            Ich sehe absolut keinen Vorteil darin, alles noch mal wieder über Request- und Response-Objekte zu leiten. Es ergibt sich nicht mal ein theoretischer Vorteil. Dass ich statt vieler Parameter nur einen komplexen Parameter habe, macht nichts besser.

                            Die Parent-Schicht muss in dem einen Fall das Request-Objekt bestücken und das Response-Objekt verarbeiten. Würde es die Request- und Response-Objekte nicht geben, würden die Daten direkt an die jeweilige Methode gebunden.

                            Speziell zu Request-Objekten
                            Es entsteht sogar ein Nachteil, wenn ich über Request- und Response-Objekte gehe. Was ist, wenn ich eine Facette des Request-Objekts nicht mehr brauche? Das erkenne ich weder zur Design- noch zur Laufzeit. Das Objekt ist da, der Call, der das Objekt zu erzeugt, ist gemacht, aber die IDE sagt dir nicht, dass das sinnlos ist. Mathematisch gesehen, kann ich die Request-Objekte einfach aus der Gleichung rauskürzen - ohne Nachteile, jedoch mir verminderter Komplexität. Request-Objekte sind nüchtern betrachtet nur Wasserträger.

                            Speziell zu den Response-Objekten
                            Prinzipiell gilt hier das gleiche, wie bei den Request-Objekten. Der Unterschied hier ist jedoch, dass ein Response-Objekt ein Aktives Objekt sein kann. Beispielsweise ein Template-Renderer. Und davon weiß die Komponente, die dieses Response-Objekt als Parameter bekommen hat nichts. Sie weiß nur, wie man das Response-Objekt mit den jeweiligen Daten befüllt. In meinem Beispiel war das nur eine ID. Genau das, was ein Service-Objekt traditionell tut. Der Service kann auch komplexer sein - beispielsweise kann hier geprüft werden, ob es irgendwelche formellen Verstöße gibt, wegen denen der Kommentar nicht angelegt werden kann (zu lang, zu kurz, etc). Wenn ich nur eine ID eines Eintrags zurückgeben will, dann ist ein Response-Objekt viel zu aufwändig. Die ID ist sowohl im Web- als auch im Consolenkontext gleichbedeutend.

                            Das Response-Objekt an sich bringt wieder einen Nachteil mit, der dem nach Request-Objekten gleicht - nur diesmal direkt in der aktuell fokussierten Methode. Wenn ich hier zwei Methoden aufrufen muss, um meine Response-Daten zu vermitteln, dann merke ich nicht, wenn es irgendwann mal eine dritte gibt, die ich nicht befülle. Heißt, dass das Response-Objekt tendentiell nur eine Methode gaben darf, um den kompletten Response entgegenzunehmen (exakt das, was auch das return-Statement von dir verlangt).

                            Wenn das nun so ist, dann ist mein Response-Objekt eigentlich gleich-funktional mit einer ResponseFactory. Denn, wenn es nur eine Methode gibt, mit der ich meine Response-Daten setzen kann, dann ist es zunächst egal, ob diese Methode dann eine neue Version von sich selbst (Immutable), oder sich selbst zurückgibt (Mutable).

                            Wenn meine fokussierte Methode die Response-Daten nur mit dem Aufruf einer Methode zurückgeben können sollte, dann ist es zunächst mal egal, ob ich die Daten via return als Tuple, oder als Response-Objekt zurückgeben. In der darüberliegenden Schicht müssen die Daten sowieso neu vertütet werden.

                            Zitat von BlackScorp Beitrag anzeigen
                            ja hier hast du nur ein return wert, wie willst du aber die commentId anzeigen? das usecase weis nicht ob es in CLI oder im Web aufgerufen wird, desswegen schreibst du response->setCommentId bei der konkrete implementierung des Requests würdest du dann schreiben
                            Zitat von BlackScorp Beitrag anzeigen
                            mit nem return statement hättest du da schwierigkeiten, die Request und Response objekte sind auch interfaces
                            Verstehst du jetzt, was ich meine?

                            Standards - Best Practices - AwesomePHP - Guideline für WebApps

                            Kommentar


                            • #15
                              ich hatte das in der Tat früher so gemacht dass ich parameter übergeben habe, jetzt nicht so wie du wo konkrete objekte übergeben werden, denn dadurch muss ich ja in dem übergeordneten zirkel die objekte irgendwoher holen, im controller darf ich aber das nicht.

                              das problem war dass ich irgendwann eine große prozess methode hatte mit vielen parametern, teilweise hatten die parameter dann default werte damit ich diese nicht ständig übergeben musste.

                              dann habe ich dann das Request/Response model übernommen, so wie es auch im Bild beschrieben wird, input port und output port.

                              Jedes UseCase hatte seine eigene Request/Response klasse.

                              War auch soweit alles ok, bis ich dann schließlich die usecases zu einem übergeordneten usecase zusammen gebaut habe und die response werte von kind usecases and das eltern usecase übergeben habe. denn sobald dann irgendwie ein weiterer parameter dazu kam musste ich ersmtal herausfinden in was alles meine eltern usecases sind und dort dann die parameter nachpfelegen.

                              Aktuell ist es so, dass jeder Controller ein Request/Response objekt hat, dieses Request/Response objekt implementiert alle Request/Response interfaces die in dem Controller verwendet werden. Wenn ich irgendwann im UseCase eine weitere request methode brauche, lege ich diese im interface an und weis sofort wo ich sonst die einbauen muss, sonst gibts exceptions.

                              In der tat gibt es einen nachteil wenn ich wirklich kein Request oder kein Response brauche, diese aber dennoch einbinde, habe wirklich teilweise UseCases die leere Request Response interfaces haben. Damit kann ich aber leben da der Rest flexibel ist.


                              apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp

                              Kommentar

                              Lädt...
                              X