【问题标题】:Entity design suggestion实体设计建议
【发布时间】:2016-07-05 03:52:49
【问题描述】:

我需要设计一个具有到期日期属性以供使用的某种优惠券的实体。问题是到期日可以是从用户获得优惠券后的一段时间(如 60 天)分配或计算的特定日期。所以我的问题是如何设计一个优惠券实体来满足这个要求,以便我可以轻松获得不同类型优惠券的到期日期?任何建议将不胜感激。

这是一个例子。现在我有 2 个实体,User 和 Coupon,以及这 2 个对象的关系实体。

@Entity
@Table(name = "user")
public class User { 

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    // ....

}


@Entity
@Table(name = "coupon")
public class Coupon {

    @Id
    @GeneratedValue
    private Long id;

    private Date dueDate;

    private Integer periodDays;

    // ...
}

@Entity
@Table(name = "user_coupon")
public class UserCoupon {

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne(fetch = FetchType.Lazy, optional = false)
    private User user;

    @ManyToOne(fetch = FetchType.Lazy, optional = false)
    private Coupon coupon;

    private Date dueDate;

    /**
     * Constructor
     */
    public UserCoupon(User user, Coupon coupon) {
        this.user = user;
        this.coupon = coupon;
        if (coupon.getDueDate() != null) {
            this.dueDate = coupon.getDueDate();
        } else if (coupon.getPeriodDays() != null) {
            this.dueDate = DateUtils.addDays(new Date(), coupon.getPeriodDays());
        }
    }

    // ....
}

Coupon 类中填充的dueDate 和periodDays 在业务逻辑上是互斥的。也就是说,优惠券要么有固定的到期日,要么有一个整数属性(periodDays),用于计算用户获得优惠券后的到期日。

现在我可以将这两个字段都放在Coupon 类中,但是当我需要在UserCoupon 类中设置dueDate 字段时,我发现检查哪个字段有点繁琐且不方便Coupon 类中的独占字段为null,最后计算出UserCoupon 类中的dueDate(参见UserCoupon 类构造函数)。

因此,我想知道是否有一些好的实体设计策略可以避免计算到期日时繁琐的字段空检查,并确保Coupon类中的2个字段同时互斥由业务逻辑而非代码排他。

【问题讨论】:

  • 你的问题有点宽泛。也许添加您的尝试(即使是在伪代码中)以显示您想要实现的目标。
  • @user1803551 我为我的问题添加了一些代码和详细解释。希望这对你来说很清楚。 :)
  • 你不能在Coupon 中创建一个基于dueDate 和periodDays 计算dueDate 值的方法,不管你这样做的逻辑是什么?
  • @user1803551 我添加了一个构造函数来从User和Coupon初始化UserCouponobject,其中包含计算逻辑。

标签: java entity


【解决方案1】:

我认为你可以把计算逻辑放在Coupon类中:

public class Coupon {

    private Date dueDate;

    private Integer periodDays;

    public Date getExpirationDate() { // name this whatever makes sense

        // assuming you can guarantee that one and only one is null == mutually exclusive
        return (dueDate != null) ? dueDate : DateUtils.addDays(new Date(), periodDays);
    }
}

然后在UserCoupon

public class UserCoupon {

    private Date dueDate;

    public UserCoupon(User user, Coupon coupon) {

        dueDate = coupon.getExpirationDate();
    }
}

这看起来清晰易读(对我来说),同时在设计方面也很有意义。这是因为“到期日期”的计算只依赖于Coupon 数据,所以它应该是实现逻辑的那个。另一种看待它的方式是:其他类不关心计算是如何完成的,他们只想要最终结果。 Coupon“有一个合同”来提供这个结果,所以它应该对此负责。

【讨论】:

  • 哇,我只是没有意识到我可以以如此简单的方式更好地改进我的代码。我绝对应该再次回顾面向对象的编程。感谢您提醒我,我只是完全忘记了封装。这是一个很好的答案,但是Coupon 类仍然不能保证dueDate 和periodDays 是相互排斥的。可以改进Coupon 类以满足“互斥”要求,这将是完美的。非常感谢您的时间和这个很好的答案。 :)
  • @lute 我认为互斥已经在外部得到保证。既然不是,我需要知道Coupon 是如何创建的,因为那是你可以保证的地方。
【解决方案2】:

您可以在 Coupon 类中添加一个字段来显示它的有效时间优惠券或优惠券自收到以来。根据领域,您有不同的计算策略。

【讨论】:

    【解决方案3】:

    您可以使用截止日期和激活日期,激活后只需设置截止日期。

    【讨论】:

    • 对不起,我可能不完全理解你。能否详细解释一下?
    • 现在想得更好,我想如果你映射另一个实体/表来加入 User 和 Cupom 会更好。如果用户可以拥有多个cuom,这将很有用,在这个新实体中,您也可以设置截止日期。
    • 是的,这就是我迄今为止所做的。我将截止日期放入连接的实体/表中。但我想知道如何获得到期日的价值。因为它可以来自 2 个不同的来源。一种是在创建优惠券时指定的固定到期日,无论用户在什么日期获得优惠券。另一种是从优惠券激活后的固定天数计算的动态日期,例如优惠券激活后的 90 天。所以优惠券要么有一个固定的到期日,要么有一个固定的到期日,比如 90 天。如何在 Coupon 实体中安排这两个相互排除的属性是我遇到的问题。
    • @lute 您需要在问题中详细说明确切的规格。非常准确地了解日期和持续时间的工作方式以及您在功能方面需要实现的目标。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 2021-12-09
    • 1970-01-01
    • 2012-10-31
    相关资源
    最近更新 更多