现在,假设一个表单在网页上提交,我的控制器知道它需要根据提交的信息创建一个新的UserEntity.
可以:
>当场新建UserEntity(),并根据提交的表单数据运行所有必要的setter方法,然后将UserEntity传递给repo,后者将传递给mapper进行插入?
控制器创建UserEntity => Repo => Mapper => D B
>将表单数据转换为数组,并将其传递给UserRepository,然后UserRepository运行新的UserEntity()和setter,并将其传递给mapper进行插入?
控制器传递用户数据=> Repo创建UserEntity => Mapper => D B
>将数组传递给UserRepository,UserRepository将数组传递给映射器以获取新的UserEntity和插入?
控制器传递用户数据=> Repo传递用户数据=> Mapper创建UserEntity => D B
谁负责管理对象的创建?
控制器
我认为控制器是应用程序的粘合剂.我们可以将我们想要的所有问题分成尽可能多的部分,但是在某个地方,某些东西必须要理解视图侧和模型侧,并且该对象是控制器.话虽这么说,我相信控制器应该是瘦的,所以控制器唯一真正的工作就是将请求映射到响应.任何类型的中间处理都应该在其他地方开始.
在CRUD应用程序中,通过实例化新对象并将它们持久保存在控制器中非常容易,即使它不止一次,因为它只需几行就可以粘贴.如果对象创建不是微不足道的呢?我正在维护一个具有许多复杂关系的应用程序,而用户提交的创建通常需要同时创建许多对象.在仅控制器和模型环境中维护是不可行的.
额外的服务层
为了解决这个问题,我创建了2个额外的服务层:FormHandler和Manager.每次提交表单时,表单内容都会发送到表单处理程序层.表单处理程序负责理解进入的表单数据并使其正常化.然后,表单处理程序可以将数据传递给适当的管理器对象以进行处理. Manager对象处理数据并更新域层.他们负责创建模型,更改模型并将其持久化到后端.
通过这种方式,控制器具有Request,Response,Form(可能,如果您的框架支持服务器端表单创建)和FormHandler的知识.表单处理程序具有表单(或表单数据)和管理器的知识. Manager具有Repository,Mapper和Model的知识.请注意,现在,Managers是与Models和Mapper交互的唯一点,他们不了解Form数据或Request或Response.另一方面,控制器和表单处理程序不需要知道域层数据或持久性.
结论
有了这个设计:
控制器 – > FormHandler – > ModelManager – >映射器
我发现我的所有类都是单元可测试的(甚至控制器在某种程度上)由于关注点的分离很好地拆分,单点交互是避免重复逻辑的福音.
笔记
我脑子里的回购只是为了查询数据库 – 询问它是否有东西,而不是创造新东西.
我在这种情况下的经验来自于使用Symfony 2和Doctrine 2.
因人而异;例如您可能会发现表单层是不必要的,但我发现从表单/视图数据到域模型理解的数据转换非常方便.