Introdução a Redux em Swift - Parte 1

Uma simples abordagem para aprender os primórdios de Redux em Swift.

Redux é a implementação de um padrão arquitetural de software que prioriza o fluxo de dados unidirecional. Foi criada a partir da arquitetura Flux (desenvolvida pelo Facebook), vem crescendo bastante no desenvolvimento de aplicações e promete grandes vantagens na sua utilização. Ela é uma alternativa a outros padrões arquiteturais como, por exemplo: MVC, MVVM, Viper e CleanSwift.

Vantagens

Uma das grandes promessas do Redux é criar restrições que incentivam um desenvolvimento de software mais organizado e mais fácil de testar, assim, por esses motivos, acaba diminuindo a complexidade na fase de desenvolvimento além de oferecer facilidades na manutenção do estado da aplicação e depuração avançada.

Esse artigo descreve uma abordagem simples para começar a entender este novo padrão.

Requisitos para a implementação

  • Nível básico na construção de aplicações em iOS (Swift + Xcode).
  • Conhecimento do padrão de projeto Observer.
  • Saber utilizar o sistema de dependências CocoaPods.

Componentes

O Redux é composto por um número de componentes, cada um com sua responsabilidade. São eles:

  • State: Representa o estado da aplicação. Deve existir apenas um, podendo este ser dividido em sub-estados.
  • Actions: São objetos simples que descrevem o que o sistema pode fazer. Esses objetos podem carregar informações ou não, dependendo do caso. Eles são despachados pela camada View como intenções de alterar o estado da aplicação.
  • Reducers: É aqui que desenvolvemos a lógica principal da aplicação. Reducers devem ser funções puras, sem efeitos colaterais e devem ser síncronos. São os únicos objetos que podem criar um novo estado para a aplicação. Eles recebem uma ação e o estado atual, e retornam um novo estado.

Vejam que o fluxo unidirecional acontece quando a View despacha uma Action. Essa Action é passada para o Reducer correspondente, então este Reducer gera um novo State de acordo com a Action passada, e o State é passado de volta para a View para que esta seja alterada.

  • Store: É um dos componentes mais importantes dessa implementação. É ela que agrega todos os componentes citados acima e faz o fluxo funcionar. A View despacha uma nova Action para a Store. A Store então, passa essa Action para o Reducer junto com o State atual e então recebe de volta o novo State do Reducer. A View é avisada sempre que um novo State é criado, isso é possível pela implementação do padrão de projeto Observer que permite que a View vire “assinante” da Store, para ser notificada.

Vamos começar

Minha abordagem para começarmos a aprender Redux é construir uma aplicação de exemplo — um jogo de “Pedra, Papel e Tesoura” — utilizando uma biblioteca chamada ReSwift que implementa os conceitos dessa arquitetura em Swift.

Começamos então fazendo um esboço de como deve ser a aplicação. Para simplificar, a aplicação deverá funcionar em um único ViewController, contendo 3 botões na parte inferior (Pedra, Papel e Tesoura), 1 campo de mensagem na parte superior e 2 placeholders para mostrar quando um jogador já realizou sua jogada e no final para revelar a arma dos jogadores.

Para começar o desenvolvimento, propus um caso de uso em que o Jogador1 escolhe Tesousa e o Jogador2 escolhe Pedra, resultando na vitória do Jogador2. Esse fluxo aconteceria da seguinte forma:

Desenvolvimento

Criamos um novo projeto no Xcode do tipo “Single view application” e habilitamos “Include Unit Tests” para podermos fazer um teste usando os conceitos de Redux.

Instale o pod “ReSwift”, utilizando CocoaPods.

Em seguida vamos criar o primeiro componente, o State. Observando as imagens acima, conseguimos perceber claramente as partes do app que irão se alterar durante a execução, cada parte desta consiste no estado da aplicação. Criei então um arquivo State.swift e dentro dele coloquei as estruturas que formam o estado, juntamente com possíveis estruturas de modelo que formam o conceito da aplicação. É importante salientar que as estruturas devem ser imutáveis para que o Redux funcione, só assim garantimos que o State seja alterado apenas pelos Reducers, por isso utilizei Structs e Enums ao invés de Classes:

Agora vamos criar uma Action, que será a descrição de uma ação que tem intenção de alterar o State. Neste caso temos apenas uma, ChooseWeaponAction, que é disparada quando cada jogador escolhe uma arma:

Por último vamos construir o Reducer, aqui nós filtramos a Action criada, pegamos o State atual da aplicação e geramos um novo State baseado na lógica que desenvolveremos com as informações contidas na Action:

Teste

Pronto, simples assim, nós implementamos um padrão Redux com fluxo unidirecional. Para mostrar a facilidade de testar esse tipo de arquitetura, construi esta classe de XCTest que testa lógicas da aplicação sem mesmo termos construído a UI (View).

Finalizando

Para finalizar, criei um ViewController com as características mostradas do desenho de esboço, e fiz esse ViewController se tornar um “assinante” da Store, podendo assim executar uma mudança nas views sempre que o State mudar. Isso acontece com a implementação do protocolo StoreSubscriber:

Créditos

Para se aprofundar no assunto


Acesse este projeto no Github. Deixe uma estrela no repositório, se puder. 😉

Click here to change the language of this article to English.

https://github.com/juliobertolacini