(Eu já vi essa pergunta , mas a primeira resposta é mais sobre propriedades automáticas do que sobre design, e a segunda diz ocultar o código de armazenamento de dados do consumidor , o que não tenho certeza é o que eu quero / meu código, então eu gostaria de ouvir outra opinião)
Eu tenho duas entidades muito semelhantes HolidayDiscount
e RentalDiscount
, que representam descontos de comprimento como 'se durar pelo menos numberOfDays
, um percent
desconto é aplicável'. As tabelas possuem fks para diferentes entidades pai e são usadas em locais diferentes, mas onde são usadas, existe uma lógica comum para obter o desconto máximo aplicável. Por exemplo, a HolidayOffer
possui vários HolidayDiscounts
e, ao calcular seu custo, precisamos descobrir o desconto aplicável. Mesmo para aluguel e RentalDiscounts
.
Como a lógica é a mesma, quero mantê-la em um único local. É isso que o seguinte método, predicado e comparador fazem:
Optional<LengthDiscount> getMaxApplicableLengthDiscount(List<LengthDiscount> discounts, int daysToStay) {
if (discounts.isEmpty()) {
return Optional.empty();
}
return discounts.stream()
.filter(new DiscountIsApplicablePredicate(daysToStay))
.max(new DiscountMinDaysComparator());
}
public class DiscountIsApplicablePredicate implements Predicate<LengthDiscount> {
private final long daysToStay;
public DiscountIsApplicablePredicate(long daysToStay) {
this.daysToStay = daysToStay;
}
@Override
public boolean test(LengthDiscount discount) {
return daysToStay >= discount.getNumberOfDays();
}
}
public class DiscountMinDaysComparator implements Comparator<LengthDiscount> {
@Override
public int compare(LengthDiscount d1, LengthDiscount d2) {
return d1.getNumberOfDays().compareTo(d2.getNumberOfDays());
}
}
Como as únicas informações necessárias são o número de dias, termino com uma interface como
public interface LengthDiscount {
Integer getNumberOfDays();
}
E as duas entidades
@Entity
@Table(name = "holidayDiscounts")
@Setter
public class HolidayDiscount implements LengthDiscount {
private BigInteger percent;
private Integer numberOfDays;
public BigInteger getPercent() {
return percent;
}
@Override
public Integer getNumberOfDays() {
return numberOfDays;
}
}
@Entity
@Table(name = "rentalDiscounts")
@Setter
public class RentalDiscount implements LengthDiscount {
private BigInteger percent;
private Integer numberOfDays;
public BigInteger getPercent() {
return percent;
}
@Override
public Integer getNumberOfDays() {
return numberOfDays;
}
}
A interface possui um método getter único que as duas entidades implementam, o que obviamente funciona, mas duvido que seja um bom design. Não representa nenhum comportamento, dado que manter um valor não é uma propriedade. Este é um caso bastante simples, tenho mais alguns casos semelhantes e mais complexos (com 3-4 getters).
Minha pergunta é: esse é um design ruim? Qual é uma abordagem melhor?