I have seen the following question on one of the forums I follow
"I have studied up on the SOA approach and it all sounds good. But most articles stop at the theory.
Lets
say I sell things. I have a CustomerProfileService. The application
does CRUD through this service to a back end database. Its autonomous
and isolated.
I have anther service, InventoryItemProfileService.
Again, the application does CRUD through this service to a back end
database. It is autonomous from the CustomerProfileService. Not only
may it live on a different DB from the CustomerProfileService, it might
exist on a different platform.
Now lets get to the InvoiceService.
Lets say from the client side, I would guess that i would have a
CreateInvoice(custID,itemID[] ) method. The InvoiceService would then
call out to the CustomerProfileService for profile that meets the needs
of the invoice, then another call out to the
InventoryItemProfileService for the item descriptions and such.
Here
is the question. It would seem like in the back end (the db) of the
InvoiceService there would be tables to support the customer info and
the item info from the invoice. Where prior to SOA, when everything
was in the same db, these requirements would be largely satisfied by
joins. Now a logical join across services just seems radically
expensive (everytime you touch the invoice). hence the need for the
customer and item tables local to the invoice service.
Does this sound right? Just how often does the InvoiceService have to go back to these other supporting services?"
I also got a comment with a similar theme on my
Cross Service Transactions post.
I
see a few problems with the way the services in the question are
modeled (like CRUDy interface) but in the end it all boils down to the
root cause -and the real problem:
granularity of the services.
Sure
when "a service" is too small it doesn't make sense to separate its
tables from those of other services. it doesn't make sense to have
transactions that span only what's internal to the service. It doesn't
make sense to pay the price to make a service autonomous (like caching
reference data from other services). When the granularity is too small
you will often find that you need to make a loot of interactions with
other so called services. you are more likely to have CRUDy interfaces.
You are also more likely to have slow performing solution and suffer from low-availability.
Using
services in a granularity mentioned above is, in my opinion, a
nightmare that would probably make you work very hard to maintain the
SOA principles in place - or the more likely option, that you would
circumvent the principles so that you can get something maintainable,
usable and performing (and flip the bozo bit on this all SOA thing)
So
what is the right granularity. Well, it is not a one-size-fits-all kind
of thing, but as a rule of thumb I would say anything just shy of a
sub-system and up. A service has to have enough meat so that it would
make sense having it autonomous; that the transactions would fit nicely
inside its boundaries; that it would be worthwile making it
highly-available; that you can pass a complete task/document to it and
it won't have to talk to a gazillion other services to complete
processing it; etc.
If your application's idea of invoices is a
2 tables one with a header and one with invoice details - then don't
make that a service. if invoicing is a sub-system with complex business
rules a lot of options and what-not - then it can be a good candidate
Think about it next time you design a service :)