Ankündigung

Einklappen
Keine Ankündigung bisher.

Presenter in Clean Code Architektur

Einklappen

Neue Werbung 2019

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

  • Presenter in Clean Code Architektur

    Hallo leute,

    ich würde gerne mal in Erfahrung bringen wie ich korrekt den Presenter in der Clean Code Architektur verwenden kann.

    Folgendes Bild:


    Ich nutze an der Stelle den Begriff UseCase statt Interactor, um eine Verwirrung vorzubeugen.

    Ich habe Ursprünglich ein UseCase interface angelegt um zu definieren wie jedes UseCase auszusehen hat.

    PHP-Code:
    interface UseCase {
        public function 
    process(Request $request,Response $response);

    Meine konkreten UseCases hatten wiederum eine doProcess methode mit Konkreten Request/Response Typehint
    PHP-Code:
    class FooUseCase implements UseCase{
        public function 
    process(Request $request,Response $response){
           
    $this->doProcess($request,$response);
        }
        public function 
    doProcess(FooRequest $request,FooResponse $response){
            
    //Fancy magic
        
    }


    Natürlich musste man die FooRequests von den basis Requests ableiten damit das Funktioniert.

    Die Response Objekte habe ich von außen Injeziert damit ich diese je nach dem Welches Framework ich nutzen würde, dann konkret implementieren kann.

    Dann hat mir aber Anthony Ferrara(einige PHP Entwickler müssten ihn sicherlich kennen und wissen dass er doch ein erfahrener Entwickler ist) gesagt dass ich das so nicht machen darf. Und hat dabei auf folgenden Artikel verlinkt http://en.wikipedia.org/wiki/Covaria...ter_science%29 (Wobei ich das mit den Request/Responses aus Symfony Console application übernommen habe, dort ist es genauso definiert mit InputInterface und OutputInterface)

    Zusätzlich habe ich neulich die Mocking Videos von cleancoders.com angesehen und da war es Tatsächlich so, dass innerhalb des Interactors(bie mir UseCase) das Response Objekt erstellt wurde, dieser wurde dann an den Presenter übergeben.

    Also habe ich mir meine Struktur noch mal durch den Kopf gehen lassen und will jetzt genauso wie oben im Bild mit Presenter Arbeiten.

    Mein erster gedanke wäre, ich erstelle einen Presenter interface den ich in meine UseCases injeziere.

    PHP-Code:
    interface Presenter{
     public function 
    setResponse(Response $response);

    So kann ich dann zb ein MustachePresenter erstellen der dann das Response direkt Rendern kann.

    Aber dann habe ich folgendes gelesen
    http://blog.8thlight.com/uncle-bob/2...hitecture.html

    Interface Adapters

    The software in this layer is a set of adapters that convert data from the format most convenient for the use cases and entities, to the format most convenient for some external agency such as the Database or the Web. It is this layer, for example, that will wholly contain the MVC architecture of a GUI. The Presenters, Views, and Controllers all belong in here.
    Hier spricht er von Mehreren Presentern. Soll das etwa heißen dass ich Pro UseCase dann einen Eigenen Presenter erstellen muss? Oder eher Pro Output? Also ConsolePresenter, MustachePresenter ?

    Oder habe ich überhaupt alles Falsch verstanden? Bin aktuell ein Wenig verwirrt weil ich diese eine Zeile in dem Video gesehen habe + den Artikel mit Covariance gelesen habe(und nur Teilweise verstanden habe)

    Vielleicht kann mich ja einer hier aufklären?

    Viele Grüße
    apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp | Mein Youtube PHP Kanal: https://www.youtube.com/c/VitalijMik


  • #2
    hi BlackScorp,

    wenn ich ehrlich bin, bin ich mir nicht so ganz sicher, ob ich das verstanden habe

    Ich hätte das etwa so gemacht:
    man sollte vll eine Art AbstractMustachPresenter machen:
    dann sähe das so aus. Du hättest in deinem Clean Code Ding ein PresenterInterface:
    PHP-Code:
    interface PresenterInterface {
        public function 
    setResponse(Response $response);

    In deiner konkreten whatever Implementierung hättest du dann den AbstractMustachePresenter:
    PHP-Code:
    abstract class AbstractMustachePresenter {
        public function 
    setResponse(Response $response) {
            
    // ToDo: implement setResponse()
        
    }
        public function 
    render()
        {
            
    // ToDo: implement render()
            // diese Methode wäre FrameworkSpezifisch (das Interface weiß nix von nem UI -> also auch nix von ner render() Methode)
        
    }

        abstract public function 
    setTemplateName();

    da dein UseCase keine Templates kennt (independent of UI) weiß er nichts von einem Template Namen, der in deiner konkreten Klasse festgelegt wird.
    https://github.com/Ma27
    Javascript Logic is funny:
    [] + [] => "", [] + {} => object, {} + [] => 0, {} + {} => NaN

    Kommentar


    • #3
      Naja die Frage , die ich mir gerade Stelle:"Macht man das so überhaupt mit dem Presenter?"

      Ich stell mir gerade irgendwie ein Code ala

      PHP-Code:
      use Symfony\Component\HttpFoundation\Request;
      use 
      Symfony\Component\HttpFoundation\Response;
      class 
      AuthenticationController {

      public function 
      loginAction(Request $httpRequest){
      $request = new SymfonyLoginRequest($httpRequest);
      $presenter = new MustachePresenter('login.mustache');
      $this->loginUseCase->setPresenter($presenter);
      $this->loginUseCase->execute($request);
      $this->someOtherUseCase->setPresenter($presenter);
      $this->someOtherUseCase->execute($request);
      $this->anotherUseCase->setPresenter($presenter);
      $this->anotherUseCase->execute($request);
      return new 
      Response($presenter->getContent());

      }

      statt den Settern müsste ich wahrscheinlich ein PresenterAwareInterface erstellen und diesen dann in die UseCases implementieren. aber irgendwie sieht es nicht korrekt aus . Vielleicht dann über den Construktor in das UseCase injezieren mit einem DI Container? aber dann müsste ich für jede Action einen Presenter erstellen..

      ich glaube ich komme hier ohne Experemente nicht an mein Ziel
      apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp | Mein Youtube PHP Kanal: https://www.youtube.com/c/VitalijMik

      Kommentar


      • #4
        Naja, daß das hier ein NO-GO ist:

        PHP-Code:
        class FooUseCase implements UseCase
            public function 
        process(Request $request,Response $response){ 
               
        $this->doProcess($request,$response); 
            } 
            public function 
        doProcess(FooRequest $request,FooResponse $response){ 
                
        //Fancy magic 
            



        dürfte wohl klar sein. Indem die Klasse FooUseCase das UseCase-Interface implementiert soll sichergestellt werden dass FooUseCase über eine Methode process() verfügt, die Objekte vom Typ Request und Response akzeptiert. Diese Vereinbarung wird allerdings in der Methode selbst gleich wieder verletzt, weil tatsächlich nur Objekte vom Typ FooRequest und FooResponse verarbeitet werden können. So wie Du das Interface implementiert hast macht es keinen Sinn und führt einen nur in die Irre. Ich glaube, darauf zielt der Verweis auf den WIKI-Artikel ab.

        vg
        jack
        -

        Kommentar


        • #5
          also meine Idee war ja, eine Art UseCase Container zu bauen und ich wollte sicherstellen dass jeder UseCase auf jedenfall eine execute methode braucht mit dem Basis Request/Response interface, Konkrete UseCases jedoch sollen für die Konkrete Request/Responses implementieren.

          Die Idee war eine sehr allgemeine Version zu definieren und durch konkrete Implementierung, einschränkungen einbauen.

          Gut, dann lass ich das mal weg, Stattdessen erstelle ich das Response Objekt innerhalb des Usecases welches ich dann an den Presenter übergebe, jedoch bringt es weitere Probleme mit.

          Ich habe hier halt schön in meinem Projekt, Pro Controller ein eigenen Response und eigenen Request Objekt. Das Response und Request objekt implementiert alle Request/Response Interfaces der Usecases die in dem Controller aufgerufen werden.

          D.h. es gibt am Anfang ein fertiges Response Model und dieser wird von jedem Usecase nach und nach modifiziert und am ende einmalig durch ne Template engine gerendert.

          Presenter funktioniert irgendwie an der Stelle garnicht mehr
          apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp | Mein Youtube PHP Kanal: https://www.youtube.com/c/VitalijMik

          Kommentar


          • #6
            Gut, dann lass ich das mal weg, Stattdessen erstelle ich das Response Objekt innerhalb des Usecases welches ich dann an den Presenter übergebe, jedoch bringt es weitere Probleme mit.
            Die Kritik von Anthony Ferrara betrifft nicht das Response-Objekt, sondern daß Du ein Interface so nicht implementieren darfst. Das hat erst mal nichts mit der "Clean-Code-Architektur" zu tun. Das sind OOP-Grundlagen.

            vg
            jack
            -

            Kommentar


            • #7
              Das ist mit schon klar, aber basierend auf dieser Kritik habe ich jetzt noch das Gefühl dass da noch mehr schief gelaufen ist.

              Und ich würde jetzt nicht sagen dass Kovarianz und Kontravarianz zu den Grundlagen von OOP gehören.

              Ich habe da wohl gegen das L im SOLID verstoßen(Interface entfernen steht auf meiner TODO)
              apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp | Mein Youtube PHP Kanal: https://www.youtube.com/c/VitalijMik

              Kommentar


              • #8
                Zitat von jack88 Beitrag anzeigen
                Die Kritik von Anthony Ferrara betrifft nicht das Response-Objekt, sondern daß Du ein Interface so nicht implementieren darfst. Das hat erst mal nichts mit der "Clean-Code-Architektur" zu tun. Das sind OOP-Grundlagen.

                vg
                jack
                Anders funktioniert es in PHP aber nicht.

                PHP-Code:
                class BlaClassRequest implements FooRequestBlaBlaRequest {
                    
                // implementation
                }

                class 
                BlaClassResponse implements FooResponseBlaBlaResponse {
                    
                // implementation
                }

                class 
                FooUseCase implements UseCase {

                    public function 
                process(Request $requestResponse $response) {
                        
                $this->doProcess($request$response);
                    }

                    public function 
                doProcess(FooRequest $requestFooResponse $response) {
                        
                // do anything
                    
                }

                }

                $fooUseCase = new FooUseCase();
                $fooUseCase->process(new BlaClassRequest(), new BlaClassResponse()); 
                Das wäre so nicht möglich.

                Kommentar


                • #9
                  doch das wäre so möglich, mein UseCaseInterface ist einfach nur Fehl am Platz ich muss es so hinnehmen dass ein UseCase nicht zwangsläufig eine execute Methode haben soll

                  EDIT: also eher so

                  PHP-Code:
                  class BlaClassRequest implements FooRequestBlaBlaRequest {
                      
                  // implementation
                  }

                  class 
                  BlaClassResponse implements FooResponseBlaBlaResponse {
                      
                  // implementation
                  }

                  class 
                  FooUseCase //<-- kein implements

                      
                  public function process(FooRequest $requestFooResponse $response) {
                          
                  // do anything
                      
                  }

                  }

                  $fooUseCase = new FooUseCase();
                  $fooUseCase->process(new BlaClassRequest(), new BlaClassResponse()); 
                  apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp | Mein Youtube PHP Kanal: https://www.youtube.com/c/VitalijMik

                  Kommentar


                  • #10
                    Zitat von BlackScorp Beitrag anzeigen
                    doch das wäre so möglich, mein UseCaseInterface ist einfach nur Fehl am Platz ich muss es so hinnehmen dass ein UseCase nicht zwangsläufig eine execute Methode haben soll

                    EDIT: also eher so

                    PHP-Code:
                    class BlaClassRequest implements FooRequestBlaBlaRequest {
                        
                    // implementation
                    }

                    class 
                    BlaClassResponse implements FooResponseBlaBlaResponse {
                        
                    // implementation
                    }

                    class 
                    FooUseCase //<-- kein implements

                        
                    public function process(FooRequest $requestFooResponse $response) {
                            
                    // do anything
                        
                    }

                    }

                    $fooUseCase = new FooUseCase();
                    $fooUseCase->process(new BlaClassRequest(), new BlaClassResponse()); 
                    Stimmt, du hast Recht!

                    Kommentar


                    • #11
                      Und ich würde jetzt nicht sagen dass Kovarianz und Kontravarianz zu den Grundlagen von OOP gehören.
                      Das habe ich auch nicht gesagt Es ging mir nur darum „daß Du ein Interface so nicht implementieren darfst.“


                      PHP-Code:
                      Interface Xyz {
                          public function 
                      test(Foo $foo);
                      }

                      class 
                      Bar implements Xyz {

                          public function 
                      test(Foo $foo) {
                              if( !
                      is_a($foo'FooBar')) {
                                  throw new \
                      InvalidArgumentException();
                              }
                          }

                      Wenn Du dafür eine wissenschaftliche Erklärung benötigst, dann wirst Du Dich wahrscheinlich mit Kovarianz und Kontravarianz beschäftigen müssen – ich meine jedoch das sollte auch so klar sein

                      Vg
                      jack
                      -

                      Kommentar


                      • #12
                        naja so klar ist es ja nicht, in anderen Sprachen wie Java z.b. ist es durchaus möglich dinge wie Methodoverloading zu machen, damit kann man dann ein Interface mit Methode wie execute(Request request,Response response) definieren und in der Konkreten klasse dann wiederum eine weitere Methode definieren die genauso heißt nur andere Typen erwartet.

                        Wie gesagt, idee war eine art Interactor Stack zu bauen

                        PHP-Code:
                        foreach($interactors as $interactor){
                        $interactor->execute($request,$response);

                        für den Fall wollte ich eben sagen dass ein Interactor auf jeden fall eine execute methode haben muss, jedoch jeder interactor hat seinen eigenen Request/Response interface
                        apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp | Mein Youtube PHP Kanal: https://www.youtube.com/c/VitalijMik

                        Kommentar


                        • #13
                          Ich glaube, ich habe so eine Ahnung, wo ich ansetzen könnte. Kannst du vielleicht noch mal ein umfänglicheres Beispiel geben? Die explizite Festlegung auf bestimmte Subtypen macht dein Interface ja gerade weniger kompatibel zu unterschiedlichen (Framework-)Implementationen.
                          Ich bin aber ohnehin kein Freund von Response-Objekten und noch weniger von Request-Objekten . Vielleicht verstehe ich dann auch mal, wann es Sinn macht, mit solchen Objekten zu arbeiten, statt auf simple Parametertypen zu setzen.
                          Standards - Best Practices - AwesomePHP - Guideline für WebApps

                          Kommentar


                          • #14
                            Zitat von rkr Beitrag anzeigen
                            Ich glaube, ich habe so eine Ahnung, wo ich ansetzen könnte. Kannst du vielleicht noch mal ein umfänglicheres Beispiel geben? Die explizite Festlegung auf bestimmte Subtypen macht dein Interface ja gerade weniger kompatibel zu unterschiedlichen (Framework-)Implementationen.
                            Ich bin aber ohnehin kein Freund von Response-Objekten und noch weniger von Request-Objekten . Vielleicht verstehe ich dann auch mal, wann es Sinn macht, mit solchen Objekten zu arbeiten, statt auf simple Parametertypen zu setzen.
                            Die Interfaces sind nicht das Problem, ich habe es rausgehauen, mir gings es eher um die Umsetzung eines Presenters.

                            Hier mal ein Beispiel aus dem Aktuellen Testprojekt,

                            hier ist das UseCase
                            PHP-Code:

                            /**
                             * Class RegistrationUseCase
                             * @package Core\UseCase
                             */
                            class RegistrationUseCase
                            {
                                
                            /**
                                 * @var UserRepository
                                 */
                                
                            private $userRepository;
                                
                            /**
                                 * @var RegistrationValidator
                                 */
                                
                            private $validator;
                                
                            /**
                                 * @var PasswordHasher
                                 */
                                
                            private $passwordHasher;

                                
                            /**
                                 * @param UserRepository $userRepository
                                 * @param RegistrationValidator $validator
                                 * @param PasswordHasher $passwordHasher
                                 */
                                
                            public function __construct(
                                    
                            UserRepository $userRepository,
                                    
                            RegistrationValidator $validator,
                                    
                            PasswordHasher $passwordHasher
                                
                            ) {
                                    
                            $this->userRepository $userRepository;
                                    
                            $this->validator $validator;
                                    
                            $this->passwordHasher $passwordHasher;
                                }

                                
                            /**
                                 * @param RegistrationRequest $request
                                 */
                                
                            private function setValidatorValues(RegistrationRequest $request)
                                {
                                    
                            $this->validator->username $request->getUsername();
                                    
                            $this->validator->password $request->getPassword();
                                    
                            $this->validator->passwordConfirm $request->getPasswordConfirm();
                                    
                            $this->validator->email $request->getEmail();
                                    
                            $this->validator->emailConfirm $request->getEmailConfirm();
                                    
                            $this->validator->acceptedTerms $request->hasAcceptedTerms();
                                    
                            $this->validator->usernameExists = (bool)$this->userRepository->findByUsername($request->getUsername());
                                    
                            $this->validator->emailExists = (bool)$this->userRepository->findByEmail($request->getEmail());
                                }


                                
                            /**
                                 * @param  RegistrationResponse $response
                                 * @param  RegistrationRequest $request
                                 * @return void
                                 */
                                
                            public function process(RegistrationRequest $requestRegistrationResponse $response)
                                {
                                    
                            $response->setRegistrationRequest($request);
                                    
                            $this->setValidatorValues($request);

                                    if (!
                            $this->validator->isValid()) {
                                        
                            $response->addErrors($this->validator->getErrors());
                                        return;
                                    }
                                    
                            $this->createUser($request);
                                }

                                
                            /**
                                 * @param RegistrationRequest $request
                                 */
                                
                            private function createUser(RegistrationRequest $request)
                                {
                                    
                            $userId $this->userRepository->getUniqueId();
                                    
                            $passwordHash $this->passwordHasher->hash($request->getPassword());
                                    
                            $user $this->userRepository->create($userId$request->getUsername(), $passwordHash$request->getEmail());
                                    
                            $user->setRegistrationDate(new \DateTime());
                                    
                            $this->userRepository->add($user);
                                }

                            dazu die Request/Response interfaces
                            PHP-Code:

                            interface RegistrationRequest
                            {
                                
                            /**
                                 * @return boolean
                                 */
                                
                            public function hasAcceptedTerms();

                                
                            /**
                                 * @return string
                                 */
                                
                            public function getEmail();

                                
                            /**
                                 * @return string
                                 */
                                
                            public function getEmailConfirm();

                                
                            /**
                                 * @return string
                                 */
                                
                            public function getPassword();

                                
                            /**
                                 * @return string
                                 */
                                
                            public function getPasswordConfirm();

                                
                            /**
                                 * @return string
                                 */
                                
                            public function getUsername();
                            }

                            interface 
                            RegistrationResponse extends ErrorResponse
                            {
                                public function 
                            setRegistrationRequest(RegistrationRequest $request);

                            in meinem Fall nutze ich das Silex Framework also muss ich Request/Responses und die Abhängigkeiten die über den Construktor kommen dann für das Framework Implementieren.

                            Ich habe mehrere usecases an mein Controller übergeben so sieht das Ganze dann aus:
                            PHP-Code:

                            class AuthController
                            {
                                private 
                            $userRepository;
                                private 
                            $loginUseCase;
                                private 
                            $registrationUseCase;

                                public function 
                            __construct(
                                    
                            LoginUseCase $loginUseCase,
                                    
                            RegistrationUseCase $registrationUseCase,
                                    
                            WritableRepository $userRepository
                                
                            ) {
                                    
                            $this->loginUseCase $loginUseCase;
                                    
                            $this->userRepository $userRepository;
                                    
                            $this->registrationUseCase $registrationUseCase;
                                }


                                public function 
                            loginAction(Request $httpRequest)
                                {
                                    
                            $request = new AuthRequest($httpRequest);
                                    
                            $response = new AuthResponse('index');

                                    if (
                            $httpRequest->isMethod('POST')) {
                                        
                            $this->loginUseCase->process($request$response);

                                        if (!
                            $response->hasErrors()) {
                                            
                            $this->saveUsername($response->username$httpRequest);
                                            return new 
                            RedirectResponse('/game');
                                        }
                                    }

                                    return 
                            $response;
                                }

                                public function 
                            logoutAction(Request $httpRequest)
                                {
                                    
                            $session $httpRequest->getSession();
                                    
                            $session->remove('username');
                                    return new 
                            RedirectResponse('/');
                                }

                                public function 
                            registerAction(Request $httpRequest)
                                {
                                    
                            $request = new AuthRequest($httpRequest);
                                    
                            $response = new AuthResponse('register');

                                    if (
                            $httpRequest->isMethod('POST')) {
                                        
                            $this->registrationUseCase->process($request$response);
                                        if (!
                            $response->hasErrors()) {
                                            
                            $this->saveUsername($response->username$httpRequest);
                                            
                            $this->userRepository->sync();
                                            return new 
                            RedirectResponse('/game');
                                        }
                                    }
                                    return 
                            $response;
                                }

                                public function 
                            saveUsername($usernameRequest $request)
                                {
                                    
                            $session $request->getSession();
                                    
                            $session->set('username'$username);
                                }

                                public function 
                            isLoggedIn(Request $request)
                                {
                                    
                            $session $request->getSession();
                                    
                            $username $session->get('username');
                                    return (bool)
                            $username;
                                }

                            Ich habe also ein AuthController der Login und RegistrationUseCase benutzt und dafür sorgt dass das UserRepository die Daten Persistent hält(also mit der DB Syncronisiert/Speichert werte in DB)

                            Hier ist die Konkrete implementierung meines AuthRequests

                            PHP-Code:

                            class AuthRequest extends SFRequest implements LoginRequest,RegistrationRequest
                            {
                                
                            /**
                                 * @return boolean
                                 */
                                
                            public function hasAcceptedTerms()
                                {
                                    return (bool)
                            $this->getRequest()->get('toc');
                                }

                                
                            /**
                                 * @return string
                                 */
                                
                            public function getEmail()
                                {
                                    return 
                            $this->getRequest()->get('email');
                                }

                                
                            /**
                                 * @return string
                                 */
                                
                            public function getEmailConfirm()
                                {
                                    return 
                            $this->getRequest()->get('emailConfirm');
                                }

                                
                            /**
                                 * @return string
                                 */
                                
                            public function getPassword()
                                {
                                    return 
                            $this->getRequest()->get('password');
                                }

                                
                            /**
                                 * @return string
                                 */
                                
                            public function getPasswordConfirm()
                                {
                                    return 
                            $this->getRequest()->get('passwordConfirm');
                                }

                                
                            /**
                                 * @return string
                                 */
                                
                            public function getUsername()
                                {
                                    return 
                            $this->getRequest()->get('username');
                                }

                            ich habe noch eine klasse SFRequest erstellt, damit ich ableiten kann und nicht immer den konstruktor definieren muss

                            PHP-Code:
                            use Symfony\Component\HttpFoundation\Request;

                            class 
                            SFRequest
                            {
                                private 
                            $request;
                                public function 
                            __construct(Request $request)
                                {
                                    
                            $this->request $request;
                                }

                                
                            /**
                                 * @return Request
                                 */
                                
                            public function getRequest()
                                {
                                    return 
                            $this->request;
                                }

                            Also im Controller kann man es wunderbar sehen. wenn ich weitere Usecases benutzen will muss das Request/Response objekt die Request/Response interfaces des usecases implementieren.

                            Nach dem die Action des Konstruktors ausgeführt wurde, nehme ich den Response objekt und rendere es mit der Template engine.

                            PHP-Code:
                            use Symfony\Component\EventDispatcher\EventSubscriberInterface;
                            use 
                            Symfony\Component\HttpKernel\Event\FilterResponseEvent;
                            use 
                            Symfony\Component\HttpKernel\KernelEvents;
                            use 
                            Mustache_Engine;

                            class 
                            MustacheListener implements EventSubscriberInterface
                            {
                                private 
                            $mustache;
                                public function 
                            __construct(Mustache_Engine $mustache)
                                {
                                    
                            $this->mustache $mustache;
                                }
                                public function 
                            onResponse(FilterResponseEvent $event)
                                {
                                    
                            $request $event->getRequest();
                                    
                            $response $event->getResponse();
                                    if (
                            $response instanceof MustacheResponse) {
                                        
                            $content $this->mustache->render($response->getTemplate(), $response);
                                        
                            $response->setRequest($request);
                                        
                            $response->setContent($content);
                                    }

                                    
                            $event->setResponse($response);
                                }
                                public static function 
                            getSubscribedEvents()
                                {
                                    return array(
                                        
                            KernelEvents::RESPONSE => 'onResponse'
                                    
                            );
                                }

                            in anderen Frameworks die zb keine Events anbieten, würde ich das Rendering in after methode machen.

                            Ich habe dadurch die Möglichkeit UseCases in einer Reihe auszuführen, diese in anderen Frameworks wiederzuverwenden, diese Usecases mit Fake Objekten injezieren und schnell Testen usw.

                            Auch ist der Rote Faden total klar. es gibt actions in den Controllern, am anfang wird ein Request/Response objekt erstellt und nacheinander manipulieren die Usecases das Response objekt sowie anderen injezierte klassen.

                            Ein Presenter passt in mein konzept aktuell garnicht rein.

                            Die wichtigste Frage ist nun, ist mein Konzept total falsch und schlecht? ooder ein Presenter Bringt in PHP Garnichts und ist eigentlich für Sprachen wie C#/Java usw gemacht, bei denen man nicht bei jedem klick den Zustand der Software wiederhestellen muss sondern einfach nur die Events des Presenters triggern um daten zu aktualisieren.

                            Wenn es doch der erste Fall ist, was könnte man da Machen?
                            apt-get install npm -> npm install -g bower -> bower install <package> YOLO https://www.paypal.me/BlackScorp | Mein Youtube PHP Kanal: https://www.youtube.com/c/VitalijMik

                            Kommentar


                            • #15
                              Da ich im Moment sehr Javascript/AJAX/JSON-Lastig entwickle, kann ich mit diesem Ansatz ohnehin nicht viel anfangen. Für mich wäre der Aufwand für jede Aktion ein Request/Response-Objekt zu erzeugen schlicht zu hoch, bzw. zu wenig effizient. Für mich muss ein "UseCase" so aussehen:

                              PHP-Code:
                              <?php
                              /* ... */

                              class RegistrationUseCase {
                                  
                              /**
                                   * @var UserRepository
                                   */
                                  
                              private $userRepository;
                                  
                              /**
                                   * @var UserValidator
                                   */
                                  
                              private $userValidator;

                                  
                              /**
                                   * @param UserRepository $userRepository
                                   * @param UserValidator $userValidator
                                   */
                                  
                              public function __construct(UserRepository $userRepositoryUserValidator $userValidator) {
                                      
                              $this->userRepository $userRepository;
                                      
                              $this->userValidator $userValidator;
                                  }

                                  
                              /**
                                   * @param array $userData
                                   * @return array
                                   */
                                  
                              public function register(array $userData) {
                                      
                              $result $this->userValidator->validate($userData);
                                      if(
                              $result->isValid()) {
                                          
                              $id $this->userRepository->store($userData);
                                          
                              $userData $this->userRepository->fetch($id);
                                      }
                                      return [
                                          
                              'valid' => $result->isValid(),
                                          
                              'remarks' => $result->getRemarks(),
                                          
                              'data' => $userData
                                      
                              ];
                                  }
                              }
                              Parameter? Über die Route deklariert.
                              Constructor-Injektion? Autowiring.
                              Preprocessing? Über die Route deklariert.
                              Response-Type/Postprocessing? Über die Route deklariert.
                              Testability? Einfacher geht es nicht.

                              Mein Response könnte durchaus ein Objekt sein. Dann müsste ich daraus aber in vielen Fällen wieder ein Array machen. So rum ist es einfacher (wenngleich auch nicht sehr refactoring-safe) mit den Daten im Postprocessing zu arbeiten - in meinem Fall wird einfach nur ein json_encode darauf ausgeführt.
                              Standards - Best Practices - AwesomePHP - Guideline für WebApps

                              Kommentar

                              Lädt...
                              X