6

我经常听到人们抨击 ORM 不灵活和“抽象漏洞”,但你真的没有听到它们为什么会出现问题。如果使用得当,ORMs到底有哪些缺陷?我问这个是因为我正在开发一个 PHP orm,我希望它能够解决许多其他 ORM 失败的问题,例如延迟加载和缺少子查询。

请具体回答。显示一些代码或描述 ORM 遇到困难的数据库模式。语言或 ORM 无关紧要。

4

5 回答 5

5

在我使用的所有 ORM 中,我注意到的一个更大的问题是只更新几个字段而不首先检索对象。

例如,假设我在数据库中映射了一个 Project 对象,其中包含以下字段:Id、name、description、owning_user。说,通过ajax,我只想更新描述字段。在大多数 ORM 中,我在只有 Id 和描述值的情况下更新数据库表的唯一方法是从数据库中检索项目对象,设置描述,然后将对象发送回数据库(因此需要两个数据库操作只是为了一个简单的更新)或通过存储过程更新它(这是我目前使用的方法)。

于 2010-05-10T14:06:01.847 回答
4

对象和数据库记录确实不是那么相似。他们已经键入了可以存储东西的插槽,但仅此而已。数据库具有与编程语言完全不同的身份概念。它们不能很好地处理复合对象,因此您必须使用额外的表和外键来代替。大多数没有类型继承的概念。而导航对象网络的自然方式(跟随一个对象中的一些指针,获取另一个对象,然后再次取消引用)在映射到数据库世界时效率要低得多,因为您必须进行多次往返并检索很多您不关心的数据。

换句话说:抽象不能一开始就做得很好;不好的不是 ORM 工具,而是它们实现的隐喻。它不是一个完美的同构,它只是一个表面的相似性,所以任务本身并不是一个很好的抽象。(不过,它仍然比必须深入了解数据库更有用。对 ORM 工具的蔑视主要来自 DBA 看不起单纯的程序员。)

于 2010-05-10T13:56:19.307 回答
3

ORM 也可以编写效率不高的代码。由于数据库性能对大多数系统至关重要,因此它们可能会导致如果有人编写代码本来可以避免的问题(但如果相关人员不了解数据库性能调整,情况可能不会更好)。当查询变得复杂时尤其如此。

我认为我对它们的最大问题是,通过抽象出细节,初级程序员对如何编写查询的理解越来越少,他们需要能够处理边缘情况以及 ORM 编写非常糟糕的代码的地方。当您不必了解基础知识时,很难学习高级的东西。了解联接和分组以及高级查询的人手中的 ORM 是一件好事。在不了解布尔代数和连接以及一堆其他基本 SQL 概念的人手中,这是一件非常糟糕的事情,导致数据库和查询的设计非常糟糕。

关系数据库不是对象,不应被视为对象。试图把一只老鹰做成一个丝绸钱包,一般都不会成功。了解老鹰擅长什么以及为什么并让老鹰飞翔远比拥有一个坏钱包和一只死鹰要好得多。

于 2010-05-10T15:06:05.503 回答
1

我的看法是这样的。要使用 ORM,您通常必须堆叠几个 php 函数,然后连接到数据库并基本上仍然运行 MySQL 查询或类似的东西。

为什么代码和数据库之间的所有抽象?为什么我们不能只使用我们已经知道的东西?通常,Web 开发人员了解他们的后端语言、数据库语言(某种 SQL)和某种前端语言,例如 html、css、js 等……

本质上,我们正在尝试添加一个包含许多函数的抽象层(我们都知道 php 函数可能比分配变量要慢)。是的,这是一个微观计算,但它仍然加起来。

我们现在不仅有几个函数要处理,而且我们还必须学习 ORM 的工作方式,所以在那里浪费了一些时间。我认为代码分离的整个想法是让你的代码在所有级别上都是分开的。如果您在 LAMP 世界中,只需创建您的查询(您应该了解 MySQL)并使用已经存在的 php 功能来准备语句。完毕!

灯方式:

  • 创建查询(字符串);
  • 使用 mysqli 准备好的语句并将数据检索到数组中。

ORM方式:

  • 运行一个获取实体的函数
  • 运行 MySQL 查询
  • 运行另一个添加条件的函数
  • 运行另一个添加另一个条件的函数
  • 运行另一个加入的函数
  • 运行另一个在连接上添加条件的函数
  • 运行另一个准备的函数
  • 运行另一个 MySQL 查询
  • 运行另一个获取数据的函数
  • 运行另一个 MySQL 查询

其他人对 ORM 堆栈有问题吗?为什么我们会变得如此懒惰的开发者?或者太有创意以至于我们损害了我们的代码?如果它没有坏,就不要修理它。反过来,修复您的开发团队以了解 Web 开发的基础知识。

于 2014-05-29T17:49:47.887 回答
0

ORM 试图解决一个非常复杂的问题。有大量的边缘案例和主要的设计权衡,没有明确或明显的解决方案。当您针对情况 A 优化 ORM 设计时,您天生就难以解决情况 B。

有一些 ORM 以“足够好”的方式处理延迟加载和子查询,但几乎不可能从“足够好”到“很好”。

在设计您的 ORM 时,您必须很好地处理您的 ORM 将要处理的所有可能的笨拙数据库设计。您必须明确权衡您愿意笨拙地处理哪些情况。

我不认为 ORM 比一般的复杂抽象更不灵活或更容易泄漏。也就是说,某些 ORM 在这些方面比其他 ORM 更好。

祝你好运重新发明轮子。

于 2010-05-10T13:34:43.647 回答