Why are CRUD operations so bad in a SOA design?
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 car开发者_开发问答s 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?
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 an InvoiceHeader
and one or more InvoiceLine
. If you use a CRUD interface for invoice you will first call CreateInvoiceHeader
operation to create InvoiceHeader
and then several AddInvoiceLine
operations to add all InvoiceLines
- that is low level CRUD approach. But if you implement business logic on the service side you will call single CreateInvoice
and pass a complex object graph (header with all lines) to the service to create and add what is needed. The Create
method can also do other business operations like starting some workflow etc. That is common SOA and distributed system approach.
RESTfull web services which have been lately gaining popularity are proving wrong Mr. John Evdemon's post.
I think he has on purpose designed the worst possible interface here and it is not really a CRUD interface.
<WebMethod()> _
Public Function MoveNext() As Boolean
End Function
<WebMethod()> _
Public Function Current() As Object
End Function
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 :)
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:
{
"post_title": "New Post",
"post_content": "Some Stuff....",
"comments": [{
"comment": "This is right on!",
"userId": 101
}, {
"comment": "I agree.",
"userId": 105
}],
"images": [{
"imgURL": "http://some.img.com/1"
}, {
"imgURL": "http://some.img.com/2"
}]
}
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.
精彩评论