Previous column

Next column


Confessions of a Service-Oriented Abuser

Mahesh H. Dodani, IBM Software, U.S.A.

space COLUMN

PDF Icon
PDF Version

1 MEET PAT TERNA BUSER

“One comment I saw in a news group just after patterns started to become more popular was someone claiming that in a particular program they tried to use all 23 GoF patterns. They said they had failed, because they were only able to use 20. They hoped the client would call them again to come back again so maybe they could squeeze in the other 3.

Trying to use all the patterns is a bad thing, because you will end up with synthetic designs—speculative designs that have flexibility that no one needs.” – Erich Gamma, http://www.artima.com/lejava/articles/gammadp.html

Hello, my name is Pat, and I resemble the person that Erich is talking about in his quote above. I introduced my pattern abusing story to you in 1999 [Dodani, M., "Rules are for Fools, Patterns are for Cool Fools", Journal of Object-Oriented Programming, Vol. 12, No. 6, pp. 21-23, SIGS Publications, October 1999], and asked for help in getting over my abuse.

To summarize my abuses, I applied patterns mercilessly to any software development project, and in fact came up with a “pattern” to abuse patterns – which ensured that I could apply almost every pattern (yes, I was disappointed that I could not apply all 23 as well) to the implementation of a single class hierarchy (I assume that you are familiar with the Gang of Four Patterns):

  • For a single class, I used the State pattern to implement the instance variables to facilitate flexibility in changing the behavior of the instance based on its state and the Stategy pattern to implement the methods to facilitate flexibility in the choice of algorithms. For the more complex methods, I used the Bridge pattern to ensure that the interface of the method was decoupled from the actual implementation, providing even greater flexibility. I used the Adaptor pattern to implement the interface defined by the class using existing legacy code.
  • For a grouping of instances of a class, I applied the Chain of Responsibilitiy pattern to facilitate the flexibility of allowing the handler of the request to be determined dynamically. Additionally, I used the Composite, Iterator and Visitor patterns to group the instances into a tree-like structure and to facilitate uniform access and treatment of the organized objects. For a hierarchy of classes, I used the Façade pattern to ensure that the entire set of classes could be accessed through a single interface which I could separate from the implementation. To create objects that are part of a family, I used the Abstract Factory, Builder and Factory Method patterns to facilitate flexibility in creating instances. In some cases, I achieved greater flexibility using the Prototype pattern to clone objects from existing ones rather than creating them as instances from a class.
  • For the clients of objects, I used the Observer pattern to facilitate flexibility in how the client reacts to changes in the object. Furthermore, I used the Proxy pattern to completely decouple the methods provided by the object from the manner and location from which they need to be accessed.

As I became more abusive, I requested help from you in resolving the following issues:

  • How do I know when a pattern is really applicable, and will have the needed impact on the application?
  • How do I know that the application of the pattern has made the application more flexible and reusable?
  • Will the application become “better” after the patterns are applied? How do I define “better”, and determine that the application has become “better”.

2 REMISSION FROM ABUSING PATTERNS

The outpouring of support and help from the community was overwhelming. I got help that focused on several facets of my abuses – including, unfortunately, how to increase the number of patterns that I could use in my approach above! The key antidotes that I received that helped me overcome my sickness were the following:

  • AntiPatterns which documents bad practices using the same template as patterns. It therefore identifies common problems with solutions, and then show how to refactor the solution to get rid of the problem. Several of these antipatterns deal with my problem of applying patterns just for the sake of applying patterns (e.g. BigDesignUpFront, DesignForTheSakeOfDesign, PolterGeists) and other (not really categorized as antipatterns) ways of handling “smells” in your design and implementation. I was able to leverage these antipatterns and their refactored solutions to bring back some sanity into my design and coding practices, and slowly wean myself off using patterns for the sake of patterns.
  • Using larger grained assets through a gradual progression from design patterns to frameworks and finally to architectures. My first step was to move from design patterns to components, which allowed me to break away from the fine-grained confines of objects to the large-grained world of components, and from the constricted inheritance-based flexibility to the more powerful world of composition. From components, it was easy to transition into architectures, which provided the most effective antidote to my design pattern abuses. Layered architectures allowed me to separate functionality and concerns between layers that have well defined interfaces (and consequently hidden implementations) to interact with – typically layers (from the outside in) include presentation, business logic, persistence, integration and enterprise applications. Within each layer, I can implement the required functionality (maybe through components, and the components in turn are implemented via objects.) The next step was to evolve to component architectures where the components themselves were considered first class citizens, and this led to using interacting components as the primary mechanism to build flexible systems.
    • Agile methods facilitate individuals interacting with each other and in close collaboration with their customer to build incremental versions of the system and quickly respond to needed changes. Agile methods forced me to focus on particular parts of the system, and build flexibility for one piece of functionality at a time.

Using the above three antidotes, I was able to push myself into remission from abusing patterns. The architectures, frameworks, and components that I was having to deal with in addition to the design patterns made my design and development life complex and engrossing. These higher-level abstractions allowed me to use a model-driven approach to my development, so that by the time I came to implementing the components with objects, I knew which patterns would be applicable to provide the flexibility in the smaller context of implementing the needed interface. The agile methods gave me further focus by facilitating iterative and incremental feature/function driven.

3 RELAPSING INTO ABUSING SERVICES

As you must be aware, a few years ago, the entire technical world was awash with services – here was the ultimate construct for building flexible systems. A Service is a discoverable software resource which has a service description. The service description is available for searching, binding and invocation by a service consumer. The service description implementation is realized through a service provider who delivers quality of service requirements for the service consumer.

I got introduced to services through web services. Web Services are self-describing, self-contained, modular applications that have to be described, published, found, bound, invoked and composed. Web services conform to the structure summarized in Figure 1.

Fig. 1: The Web Service Structure

As shown in the figure, service providers create application functions that are available on disparate implementation platforms as web services and describe them using a standard definition language. These services are published in a service registry. Service requestors who need a particular type of service search the service registry and find the desired service. Once a service is found the requestor and the provider of the service negotiate to access and invoke the service.

The other beauty of web services is that they are standards based, implying that the underlying technologies supporting web services need to be platform and implementation neutral, and are therefore specified in XML. The core technologies include

  • Simple Object Access Protocol (SOAP) is the XML based messaging specification that defines the message envelope content, the encoding rules for the data types, and conventions for defining requests and responses. SOAP is vendor neutral, and can support any language, programming model, and platform. Implementations of SOAP exist in Java, Perl, C/C++, and C#.
  • Web Services Definition Language (WSDL) is the XML based description of a web service as a group of ports which are in turn defined by associating a network address with a reusable binding. Each binding defines a group of operations (port type) that is associated with a protocol. Each operation in turn is defined in terms of messages and types. WSDL facilitates the abstract definition of web services to be separated from their concrete implementations.
  • The Universal Description, Discovery and Integration (UDDI) specifications define a way to publish and discover information about Web services. The core component of the UDDI is the UDDI business registration, an XML file used to describe a business entity and its Web services, and which are used to provide white pages (service provider), yellow pages business categories), and green pages (technical binding information.)

So, this was great – I was able to relapse right back to working with smaller-grained constructs (services), achieve great flexibility, and I had the added bonus of working in a standards-based environment! It was just too good to be true. I took to services, with the same excitement and fervor that I did with objects.

Very soon, I realized I had relapsed right back to abusing services. Here is what I was doing in my design and implementation:

  • For every interface and API in my system, I implemented a web service. I replaced every (remote) call or point-to-point message with a SOAP message.
  • I created these services for every application in my system, including for the non-business logic functionality that I had developed to support the application.
  • I created UDDI based service registries to support the services that I was creating for each application, and used that to find the services that I needed.
  • I created lots of fine-grained services to handle the interactions that I needed between the presentation and business logic functionality. So, for example, I would have individual services to get each of the attributes needed to populate information about a cutomer.
  • I quickly found that I could convince customers who had spent all their time on putting in complex and expensive middleware to facilitate integration to change over to using point-to-point integration using services. Basically, I would wrapper the two applications that needed to be integrated as web services, and then invoke them using SOAP messaging. The fact that we were using standards convinced them that it would be cheaper and easier to maintain.
  • I relied on web services to reach any part of the system that I wanted, and basically used that as the unifying structure across all applications. I argued that this made the systems simpler and therefore easier to change, manage and maintain.

Of course, I soon realized that I was back to my old pattern abusing days – taking advantage of my prowess with this new services construct and the hype surrounding it to brow beat any customer into agreeing that I was leaving them with a much more flexible, changeable and cheaper to maintain system. Of course, I used the metric of number of services as the key indicator of these “qualities”, along with the added “open standards” that were now an integral part of the system. Like before, the reality was far from what I was selling. The proliferation of services and registries, the unstructured nature of the system, the number of fine-grained services, and the point-to-point integration quickly led to systems that performed poorly, were difficult to maintain, and were expensive to make changes to.

4 RISING BACK FROM THE ABYSS

I quickly realized that I had relapsed so far into the dark side again that it was time for me to go back to my rehabilitation “pattern.” Using the same techniques and approaches that I did to get out of my pattern-abusing nightmare, I was able to fight back from my services abyss. I got involved with Service Oriented Architectures and use those first to organize and structure the services that I would build and use and to define how these services could interact with another through the Enterprise Service Bus. I also determined how to handle qualities of service effectively through the layers of services. I used appropriate methods to help me identify services that are appropriate to the domain that I was involved with, starting first with modeling the business process, and then establishing the services needed to implement the process. I used “smell” tests to determine the appropriate validity and granularity of services. To provide the services, I used components to first pull together relevant functionality and then to make these available as services. I composed components and services to provide larger grained services.

Learn from my story, and heed my words – architecture is the salvation for your technical soul.


About the author



space Mahesh Dodani is a software architect at IBM. His primary interests are in enabling communities of practitioners to design and build complex on demand business solutions. He can be reached at dodani@us.ibm.com.


Cite this column as follows:Mahesh Dodani: “Confessions of a Service-Oriented Abuser”, in Journal of Object Technology, vol. 4, no. 7, September-October 2005, pp 19-24, http://www.jot.fm/issues/issue_2005_09/column2


Previous column

Next column