Showing posts with label reuse. Show all posts
Showing posts with label reuse. Show all posts

Monday, April 7, 2008

SOA and Reuse

One of the key benefits often touted by SOA practitioners is reuse. It is usually described in the following way:

A business will establish an asset of a number of services over time. When the need arises to implement some new business process, we simply use a process orchestration engine to wire up our existing services in support of the new business process.

The concept is certainly appealing. The ability to be able to support entirely new business processes so quickly, cheaply and easily certainly would drive a lot of business agility. But is this nirvana actually achievable? As usual, the devil is in the detail.

The kind of reuse described here is the kind that we see in traditional programming. One component exposes a function which many other components can invoke, passing parameters to control the execution of the shared component.

This model is not appropriate for SOA because of the coarse grained nature of services and the need for asynchrony. It is also problematic because the calling component is instructing the shared component what to do. This translates to the use of command messages in SOA, which as previously discussed introduces coupling between our services. It is in fact this coupling that prevents us from reusing the shared service effectively.

Component oriented programming has taught us that the larger the granularity of the shared component, the harder it is to reuse in different contexts. In SOA terms, the different contexts we are talking about are the different services sending the shared service the command messages.

When we have Service A sending Service B a command message, Service B is performing a function in the context of the activities occurring in Service A. If we now reuse Service B by having Service C send Service B the same command (albeit perhaps with different content), Service B is now performing a function in the context of the activities occurring in Service C as well.

The problem here is in the intent of the command message. Services A and C are instructing Service B what to do in support of Service A and C's activities respectively. A change in the needs of Service A or C can potentially lead to the need for a change in the implementation of Service B.

As we add more and more services reusing Service B in this way, Service B will become increasingly confused and complex, attempting to cater for the different needs of all the services reusing it.

Consequently, we need to think about reuse in SOA differently than with traditional programming. With SOA the unit of reuse should be the event, not the function. As our SOA matures, we evolve an event catalogue where each event has business relevance (such as a sale event or policy cancelled event).

We can then add a new process that subscribes to relevant business events and potentially publishes new events. If necessary, services are then updated to respond to new events published by the new process.

Now I can hear many of you saying, with the approach described in the opening paragraph we don't have to update any of our existing services - we just wire them up with middleware to support a new process. Well, as previously discussed that is a false promise as the service operations you are attempting to reuse will very likely need to change in the context of different processes leveraging it. So it is likely they will need to be updated anyway.

Furthermore, if a business process supported by an existing service needs to be updated to respond to a new event, then it is completely reasonable that we update the service implementation. That is where the change has taken place! By wiring up existing services with process orchestrations in the middleware you are effectively leaking your service logic outside your service boundary. I'll discuss this in more detail in a future post.

The reason why the event driven approach does not suffer from the issues of the command message approach is that the service publishing the event does not make any assumptions as to which services(s) are subscribed or how they will behave in response to the event.

In conclusion, SOA does indeed deliver reuse in that any given business logic is implemented in one and only one service. Services are written once and then they evolve over time. They are not necessarily static pieces of functionality that are then composed to deliver new value. So although reuse is a key benefit of SOA, the kind of reuse often touted by SOA practitioners is often not achievable.

Saturday, April 5, 2008

Mandated vs. Coincidental Reuse

Developers and architects alike often strive to achieve the holy grail of reuse in the systems they design. It makes sense - reuse is a worthy goal. It means we get repeated value from the software we implement. It also means the total volume of software is reduced, reducing the amount of software that needs to be maintained. This means less effort for developers and lower costs to the people footing the bill.

But reuse must be employed with caution. Often in my travels I have seen reuse become a goal unto itself, rather than designing a system that is aligned with the problem domain. Developers often see patterns where the same logic appears multiple times and aim to extract that logic out into a common place to be reused, despite there being no mandate in the context of the business that the logic in fact be the same for all time.

If it is not mandated in the context of the business that the logic be the same, then we very likely will end up shooting ourselves in the foot by reusing it.

Business requirements are fluid. This is why loose coupling is so crucial in software systems. It allows us to better cater for change. Once a system has been deployed, it must then evolve to support the changing needs of the business. We need to ask whether the business may require that logic duplicated in multiple areas be allowed to evolve independently. If so, the logic should not be reused.

Consider an insurance system that manages policies within number of different product families. The logic that is in common between the product families at the time the system is first developed is not necessarily the logic that will be in common in the future - especially if the business expects to be able to evolve the rules of these product families independently. We must identify which rules very likely will be in common for all time and reuse only the logic corresponding to those rules.

Note that this guidance applies not only to the reuse of business logic, but also the reuse of data representation. This is one of the reasons why we do not allow services to share data directly. The representation of a customer in one service must be allowed to evolve independently to the representation in another. If it is mandated by the business that the representations be the same, then it is likely that the two services in fact should be one.

Maintainability is the ultimate dimension of software quality to which we as architects or developers must aspire. Where reuse improves maintainability, then it is appropriate. However when it hurts maintainability, even though it means we must write the same logic multiple times, it should be avoided.