Value of Service Interfaces

January 4, 2015

Wrote earlier about why interfaces are important and in this post want to elaborate on their advantages for building reusable services. Service interfaces contain only the operation or method definitions and have no implementations. They can be used in a variety of ways:

  • Package service interfaces into a separate artifact to make it easy for client teams to integrate with services without pulling in bulky set of transitive dependencies
  • Bind the interfaces to one or more transport / integration technology via standard Dependency Injection (DI). For example, service interfaces can be integrated with a REST-ful Resource or a EMS listener.
  • Service interfaces can be backed by stub and/or mock implementation for automated unit and regression testing.
  • Service interfaces can be decorated with common cross-cutting concerns to separate them from the implementation. This is the strategy implemented via the Java Dynamic Proxy example.
  • Service interfaces can be implemented as a proxy to a remote implementation. For example, the client invokes the functionality via the interface but the runtime implementation makes a call to a server side API. This is useful if your teams need the flexibility to swap local / remote implementations depending on performance / dependency management related requirements

5 Advantages of Using Interfaces for Designing Reusable Assets

April 24, 2010

Interfaces are fundamental to good design and more important when designing resuable assets. They provide several benefits:

  1. They model key behaviors that need to be supported – by designing interfaces, you are forced to partition a big chunk of functionality into a set of behaviors. The amount of detail in each interface varies but the very act to thinking through behaviors will provide a more loosely coupled design.
  2. Provides flexibility to change parts of a module/sub-system at anytime. This is specially relevant with projects where knowledge accumulates over time and domain understanding is unclear in during project inception. Interfaces help switch to a better implementation without adversely impacting the rest of the codebase (assuming, the contract stayed the same or only minimal changes were required).
  3. Explicitly support variability in an asset based on a defined set of behaviors. Interfaces are useful to encapsulate variations in a particular step (using Strategy), how different behaviors are combined (using pipe/filter) , or several steps in an overall algorithm (template method).
  4. With reusable assets, when you provide interfaces as contracts to your consumers – it gives you the freedom to change implementations and not break them. Note: this can be comforting but unless you ensure your consumers don’t instantiate concrete classes and don’t bypass integration-facing contracts there is no guarantee that they won’t break.
  5. Interfaces can potentially out live the implementation. This is related to #2 – as you learn new technologies, new ways to solving problems, interfaces give you the freedom to swap to a better implementation at any time. The interfaces that model domain concepts tend to be more stable as well – core business concepts don’t change overnight. However, business practices do change more frequently and the flexibility to combine and recombine concepts – conveniently captured using interfaces – is very powerful.

In a recently concluded project, I realized these benefits first-hand. The initial implementation of a search service was to go against the database directly. After a couple of iterations, we realized the need for a more effective and efficient solution – an indexed search engine. Even though the search module was used by several consumers the switch to a search engine based implementation was faster, more scalable, and most importantly, didn’t force consumers to make code changes.


5 Tips When Managing Multiple Service Versions

November 28, 2009

Many teams that build service capabilities have to manage multiple versions – this is a problem for any shared asset really – be it a library, component, or service. Using extensible schema contracts (also referred to as Consumer Driven Contracts) you can design service contracts that allow both provider to evolve and consumer to integrate in a flexible manner. In this post, I want to suggest five additional tips when managing web services:

1. Figure out how many versions your team will support concurrently. Too little will force all your consumers to be on a single version and too many will become a maintenance nightmare for you (the provider). In past implementations, I have maintained upto 3 versions while actively moving all service consumers towards one target version. A related approach is to have multiple flavors for your service capability one that returns data that most consumers want, the second that provides the minimal set of attributes, and a third flavor that returns the full list of data items. This may or may not be possible in your case, but something to consider when designing contracts.

2. Figure out how you are going to support multiple versions as a service provider. You can use xml schema namespaces to indicate versions: http://some-company.com/services/CustomService_ver1_0.xsd, ver1_1.xsd and so on. Consider creating a service adapter that can translate back and forth between a new service implementation and the existing one. This can potentially help you with one server side implementation of the functional logic and still service your current and new consumers. This adapter component can perform necessary data transformations, error code & error message translations, and massage response with data attributes as appropriate.

3. Communicate the change in the service capability and gauge the appetite with existing consumers for their ability to absorb the changes in the same release time frame that you are targeting to drop your new version. If you co-ordinate the release, you can get them to new version when you go live. However, for mission critical applications you will want to support both your current and new version concurrently for a small time period before switching the old one off.

4. When you design forward-compatible schemas, you can test the data-binding against multiple platforms. For example, use WSDL2Java if you are using Apache Axis in Java or wsdl.exe if you are in .NET and generate appropriate web service proxy classes and data binding classes. What i have done is to implement JUnit and NUnit automated test cases that run everytime there is a new WSDL or service contract (XSD) change. This will not only validate the service functional logic, but also the forward-compatibility of existing clients. Make sure your when you generate bindings that you generate with both the new schema/wsdl (your updated version) and the existing schema/wsdl files (the version currently used by production clients).

5.  Establish lightweight service governance – it is critical to plan how many service flavors and versions you will support, when will they get upgraded, deprecated, decommissioned, etc. and communicate those with your consumers. Identify checkpoints in your development process where contracts can be reviewed and service behavior can be discussed openly. The well thought out service orientation strategy is a benefit for both the provider and the consumers in your organization.

What other tips/techniques have you used?

Like this post? Subscribe to RSS feed or get blog updates via email.

tweet this add to del.icio.us post to facebook


Systematic Reuse Success Factor #9 – Consistent API

November 26, 2009

Have you noticed how some application interfaces are consistently named and exhibit consistent behavior across components and services? This can be a critical success factor for systematic reuse. Reusable components are not isolated islands of functionality. Instead, they are meant to be leveraged in a variety of applications and business processes. Consistent interfaces provide several benefits:

  • They reduce learning curve when a developer tries to understand and evaluate the asset for his/her need.
  • Reduces technical debt – consistent API reduces the need to refactor code and reduces regression testing efforts as well.
  • They increase the likelihood of predictable behavior across applications. This is critical for assets that get reused across business processes with an impact ultimately to end user experience (e.g. what if your customer can update address when opening accounts but won’t be able to do that when updating accounts?).
  • Eases integration and testing efforts. Consistent behavior can simplify testing reusable assets. If an asset behaves consistently whether it is invoked by a web application or a backend process, knowledge about test data and integration behavior is applicable across multiple projects
  • Makes documentation easier to follow: consistent interfaces can facilitate the use of templates for document generation as well where similar files/hyperlinks can be generated.

These aren’t the only benefits – feel free to suggest additional ones.


Software Reuse Quick Tip #24

November 25, 2009

Tip #24 – Identify common behavior and encapsulate it

Looking for common behavior across classes is an effective way to reuse behavior. When you find yourself cutting and pasting code, take a step back and reflect on the common behavior that is being implemented. If the duplication is due to the same behavior realized in different ways, introduce a new interface. If multiple objects have the same functionality and can derive from a parent object, introduce an inheritance hierarchy.

This can be done in an iterative fashion as well – if you failed to recognize an interface initially that is okay. Look for opportunities to refactor existing code to introduce a new interface. For example, you can use the Eclipse IDE’s refactoring feature – extract interface – to create a new interface from an existing class.

Why is this important for systematic reuse? Because, by isolating and realizing common behavior you reduce the need for multiple components and classes to re-implement the same functionality. If two classes need the same piece of data, or if they both connect with the same external system, why would you want to code them separately?

Like this post? Subscribe to RSS feed or get blog updates via email.

tweet this add to del.icio.us post to facebook


%d bloggers like this: