Eu trabalho em um sistema que pode representar uma "estimativa de remessa" de duas maneiras:
- Uma data específica: é garantido que o item seja enviado nessa data
- Um intervalo de dias: o item será enviado "X a Y" dias a partir de hoje
As informações no modelo são semanticamente iguais, é "a estimativa de remessa". Quando obtenho as informações sobre a estimativa de remessa no sistema, posso saber se a estimativa é do primeiro ou do segundo formulário.
O modelo atual para isso é semelhante ao seguinte:
class EstimattedShippingDateDetails
{
DateTime? EstimattedShippingDate {get; set;}
Range? EstimattedShippingDayRange {get; set;}
}
Range
é uma classe simples para agrupar um "começo -> fim" de números inteiros, mais ou menos assim:
struct Range
{
int Start {get; set}
int End {get; set}
public override ToString()
{
return String.Format("{0} - {1}", Start, End);
}
}
Não gosto dessa abordagem, porque apenas uma das propriedades no modelo de estimativa será preenchida e preciso testar o valor nulo em uma delas e assumir que a outra possui os dados.
Cada uma das propriedades é mostrada de maneira diferente para o usuário, mas no mesmo local da interface do usuário, usando um MVC DisplayTemplate personalizado, onde a lógica de comutação atual reside:
@Model EstimattedShippingDateDetails
@if (Model.EstimattedShippingDate.HasValue)
{
Html.DisplayFor(m => Model.EstimattedShippingDate)
}
else
{
Html.DisplayFor(m => Model.EstimattedShippingDayRange)
}
Como modelar isso para torná-lo mais representativo do requisito real, mantendo a lógica de exibição simples em um aplicativo MVC?
Pensei em usar uma interface e duas implementações, uma para cada "tipo" de estimativa, mas não consigo entender a interface comum para ambas. Se eu criar uma interface sem membros, não consigo acessar os dados de maneira unificada e é um IMHO de design ruim. Eu também queria manter o viewmodel o mais simples possível. Eu obteria um código "correto por construção" com essa abordagem, já que não seria mais necessário anular: cada implementação teria uma propriedade não anulável, a DateTime
ou a Range
.
Também considerei usar apenas um Range
e, quando a situação nº 1 acontecer, use o mesmo DateTime
para ambos Start
e End
, mas isso adicionaria complicações sobre como emitir os valores para a interface do usuário, pois eu precisaria detectar se é um estático ou intervalo por comparando os valores e formate corretamente o intervalo para ser exibido como uma única data ou um intervalo formatado.
Parece que o que eu preciso é de um conceito semelhante aos sindicatos do Typescript: basicamente uma propriedade que pode ser de dois tipos. Naturalmente, não existe tal coisa em C # ( dynamic
seria apenas próximo disso).