创建适配器

Creational adapter

我有很多这样的代码

additional_params = {
  date_issued: pending.present? ? pending.date_issued : Time.current,
  gift_status: status,
  date_played: status == "Opened" ? Chronic.parse("now") : (opened.present? ? opened.date_played : nil),
  email_template: service&.email_template,
  email_text: service&.email_text,
  email_subject: service&.email_subject,
  label: service&.label,
  vendor_confirmation_code: service&.vendor_confirmation_code
}
SomeService.new(reward, employee: employee, **additional_params).create

相同的模式适用于许多模型和服务。

这个图案叫什么名字?

如何重构当前解决方案?

有gem解决这种方案吗?喜欢 draper 或其他东西

你可以试试建造者模式。我不熟悉 ruby gem,但你可以在这里找到信息:https://en.wikipedia.org/wiki/Builder_pattern and https://en.wikipedia.org/wiki/Fluent_interface

对我来说,对于每种类型的实体来说,这看起来有点像上帝对象。您希望您的服务能够处理与您的实体相关的所有事情。实体本身只是一个数据容器,并不对其数据负责。这就是所谓的贫血模型。

首先,您需要了解同一实体可以有多个表示形式。您可以有多个不同的 class 代表一个用户。在“列出用户”页面上,class 仅包含信息的一个子集,可能与帐户系统中的信息(上次登录、登录尝试等)相结合。在用户注册页面上,您还有另一个 class,因为为用户提供所有信息是无效的。

那些classes被称为数据传输对象。它们的目的是提供特定用例所需的信息,并将内部实体与外部 API(即网页)分离。

完成后,您的服务 classes 将开始缩减,您每次方法调用所需的自定义参数也会减少。

现在您的服务 class 有两个职责:管理所有实体并对其业务规则负责。

为了解决这个问题,你应该开始只通过行为(方法)修改你的实体,而不是直接更新字段。当您这样做时,您将自动将逻辑从您的服务 class 移动到您的实体 class.

完成后,您的服务 classes 会更干净。

您可以阅读领域驱动设计来获得灵感(无需使用 DDD,但可以从应用层的结构中获得灵感)。