Udi has posted more clarification on his comments about migrating an N-Tier app to SOA. I like reading Udi’s blog, because he makes me think.
If I understand Udi correctly, he’s really arguing for componentized software development and factoring an application into a set of reusable frameworks. His approach to building apps is to factor out common functionality like logging, exception handling and security into their own separate chunks, which he refers to as “services”. I think this is unquestionably best practice. Udi rightly identifies the benefits of this approach. I totally agree with Udi’s points, but is what he’s talking about “SOA”? No, at least in my definition of “SOA” (which I admit is both nebulous and fallible). What he’s talking about is componentized software and application frameworks.
First off, I happen to be a big fan of application frameworks. I build them for a living. My day-to-day job is to build a reliable set of common functionality that can be built unchanged into many different applications. The canonical application framework examples are the MS application blocks (what I work on is sort of like the MS blocks on steroids). Although I think using application frameworks are unquestionably the right idea, I don’t consider these frameworks to be services in the SOA sense. There are certainly common themes running through an application built on frameworks and a system composed of services, but there are also significant differences between the two.
My difference with Udi is largely semantic. I realize I'm arguing definitions. But I think it's important to be clear on what I mean when I use the term “SOA.“
Update: Vargas thinks this getting excessive. In retrospect, I think I agree with him.
Similarities:
- Orthogonality. Services and frameworks both partition behavior into a logical set of independent organizational units. Functionality present in one service or framework is not duplicated in another service or framework.
- Generality. Both services and frameworks are designed to be general solutions to a set of problems, instead of a specific solution to a single problem. They are not bound to the particular problem domain for which they are originally implemented.
- Reusability. Both frameworks and services are designed for “black box” reusability. Thus, a service or framework can be incorporated into a solution without having to change the underlying details of the service or framework.
Differences:
- Level of functional abstraction. The functionality encapsulated by a service operation is generally much greater than the functionality of framework method. Services encapsulate and are an abstraction upon business process, while frameworks encapsulate and are an abstraction upon technical plumbing.
- Messaging / interaction patterns. Service operations are very coarsely grained, again because they encapsulate process. Services communicate via messages, which they generally send and receive asynchronously. An application communicates with its underlying frameworks via method calls, often synchronously. When an application invokes a service, it is consciously transitioning responsibility to a third party. When a framework method is invoked, there’s no logical transition of responsibility – the logical scope of the call still remains in the application; it’s just delegating the responsibility to a different part of itself.
- Platform assumptions. When an application depends on the functionality provided by a service, it has no dependencies on the underlying platform on which that service is implemented. Applications that are built upon frameworks generally assume that the framework is running on the same platform as the application (they often assume that the framework is running in the same process space, too, but that’s another bullet). It’s rare that I would write a .NET application in such a way that I could use a Java box for exception handling, but it’s very likely that I wouldn’t care if the credit authorization service I’m using runs on a different platform.
- Shared type system. Applications share types with their frameworks. Services do not share a type system, only a common message structure. Open content is the rule with services, but closed content and strong types are the rule with frameworks.
- Versioning. It’s rare to upgrade a framework without also upgrading the application that uses that framework. After all, why upgrade a framework if you’re not going to use the new functions? Thus, applications are usually versioned simultaneously with the frameworks on which they are built. This is absolutely not true for service dependencies. Services can version themselves spontaneously and without warning, and do not require or imply that the consumers of that service should be versioned at the same time.
- Deployment. This is a touchy one, and I may be over generalizing here, but I think the general assumption with frameworks is that they execute in-process. Frameworks are generally physically deployed on the same machine and executed in the same process as their consumers. This is the exact opposite of services, which are usually executed out-of-process and are almost always physically remote.
- Configurability. A good application framework drives its behavior through configuration. Based upon how I configure my framework, I should be able to get different behavior. I do not have that expectation when I consume an external service. I can’t customize the behavior of that service to meet my own needs; all I can do is change the messages that I send it. For all intents and purposes, that service is untouchable by the application developer. Only the application that consumes the service can be modified.
- Scope of control. The biggest difference between services and frameworks: a framework is logically owned by the team, group, or company that is consuming that functionality. As such, an application developer has control over how that framework functions. In contrast, services are not owned by the application that consumes them. Services are unalterable, externally located units of behavior.
I realize that there are probably legitimate exceptions to everything I just said.
Are application frameworks sort of a special case of SOA? It would appear so. Start with a macroscopic definition of SOA and remove the requirements around platform independence, type systems and versioning, lower the level of abstraction a bit, and expand the scope of control – what do you get? A set of application frameworks. Start with the common ideas behind application frameworks and zoom out until your framework implements an entire business process, and you have my idea of SOA. It's not really a new thing, necessarily -- just a higher level of abstraction.
