Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
July 15, 2022 05:18 pm GMT

Arquitetura Limpa: Aplicando com React

Esse texto faz parte de uma srie de textos sobre anlise da Arquitetura Limpa aplicada com frameworks e linguagens distintas.

Os propsitos deste texto seguem alinhados com os do texto anterior, sendo eles: I. Mostrar uma diviso arquitetural de uma aplicao React usando Arquitetura Limpa; II. Guiar a implementao de novas features nesta arquitetura proposta.

Diviso Arquitetural

O passo inicial analisar como feita a diviso.

cypress/src/  data/    protocols/    test/    usecases/  domain/    errors/    models/    test/    usecases/  infra/    cache/    http/    test/  main/    adapters/    config/    decorators/    factories/      cache/      decorators/      http/      pages/      usecases/    routes/    scripts/    index.tsx  presentation/    assets/    components/    hooks/    pages/    protocols/    routes/    styles/    test/  requirements/  validation/    errors/    protocols/    test/    validators/

Em detalhes, o propsito de cada estrutura de arquivos o seguinte:

  • cypress: Contm os arquivos de teste end to end da aplicao (para projetos grandes, essa pasta comendvel que seja em um projeto a parte, para que o time responsvel pelos testes e2e cuide dele, uma vez que no precisa conhecer o cdigo do projeto).
  • src: Contm todos os arquivos necessrios para o sistema.
    • Data: A pasta data representa a camada de dados da Arquitetura Limpa, sendo dependente da camada de domnio. Contm as implementaes das regras de negcio que so declaradas no domain.
    • Domain: Representa a camada de domnio da Arquitetura Limpa, a camada mais interna da aplicao, no apresentando dependncia com nenhuma outra camada, onde contm as regras de negcio.
    • Infra: Essa pasta contm as implementaes referentes ao protocolo HTTP e ao cache, tambm nico local onde ter acesso a dependncias externas relacionadas para esses dois itens citados.
    • Main: Corresponde a camada principal da aplicao, ponto que ocorre a integrao das interfaces desenvolvidas na camada de UI, com as regras de negcio criadas nas pastas que representam as camadas mais internas da Arquitetura Limpa. Tudo isso se d devido ao uso de padres de projetos como Factory Method, Composite e Builder.
    • Presentation: Nesta pasta contm a parte visual da aplicao, com suas pginas, componentes, hooks, assets e estilizaes.
  • Requirements: Contm os requisitos do sistema documentados, essa pasta pode ou no ter todas as subpastas a seguir, depende muito de como o time trabalha.
  • Validation: Onde contm as implementaes das validaes utilizadas nos campos.

Diferente da abordagem com Flutter onde havia uma pasta central que se concentravam todos os testes, nessa abordagem os testes se encontram nas respectivas pastas dentro da src.

Guia de Implementao

Nesta seo ser descrita uma sequncia lgica recomendada para um melhor desempenho de implementao de sistemas React utilizando esta arquitetura.

Para finalidade de simplificar a explicao, no ser descrito em detalhes os testes unitrios. No entanto, fortemente recomendado comear pelos testes unitrios antes do desenvolvimento (TDD) de cada passo utilizando os requirements para embasar os cenrios. E aps finalizar os cenrios, fazer o teste end to end do fluxo (se for um dos principais, ter em mente a pirmide de testes).

A demonstrao a seguir da criao do fluxo de Login para entrar em uma aplicao.

Primeiro passo: Criar as regras de negcio na camada de domnio

Dentro de src/domain/usecases, criar o authentication.ts. Esse arquivo ser uma interface que vai descrever a regra de negcio da autenticao.

import { AccountModel } from '@/domain/models/';export interface IAuthentication {  auth(params: Authentication.Params): Promise<Authentication.Model>;}export namespace Authentication {  export type Params = {    email: string;    password: string;  };  export type Model = AccountModel;}

Como vemos, essa interface tem um mtodo auth() que recebe os parmetros Authentication.Params que so declarados num namespace abaixo - contendo o tipo dos parmetros (email e password) e o tipo do model (AccountModel) - e espera retornar um Authentication.Model de maneira assncrona.

O AccountModel uma exportao nomeada do model criado em src/domain/models que representa o token que retornado aps a autenticao para persistir a sesso.

export type AccountModel = {  accessToken: string;};

Segundo passo: Implementar as regras na camada de dados

Nessa camada, criamos o caso de uso para implementar a interface criada anteriormente na camada de domnio, porm dentro de src/data/usecases.

O arquivo tende a ficar como o exemplo abaixo.

import { IHttpClient, HttpStatusCode } from '@/data/protocols/http';import { UnexpectedError, InvalidCredentialsError } from '@/domain/errors';import { IAuthentication, Authentication } from '@/domain/usecases';export class RemoteAuthentication implements IAuthentication {  constructor(    private readonly url: string,    private readonly httpClient: IHttpClient<RemoteAuthenticationamespace.Model>  ) {}  async auth(    params: Authentication.Params  ): Promise<RemoteAuthenticationamespace.Model> {    const httpResponse = await this.httpClient.request({      url: this.url,      method: 'post',      body: params,    });    switch (httpResponse.statusCode) {      case HttpStatusCode.ok:        return httpResponse.body;      case HttpStatusCode.unauthorized:        throw new InvalidCredentialsError();      default:        throw new UnexpectedError();    }  }}export namespace RemoteAuthenticationamespace {  export type Model = Authentication.Model;}

Como podemos observar, a classe RemoteAuthentication implementa a interface IAuthentication, recebendo o cliente HTTP e a url para a requisio. No mtodo auth() ele recebe os parmetros, e chama o httpClient passando a url, o mtodo (nesse caso o post) e o body (que so os parmetros). Esse retorno uma httpResponse do tipo referente ao Authentication.Model que tem um cdigo de status de resposta, e que a depender do seu resultado, d o respectivo retorno - podendo retornar o valor esperado pela requisio ou um erro.

Os cdigos de status so os HTTP:

export enum HttpStatusCode {  ok = 200,  created = 201,  noContent = 204,  badRequest = 400,  unauthorized = 401,  forbidden = 403,  notFound = 404,  serverError = 500,}

Terceiro passo: Implementar as pginas na camada de presentation

Para simplificar o entendimento, ser apresentado apenas trechos de cdigos referentes a chamada do mtodo de autenticao. A pgina de Login contm mais aes e detalhes que vo alm da autenticao. Levar em considerao o prottipo da pgina abaixo para facilitar a visualizao.

Login page

Em src/presentation/pages/ ser criada a pgina de Login que composta por componentes, mtodos e funes. O componente que chama o mtodo de autenticao o <Button/> que est contido no formulrio para pegar os valores dos inputs, conforme o trecho de cdigo a seguir:

<form  data-testid="loginForm"  className={Styles.form}  onSubmit={handleSubmit}>   <Input    autoComplete="off"    title="Digite seu e-mail"    type="email"    name="email"  />  <Input    autoComplete="off"    title="Digite sua senha"    type="password"    name="password"    minLength={6}  />  <Button    className={Styles.loginBtn}    type="submit"    disabled={state.isFormInvalid}    title="Entrar"    data-testid="loginButton"  /></form>

Ao clicar no Button, chamado o handleSubmit() que est no onSubmit do form.

const handleSubmit = async (    event: React.FormEvent<HTMLFormElement>  ): Promise<void> => {    event.preventDefault();    try {      const account = await authentication.auth({        email: state.email,        password: state.password,      });      setCurrentAccount(account);      history.replace('/');    } catch (error) {      // Error handling here    }  };

Onde o authentication.auth() clicado chamar uma factory (veremos mais a seguir) para fazer a autenticao. Nesse caso est passando os parmetros capturados pelo input e o valor retornado da requisio salvo no cache atravs do setCurrentAccount(account);.

Quarto passo: Conectar todas as camadas para que as requisies funcionem

Aps tudo implementado, agora basta conectar todas as partes. Para isso, utilizado o padro de projeto Factory Method.

Dentro de src/main/factories/usecases, criamos a factory do caso de uso que est sendo implementado. No caso desse exemplo, o relacionado a autenticao.

criado o makeRemoteAuthentication, que retorna o RemoteAuthentication que recebe como parmetro a factory que cria a URL e a factory do Http Client. passado como parmetro a URL da API que deseja requisitar junto da factory que cria a URL. No exemplo a URL que finaliza com /login.

import { RemoteAuthentication } from '@/data/usecases/';import { IAuthentication } from '@/domain/usecases';import { makeAxiosHttpClient, makeApiUrl } from '@/main/factories/http';export const makeRemoteAuthentication = (): IAuthentication => {  const remoteAuthentication = new RemoteAuthentication(    makeApiUrl('/login'),    makeAxiosHttpClient()  );  return remoteAuthentication;};

Aps isso, em src/main/factories/pages, criada a pasta para as factories do Login. Em pginas com formulrio tambm so injetadas validaes, porm como o foco desse texto so as integraes, deixaremos esse ponto de fora da explicao.

import React from 'react';import { Login } from '@/presentation/pages';import { makeRemoteAuthentication } from '@/main/factories/usecases/';const makeLogin: React.FC = () => {  const remoteAuthentication = makeRemoteAuthentication();  return (    <Login      authentication={remoteAuthentication}    />  );};export default makeLogin;

criada uma const makeLogin que representa a factory. Ela possui o makeRemoteAuthentication que injetado dentro da pgina de Login criada na camada de presentation para que a pgina tenha acesso a essas requisies.

Quinto passo: Aplicar a pgina criada na aplicao

Por fim, necessrio adicionar a factory do Login nas rotas da aplicao para que ela seja acessada pelos usurios.

No arquivo router.tsx que fica localizado em src/main/routes, adicionar a factory da pgina criada dentro do Switch do BrowserRouter. passado no path a rota, no caso a /login, e a pgina no component, que no caso o ponteiro para a factory makeLoginPage. Essa lgica utilizada com todas as outras pginas, alterando apenas de Route para PrivateRoute caso a rota seja autenticada. O cdigo parecido com este abaixo.

const Router: React.FC = () => {  return (    <ApiContext.Provider      value={{        setCurrentAccount: setCurrentAccountAdapter,        getCurrentAccount: getCurrentAccountAdapter,      }}    >      <BrowserRouter>        <Switch>          <Route exact path="/login" component={makeLogin} />          <PrivateRoute exact path="/" component={makeDashboard} />        </Switch>      </BrowserRouter>    </ApiContext.Provider>  );};

Concluso

A Arquitetura Limpa apesar de ser um pouco complexa de se entender e implementar no comeo - e at parecer redundante -, as abstraes so necessrias. So aplicados diversos padres de projetos para garantir a qualidade e independncia do cdigo, facilitando a evoluo e manuteno independente de framework. Em casos como esse, se desejar mudar o framework de React para Angular ou qualquer outro baseado em Typescript, basta mudar a camada de apresentao e fazer ajustes nas dependncias.

Seguir o processo de desenvolvimento e entender o porqu est fazendo de tal maneira facilita a produo do cdigo. Aps um tempo acaba sendo feito de maneira natural, pois tem um processo linear de desenvolvimento: I. Caso de uso na camada de domnio; II. Caso de uso na camada de dados; III. Criao das interfaces na camada de presentation; IV. Criao das factories para integrar todas as camadas na camada principal; V. E a chamada da factory principal nas rotas da aplicao.

Pelo exemplo ter muitas partes abstradas, recomendvel a leitura do cdigo das partes ocultas para uma maior compreenso. Nesse repositrio do curso do Rodrigo Manguinho voc consegue ter acesso a cdigos abstrados similares ao desse exemplo dado.

Referncias

  • Rodrigo Manguinho https://github.com/rmanguinho/clean-react
  • MARTIN, Robert C. Clean Architecture: A Craftsmans Guide to Software Structure and Design. 1st. ed. USA: Prentice Hall Press, 2017. ISBN 0134494164.

Original Link: https://dev.to/rubemfsv/arquitetura-limpa-aplicando-com-react-1eo0

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To