segunda-feira, 19 de novembro de 2018

Isso é MVP (Model-View-Presenter)? Reflexão e questões

Hum... Fiquei pensando em algumas coisas após ter terminado o tutorial (se é que é um tutorial :P) ...

Uma das coisas é colocar o "assincronismo" na parte "Model" da coisa.

Pensando bem, se é a tela do Android (por exemplo) que trava por causa da resposta do serviço, por que diabos tenho que colocar o "assincronismo" no lado do serviço?

Eu poderia resolver com alguma coisa assim, no lado da View:

this.startLoading();
this.callAsync(presenter.callLogin, (returned: Object) throws Exception -> {
       this.finishLoading();
      if (object is User) {
            ...
      } else if (object is Error) {
           ...
      }
});


E colocar o Model e o Presenter síncronos.

E por que pensei nisso? Por causa que nem todas as aplicações pedem coisas assíncronas (por exemplo, um serviço de API que, na teoria, ao receber uma requisição, não seria necessário executar o serviço assíncrono).

Mas, se em todo o caso, os serviços (Models) são assíncronos (seja por que foi pensado assim, ou esteja utilizando uma biblioteca assíncrona) e você estiver precisando usar em alguma coisa síncrona, dependendo da linguagem, é possível fazer algo assim:

public function onRequest(request: Request, response: Response) {
      ...
      presenter.callLogin();
     this.wait();
     if (this.user != null) {
          ...
    } else if (this.error != null) {
         ...
     }
     ...
}

public function onLogin(user: User) {
     this.user = user;
     this.notify();
     ...
}

public function onLoginFail(error: Error) {
      this.error = error;
      this.notify();
      ...
}


Tomara que, desta vez, eu tenha acertado! :P

Até mais!

sexta-feira, 16 de novembro de 2018

Isso é MVP (Model-View-Presenter)? Terceira (e acho que última) parte - Presenter

Como muita gente viu, eu arrumei a parte dois (realmente, fazer as coisas com pressa dá nisso...).

Vamos a última parte (eu acho), a implementação da classe Presenter.

Esta classe tem como característica juntar a parte View (da segunda parte deste artigo) com a Model (da primeira parte deste mesmo).

Então temos:

//Classe de Presenter que implementa a delegação do Modelo (ILoginModelDelegate) e da View (ILoginViewDelegate)
public class LoginPresenter implements ILoginModelDelegate, ILoginViewDelegate  {

         //Propriedades privadas
         private property model: ILoginModel;
         private property view: ILoginView;

         //Construtor da classe
         public constructor(view: ILoginView) {
                   //Cria o model através de uma Fábrica (Factory)
                  model = Factory::instance.getModel(ILoginModel.class);
                  model.delegate = this;
                  view.delegate = this;
         }

         //Função de login
         private function login() {
                  model.login(view.username, view.password);
        }

        @implementation
         public function onLoginSuccess(user: User) {
                  view.onLogin(user);
         }

         @implementation
         public function onLoginError(error: Error) {
                 view.onLoginFail(error);
         }

        @implementation
         public function callLogin() {
                 login();
         }
}

E, assim, temos a junção de tudo. Por exemplo, se fosse uma "página web":

public class LoginPageView: Page, ILoginView, OnClickListener {
       private property presenter: LoginPresenter;
       private property @UI okButton: UIButton;
       ...
       public constructor() {
              ...
              presenter = new LoginPresenter(this);
             okButton.setOnClickListener(this);
             ...
       }
      ...
       @implementation
       public function OnClick(sender: UIObject) {
              presenter.callLogin();
       }
       ....
}

Se fosse uma "Activity do Android":

public class LoginActivity: Activity, ILoginView, OnClickListener {

       private property presenter: LoginPresenter;
       private property okButton: Button;
       ...
       @override
       public function onCreate(savedInstanceState: Bundle) { 
              ...
              presenter = new LoginPresenter(this);
             okButton.setOnClickListener(this);
             ...
       }
      ...
       @implementation
       public function OnClick(sender: View) {
              ...
              presenter.callLogin();
              ...
       }
       ....
}

Ou se fosse um "serviço JSON":

public class LoginJSONView: JSON, ILoginView {

       private property presenter: LoginPresenter;
       ...
       public constructor { 
              ...
              presenter = new LoginPresenter(this);
             ...
       }
      ...
      @override
       public onPost(request: Request, response: Response) {
               ...
               presenter.callLogin();
              ...
       }
       ....
}

Acho que é isso... Se eu esquecer de alguma coisa, depois eu arrumo. (errar é humano, ainda mais depois dos 40... :P )

Até mais!