I am developing a WCF web service which has become quite bloated. What techniques do you use to split up the implementation of the contract?
Well you have a couple choices:
First, you could leave it all in one class, but split up into different files using the partial class feature of C#.
Second, you could have the main service class just pass requests off to one of a number of other actual classes that are organized logically.
A third alternative is to consider refactoring to reduce the number of operations you have. Is there actually a use to all of the methods you're exposing?
Finally, you could always split up the service into multiple WCF services.
It's hard to answer your question if you don't give any more information.
Do you mean that your service interface is bloated, or the class implementation? It's hard to answer well, if I don't see the code, or have no other information, anyway, I'll try:
Notice that WCF service is basically just a regular class that implements an interface and has some attributes on its methods. So all the other good OO design rules apply to it. Think about what it does, does it have really single responsibility, if not try to outsource some of that responsibility to other classes that your service depends on. If you need a non-default constructor, use IInstanceProvider to create the service class, and supply it with its dependencies (or if you use Windsor Container use WCF Facility).
If you really want to you can streach your inheritance chain, and move some of the code to a base class. I don't do it, however and always prefer to use composition over inheritance.
Inspect your service contract, and think about how cohesive it really is. Maybe what you should do is to split it, into few smaller, more cohesive services.
Related
I am currently in the process of developing a Web Service which should expose a relatively large number of ways to interact with it.
For example, Clients may be able to interact with the Web Service in order to manage users or projects in a Database.
To that effect, I created the following classes:
Two Data Contracts: IUsersServiceContract and IProjectsServiceContract
Two Service Contracts Interfaces: IUsersServiceContract and IProjectsServiceContract
My question is the following:
Does it make sense to create two different Web Services, each with their own endpoint(s), instead of creating one big class that implements both Service Contracts Interfaces ?
Keep in mind that in reality I would have many more Service Contracts Interfaces that deal with different sorts of data.
From what I understand, using a partial class (split in multiple files) will allow me to create one big Web Service with only one Endpoint.
This has the disadvantage of dealing with one big class split in multiple files, i.e: its harder to maintain and more prone to errors if developers "don't see the big picture".
The other solution would be to have one Web Service per Service Contract Interface implemented.
In essence, if I have X Service Contracts Interfaces, I end up with X Web Services with X Endpoints.
Which solution would you choose and why ?
Thanks for your input !
Personally I would not use partial classes for splitting a class; the sheer size motivating tgis split suggests that the class is too large and needs a refactoring. In my opinion partial classes main purpose is to add changes to auto generated code.
Since service and endpoint configuration can be shared using named behaviours in web.config splitting the service should not be that cumbersome. But the split should be motivated by grouping of functionality.
Without knowing the exact nature of you services it sounds like there could be a natural separation in two services; one for user related operations and one for project oriented operations.
If the implemantation classes grows above what you think are reasonable sizes I would consider letting separate classes - or preferably interfaces - handle each methods inner logic and let the service implementation it self be a shallow facade that delegates its own method parameters to the correct logoc instance
An important thing to consider here, when you're talking about n number of service contracts, is the cost associated with implementing each service contract. There's a good blog post on that here, "Service Contracts Factoring and Design", although if it wasn't Juval Lowy who posted this article then someone is clearly ripping him off (I am referring to Juval's book - "Programming WCF Services" page 93).
As the subject line describes, I am in the process of exposing a C# library into a WCF Service. Eventually we want to expose all the functionality, but at present the scope is limited to a subset of the library API. One of the goals of this exercise is also to make sure that the WCF service uses a Request / Response message exchange pattern. So the interface /API will change as the existing library does not use this pattern
I have started off by implementing the Service Contracts and the Request/Response objects, but when it comes to designing the DataContracts, I am not sure which way to go.
I am split between going back and annotating the existing library classes with DataContract/DataMember attributes VS defining new classes which are like surrogate classes to the existing classes.
Does anyone have any experience with similar task or have any recommendations on which way works best ? I would like to point out that our team owns the existing library so do have the source code for it. Any pointers or best practices will be helpful
My recommendation is to use the Adapter pattern, which in this case basically means create brand new DataContracts and ServiceContracts. This will allow everything to vary independently, and will allow you to optimize the WCF stuff for WCF and the API stuff for the API (if that makes sense). The last thing you want is to go down the modification route and find that something just won't map right once you are almost done.
Starting from .NET 3.5 SP1 you no longer need to decorate objects that you want to expose with [DataContract]/[DataMember] attributes. All public properties will be automatically exposed. This being said personally I prefer to use special DTO objects that I expose and decorate with those attributes. I then use AutoMapper to map between the actual domain models and the objects I want to expose.
If you are going to continue to use the existing library but want to have control over what you expose as the web service API, I would recommend defining new classes as wrapper(s) around the library.
What I mean to say is don't "convert" the existing library even if you think you're not going to continue to use it in other contexts. If it has been tested and proven, then take advantage of that fact and wrap around it.
My understanding is that all contract-implementing code has to be in a single class, that can become very large, obviously. How do I avoid this? I really prefer to have a few small classes doing one part of the communication with clients than a single behemoth class.
The only idea I could think of is using multiple interfaces implemented by a single class split up by partial, but I don't think this is really solving the issue.
You might want to use Inheritance, depending on the structure of yoru code. Usually you can break all code up into smaller pieces, helpers, sub-routines, etc.
It's like with any other API-development, you don't want / don't need everything in the same place in the same package.
First, if your contract is big, can they be refactor into more specific service contracts?
The contract implementation class can be implemented as entry point method. You can always model the implementation and define the appropriate abstraction and have your service contract implementation class calls those internal implementation.
If you could change your code fundamentally, you could expose just a single endpoint that works with request/response messages. This way there could be a single end-point and a single service definition that takes a (possibly derived) request message and returns a response message. Your interface into the service would then just be a single method and in the server side implementation you would route that request object to the actual service implementation (possibly determined by a factory) possibly using metadata on the request message (or even it' type-name) to define what service is being called.
So, your end service interface would just have a method like this:
public interface IServiceRequestor
{
Response ProcessRequest(Request request);
}
This allows you to handle a possibly unlimited number of exposed services without having to know what they will be at compile/dev time, and also avoid a proliferation of Service methods defining the service calls available
That 'single class' usually is a facade, just a communication front-end.
So you should not implement all your logic in the Service implementor.
And your interfaces should be as small as possible (do 1 thing well). But if necessary your facade can call on multiple classes.
We have about 60 partial files called "BeamServer.cs", each in a sub-folder that corresponds to the purpose of the functions in that file. Any helper classes (or other helper files) that are for the same area of our program resides in that folder as well.
Your "one class" represents your "one business need". We found a nice side benefit in that if one of the members of our team is working on the "Accounting" portion of BEAM (our software), then they would check out the file "Accounting\BeamServer.cs" and none of the rest of the team would be effected.
EDIT: Also, the class should only contain the method signatures (and wrapper functions that simply call base.Channel.DoSomething()... Any data structures would of course be their own class files (such as "Person.cs" or "Employee.cs" or whatever).
WCF promotes good design by using interfaces and contracts etc. What baffles me is that, for example in my case if I have 2 sets of business functionality like ICustomerMgmtBIZ
and IProductMgmtBiz. If these two are ServiceContracts, and I have an interface like
IBusinessService:IProductMgmtBIZ,ICustomerMgmtBIZ
and implementation class BusinessService. I see that BusinessService class will be having too much implementation. The workaround I have been using so far is by implementing partial classes.
So bluntly put, can a WCF service have only 1 implementation and 1 service contract ??
No, it is possible to implement more than one Service contract on a WCF Service type (the class that is attributed with the ServiceBehavior attribute), since it is just a matter of having the class implement multiple interfaces. If you are using any of the Visual Studio templates or other kinds of code generators, this may not be immediately clear. However, although you can implement more than one Service Contract interface on a Service type, it does not do you much good if you need the service, presumably a singleton in this case(?), to behave as one service. IBusinessService implies that you need all of the service's functionality to be callable from one client proxy, so that all operations may operate in the same logical session (similar to ASPX web session). If that is not the case, then you are free to define individual proxies for each contract interface, but that will also require that you support one endpoint for each contract.
Is it an absolute requirement that you can only have on WCF ServiceHost instance for your implementation? What factors are influencing your decision?
By the way, partial classes do not trouble me anymore. The idea of splitting out code into multiple files now seems rather natural. For example, storing partial classes in files like ServiceType_IProductMgmtBiz.cs and ServiceType_ICustomerMgmtBIZ.cs seems natural enough, in addition to storing the core logic in ServiceType.cs.
Finally, the following question might be of use...
WCF and Interface Inheritance - Is this a terrible thing to do?
Bluntly put, no - sort of - yes, but. Any workaround is non-optimal and involves using an "IBlank" as a master WCF interface (where your interfaces derive from IBlank), and two endpoints, one implementing IProductMgmtBIZ and the other implementing ICustomerMgmtBIZ. I don't have my dev machine in front of me, this might involve some other overrides. So, at the WCF level you're screwed unless you want to have two WCF ServiceHosts (which is perfectly reasonable).
In short, the workaround is inelegant. Its easier to have two WCF endpoints on the same port with a different extension.
We're using about 7 services at the moment. There quite large.
Does anyone have any experience with the single responsibility principle and WCF services? Does this mean that you'll end up with lot's of small contracts? If so, how do you manage these in your application?
I think you are confusing single responsibility with interface segregation.
From the client/service interface perspective, you should keep your contracts lean and mean. See below for an example of that.
On the SRP side of things, that should be entirely internal to the service implementation and the client should not be aware of this. If you service code is too large, split it up into classes. Then have your service code, at least initially, act as a facade and forward all the calls to the relevant objects. Later on, you have the option of spliting your service into multiple services. But be aware, that SOA and object oriented design, although overlap, are separate and have different requirements.
Interface segregation example: We have a service here at work that we use to do various functions on some business objects. The original service had one interface. As it grew, we realized we had three family of methods: data object persistence, business updates, business analysis. We split up into three contracts. Our client/service implements all 3, so the only thing we had to do was split the contract into three and setup two additional endpoints in our WCF configuration. Very simple.
Hope this helps.
I would suggest you listen to this podcast on the hanselminutes :
SOLID Principles with Uncle Bob - Robert C. Martin
It would help understand things better. . .
You could apply facade pattern for the web service that interface with the client, and in your implementation code you can apply single responsibility to make it maintainable.