Flutter — Construindo um Projeto Boilerplate perfeito do zero.
Crédito: Nguyễn Thành Minh (Desenvolvedor Android)
Anteriormente, compartilhei cerca de 5 pontos problemáticos frequentemente experimentados no passado. Se você ainda não leu, deveria dar uma lida antes de ler isso.
Flutter — Construindo um Projeto Boilerplate perfeito do zero Flutter — Construindo um Projeto Boilerplate perfeito do zero. Parte 2: Ponto de dorVeja o Projeto Boilerplate no Github
Desta vez, falarei sobre como você pode se livrar desses 5 pontos problemáticos com algo chamado Arquitetura Limpa. Antes de nos aprofundarmos nisso, precisamos entender alguns conceitos relevantes.
1. Conceitos
1.1. Regras de negócios corporativos versus regras de negócios de aplicativos
- Enterprise Business Rules são regras relacionadas ao lado comercial de um campo. Existe em um negócio antes de automatizá-lo. Por exemplo, no campo bancário e financeiro, temos regras relevantes, como idade, renda e garantias, às quais nos referimos como regra de negócios da empresa.
- Regras de Negócios de Aplicativos são a lógica do software, podem conter Regras de Negócios Corporativos. Um aplicativo bancário, por exemplo, poderia ter: o processo de login, etc.
Na Arquitetura Limpa, haverá 2 classes desconhecidas chamadas classe Entidade e classe Caso de Uso.
A classe Entity contém Enterprise Business Rules. Suponha que temos uma Userentidade como esta:
class User {
User(this.income, this.age);
final double income;
final int age;
bool couldBorrowMoney() {
return age >= 18 && income >= 1000;
}
}
1.3. Classes de caso de uso
Um caso de uso representa uma lógica de negócios do aplicativo do projeto. Ele pode conter um fluxo processando a lógica de obter a entrada da exibição e produzir a saída a ser exibida na exibição. Aqui está um exemplo para o fluxo de empréstimo de dinheiro do usuário:
import 'package:data/user_repository.dart';
class BorrowMoneyUseCase {
const BorrowMoneyUseCase(this._userRepository);
final UserRepository _userRepository;
Future<BorrowMoneyStatus> execute(double money) async {
final currentUser = await _userRepository.getMe();
if (currentUser == null) {
return BorrowMoneyStatus.userNotAuthorizedError;
}
if (!currentUser.couldBorrowMoney()) {
return BorrowMoneyStatus.couldNotBorrowError;
}
await _userRepository.borrowMoney(money);
return BorrowMoneyStatus.success;
}
}
enum BorrowMoneyStatus {
success,
couldNotBorrowError,
userNotAuthorizedError,
}
1.4. Dependência
A classe A depende da classe B quando a classe A importa a classe B.
Usando o mesmo código acima, podemos dizer que a classe BorrowMoneyUseCaseé dependente da classe UserRepository.
Da mesma forma, quando o módulo B é adicionado ao arquivo pubspec.yaml do módulo A, podemos dizer que o módulo A depende do módulo B.
2. A arquitetura de 3 módulos
Normalmente, a Clean Architecture consiste em 3 módulos principais: dados, domínio e apresentação (neste projeto, chamei-os de aplicativo de módulo em vez de apresentação).
- O módulo de apresentação contém classes UI e Bloco. Sua finalidade é receber eventos do usuário e executar os casos de uso de acordo para enviar de volta os dados que precisam ser exibidos na interface do usuário.
- O módulo Domain contém as classes Entity e Use Cases. Em outras palavras, este é o módulo que contém a lógica de negócios do aplicativo.
- O módulo de dados contém repositórios para receber dados de casos de uso, bem como fornecer dados para casos de uso. A fonte de dados pode vir de diferentes servidores por meio de API, banco de dados local ou preferência compartilhada, etc.
3. Regra de Dependência
Esta regra pode ser entendida assim:
Módulos instáveis devem depender de módulos estáveis.
Módulos instáveis provavelmente serão alterados repetidamente. Pegue o aplicativo do Facebook, por exemplo, seus arquivos de interface do usuário e bancos de dados locais são coisas que o desenvolvedor do Facebook muda a cada semana ou mês. Dessa forma, os módulos Apresentação e Dados são módulos instáveis, deixando o Domínio como o mais estável. É claro porque o módulo Domínio contém Regras de Negócios que dificilmente são alteradas.
Resumindo, a relação entre os 3 módulos é a seguinte: os módulos Apresentação e Dados vão depender do módulo Domínio.
Como fazer o módulo Domínio não depender do módulo Dados quando classes Use Case precisam importar classes Repositório? É aí que a técnica de Inversão de Dependência entra em ação.
4. Inversão de Dependência
O problema atual é que o módulo Domínio agora depende do módulo Dados porque a BorrowMoneyUseCaseclasse precisa importar a UserRepositoryclasse.
Para reverter essa dependência, precisamos criar um Repositório de Interface ou Classe Abstrata no módulo Domínio, e no lado do módulo Dados, criaremos classes de Implementação do Repositório que herdarão esse Repositório de Interface/Classe Abstrato. Então, as classes de caso de uso precisarão apenas importar o Repositório de Classes Interface/Abstract.
Assim, o módulo Domínio não depende mais do módulo Dados. Ambos agora dependem da abstração. Essa também é a declaração do princípio de Inversão de Dependência nos 5 princípios do SOLID.
Depois de entender a regra de dependência, precisamos ajustar o código. O primeiro passo será criar uma classe abstrata UserRepository.
import '../user.dart';
abstract class UserRepository {
Future<User?> getMe();
Future<void> borrowMoney(double money);
}
import '../user_repository.dart';
class BorrowMoneyUseCase {
const BorrowMoneyUseCase(this._userRepository);
final UserRepository _userRepository;
Future<BorrowMoneyStatus> execute(double money) async {
final currentUser = await _userRepository.getMe();
if (currentUser == null) {
return BorrowMoneyStatus.userNotAuthorizedError;
}
if (!currentUser.couldBorrowMoney()) {
return BorrowMoneyStatus.couldNotBorrowError;
}
await _userRepository.borrowMoney(money);
return BorrowMoneyStatus.success;
}
}
import 'package:domain/user_repository.dart';
import 'package:domain/user.dart';
class UserRepositoryImpl implements UserRepository {
@override
Future<User?> getMe() {
// TODO
}
@override
Future<void> borrowMoney(double money) {
// TODO
}
}
Conclusão
O modelo de 3 módulos é uma das características da Clean Architecture. Ainda tem muitas características excelentes e emocionantes. Na próxima parte, aprenderemos mais sobre ele e veremos como ele realmente é lindo.





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)