Skip to content

Latest commit

 

History

History

monorepo

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

FLUTTER - Monórepo

Versão 1.0

I - Introdução

Este é um projeto de exemplo de Flutter utilizando o conceito de monórepo, ou seja, um único repositorio contendo os projetos do microfrontend

A arquitetura do projeto esta baseada no Clean Dart com modular, tendo suas funcionalidades quebradas por módulos.

Estrutura de pastas

Para criação de um novo modulo utilize o comando abaixo no CLI

flutter create --template=package module_name

feito isto adicione a referencia dele no pubspec do core

commons_dependencies:
	path: '../commons_dependencies'

Para rodar o projeto execute o flutter pub get para baixar as dependências e depois flutter run

II - Gerenciamento de Estado

O pacote de gerencia de estado foi o rx_notifier entretanto devido a utilização do padrão triple isso pode ser facilmente modificado bastando trocar a extensão da store pela classe referente a gerencia de estado que preferir (como a MobxStore por exemplo), consultar documentação

DE

class HomeStore extends NotifierStore<Failure, EnterpriseVM> {
}

PARA

class HomeStore extends MobxStore<Failure, EnterpriseVM> {
}

Triple Pattern

O triple é um pacote que propõe um padrão de desenvolvimento para suas gerencias de estado Triple

Basicamente ele segmenta o estado da sua aplicação em três, estado de Load, estado de sucesso e estado de erro

Com isso podemos facilmente criar nossa classe de estado e utilizamos o setLoad(bool) para atualizar o estado de load, o update(dynamic) para atualizar o estado de sucesso e o setError(Failure) para atualizar o estado de erro

class ProductStore extends StreamStore<Exception, ProductList> {
	final ProductRepository repository;
	
	Counter({required this.repository}): super([]);
	
	fetchProduct() async {
		setLoading(true);
		try {
			final list = await repository.fetchAllProducts();
			update(list);
		} on Exception catch (e) {
			setError(e);
		} finally {
			setLoading(false);
		}
	}
}

ScopedBuilder

Desta forma quando quisermos construir um widget de forma reativa teremos que utilizar o ScopedBuilder que poderemos segmentar por estado e informar o que faremos em cada segmento do estado da aplicação (erro, sucesso ou load)

Widget build(BuildContext context){
	return Scaffold(
		body: Center(
			child: ScopedBuilder(
				store: counter,
				onState: (context, state) => Text('$state'),
				onError: (context, error) => Text(error.toString()),
				onLoading: (context) => CircularProgressIndicator(),
			);
		),
	);
}

Observer

Se quisermos segmentar a reatividade para executarmos funções em background podemos utilizar o observer()

store.observer(
	onState: (state) => print(state),
	onError: (error) => print(error),
	onLoading: (loading) => print(loading),
);

Para testes do triple consulte o pacote triple_test

Para mais informações consulte o artigo

PACOTES

Neste projeto foram utilizados alguns pacotes

  • effective_dart - Auxilia a seguir a guideline do Dart

  • flutter_modular - Gerencia as rotas e as injeções de dependência, além de ter um sistema de dispose inteligente para eliminar classes que não estão sendo mais utilizadas.

  • flutter_triple - Auxilia no padrão de gerencia de estado

  • dio - HTTP client poderoso

  • dartz - Auxilia no retorno de tuplas e também traz o conceito de programação funcional para dentro do DART

  • asuka - Mostra Snackbars, dialogs, ModalSheets em um único provider de forma simples e limpa

  • flutter_svg - Renderiza arquivos svg dentro do app

  • hive - Banco de dados local, simples, performático e poderoso

  • build_runner - Pacote utilizado por alguns packages para geração de código (neste caso foi utilizado no mockito) para gerar as classes rodar flutter pub run build_runner build --delete-conflicting-outputs

  • mockito - Pacote que auxilia na geração de Mocks para testes

  • Slidy - CLI para auxiliar na criação de classes do flutter

III - Estrutura do Projeto

A estrutura do projeto esta em monorepo e suas funcionalidade(módulos) quebrado por packages.

Estrutura

DOCUMENTO

Base APP

O base app é o ponto de entrada da minha aplicação, ele irá conversar somente com o CORE que irá acessar os modulos.

Ele irá ter a chamado do runApp()

void main() => runApp(
	ModularApp(
	module: AppModule(),
	child: AppWidget(initialRoute: '/splash'),
	),
);

CORE

O core é o coração do nosso app, ele fará a ponte de conversa entre o base_app e os módulos é nele que estará a configuração das rotas principais e a chamada para o MaterialApp()

Widget build(BuildContext context) {

	return MaterialApp(

	title: 'Flutter Slidy',

	theme: ThemeData(primarySwatch: Colors.blue),

	initialRoute: initialRoute,

	builder: asuka.builder,

	).modular();

}

Modules

Os módulos são as quebras de funcionalidades do app. Eles são responsavei pelas features do app, cada modulo deve possuir uma e somente uma responsabilidade

IMPORTANTE: Os módulos são totalmente desacoplados e independente de outros modulos e nao podem compartilhar informações entre eles, caso isso seja necessário, colocar no Commons

Commons

O commons é o pacote que será responsável por ter toda a funcionalidade que será compartilhado entre todos os módulos, como interceptors, widgets, stores, etc.

Commons Dependencies

Aqui é onde terá todas as dependências do projeto e os módulos pegam suas dependências daqui, desta forma garantimos que todos os módulos utilizam a mesma versão de package É a única dependência que o modulo pode possuir

IV - Telas

App

SplashScreen

Tela de Login

Home Page

Tela de Detalhe