Over the past few days my thoughts have been drawn to what I think is a common problem (in addition to the ones identified by Freddie van Rijswijk in his recent blog) in establishing and participating in a SOA architecture: Won’t Let Go Syndrome (WLGS).
WLGS is a problem akin to the Not Invented Here Syndrome (NIHS), which is itself a specific form of Reinventing the wheel. However, where NIHS is an a-posteriori problem (an unwillingness to use the inventions and work of others), WLGS is an a-priori problem: an unwillingness to let anybody else solve your problems for you.
When working within a SOA, the idea is that you create one or more components, each of which is good at solving a certain problem really well and doing nothing else but that (don’t confuse that with the idea that a single SOA component must offer only one operation). Other problems must be solved by other, specialised components. And for larger problems it is often a good idea to have subproblems solved by other components as well. Back in the good old days of “simple” OOP, this was called delegating. However, as I continue to work in my work environment and am involved in more and more projects that create different components within what will become the companies SOA, I come across a weird phenomenon more and more often. For some reason people working on any given component are unwilling to entrust the care for their subproblems to any other component.
Some examples might clarify:
Some of my work involves enhancing components that support user-facing applications operated by the company I work for. Recently the company has been developing a new user-facing application that will rely on the same supporting components (albeit with extended functionality). Among others the supporting components expose functionality offered by a number of powerful backend systems. This is a typical integration task: different backend systems offer similar functionality in differing ways and a component within the SOA provides a unified interface for all of them to the rest of the universe. The implication of this architecture is of course that the user-facing application should not incorporate knowledge of the backend systems — rather, it should rely upon the abstractions provided by the supporting components. However, for the new functionality required by the new application a question arose about how communication should be managed with the backend system (one of the backend systems offered a notational shortcut). The lead developer of the user-facing application immediately responded by saying: “[We] will use that shortcut, but not in the first version; we’ll add it later.” It didn’t even occur to him to say “That shortcut is not my problem; the developers of the supporting components will have to figure it out.”
Another example: a certain component C within the SOA is responsible for exposing functionality in a third-party system in a friendly way. One of the exposed functions is access to a certain type of record. Those records can be created from several different sources and the records from one particular source sometimes contain errors when retrieved by the component C described above. This is problematic for a certain user-facing application that is going to be extended and wants to retrieve particularly large records using C. The main objection raised by an advisor to the development effort (a former developer)was that C sometimes returns an error in the part of the record that the application will want to use and that it would be very inconvenient for the application to have to deal with this error or work around it. For some reason the thought did not occur to ask the development team for component C to try and fix the problem.
Final example: a large application within the application landscape made use of payment logic. This logic was needed elsewhere as well, so the decision was made to split this logic off into a separate component. However, the logic had been built to fit into the large application’s process, so the attempt to split the payment logic off failed — the result was just too intertwined with the large application to be reused. After a time though, the decision was made to rebuild the large application itself (not because of the payment logic). Managment pounced on the opportunity and decided not to repeat the mistakes of the past: if there was to be a new large application, that would be a perfect opportunity to build a new, separate payment component as well — a reusable one. Of course that component would have to pay special attention to the needs of the new, large application (it being a very important application), but it should be very generic. However, the new large application was being designed and built by the same people who built the old one. And they had very strong ideas about how the process of the new large application should work. So they set requirements for the new payment component to fit into their process (instead of letting the new component offer a payment solution that merely offered the needed functionality). As a result of WLGS (this time relating to letting go of control), the new payment component has the large application’s process imprinted upon it. Which makes it highly questionable that it is, in fact, very generic at all.
As I hope is clear from these examples, WLGS greatly impedes one’s ability to play well in a SOA. It makes it difficult to look past your own little garden and make use of what it out there. It makes it difficult to get your problems solved (especially if your problems don’t live in your actual problem domain). And it makes it hard to develop software that is a real SOA component and not a monolithic whole.
Of course, WLGS is not new at all. As remarked before, delegating was considered a good idea in OOP. And yet (of course?) within projects that adopted OOP it was/is always a problem to get people to delegate. How often have you come across code that does exactly what a perfectly good library already does? Java code to perform null-safe String comparisons (like the commons-lang library, which the developer didn’t know abot and didn’t bother googling for)? Or object pooling? So it is not surprising to come across the same in SOA (although on a larger scale, since SOA is on a larger scale).
The really big problem with WLGS is that it isn’t a coding issue or a standards issue or anything you can automatically test for. Like its cousin the NIHS, WLGS is a thing that lives in the minds of developers and architects. It is part of the intangible, psychological aspects that make software engineering a different discipline than computing science. And that makes dealing with it difficult as well; the only thing that I can currently think of that can counter WLGS is review of design ideas by someone from outside the scope of the development unit. Another developer working on another subsystem, for instance, might spot a missed opportunity for delegation and reuse within an OOP application.
Of course on the grander scale of SOA you need review from outside the project by someone who can look over the fence and see what the neighbors have to offer. And this in turn requires you to have a company-wide review structure that overlays individual projects, just as SOA itself is an architecture that spans the entire company.
SOA is an idea that scales software development up to the level of entire companies and industries. However, when it comes to problems such as WLGS, SOA is not a solution — those problems scale right up along with the development effort. This is, of course, not a reason to abandon SOA; much like OOP before it, SOA has too much to offer to let this problem stop you. However, WLGS is something that anybody will have to deal with who starts on the road towards SOA. In other words: buyer, beware….