服务层:是否应该隐藏域模型';API


Service Layers: Should it hide the domain models' API?

我正在加载Zend 1.11和与Doctrine 1.2的集成,并且已经阅读了很多关于服务层使用的内容。

据我所知,服务层位于业务逻辑之上,在控制器和域模型之间添加了一层。

但是,我一直纠结于如何真正实现服务层,主要是因为我有点不确定应该为服务类定义什么类型的API。

首先,给定一个服务类App_Service_Memberships,它将处理具有App_Model_Group的业务实体组和作为App_Model_User:的用户

服务类的API是否应该通过接受或返回所述域模型的实例来公开类的组成?

或者服务类的API应该通过只接受或返回本机数据类型(如整数或数组)来隐藏类的组成吗?

比如说:

class App_Service_Memberships
{
    public function addUserToGroup($user_id, $group_id)
    {
        //Create or retrieve domain models here and operate on them; handle persistence.
        $membership = new App_Model_Membership();
        $membership->member->user_id = $user_id;
        $membership->group->group_id = $group_id;
        $membership->join_date = date("Y-m-d H:i:s");
        $membership->save();
        return $membership->toArray();
    }
    public function getMembersOfGroup($group_id)
    {
         $groupMembers = array();
         //Query objects here with Doctrine or the ORM of choice...
         foreach($results as $membership){
             $groupMembers[] = $membership->member->toArray();
         }
         return $groupMembers;
    }
}

其中,控制器只将整数作为参数(表单中的数据或其他服务类的输出)传递给服务类,完全忽略了所涉及的域模型。

与相反

class App_Service_Memberships
{
    public function addUserToGroup(App_Model_UserInterface $user, App_Model_Group $group)
    {
        //Create or retrieve domain models here and operate on them; handle persistence.
        $membership = new App_Model_Membership();
        $membership->member = $user;
        $membership->group = $group;
        $membership->join_date = date("Y-m-d H:i:s");
        $membership->save();
        return $membership;
    }
    public function getMembersOfGroup(App_Model_Group $group)
    {
         $groupMembers = array();
         //Query memberships here
         foreach($results as $membership){
             $groupMembers[] = $membership->member;
         }
         return $groupMembers;
    }
}

控制器在哪里处理其范围内的域模型,并将它们传递给服务类?

你认为哪种做法更好?

服务类的API是否应该通过只接受或返回本机数据类型(如整数或数组)来隐藏类的组成?

是的,这很理想。如果您强制服务的客户端(在本例中为控制器)传入预先构建的域实体(用户),则会强制客户端了解该域的很多信息。不应该。

您的服务方法也可以是静态的(但它们不一定必须是静态的)。

您并不是真的需要服务类上的App_前缀。不确定这是ZF社区什么时候开始的,但它已经被货物崇拜致死,真的没有必要。我通常将服务(以及所有特定于应用程序的内容)放在lib下。更具体地说,我使用src/main/lib,它与src/test/*src/vendor/lib配合得很好。

至于返回值。。。我通常会让服务方法返回某种集合。数组很好;然而,在许多情况下,更丰富的集合对象是非常有用的(但不是强制性的)。有时我只是使用ZendPaginator对象来强调它的实用性。它不是可用的最丰富的集合对象,但它可以OOTB工作。