Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Melhor local para validação de dados

Não seria uma boa prática colocar as regras de negócio de validação de dados nos models? Como por exemplo a validação de possuir ou não saldo para transferência na model transferencias.dart ?

3 respostas

Oi Rafa! Beleza?

Cara seria uma ótima ideia! Para o nosso app, é claro, pois podem haver por exemplo alguns tipos diferentes de transferências que requerem uma validação diferente, mas no nosso caso é uma boa sim.

Só lembre que você teria de dar um jeito de concatenar o formulário com o model de transferência ( já que o valor do formulário que ta sendo validado), então isso por si só ja te daria uma dor de cabeça...

Se você fizer, mostra pra gente!

solução!

Depois de apanhar um pouco (e isso é bom pq aí que a gente aprende mesmo), consegui implementar a validação nos models. Pra isso eu criei um novo package "exceptions" e dentro dele criei uma nova Exception DadosInvalidosException no arquivo dados_invalidos_exception.dar com o seguinte conteúdo:

class DadosInvalidosException implements Exception {
  String motivo;
  DadosInvalidosException(this.motivo);
}

No models/transferencias.dart eu criei um novo método privado _validarAdicionarTransferencia() que faz a validação e ao executar o método adicionar() caso não passe pela validação o método lança a exceção DadosInvalidosException() com o texto explicando o motivo.

import 'package:bytebank/exceptions/dados_invalidos_exception.dart';
import 'package:bytebank/models/saldo.dart';
import 'package:bytebank/models/transferencia.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class Transferencias extends ChangeNotifier {
  final List<Transferencia> _transferencias = [];

  List<Transferencia> get transferencias => _transferencias;

  void adicionar(BuildContext context, Transferencia novaTransferencia) {
    if (_validarAdicionarTransferencia(context, novaTransferencia) == false) {
      throw new DadosInvalidosException('Você não possuí saldo suficiente para a transferência!');
      return;
    }

    transferencias.add(novaTransferencia);
    notifyListeners();
  }

  _validarAdicionarTransferencia(BuildContext context, Transferencia novaTransferencia) {
    final _camposPreenchidos = novaTransferencia.numeroConta != null && novaTransferencia.valor != null;
    final _saldoSuficiente = novaTransferencia.valor <= Provider.of<Saldo>(context, listen: false).valor;
    return _camposPreenchidos && _saldoSuficiente;
  }
}

Também implementei uma validação no construtor do models/transferencia.dart para nao permitir instanciar uma Transferencia() com dados nulos. Ficou assim:

import 'package:bytebank/exceptions/dados_invalidos_exception.dart';

class Transferencia {
  final double valor;
  final int numeroConta;

  Transferencia(this.valor, this.numeroConta) {
    if (_validarTransferencia() == false) {
      throw new DadosInvalidosException('Dados de Número da Conta e/ou Valor inválido(s)!');
    }
  }

  @override
  String toString() {
    return 'Transferencia{valor: $valor, numeroConta: $numeroConta}';
  }

  String toStringVAlor() {
    return 'R\$ $valor';
  }

  String toStringConta() {
    return 'Conta: $numeroConta';
  }

  _validarTransferencia() {
    return ((valor != null) && (numeroConta != null) && (valor > 0) && (numeroConta > 0));
  }
}

E finalmente no screens/transferencia/formulario.dart no metodo _criarTransferencia() eu envolvi o código que pode lançar essa exceção com um bloco try-catch pra tratar esse erro mostrando um Snackbar vermelho quando um erro de validação ocorrer. Ficou assim o método:

void _criarTransferencia(BuildContext context) {
    debugPrint('clicou no confirmar');

    final int numeroConta = int.tryParse(_controladorCampoNumeroConta.text);
    final double valor = double.tryParse(_controladorCampoValor.text);

    try {
      final novaTransferencia = Transferencia(valor, numeroConta);
      _atualizaEstado(context, novaTransferencia);
      Navigator.pop(context);
    } on DadosInvalidosException catch (e) {
      final snackBarErro = SnackBar(
        content: Text(e.motivo),
        backgroundColor: Colors.red,
      );

      Scaffold.of(context).showSnackBar(snackBarErro);
    }
  }

Removi todo o código do método privado que fazia a validação de dentro do formulário.

Ah! Pro SnackBar aparecer/funcionar é necessário envolver o botão de Confirmar com um Builder(), dessa forma:

                 child: Builder(
                    builder: (context) => RaisedButton(
                      child: Text(_textoConfirmar),
                      onPressed: () => _criarTransferencia(context),
                    ),
                  ),

ARRASOU RAFA

Que orgulho viu, ta de parabéns :)

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software