我是一名PHP开发人员,目前正在使用Symfony2。
我想提出我的问题如下:
- 我有 4 个实体:用户、帐户、客户、商家。他们都有地位。
- 我想为他们构建一个名为"isValid"的通用方法,但不想修改他们的代码。
-
方法逻辑非常简单
<!-- language: php --> public function isValid() { return self::STATUS_ACTIVE == $this->status; }
-
通过将它们分开并在它与实体之间应用 HAS-A 关系,我认为它将更加灵活和可维护。我不必将我的代码复制到任何需要它的实体,即使在将来也是如此。
如果你有经验。你能帮我为这种情况选择一个合适的模式吗?
在这些实体之间创建 has-a 关系是没有意义的,因为它们不相关。
但是,代码重复几乎从来都是不合理的。我将通过创建一个公共接口(User
是一个可验证的实体,Customer
是一个可验证的实体)来解决它,并创建一个特征来封装共同的行为。
创建通用接口:
interface Validatable
{
public function isValid(): bool;
}
创建一个特征来实现常见行为:
trait HasStatus
{
/**
* @var int
* @ORMColumn(type="integer")
*/
private $status;
public function isValid(): bool
{
return $this->status === EntityStatus::STATUS_ACTIVE;
}
}
让您的实体实现新接口并使用该特征以避免重复:
class User implements Validatable {
use HasStatus;
}
并使用它:
/** @var Validatable[] $validatables */
$validatables = [new User(), new Merchant(), new Customer()];
foreach ($validatables as $validatable) {
var_dump($validatable->isValid());
}
为什么我们需要接口?从技术上讲,我们不需要它,但我喜欢包含它,因为它允许使用通用的"可验证"类型提示来引用用户、客户、商家,并且它在代码中传达了您的意图。
搞砸了这不是一个好主意,实体具有状态值,并且 setter/getter 应该在实体文件声明中。 我理解 DRY 原理,但在这个层面上这样做......恕我直言,这不是一个好主意。
但是,如果您确定它们都具有状态,请在单独的文件中使用特征:
trait CheckStatusTrait{
return $this->status;
}
您只需将特征添加到您的类中:
class User {
use CheckStatusTrait
}
对于这种简单的代码,可以在每个实体中保留重复项,您可以添加一个带有"isValid"的接口,以便在必要时从外部将它们视为相同。
也许您检查验证的代码会变得更加复杂,并且拥有一个负责的类是有意义的。 然后你可以创建一个 StatusValidator 类来检查给定对象的状态是否有效。为这种对象添加一个接口是有意义的,它有一个"getStatus"方法,比如说"getStatusInterface"。后记 您可以注入 StatusValidator 并在 isValid 方法中使用它。因为你的对象是实体,所以你需要使用原则的postLoad 事件来注入状态验证器。
你也可以做同样的事情,不注入 StatusValidator 但询问 StatusValidator 带有 getStatusInterface 的 obejct 是否有效。
感谢大家的支持。我还使用 trait 来解决代码重复问题。但是,我看到这种特质似乎不是一个完美的特质。我不得不在下面遇到缺点:
- 将字段隐藏在特征中会使实体变得神秘。实际上,状态字段不仅在许多实体上可用,而且还更新日期,创建日期,类型...当一个类使用许多特征时,它看起来也很混乱。
- 经过一段时间的发展,性状收集的方法越来越多,例如StatusTrait可以有isValid,hasStatus,setStatusDefault。但并非所有实体都使用它们。我的意思是有些实体使用 isValid,有些实体使用 setStatusDefault..,所以我们在特征中会有更多的混合方法。在本期中,我认为如果我可以实现 HAS-A 关系类,那么当实体需要时,我可以轻松地在运行时设置它们。
- 通过使用 trait,修改实体类,而不是扩展。这在 OOP 设计中不是一个好的做法。实体类与数据库表的引用不一致。老实说,我更喜欢在实体类之外构建逻辑方法。
以上是我的愿景。我只是试图找到更好的方法来解决这个问题。我希望它对每个人都有用。我听说过ValueObject,但显然并不真正理解它。我会试着弄清楚的!