🐒Monorepos

Documentação: Desenvolvendo um Projeto Monorepo em Flutter

1. Introdução ao Monorepo

Um Monorepo é uma estratégia de gerenciamento de repositórios onde todos os módulos e pacotes de um projeto são mantidos em um único repositório. Esta abordagem traz várias vantagens, como facilitar o compartilhamento de código, simplificar a dependência e a gestão de versões e melhorar a colaboração entre equipes.

2. Estrutura do Projeto Monorepo

Neste projeto Monorepo de Flutter, temos uma estrutura de pastas e módulos cuidadosamente planejada para otimizar a reutilização de código, facilitar a manutenção e melhorar a colaboração entre desenvolvedores. A seguir, detalho mais sobre cada pasta:

  • app_domain:

    • Descrição: Esta library age como o núcleo da lógica de negócios e contém a definição de todos os domínios, usecases, repositórios e datasources.

    • Benefícios: Isolar a lógica de negócios desta forma permite que ela seja testada independentemente do resto do aplicativo. Além disso, ela pode ser reutilizada em diferentes aplicações ou módulos que compartilhem a mesma lógica de negócios.

Exemplo da main.dart do app_domain:

library app_domain;

export 'src/domain/repositories/i_repositories.dart';
export 'src/domain/usecases/usecases.dart';
export 'src/external/datasources/datasources.dart';
export 'src/external/models/models.dart';
export 'src/usecases/i_usecases.dart';
  • app_platform:

    • Descrição: É onde o aplicativo em si reside. Este módulo liga todas as outras libraries e faz o trabalho pesado de inicialização e execução do aplicativo.

    • Benefícios: Mantendo o código específico da plataforma separado, fica mais fácil gerir atualizações específicas da plataforma e lógicas de negócios universais.

  • common_dependencies:

    • Descrição: Esta library serve como um catálogo centralizado para todas as dependências comuns (bibliotecas externas, recursos, constantes) que são usadas em todo o projeto.

    • Benefícios: Isso simplifica o processo de atualização de dependências, pois você precisa fazer a alteração em um só lugar. Além disso, evita a duplicação de dependências em diferentes partes do projeto.

Exemplo da main.dart de common_dependencies

export 'package:retrofit/retrofit.dart';
export 'package:retrofit_generator/retrofit_generator.dart';
export 'package:json_serializable/json_serializable.dart';
export 'package:dartz/dartz.dart';
export 'package:get_it/get_it.dart';
export 'package:mobx_codegen/mobx_codegen.dart';
export 'package:build_runner/build_runner.dart';
export 'package:image_picker/image_picker.dart';
export 'package:file_picker/file_picker.dart';
  • design_components:

    • Descrição: Aqui, você encontrará todos os componentes visuais reutilizáveis como botões, caixas de texto, paletas de cores e estilos de texto.

    • Benefícios: Isolar componentes visuais torna o projeto mais gerenciável e reutilizável. Isso também permite que designers e desenvolvedores front-end trabalhem de forma mais eficiente, pois os componentes podem ser facilmente importados e usados em diferentes partes do aplicativo.

Exemplo da main.dart de design_components, com o exemplo de quais arquivos são utilizados neste tipo de library:

export 'src/core/utils/custom_colors.dart';
export 'src/core/utils/fonts.dart';
export 'src/core/utils/helpers/assets_helper.dart';
export 'src/core/utils/helpers/image_picker_helper.dart';
export 'src/core/utils/helpers/masks_helper.dart';
export 'src/core/utils/helpers/scroll_listener_helper.dart';
export 'src/core/utils/helpers/select_pictures_sheet_helper.dart';
export 'src/core/components/components.dart';

A estrutura acima não só segue os princípios de programação modular, como também abstrai várias partes do sistema para torná-las independentes e reutilizáveis. Ela também facilita a integração contínua e entrega contínua (CI/CD), tornando mais fácil para os desenvolvedores colaborarem e manterem o projeto.

3. Por que Monorepo?

  • Reutilização de Código: Com uma estrutura monorepo, é mais fácil reutilizar código entre diferentes partes do projeto.

  • Gestão de Dependências: Ter todas as dependências em um local centralizado simplifica o versionamento e atualizações.

  • Integração e Teste: Um monorepo pode facilitar a integração contínua e a implementação de testes em diferentes módulos.

4. Criando uma Nova Library

  1. Crie uma Nova Pasta:

    mkdir nome_da_library
  2. Inicialize um Novo Pacote Flutter:

    flutter create --template=package nome_da_library
  3. Adicione Dependências: Se a sua library precisa de dependências externas, adicione-as ao arquivo pubspec.yaml da library.

5. Utilizando Libraries no Projeto

Para utilizar uma library em outra parte do projeto:

  1. Adicione a Dependência no pubspec.yaml:

    dependencies:
      nome_da_library:
        path: ../nome_da_library
  2. Importe e Utilize: Em seu código, simplesmente importe e utilize as classes e funções da library:

    import 'package:nome_da_library/nome_da_library.dart';

6. Recomendações Adicionais

  • Documentação Consistente: Cada library deve ter sua própria documentação, incluindo a finalidade da library, como utilizá-la e exemplos.

  • Testes: Assegure-se de incluir testes unitários e de integração em cada library. Isso garante que as funcionalidades fornecidas pela library sejam robustas e confiáveis.

  • Atualizações de Dependências: Ao atualizar uma dependência em common_dependencies, certifique-se de testar todas as libraries e o aplicativo principal para garantir a compatibilidade.

7. Conclusão

O uso de uma abordagem Monorepo em Flutter permite uma gestão mais eficaz e organizada do projeto. Ao separar a lógica de negócios, componentes visuais, dependências e a aplicação principal em diferentes libraries, você pode obter uma arquitetura modular que é fácil de manter, escalar e testar.

Embora a configuração inicial possa parecer mais complexa, os benefícios a longo prazo em termos de reutilização de código, gestão de dependências e colaboração entre equipes tornam o Monorepo uma escolha valiosa para projetos Flutter de grande escala.

Last updated