任何想法/反馈都欢迎:)
我在一个大型Symfony2应用程序中如何处理围绕Doctrine2实体的业务逻辑时遇到一个问题。(对不起,文章长度)
阅读了许多博客,食谱和其他资源后,我发现:
好的,我完全同意,但是:在何处以及如何处理域模型上的复杂业务规则?
我们的域模型:
- 一组可以使用角色
- 一个角色可以被不同的组使用
- 一个用户可以属于多个组与许多角色,
在SQL持久层中,我们可以将这些关系建模为:
我们的特定业务规则:
- 仅当将角色附加到组时,用户才能在组中具有角色。
- 如果我们从组G1分离角色R1,则必须删除具有组G1和角色R1的所有UserRoleAffectation
这是一个非常简单的示例,但是我想知道管理这些业务规则的最佳方法。
1-在服务层中的实现
将特定的Service类用作:
class GroupRoleAffectionService {
function linkRoleToGroup ($role, $group)
{
//...
}
function unlinkRoleToGroup ($role, $group)
{
//business logic to find all invalid UserRoleAffectation with these role and group
...
// BL to remove all found UserRoleAffectation OR to throw exception.
...
// detach role
$group->removeRole($role)
//save all handled entities;
$em->flush();
}
$group->removeRole($role)
从此服务中调出。2-在域实体管理器中的实现
将这些业务逻辑封装在特定的“域实体管理器”中,也称为模型提供者:
class GroupManager {
function create($name){...}
function remove($group) {...}
function store($group){...}
// ...
function linkRole($group, $role) {...}
function unlinkRoleToGroup ($group, $role)
{
// ... (as in previous service code)
}
function otherBusinessRule($params) {...}
}
3-尽可能使用侦听器
使用symfony和/或Doctrine事件侦听器:
class CheckUserRoleAffectationEventSubscriber implements EventSubscriber
{
// listen when a M2M relation between Group and Role is removed
public function getSubscribedEvents()
{
return array(
'preRemove'
);
}
public function preRemove(LifecycleEventArgs $event)
{
// BL here ...
}
4-通过扩展实体来实现丰富的模型
将实体用作域模型类的子/父类,该类封装了许多域逻辑。但是这种解决方案对我来说似乎更加困惑。
对您来说,管理此业务逻辑的最佳方法是什么,将重点放在更干净,分离,可测试的代码上?您的反馈和良好做法?你有具体的例子吗?
主要资源:
从更长的角度来看,我发现解决方案1)是最容易维护的解决方案。解决方案2导致leads肿的“经理”类,最终将其分解成较小的块。
http://c2.com/cgi/wiki?DontNameClassesObjectManagerHandlerOrData
“大型应用程序中的服务类别过多”并不是避免SRP的原因。
在域语言方面,我发现以下代码类似:
$groupRoleService->removeRoleFromGroup($role, $group);
和
$group->removeRole($role);
同样,从您描述的内容来看,从组中删除/添加角色需要很多依赖项(依赖关系反转原理),而使用FAT /膨胀管理器可能很难做到。
解决方案3)与1)非常相似-每个订阅者实际上都是由实体管理器在后台自动触发的服务,在较简单的情况下它可以工作,但是一旦操作(添加/删除角色)需要大量上下文,就会出现麻烦。例如。哪个用户执行了操作,从哪个页面或任何其他类型的复杂验证中进行了操作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句