🍃Arquitetura Recomendada pelo FLUTTER
Nesta documentação, unimos os conceitos de teoria e prática para ajudar você a estruturar seu aplicativo Flutter de forma modular, escalável e fácil de manter, seguindo as recomendações do time do Flu
DOCUMENTAÇÃO BASEADA EM:doc oficial: https://docs.flutter.dev/app-architecture
video diego antunes: https://www.youtube.com/watch?v=_pPUqNXudXg&ab_channel=Prof.DiegoAntunes
com help do chat gpt para resumir melhor as informações que encontrei
1. Princípios Fundamentais
Antes de entrarmos nos detalhes técnicos, é importante entender os pilares que guiam a arquitetura recomendada:
Separação de Responsabilidades (Separation of Concerns)
Divida a aplicação em camadas independentes, cada uma com responsabilidades bem definidas.
Exemplo: A lógica de exibição de dados (UI) deve ser separada da lógica de negócios e da lógica de acesso a dados.
Fonte Única da Verdade (SSOT - Single Source of Truth)
Cada tipo de dado deve ter uma única fonte de verdade, que centraliza a responsabilidade pelo estado e pelas alterações desse dado.
Geralmente, isso é feito nos Repositórios.
Fluxo Unidirecional de Dados (UDF - Unidirectional Data Flow)
O estado flui do Data Layer (camada de dados) para o UI Layer (camada de interface).
Eventos do usuário fluem na direção oposta, da UI para o Data Layer.
UI como Função do Estado
A interface é declarativa: ela reflete diretamente o estado atual da aplicação.
Quando o estado muda, a UI é automaticamente reconstruída.
2. Estrutura Arquitetural
A arquitetura é composta por camadas principais e, opcionalmente, uma camada intermediária para lógica mais complexa.
Camadas Principais
Camada de UI (Apresentação)
Responsável por interagir com o usuário.
Exibe os dados e captura eventos (toques, entradas de texto).
Contém as Views (Widgets) e ViewModels.
Camada de Dados
Gerencia os dados da aplicação, seja de fontes locais (bancos) ou remotas (APIs).
Contém os Repositórios e Services.
Camada Opcional: Lógica (Domínio)
Encapsula regras de negócios complexas em Use Cases.
Abstrai a interação entre as camadas de UI e dados, reduzindo a complexidade em ViewModels.
3. Prática: Componentes Arquiteturais
Agora vamos detalhar os componentes dentro de cada camada e como eles interagem.
UI Layer: Views e ViewModels
Views
São os Widgets que compõem a interface.
Não devem conter lógica de negócios, apenas lógica simples como:
Mostrar ou esconder widgets.
Lidar com animações ou layout.
Exemplos: LoginView, ProfileView.
ViewModels
Fazem a ponte entre os dados e a View.
Suas responsabilidades incluem:
Buscar dados nos repositórios.
Transformar os dados no formato necessário para a UI.
Expor callbacks para eventos do usuário (ex.: cliques em botões).
Data Layer: Repositórios e Services
Repositórios
São a fonte única da verdade para cada tipo de dado.
Responsáveis por:
Combinar dados de múltiplos serviços.
Cachear dados.
Tratar erros.
Exemplo: UserRepository.
Services
Isolam a lógica de acesso a fontes externas, como APIs ou banco de dados.
Não possuem estado nem lógica de negócios.
Exemplo: AuthService para autenticação.
Domain Layer (Opcional): Use Cases
Encapsula regras de negócios complexas.
Exemplo: Um LoginUseCase pode validar credenciais, fazer login e salvar tokens localmente.
4. Fluxo Prático de Dados
A arquitetura segue um fluxo unidirecional de dados:
O usuário interage com a View (ex.: clica em um botão).
A View aciona um callback na ViewModel.
A ViewModel chama métodos em um ou mais Repositórios.
Os Repositórios acessam os Services para buscar ou enviar dados.
Os Repositórios retornam os dados transformados para a ViewModel.
A ViewModel atualiza o estado, que é refletido na View.
5. Exemplo de Estrutura
Aqui está um exemplo prático de como organizar as pastas do seu projeto:
lib/
├── features/
│ ├── login/
│ │ ├── data/
│ │ │ ├── repositories/
│ │ │ ├── services/
│ │ ├── domain/
│ │ │ ├── use_cases/
│ │ ├── presentation/
│ │ │ ├── views/
│ │ │ ├── view_models/
├── shared/
│ ├── utils/
│ ├── widgets/
6. Boas Práticas
Mantenha as Views "magras": A lógica deve estar na ViewModel ou nas camadas inferiores.
Teste cada camada separadamente:
Mocks para Repositórios e Services facilitam os testes.
Evite Dependências Diretas: Use injeção de dependências para desacoplar as classes.
Com essa abordagem, você garante que seu aplicativo seja escalável, fácil de manter e siga padrões modernos de arquitetura no Flutter! 🚀
Last updated