Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In our organization, we've shifted to a more "service oriented architecture". To give an example, let's assume we need to retrieve a "Quote" object. This quote has a shipper, a consignee, phone numbers, contacts, email addresses, and other location information. In other words, a Quote object is made up of many other objects.

So, it seems like it would make sense to make a "Quote Retrieval Service". In our situation, we've accomplished this by creating a .NET solution and writing the service. The service API looks something like this (in pseudo-code):

Function GetQuote(String ID) Returns Quote

So, so far so good. Now, when this service is consumed, to keep things "de-coupled", we are creating essentially a duplicate of the Quote object and mapping from the QuoteService version of the Quote into the consumer's version of the Quote. In many cases, these classes will have the exact same properties.

So, if the Quote service is consumed by 5 other applications, we would have 6 definitions of what a "Quote" is. One for each consumer, and one for the service. This feels wrong. I thought code was supposed to be DRY, but it seems like our method of SOA is forcing us to create tons of duplicated class definitions. What are we doing wrong, or is the code duplication just a "necessary evil" of SOA?

share|improve this question
    
Easy, get soap on a rope and hang it up after each shower. Sorry, it is late, and I am a little punchy. Delete after reading... –  DeveloperDon Sep 2 '12 at 3:03

5 Answers 5

up vote 6 down vote accepted

JGWiessman is correct in that the lack of DRYness in auto-generated proxies is not costly, because you do not maintain the client's generated code. Change it on the server, update your references on the clients, job done.

However, there is an alternative, if both the client and the server are .NET. You can put all your objects in a separate assembly, referenced by both the client and server. If you then auto-generate the client code, it is simply an interface, using the same objects that the server uses.

Only do this if the objects you are sharing are dumb data objects and don't include any server-side code though, otherwise you're exposing that code to your client.

If both client and server are using the same version of .NET, you can take this one step further and include the interface purely by configuration. But you need to be careful here. The interface on the server side requires the ServiceContract attribute and thus references the ServiceModel assembly, so if the versions are different, you can get into trouble.

share|improve this answer

You should not be handcoding the duplicated definition in the consumer. Instead use a tool like Visual Studios to import a reference to the web service a machine generated proxy class. There is repeated code, but it is machine generated and you don't have to maintain it, just reimport when the master definition changes.

share|improve this answer

If all else fails, I've always been able to get to DRY code by code generation. pdr has a good solution for when what you want to do fits with what Microsoft gives you, but if it doesn't you can always do your own code generation.

Then you can handle things like code generating for clients not using .NET, making explicit, coded rules like "Client B gets the generic client version of Quote except the email address, but they add a carrier pigeon homing code field", (rather than manually adding new fields to all 302 client's services) etc.

share|improve this answer

I personally prefer a slightly different approach. I'm convinced that in enterprise of a large size, business domain is way too large, so the DDD is the way to go. When the entities on the service side (or whatever the tier service talks to) are defined in a way required for the service, the logic is defined to retrieve them from persistence and perform logic of any kind, it always provide a mapped entity (aka "binding context", "dto", "data contract" etc) which is the most suitable in size and internals "sibling" for the original entity, yet not bloated with the details that will never be exposed to the outer world.

Then, when the service is to be exposed, the contract of the service goes to a separate DLL (lightweight library that you can ship to a client, no logic inside, just interfaces). You also ship entity containing library to a client. Those two distinctly describe the conversation contract and the messages format.

If I feel that there are too few pairs to be shipped now, and they are of different structure, then this is not SOA anymore, because your blackbox-service is now telling too much about itself to the consumers and moreover the consumers ask blackbox-service to change it shape. I usually employ REST in this case to reduce problems with data contracts or override serialization methods on DTO objects and depending on supplied StreamingContext, provide a different shape of the entity.

share|improve this answer

This is not an optimal SOA architecture.

The service provider should provide the same service for all consumers.

Consumers should use what they need from the Replies and ignore what they don't need.

I don't see why each consumer should need their own version of the service.

Even in the case of a security requirement that only some consumers are allowed to see certain data you can place this data in an optional group and simply not send it to unauthorized consumers. Thus preserving a single interface for all clients.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.