ORM 的失败点在哪里?
我经常听到人们批评 ORM 不灵活和“抽象漏洞”,但你真的不知道为什么它们有问题。如果使用得当,ORM 到底有什么缺点呢?我问这个问题是因为我正在开发一个 PHP orm,并且我希望它能够解决许多其他 ORM 无法解决的问题,例如延迟加载和缺少子查询。
请具体回答。显示一些代码或描述 ORM 遇到困难的数据库模式。语言或 ORM 并不重要。
I often hear people bashing ORMs for being inflexible and a "leaky abstraction", but you really don't hear why they're problematic. When used properly, what exactly are the faults of ORMs? I'm asking this because I'm working on a PHP orm and I'd like for it to solve problems that a lot of other ORMs fail at, such as lazy loading and the lack of subqueries.
Please be specific with your answers. Show some code or describe a database schema where an ORM struggles. Doesn't matter the language or the ORM.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我注意到我使用过的所有 ORM 的一个更大问题是只更新了几个字段,而没有先检索对象。
例如,假设我的数据库中映射了一个 Project 对象,其中包含以下字段:Id、name、description、owning_user。比如说,通过 ajax,我只想更新描述字段。在大多数 ORM 中,在只有 Id 和描述值的情况下更新数据库表的唯一方法是从数据库中检索项目对象,设置描述,然后将对象发送回数据库(因此需要两个数据库操作)只是为了一个简单的更新)或通过存储过程更新它(这是我当前使用的方法)。
One of the bigger issues I have noticed with all the ORMs I have used is updating only a few fields without retrieving the object first.
For example, say I have a Project object mapped in my database with the following fields: Id, name, description, owning_user. Say, through ajax, I want to just update the description field. In most ORMs the only way for me to update the database table while only having an Id and description values is to either retrieve the project object from the database, set the description and then send the object back to the database (thus requiring two database operations just for one simple update) or to update it via stored procedures (which is the method I am currently using).
对象和数据库记录确实不太相似。他们有可以存储东西的打字槽,但仅此而已。数据库具有与编程语言完全不同的身份概念。它们不能很好地处理复合对象,因此您必须使用额外的表和外键。大多数人没有类型继承的概念。当映射到数据库世界时,导航对象网络的自然方式(遵循一个对象中的一些指针,获取另一个对象,然后再次取消引用)的效率要低得多,因为您必须进行多次往返并检索大量数据您不关心的数据。
换句话说:抽象一开始就不能做得很好;糟糕的不是 ORM 工具,而是它们实现的隐喻。它并不是完美的同构,而只是表面上的相似性,因此任务本身并不是一个很好的抽象。 (不过,它仍然比必须深入了解数据库有用得多。对 ORM 工具的蔑视主要来自 DBA 对单纯程序员的蔑视。)
Objects and database records really aren't all that similar. They have typed slots that you can store stuff in, but that's about it. Databases have a completely different notion of identity than programming languages. They can't handle composite objects well, so you have to use additional tables and foreign keys instead. Most have no concept of type inheritance. And the natural way to navigate a network of objects (follow some of the pointers in one object, get another object, and dereference again) is much less efficient when mapped to the database world, because you have to make multiple round trips and retrieve lots of data that you didn't care about.
In other words: the abstraction cannot be made very good in the first place; it isn't the ORM tools that are bad, but the metaphor that they implement. Instead of a perfect isomorphism it is is only a superficial similarity, so the task itself isn't a very good abstraction. (It is still way more useful than having to understand databases intimately, though. The scorn for ORM tools come mostly from DBAs looking down on mere programmers.)
ORM 还可能编写效率不高的代码。由于数据库性能对大多数系统至关重要,因此它们可能会导致一些问题,而如果由人编写代码,这些问题本来可以避免(但如果相关人员不了解数据库性能调优,情况可能也不会好多少)。当查询变得复杂时尤其如此。
我认为他们最大的问题是,通过抽象细节,初级程序员对如何编写查询的理解越来越少,而他们需要能够处理边缘情况以及 ORM 编写非常糟糕的代码的地方。当你不需要了解基础知识时,学习高级的东西真的很难。 ORM 掌握在了解连接、分组依据和高级查询的人手中是一件好事。对于不了解布尔代数和连接以及一堆其他基本 SQL 概念的人来说,这是一件非常糟糕的事情,导致数据库和查询的设计非常糟糕。
关系数据库不是对象,不应被视为对象。试图将鹰制作成丝绸钱包通常不会成功。了解老鹰擅长什么以及为什么,然后让老鹰飞翔,远比钱包坏了和老鹰死了要好得多。
ORMs also can write code that is not efficient. Since database performance is critical to most systems, they can cause problems that could have been avoided if a human being wrote the code (but which might not have been any better if the human in question didn't understand database performance tuning). This is especially true when the querying gets complex.
I think my biggest problem with them though is that by abstracting away the details, junior programmers are getting less understanding of how to write queries which they need to be able to to handle the edge cases and the places where the ORM writes really bad code. It's really hard to learn the advanced stuff when you never had to understand the basics. An ORM in the hands of someone who understands joins and group by and advanced querying is a good thing. In the hands of someone who doesn't understand boolean algebra and joins and a bunch of other basic SQL concepts, it is a very bad thing resulting in very poor design of database and queries.
Relational databases are not objects and shouldn't be treated as such. Trying to make an eagle into a silk purse is generally not successful. Far better to learn what the eagle is good at and why and let the eagle fly than to have a bad purse and a dead eagle.
我的看法是这样的。要使用 ORM,您通常必须堆叠多个 php 函数,然后连接到数据库,并且本质上仍然运行 MySQL 查询或类似的东西。
为什么在代码和数据库之间进行所有抽象?为什么我们不能只使用我们已经知道的东西呢?通常,Web 开发人员了解他们的后端语言、数据库语言(某种 SQL)以及某种前端语言,例如 html、css、js 等……
本质上,我们试图添加一层包含许多函数的抽象(我们都知道 php 函数可能比分配变量慢)。是的,这是一个微观计算,但它仍然是加起来的。
我们现在不仅有几个函数需要执行,而且还必须学习 ORM 的工作方式,因此浪费了一些时间。我认为代码分离的整个想法是让您的代码在各个级别上保持分离。如果您在 LAMP 世界中,只需创建查询(您应该了解 MySQL)并使用已存在的 php 功能来准备语句。完毕!
LAMP WAY:
ORM 方式:
其他人对 ORM 堆栈有问题吗?为什么我们会成为如此懒惰的开发者?或者我们太有创意以至于损害了我们的代码?如果它没有坏,就不要修理它。反过来,让你的开发团队了解 Web 开发的基础知识。
The way I see it is like this. To use an ORM, you have to usually stack several php functions, and then connect to a database and essentially still run a MySQL query or something similar.
Why all of the abstraction in between code and database? Why can't we just use what we already know? Typically a web dev knows their backend language, their db language (some sort of SQL), and some sort of frontend languages, such as html, css, js, etc...
In essence, we're trying to add a layer of abstraction that includes many functions (and we all know php functions can be slower than assigning a variable). Yes, this is a micro calculation, but still, it adds up.
Not only do we now have several functions to go through, but we also have to learn the way the ORM works, so there's some time wasted there. I thought the whole idea of separation of code was to keep your code separate at all levels. If you're in the LAMP world, just create your query (you should know MySQL) and use the already existing php functionality for prepared statements. DONE!
LAMP WAY:
ORM WAY:
Does anyone else have a problem with the ORM stack? Why are we becoming such lazy developers? Or so creative that we're harming our code? If it ain't broke don't fix it. In turn, fix your dev team to understand the basics of web dev.
ORM 正在尝试解决一个非常复杂的问题。存在大量的边缘情况和主要的设计权衡,但没有明确或明显的解决方案。当你针对情况 A 优化 ORM 设计时,本质上会让解决情况 B 变得很尴尬。
有些 ORM 可以以“足够好”的方式处理延迟加载和子查询,但从“足够好”到“足够好”几乎是不可能的。伟大的”。
在设计 ORM 时,您必须很好地处理 ORM 需要处理的所有可能的尴尬数据库设计。你必须明确地权衡你愿意尴尬地处理哪些情况。
我不认为 ORM 不灵活,或者比一般的复杂抽象更容易泄漏。也就是说,某些 ORM 在这些方面比其他 ORM 更好。
祝你重新发明轮子好运。
ORMs are trying to solve a very complex problem. There are edge cases galore and major design tradeoffs with no clear or obvious solutions. When you optimize an ORM design for situation A, you inherently make it awkward for solving situation B.
There are ORMs that handle lazy loading and subqueries in a "good enough" manner, but it's almost impossible to get from "good enough" to "great".
When designing your ORM, you have to have a pretty good handle on all the possible awkward database designs your ORM will be expected to handle. You have to explicitly make tradeoffs around which situations you are willing to handle awkwardly.
I don't look at ORMs as inflexible or any more leaky than your average complex abstraction. That said, certain ORMs are better than others in those respects.
Good luck reinventing the wheel.