|
John Lam joins our discussion of Enterprise Services by discussing the obvious question
If I'm writing a managed application that has a web-based front end, and I don't need distributed transactions, why do I need to care about Enterprise Services?
The essence is, that if you're running transactions on a single resource manager, you don't need [Transaction(TransactionOption.Required)] but instead can simply use your resource managers's direct means of creating and confirming a transaction.
True, if you have full control of your application's source code, don't have to provide means of exensibility, know the exact call flows through all of your infrastructure layer components, and have the luxury of relying on a team of very smart developers of which everybody knows about the very transaction concept you're about to use in your application. No, change this to "a team of very smart developers of which everyone can recite and describe the very transaction concept you're about to use in your application even if you wake him up at 5 am after a long night at the bar.". TX' are just to precious. ;-)
I think however, that there are at least two scenarios where it simply doesn't make too much sense to go the way of imperative transactions:
First, if you're about to provide any kind of extensibility hooks (public interfaces, plugins, ...) you might run into trouble because the component which is dynamically loaded into your app (and of course, not know to you at compile time) could have different TX needs than your main app. It could for example want to run in a different transaction or even want to include another resource manager in your main transaction. Can you solve this without EnterpriseServices? Oh, definitely - E/S isn't magic, it's just some nice concepts. However, providing a clean TX logic in this case could be quite a complex task, because in essence every component would have to vote on the outcome of the TX. Actually, you might end up re-implementing some of the same things which are already available in EnterpriseServices. But why would you want to do so? It could be as easy as going for [Transaction(TransactionOption.Required)] and [Transaction(TransactionOption.RequiresNew)].
The second scenario in which I'd think about using EnterpriseServices is if I don't know the exact call chain of my infrastructure components. Using imperative, single resource manager transactions absolutely requires you to know the very call chain/s which will be used to call your infrastructure components.
<example type="very contrived"> public void StoreCustomer(Customer cust); public void AddOrder(Order ord); </example>
Perfect. In both methods, you open a transaction, store the data and return success/failure state by means of managed Exceptions. Problem is, when you designed this application like this some time ago, it was absolutely impossible (by the call chain logic in your GUI-based application) that an order could be submitted before the customer would exist in the database for at least some days. No need to share a TX here. (Pretty common scenario in the telco business because new customers have to be validated and approved using a somewhat lengthy process and would only end up in the SAP/R3 system some time later.)
However, your customer contacts you again and asks you (or some other party) to provide a web app which allows sales agents to add VIP customers ( f.e. new branch offices of already existing business customers) directly to your system without any further approval. And yes, they should of course also be allowed to order special services. So, how do you share your TX now? Yes, you could of course do it manually which is quite easy when talking about two methods but which becomes massively more complex when using a multitude of components which have not been designed, right from the start, to allow for sharing a TX. And still, what happens if you suddenly have to integrate other resource managers?
Contrived example? Well, some weeks ago, a developer working at one of my clients, called me up and told me about a problem she's currently facing. It involved a system which has not been designed to be changed but for which the initial developers decided that they know each and every possible call chain.
They were wrong.
The developer who had to extend this system was working for quite some time trying to retrofit TX sharing capabilities into the existing system and came to points where she decided that she had too make too many assumptions about the possible future call chains. The system would be quite fragile and again depend on certain invocation sequences. We discussed the issues on the phone and I recommended to her to look into EnterpriseServices before proceeding. She later sent me a thank-you note after converting most of her components to ServicedComponents instead of using manual TX sharing.
So, at least for me, the question which should be used to choose between declarative and imperative TX (and therefore also in favor or against EnterpriseServices) is not only "Do I need distributed transactions?" but also "Do I need transactions for which I don't know the exact call chains which will be used to access my infrastructure layer components?" and "Will these call chains ever change or could there be new ones?".
If you answered yes to any of these questions, you owe it to yourself to at least look into EnterpriseServices.
|