Pular para o conteúdo

Modelagem de Estado

Há muitas abordagens diferentes quando se trata de estruturar o estado do aplicativo. Cada uma tem suas próprias vantagens e desvantagens. Nesta seção, daremos uma olhada em várias abordagens, seus prós e contras, e quando usar cada uma delas.

As abordagens a seguir são simplesmente recomendações e são completamente opcionais. Sinta-se à vontade para usar qualquer abordagem que preferir. Você pode descobrir que alguns dos exemplos/documentação não seguem estas abordagens principalmente por simplicidade/concisão.

Classe Concreta e Enum de Status

Esta abordagem consiste em uma única classe concreta para todos os estados junto com um enum representando diferentes status. Propriedades são tornadas anuláveis e são manipuladas com base no status atual. Esta abordagem funciona melhor para estados que não são estritamente exclusivos e/ou contêm muitas propriedades compartilhadas.

todo_state.dart
enum TodoStatus { initial, loading, success, failure }
final class TodoState {
const TodoState({
this.status = TodoStatus.initial,
this.todos = const <Todo>[],
this.exception = null,
});
final TodoStatus status;
final List<Todos> todos;
final Exception? exception;
}

Prós

  • Simples: Fácil de gerenciar uma única classe e um status enum e todas as propriedades são prontamente acessíveis.
  • Conciso: Geralmente requer menos linhas de código em comparação a outras abordagens.

Contras

  • Não é Type Safe: Requer a verificação do status antes de acessar as propriedades. É possível fazer emit de um estado malformado que pode levar a bugs. Propriedades para estados específicos são anuláveis, o que pode ser trabalhoso de gerenciar e requer desempacotamento forçado ou execução de verificações de nulos. Alguns desses contras podem ser atenuados escrevendo testes unitários e escrevendo construtores especializados e nomeados.
  • Inchado: Resulta em um único estado que pode ficar inchado com muitas propriedades ao longo do tempo.

Veredito

Essa abordagem funciona melhor para estados simples ou quando os requisitos exigem estados que não são exclusivos (por exemplo, mostrar uma snackbar quando ocorre um erro enquanto ainda mostra dados antigos do último estado de sucesso). Essa abordagem fornece flexibilidade e concisão ao custo da segurança de tipo.

Classe Selada e Subclasses

Essa abordagem consiste em uma classe selada que contém as propriedades compartilhadas e múltiplas subclasses para os estados separados. Essa abordagem é ótima para estados separados e exclusivos.

weather_state.dart
sealed class WeatherState {
const WeatherState();
}
final class WeatherInitial extends WeatherState {
const WeatherInitial();
}
final class WeatherLoadInProgress extends WeatherState {
const WeatherLoadInProgress();
}
final class WeatherLoadSuccess extends WeatherState {
const WeatherLoadSuccess({required this.weather});
final Weather weather;
}
final class WeatherLoadFailure extends WeatherState {
const WeatherLoadFailure({required this.exception});
final Exception exception;
}

Prós

  • Tipagem segura: O código é seguro para compilação e não é possível acessar acidentalmente uma propriedade inválida. Cada subclasse mantém suas próprias propriedades, deixando claro quais propriedades pertencem a qual estado.
  • Explícito: Separa propriedades compartilhadas de propriedades específicas do estado.
  • Exaustivo: Usa uma declaração switch para verificações de exaustividade para garantir que cada estado seja explicitamente manipulado.

Contras

  • Verboso: Requer mais código (uma classe base e uma subclasse por estado). Também pode exigir código duplicado para propriedades compartilhadas entre subclasses.
  • Complexo: Adicionar novas propriedades requer a atualização de cada subclasse e da classe base, o que pode ser trabalhoso e levar ao aumento da complexidade do estado. Além disso, pode exigir verificação de tipo desnecessária/excessiva para acessar propriedades.

Veredito

Esta abordagem funciona melhor para estados bem definidos, exclusivos e com propriedades únicas. Esta abordagem fornece verificações de segurança de tipo e exaustividade e enfatiza a segurança em vez da concisão e simplicidade.