为什么 SOA 设计中的 CRUD 操作如此糟糕?
我刚刚读完 John Evdemon 撰写的 MSDN 上的一篇文章。他猛烈抨击 CRUD 接口并将其称为反模式。
虽然我同意让任何东西有状态是很困难的,并且 Current 和 MoveNext 是坏主意,但我不同意 Create Read Update 和 Delete 中的 CRUD 是坏主意。如果我有汽车服务,并且我想让客户能够执行基本操作,例如创建汽车、获取汽车详细信息、更新汽车详细信息或删除汽车,那么他们如何能够执行这些操作没有 CRUD 操作。
或者我在这里缺少什么?
I have just finished reading an article on MSDN by John Evdemon. He bashes the CRUD interfaces and calls it an anti-pattern.
While I agree that having ANYTHING stateful is difficult and Current and MoveNext are bad ideas I don't agree that CRUD as in Create Read Update and Delete are bad. If I have a car service and I want to let clients be able to do the basics, as in Create a car, get a cars details, update a cars details or delete a car then how are they meant to be able to do those things without CRUD operations.
Or what am I missing here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在分布式系统/SOA 场景中应避免使用 CRUD 接口,因为它们非常繁琐。但应该并不意味着必须。当您有一些客户端操作需要多次调用您的服务时,您就知道应该放弃 CRUD 方法并创建新的服务操作,将这些调用聚合为单个调用。在设计分布式系统时,您应该始终将调用次数减少到最少,因为网络调用非常耗时。
编辑:
您可以将 CRUD 接口视为服务中公开的数据访问。有时你真的想要这个。但在 SOA 和分布式系统架构中,您通常会公开已经封装了数据访问并提供更复杂的操作(聚合许多数据访问操作)的业务功能。
示例:
CRUD x 业务逻辑接口。假设您正在使用
发票
。每张发票均由一个InvoiceHeader
和一个或多个InvoiceLine
组成。如果您对发票使用 CRUD 接口,您将首先调用CreateInvoiceHeader
操作来创建InvoiceHeader
,然后调用几个AddInvoiceLine
操作来添加所有InvoiceLines
- 这是低级 CRUD 方法。但是,如果您在服务端实现业务逻辑,您将调用单个 CreateInvoice 并将复杂的对象图(包含所有行的标头)传递给服务以创建和添加所需的内容。 Create 方法还可以执行其他业务操作,例如启动某些工作流等。这是常见的 SOA 和分布式系统方法。The CRUD interfaces should be avoided in distributed system / SOA scenario because they are very chatty. But should doesn't mean have to. When you have some client actions which require more than one call to your service then you know that you should give up CRUD approach and create new service operation which will agregate those calls into single call. When designing distributed system you should always reduce number of calls to minimum because network call is very time consuming.
Edit:
You can think about CRUD interface as about data access exposed in a service. Sometimes you really want this. But in SOA and distributed system architecture you are usually exposing business functionality which already wraps data access and offers much more complex operations (which agregate many data access operations).
Example:
CRUD x Business logic interface. Suppose that you are working with
Invoices
. Each invoice consists of anInvoiceHeader
and one or moreInvoiceLine
. If you use a CRUD interface for invoice you will first callCreateInvoiceHeader
operation to createInvoiceHeader
and then severalAddInvoiceLine
operations to add allInvoiceLines
- that is low level CRUD approach. But if you implement business logic on the service side you will call singleCreateInvoice
and pass a complex object graph (header with all lines) to the service to create and add what is needed. TheCreate
method can also do other business operations like starting some workflow etc. That is common SOA and distributed system approach.最近流行的 RESTfull Web 服务 事实证明 John Evdemon 先生的帖子是错误的。
RESTfull web services which have been lately gaining popularity are proving wrong Mr. John Evdemon's post.
我认为他故意在这里设计了最糟糕的界面,而且它并不是真正的 CRUD 界面。
这两个方法显然不是无状态的,但它们也不是真正的 CRUD 接口所需要的。我认为这只是一个写得非常糟糕的例子,它与 CRUD 操作并没有真正的关系。
更新:
发现一个类似的问题,有一个非常好的答案:)
I think he has on purpose designed the worst possible interface here and it is not really a CRUD interface.
These two methods are obviously not stateless, but nor are they needed for a true CRUD interface. I think it just a very poorly written example and it is not really related to CRUD operations.
Update:
Found a similar question with a very good answer :)
接受的答案是不正确的。尽管 John 使用 CRUD 作为反模式示例,但使用 CRUD 对于 SOA 来说并不坏。 John 描述了 SOA 的问题:它会增加服务级别的复杂性,最终导致对多个用例的支持减少。我们构建 API 的主要原因之一是提供对多个应用程序的访问,这是构建 API 的主要投资回报率。
例如,假设我们有一个博客 API。假设我们让用户能够在外部应用程序的一个屏幕上撰写帖子、添加图像和发表评论。在 John 的 SOA 愿景中,他可能会建议我们构建 API 以使用一次调用来完成所有这些事情,这样就不会那么啰嗦和废话……所以:
现在显然存在三个不同的数据对象需要单独存储在这里:帖子、评论和图像。从数据存储的角度来看,帖子会转到 POSTS 表,评论会转到 COMMENTS 表,图像会转到 IMAGES 表。因此,如果我们按照 John 描述的那样按照 SOA 租户构建我们的服务,我们会对我们的对象进行一次调用,然后它会尝试创建帖子,例如,工作正常,然后它会尝试创建帖子注释工作正常,但当我们访问图像时,服务意识到其中一个图像 URL 有错误,因此失败。那么我们的服务返回失败?即使其他 3 个部分现在已成功存储在我们的数据存储中?我们是否要返回并撤消所有成功执行的部分?如果数据存储已经提交了更改,并且我们无法将其回滚怎么办?
再加上这样一个事实:如果我们让它变得“更健谈”并单独提交它们,我们现在可以在其他应用程序中重复使用这些服务,而无需重写服务的任何部分。
综合服务的不好之处在于,你被认为服务永远不会失败……这是荒谬的。总会有一种边缘情况,某些事情会失败,通过将所有内容整合到一项服务中,您增加了复杂性,实际上也增加了失败的能力。
我会将这个版本的 SOA 与我们在面向对象编程中构建上帝对象时已经认识到的缺点进行比较。 https://en.wikipedia.org/wiki/God_object
我们比这更清楚,所以为什么我们重述一下吗?联合或上帝服务就像上帝对象一样是个坏主意。我说构建你的服务来做一件事,并在尽可能多的用例中做好它,你的服务就会很好。
The accepted answer is incorrect. And despite the fact that John uses CRUD as a anti-pattern example using CRUD for are not bad for SOA. Here's the problem with SOA as John describes: it encourages increased complexity at the Service Level, which ultimately leads to less support for multiple use cases. One of the main reasons we build APIs is to provide access to multiple applications, this is where the primary ROI is in building APIs.
For example let say we have a blog API. Let say we give users the ability to write posts, add images and put comments in all on one screen of our external application. In John's vision of SOA he would probably recommend that we build our API to use one call to do all of these things so it would be less chatty and blah blah blah... so:
Now there are obviously three different data objects that need to be separately stored here: the post, the comments and the images. From the data store's perspective the post goes to the POSTS table the comments to the COMMENTS table and the images to the the IMAGES table. So if we build our service following the tenants of SOA as John describes them we make our one call with our object and it goes the the services which attempts to create the post which, for example purposes, works just fine then it attempts to create the comments which work fine but when we get to the images the service realizes that one of the image URLs is faulty are fails. So our service returns a failure? Even though 3 other parts are now successfully stored in our data store? Do we go back and undo all the parts that execute successfully? What if the data store has already committed the changes, and we can't roll it back?
Couple this with the fact that if we'd made it "more chatty" and submitted them individually we could now re-use those services in other applications without needing to re-write any part of the service.
The bad part of the consolidated services is that you are being sold on the idea that the service should never fail... which is ridiculous. There will always be an edge case where something will fail and by consolidating everything into to one service you have increased your complexity and actually increased your capacity to fail.
I would compare this version of SOA to the shortcomings we've already realized in building God Objects in Object Oriented Programming. https://en.wikipedia.org/wiki/God_object
We know better than this so why are we rehashing it? Consolidated or God Services are a bad idea just like God Objects. I say build your services to do one thing and do it well for as many use cases as you can and your service will be good.