在Symfony2/Doctrine中使用实体和存储库的正确方法(tm)


Right way(tm) to use entities and repositories in Symfony2/Doctrine

好的,所以这不是一个特定的"我做错了什么"编码问题,对不起。如果它更适合其他堆栈*站点之一,请告诉我。

今天我被他们使用Symfony2和Doctrine的承包演出解雇了。我是一名高级程序员,但对这两个框架都不是很有经验 - 尽管我确信我可以快速启动和运行。毕竟,这是PHP-可能出错的地方是什么?

我指定的队友(作为"Symfony专家",所以我一开始非常乐意观看和学习)一直坚持"实体应该是不可变的,所有自定义业务逻辑都应该放在存储库中"。阅读文档(入门指南,不少),这似乎是不正确的 - 存储库是针对"自定义获取者"的,但数据操作是在实体中进行的(学说-模型)。对我来说非常有意义(数据库无法知道 bitflag 1 是否表示"活动"和 2 "确认电子邮件"),但这家伙很可爱。当被问及如何在存储库中添加自定义数据编辑方法的示例时(因为我兜风了一会儿,但无法让 Symfony 看到它们而不经历箍和手动用存储库替换实体),他发送了一个代码示例,实现了或多或少的手动更新查询。那为什么首先使用ORM?

他还反复表示,永远不应该接触实体,因为更改在重新生成时可能会被覆盖。除了 Doctrine 似乎通常假设您编写实体并从中生成数据库方案这一事实之外 - 而不是相反 - 除非我对英语的了解神秘地失败,手册似乎清楚地指出,当(重新)生成实体时,现有方法被单独保留,因此它是完全安全的。

故事结束时,客户决定我们不能一起工作,选择了另一个人。他们也有这种奇怪的论点,认为我是"项目中最昂贵的人",而我"没有提供足够的资历"。我确实指出,告诉别人他们只是错了并为此大喊大叫(真实的故事,好吧,他们输入了所有大写字母,这在我的书中算作大喊大叫)也没有让我很开心,所以就是这样 - 我祝他们好运,我们分道扬镳。

我在这里失去理智了吗?我错过了一些显而易见的东西吗?还是另一个人只是被误导了(我目前的工作理论),什么属于实体,什么属于存储库?任何在Doctrine/Symfony方面有经验的人都愿意详细说明吗?我很乐意提供更具体的例子来说明我们应该构建的内容。我非常好奇地想知道在这些框架中做事的"正确方法"(tm)(供将来参考,它们还没有完全激发我的胃口),如果确实有更好的方法可以将模型代码从实体中剥离出来。

>Symfony2的构建是为了让你选择如何回答这些问题。它的结构是模块化的,允许您仅选择和使用所需的组件。有许多常见的设计模式,但显然团队需要选择一个并坚持下去。如果你们做不到这一点,那么你们没有尝试一起完成一个项目可能是件好事。

我认为在Symfony2中保持实体和控制器尽可能稀疏和易于阅读是一种很好的做法。我在存储库中几乎没有任何不构建查询并运行查询的内容。几乎所有其他东西都应该在一种或另一种服务中。如何在服务之间强制分离关注点留给开发团队进行练习。

这是一篇讨论一组常见设计模式的文章:http://www.ricardclau.com/2012/02/where-is-the-model-in-symfony2-entities-repositories-and-services/

在掌握如何做事和在哪里放置薄片时,另一个值得一看的好事是浏览一些核心/大型symfony捆绑包,看看它们把东西放在哪里,以及不同风格的组织对不同目的有多大意义(有些比其他的做得更好)。

他的具体主张:

1)实体应该是不可变的

这似乎会导致您失去Doctrine的EntityManger和UnitOfWork提供的大部分功能。如果随后仅使用手动查询更新它们,则必须重新加载实体以使其与更新的数据库状态匹配。如果您想在请求开始时加载一种状态并仅根据原始数据逐步处理对数据库的更新,我想这是有道理的。(原则确实在实体管理器中提供了将实体标记为只读的功能,以便不会保留对它们的更改。

2)所有自定义业务逻辑都应放入存储库中

在Symfony中,将"存储库"替换为"服务",这几乎是100%正确的。存储库通常应该只保存可重用的复杂查询的代码,超出了 Doctrine 的 findBy 方法所能得到的。

3)他还反复表示,永远不应该接触实体,因为更改在重新生成时可能会被覆盖。

真。。。就覆盖而言。每当您使用原则命令行工具从架构文件向实体添加更改时,都会发生这种情况,以便进行备份。但是,该工具相当聪明,我没有看到我的任何更改被覆盖。

您的具体索赔:

1)但数据操作在实体中进行(学说-模型)

实体不是"MVC"中的"M",而通常只是存储状态的"M"的一部分。相关逻辑通常在表单、数据转换器、验证器和其他服务中保持独立。

2)他发送了一个代码示例,实现了或多或少的手动更新查询。那为什么首先使用ORM?

即使您仅通过手动查询而不是使用 EntityManger 来更新数据,Doctrine 也提供了许多其他优势:编程查询生成、输入清理、实体催眠、查询/结果缓存、嵌套事务等。

只是听听你的故事,这听起来像是一个框架经验较少的高级开发人员与一个框架经验较多的不太高级的开发人员一起工作。我猜另一个开发人员从未单独/领导过绿地Symfony2项目,只是在鹦鹉学舌地模仿他以前的高级开发人员所做的设计决策。

你们

俩听起来都不完全"正确",你们俩都错了,因为你们陷入了一场必须由客户裁决的争论中。也许如果你不那么热衷于展示自己的正确性,并且更愿意通过深入研究他所倡导的做法背后的原因来利用和探索你伴侣的经验,你也许能够把它变成一个成功。或者,也许另一个开发人员只是一个工具,你为自己节省了一大堆压力和戏剧性,试图掩盖他的屁股:)