SOA, coupling, flexibility and discipline

Some thoughts on Service Oriented Architectures and how for some people the silver bullet du jour is the only tool in their toolbox… Just a bit of a rant really…

Recently, both Rocky Lhotka and Ted Neward have said plenty of interesting things about Service Oriented Architecture (SOA). I’m in complete agreement, SOA is a “good thing” and yet since it’s such an expensive option, in terms of complexity, performance and (potentially) cash, you need to make sure that you know where not to use it. A post on Hurricane Blog links Rocky’s ideas about trust boundaries to Roger Sessions’ Software Fortresses ideas; which again makes perfect sense to me.

For me, SOA is for providing an interface into your world for those who are not of your world… It’s a way of allowing platform and language independent access to your systems whilst protecting both your users and yourself from the cost of change. The loose coupling and flexibility that the SOA model provides is required so that you can allow as many people as possible access to your systems whilst imposing as few restrictions as possible on how they access you. The cost of this flexibility is complexity; no matter how easy the tools and wizards make it, and how much they hide, using a Service to do something is more complex than making a function call in your language of choice. What’s more, because of that flexibility you need to be vigilant in how these outsiders access you…

Steve Loughran seems to suggest that all this flexible goodness should be pulled deep into your application; if it’s good enough for web services, it’s good enough for function calls… He’s passing DOM objects around…

I’m sorry Steve, but as far as I’m concerned, that way lies madness. As Ted points out, if you’re passing DOM objects or XML around inside your application, you may as well just be using a map of maps, or, as it was back in the day, a void *. All that untyped data that you’re passing around isn’t really as loosely coupled as you think; it’s just implicitly coupled via the schema of the blob of data that you’re passing around. The function you’re calling and the instigator of the call both need to agree on what you need to do the work that’s required. You may have made it easier to get that data from A to B (look ma, I don’t need to change all the functions between here and there to pass this new boolean flag into SoAnSo()) but what you’re really doing is transferring rules that your compiler can help you enforce into rules that your schema needs to enforce… You’re breaking down the walls of your code to increase the flexibility and reduce the coupling but when taken to extremes you just end up with soup…

The problem is that reducing the explicit coupling doesn’t reduce the discipline that’s required to write good and maintainable code; in fact, it increases it. In the explicitly coupled world, when you need to add a new parameter you need to think about how that affects your system, you need to change things, redesign perhaps. This takes time, your compiler forces you to take some of the steps; true you can cheat, use ‘poor’ coding practices to ‘speed things up’ but it’s easy to see the code rot if you take shortcuts… In the world of implicit coupling you don’t need to think about the knock on effects if you don’t want to… You can just adjust your schema and poke in the new piece of data and watch it flow through to where it’s needed… Unfortunately this can break down… When things get hairy and schedules start to slip I’ve been told that some people might consider the schema to their data blob to be something that is ‘slowing them down’, it’s something that ‘makes it harder to change the system in the way that the business needs’, etc. So, I’ve been told, some people, sometimes, ditch the schema… Soup is all well and good, but I wouldn’t want to live in it.

I often find that a flexible system is harder to understand than a rigid system. The rules are often implicit rather than explicit; they may be in a schema, a document, or someone’s head. As the system becomes bigger and more flexible it actually becomes harder to change because the affects of the changes that you want to make are harder to determine, you cant tell what code is dead because you’d need to examine all the inputs to your system to work out if that particular data blob could ever exist in the wild…

When the world consists of umpteen components that have a single method, DoIt(), that takes a void * blob of data in and returns a void * blob of data and the application can solve any problem just by adding a new component or two and adjusting the implied meaning buried in the blob of phlegm that the components spit at each over, then, well, it’s probably way past the time that the original designers decided to catch the next silver bullet train out of the organisation…