🆚Result Dart
Documentação: Uso do result_dart
em Camadas Arquiteturais no Flutter
result_dart
em Camadas Arquiteturais no FlutterEsta documentação descreve como utilizar a biblioteca result_dart
para tratar erros e sucessos de forma segura e escalável nas camadas de datasource, repository, e como apresentar os dados corretamente até a camada de view.
Motivação
O result_dart
oferece uma abordagem funcional para lidar com sucessos e falhas, encapsulando o resultado de uma operação em objetos Success
ou Failure
. Isso elimina a necessidade de exceções no fluxo principal e facilita o manuseio de erros de maneira consistente.
Camadas Arquiteturais
1. Datasource
Responsabilidade: Comunicação direta com APIs ou bancos de dados.
Erros Tratados: Conexão, autenticação, e erros específicos de HTTP.
Retorno: Dados brutos (
Map<String, dynamic>
), encapsulados emAsyncResult
.
Exemplo de Implementação
import 'package:result_dart/result_dart.dart';
class ExampleDatasourceImpl implements ExampleDatasource { final HttpClientInterface httpClient;
ExampleDatasourceImpl({required this.httpClient});
@override AsyncResult<Map<String, dynamic>, ExampleError> getExample() async { try { var result = await httpClient.get( 'todos/1', );
return Success(result.data);
} on DioException catch (e) {
if (e.response?.statusCode == 401) {
return Failure(ExampleError("Usuário não autenticado."));
} else if (e.response?.statusCode == 500) {
return Failure(ExampleError("Erro interno da API."));
}
return Failure(
ExampleError("Ocorreu um erro inesperado."),
);
}
} }
2. Repository
Responsabilidade: Transformar os dados brutos do
datasource
em modelos de domínio.Erros Tratados: Apenas repassa falhas do datasource.
Retorno: Modelo de domínio encapsulado em
AsyncResult
.
Exemplo de Implementação
import 'package:result_dart/result_dart.dart';
class ExampleRepositoryImpl implements IExampleRepository { final ExampleDatasource exampleDatasource;
ExampleRepositoryImpl({required this.exampleDatasource});
@override AsyncResult<ExampleModel, ExampleError> getExample() async { final result = await exampleDatasource.getExample();
return result.fold(
(success) {
return Success(ExampleModel.fromJson(success));
},
(failure) {
return Failure(failure);
},
);
} }
3. Usecase
Responsabilidade: Reunir dados de múltiplos repositórios ou aplicar lógica de negócios antes de passar para a camada superior.
Erros Tratados: Apenas repassa falhas do repositório.
Retorno: Dados prontos para consumo pela camada de apresentação.
4. View
Responsabilidade: Apresentar os dados ao usuário.
Erros Tratados: Exibir mensagens amigáveis baseadas no erro recebido.
Uso do Resultado: Consome os dados encapsulados e trata
Success
ouFailure
.
Exemplo de Consumo na View
void fetchExampleData(ExampleRepository repository) async {
final result = await repository.getExample();
result.when(
success: (data) {
print("Dados recebidos: ${data.title}");
},
failure: (error) {
print("Erro ao buscar dados: ${error.message}");
},
);
}
Fluxo Resumido
Datasource:
Realiza a requisição HTTP.
Trata erros de API e conexão.
Retorna
Success
ouFailure
com dados brutos.
Repository:
Converte os dados brutos do
datasource
em modelos de domínio (ExampleModel
).Propaga erros para as camadas superiores.
Usecase (opcional):
Aplica lógica de negócios.
Agrega dados de múltiplos repositórios.
View:
Observa e consome o resultado (
Success
ouFailure
).Mostra os dados ou mensagens de erro ao usuário.
Benefícios
Tratamento Consistente de Erros: Todos os erros são encapsulados em
Failure
, simplificando o tratamento.Lógica Centralizada: Parsing e validação ocorrem em um único lugar (repositório), mantendo o datasource limpo.
Facilidade de Teste: As camadas são desacopladas e podem ser testadas independentemente.
Código Funcional e Seguro: Operações encadeadas com
fold
evitam erros imprevisíveis no fluxo.
Last updated