Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Arquitetura para android

Arquitetura para android

Avatar for José Caique Oliveira

José Caique Oliveira

August 23, 2017
Tweet

More Decks by José Caique Oliveira

Other Decks in Programming

Transcript

  1. Agenda - Introdução - Problemas comuns no desenvolvimento - Arquitetura

    Limpa(Clean Architecture) - Dependências úteis
  2. No começo do aprendizado - Tudo na activity ou fragment

    - Pouca preocupação com organização - View Einstein - Não me chamo MainActivity atoa
  3. Arquitetura de software Como eu posso criar um projeto de

    forma a não ser xingado por quem pegar meu código?
  4. Arquitetura de software - Desacoplar o código - Passar a

    usar o framework ao invés de depender dele - Separar responsabilidades - Testabilidade - Manutenibilidade - Escalabilidade
  5. Desacoplando do framework - A view deve apenas exibir informações

    - Remover lógica da sua view - Remover acesso a banco de dados - Remover request
  6. Einstein Activity class EinsteinActivity: AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { showList() } fun showList() { retrofit.enqueue(object : Callback<Contacts> { override fun onResponse(call: Call<Contacts>, response: Response<Contacts>) { // exibe lista } override fun onFailure(call: Call<Contacts>, t: Throwable) { // exibe erro } }) } }
  7. Desacoplando do framework interface Contract { interface View { fun

    showContacts(contacts: ArrayList<Contacts>) fun showError(msg: String) } } class MainActivity : AppCompatActivity(), Contract.View { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } override fun showContacts(contacts: ArrayList<Contacts>) { //exibe lista } override fun showError(msg: String) { //mostra erro } }
  8. Desacoplando do framework interface Contract { interface View { fun

    showContacts(contacts: ArrayList<Contacts>) fun showError(msg: String) } interface Presenter { fun loadContacts() } } class Presenter : Contract.Presenter { override fun loadContacts(){ // faz algo aqui } }
  9. Modelos de arquitetura - MVP - MVVM - Viper -

    Clean Architecture - Hexagonal - ...
  10. Clean Architecture - Depender o mínimo possível de framework -

    Depender de comportamentos(interface) - Núcleo Testável
  11. Q?

  12. Domain - Regras de negócio - Entidades - Sabe executar

    uma operação - Dependência apenas da linguagem de programação usada
  13. interface PhotoRepository { fun photoUpload(string: String, callback: ResultCallback) } interface

    ResultCallback(){ fun success(result:String) fun 4xx() fun 5xx() fun timeOut() } data class User( val id: Int, val name: String, val email: String, val phone: String, val birthDate: Date, val photoUrl: String)
  14. Data - Entrada e saída de dados - Rest -

    Banco de dados - Cache - Deve ser fácil de substituir - Implementação dos contratos definidos pelo Domain(Repository)
  15. class PhotoManager : PhotoRepository { var photoService: PhotoService override fun

    photoUpload(string: String, callbackResult :ResultCallback){ photoService.upload(string).enqueue(object : Callback<String>{ override fun onResponse(call: Call<String>, response:Response<String>) { callbackResult.success(response.body()) } override fun onFailure(call: Call<String>, t: Throwable) { //trata erro e passa para callbackResult } }) } } interface PhotoRepository { fun photoUpload(string: String, callback: ResultCallback) } interface ResultCallback(){ fun success(result:String) fun 4xx() fun 5xx() fun timeOut() }
  16. Presentation Sabe como se comunicar com o domínio da aplicação

    Fornece os dados para o framework - Data formatada - Entrega tudo mastigado para a view só exibir
  17. class SearchPresenter() : SearchContract.Presenter { var useCase = SearchUseCase() var

    view: SearchContract.View override fun search(name: String) { useCase.execute(name,object : OnComplete { override fun success(result: String) { view.showSearch(result) } override fun error(t: Throwable) { view.showError(“msg”) } }) } } interface OnComplete { fun success(result: String) fun error(t: Throwable) }
  18. Establishment{ id = 123 address{ address = "R. Visconde", number

    = "414", state = "Rio de Janeiro", city = "Rio de Janeiro", district = "Ipanema", zip_code = "22410-002", latitude = 22.9837684, longitude = -43.2074878 } name = "Estabelecimento do bolinha" status : enum = [open, close] } Data Domain Presentation Establishment{ id = 123 address{ "address": "R. Visconde", "number": "414", "state": "Rio de Janeiro", "city": "Rio de Janeiro", "district": "Ipanema", "zip_code": "22410-002" } name = "Estabelecimento do bolinha" distance = 1400 status= true } Establishment{ id = 123 address=”Rua visconde, 414, Rio de janeiro - Rj” name = "Estabelecimento do bolinha" distance = 1,4Km status= “Aberto” }
  19. Passo a passo Defina uma interface para repository Defina seus

    casos de uso e suas entidades interface ResultCallback{ fun success(profile:Profile) fun 4xx() fun 5xx() fun error() } interface AuthenticationRepository{ fun login(credential: Credential, callback:ResultCallback) } class LoginUseCase(){ fun login(credentials: Credentials){ return authenticationRepository.login(credentials,callback) } } data class Profile(var name: String, var age : Int) data class Credential(var email: String, var password)
  20. Passo a passo Implemente seu repository interface Service { @Get(...)

    fun signIn(@Body credential: Credential): Call<ProfileResponse> } class AuthenticatorManager(): AuthenticationRepository{ val service : Service override fun login(credential,callback){ service.signIn(credential).enqueue( success(profileResponse){ callback.success(Mapper.toProfile(responsse)) } error(){ // controle o erro aqui }) } }
  21. Passo a passo Defina o contrato para View e Presenter

    interface Contract { inteface View(){ fun showProfile(profile: ProfilePresentation) } interface Presenter { fun attachView(view: View) fun login(email: String, password: String) } }
  22. Passo a passo Implemente o presenter inteface OnComplete{ fun onSuccess()

    fun onError() } class Presenter(loginUseCase: LoginUseCase): Contract.Presenter{ val view : View?=null override attachView(view : View){ this.view = view } override login(email: String, password : String){ loginUseCase.login(Credential(email,password),onComplete{ onSuccess(response){ view?.showProfile(Mapper.toProfilePresenter(response)) } onError(throwable : Throwable){ //trata erro aqui } }) }
  23. Passo a passo Implemente o contrato da View class ProfileFragment

    : Fragment(), Contract.View{ val presenter : Contract.Presenter ?= null override fun onViewCreated(....) { super.onViewCreated(....) presenter = Presenter(...) presenter.attachView(this) } override showProfile(profile: ProfilePresentation){ nameTextView.text = profile.name ageTextView.text = profile.age } override showErrorLogin(msg: String){ toast(msg) } @OnClick(R.id.loginButton) fun onClick(){ presenter.login(emailEditText.text.toString, passwordEditText.text.toString()) } }