Qualities of a Good Web Service
Let's start by identifying what can be considered to be traits of a good web service- encapsulation of knowledge
- fine and coarse grained operations
- self documenting
- application agnostic
- ease of use
Fine and Coarse Grained Operations
Every good developer understands the advantage of breaking up their code into reusable parts that can be invoked from different sources. Somehow this approach never translates itself into web services. It seems that developers are so focused on reaching the next milestone that they don't take the time to ask a very basic question.Can this operation be broken up into useful parts?
Agile methodology involves delivering functionality with short development cycles, and this makes it easy to forget about the larger context. Developers may be focused on writing a service operation to deliver a car's door, that they don't think how a door is composed of many pieces. What happens if in the next development cycle there's a need for an operation to deliver a door mirror or a window control switch (these are parts of a car's door)? Instead of writing a coarse grained operation that looks like this:
CarDoor getCarDoor(){ }
it can be broken up into several fine grained operations
DoorMirror getMirror(){ } DoorSwitch[] getSwitches(){ } CarDoor getCarDoor(){ CarDoor = getMirror() + getSwitches(); }
With little additional work, the service is now much more useful and can handle future requests that may not have been anticipated.
Encapsulation of Knowledge
A big reason organizations decide to develop web services is not only to expose back end systems, but also to encapsulate/hide the complexity of those systems. Software applications have a way of far outliving their original lifespan due to embedded business logic or the cost of rewriting them. A web service can be written that leaks the internal workings of the system it is exposing.This is bad. How do these leaks happen?
Let's take the car example which is manufactured by the fictitious Acme car company. As is the case for most industries, Acme uses an internal vocabulary to describe parts of their cars (I'm making these up):
- windows are called "clear silica substrate" (or CSS)
- door switches are called by their product codes such as D39's
CarDoor { CSS cssItemNumber; D39[] switches; }
use something that is agnostic of the underlying system but supports the business objects:
CarDoor{ Window windowID; Switch[] doorSwitchID; }
This approach makes the operations easy to understand, and cuts down on the need to document.
Self Documenting
The bane of all software development is documentation. Nobody likes to do it, and when done, it gets misplaced or quickly falls out of date with the implementation. I can write about how developers need to get their act together, but the truth is that it just doesn't happen that way. They can be coaxed into writing a few lines to describe their functions but formal documentation is not realistic. An alternative way to handle this situation is to write a service interface that uses business terms instead of technical ones and exposes explicit, fine grained operations. The following is an example of a poor interface to handle seats in a car:handleSeat(String operation, Seat newSeat, Seat oldSeat, String seatID){ if operation = "add" then .... if operation = "remove" then ... if operation = "replace" then ... }
The above operation requires documentation that describes the options for "add", "remove" and "replace". It is impossible that a consumer of the service will be able to guess the values without referring to some documentation (which is probably non existent or out of date). What's more is that because the operation requires a "Seat" object for "add", the consumer also needs to pass one for "remove", even though it is not necessary for that particular operation. A better interface looks like this:
addSeat(Seat seat){ } removeSeat(String seatID){ } replaceSeat(Seat newSeat, Seat oldSeat){ }
Again, just a little more effort makes the service infinitely more usable. A business subject matter expert (SME) should be able to understand the interface.
Application Agnostic
In summary, don't create services for a specific application, instead code generic operations that can be used by any application. Acme needs a service that supplies wheels for it's latest model, the XJ2000. The immediate thought is to create operation like so:Wheel[] getXJ200Wheels(){ }
Six months later management decides that the web service has worked out so well, they want to leverage their investment to provide wheels for an older model, the FRT3000. The FRT3000 is a sport model which has two kinds of wheels, 18 inch alloys as well as 16 inch standard. Unfortunately the existing operation cannot be reused because it doesn't take into consideration that wheels come in different sizes and will have to be rewritten.
Operations should reflect the business knowledge domain (in this case, the auto industry), not the application's.
Ease of Use
Here's a common scenario that unfolds when a developer begins to work on a new feature. They look at a document from the design team and are made aware of some existing service operations that should be leveraged to accelerate their work. They pull up the service with a testing tool and attempt to make use of it. If- they can't find the WSDL document
- the service is not well documented
- they can't find the correct parameters to invoke the service operations
- the operations are too difficult to understand or are perceived to be inadequate
- they have an alternative way to get their work completed