One of the problems I have with WSDL based web services is the fact that operations are typically generated into one big interface file that must be implemented. I’ve seen WSDLs with 50 to 70 operations, and this leads to a Service/Client Implementation that has 50 to 70 methods that need to be implemented. The problem here is that the code becomes a magnet for change. The correct thing to do is to refactor the WSDL into multiple services, but if you can’t do this and you don’t have control over the WSDL, how can you deal with this situation?
On twitter I mentioned we had a situation like this on the Turmeric SOA project, and I’ve talked about similar situations regarding various eclipse project code as well. For Turmeric there is a Repository Service, which provides a specification for Governance of Assets for a service as well as the lifecycle management of these assets. The initial implementation of which for the WSO2 Governance Registry provider can be see here. The code is done the way I see a majority of WSDL web service implementations done. The methods contain all code related operations in the one class file. This leads to several problems. First the class is over 1500 lines long, making more difficult to understand what the class is doing and maintain. Second it has more than one reason to change. The class is handling Update, Delete, Subscription, Submittal, Add, etc of various repository assets. So it is a magnet for any change that has to happen in the implementation. It is difficult to test in isolation, and also tends to lead to some over use of static utility methods. (The static utility method is another plague, but that is for another post).
There is a general rule of thumb that your classes should ideally be no more 500 lines long, and that they should have very few reasons to change. The implementation above was refactored into the following:
Each of the operations now only has a single reason to change. Each class is less than 500 lines, and is a bit easier to understand. Just because an Interface defines all the methods does not mean that you have to put all the functionality within the class and method. Break it up, make your code easier to test, and easier to maintain. Ideally, I’d refactor this service into at least two or more separate services. Are there other ways to handle this? Is there another set of patterns besides Proxy/Delegate that could be used to handle this situation?