3

When adding a new WCF service in a project, Visual Studio creates the following two templates (namespaces and comments removed by me for brevity):

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    void DoWork();
}

public class MyService : IMyService
{
    public void DoWork()
    {
    }
}

Following YAGNI, I usually immediately simplify it to

[ServiceContract]
public class MyService
{
    [OperationContract]
    void DoWork()
    {
    }
}

based on the assumption that there's always going to be only one class implementing that interface and there's no obvious advantage of typing everything twice. If, for some strange and unforeseen reason, there will be another implementation in the future (or I want to use the same class for two services), I can always extract the interface(s) later when I need it. After all, my contract with the outside world is WSDL, not the interfaces in my code.

However, I'm always skeptical when going against best practices recommended by Visual Studio, hence I'd like to ask the community:

Is there some obvious advantage of splitting the interface and the class of a WCF service right from the beginning that I'm missing?

Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • 5
    To short to post it as answer but: **testing**. To mock an interface is pretty easy, to mock a base class (unless it's almost empty like...an interface) may be much harder. Given that VS IDE does all the typing work for me then I usually go with an interface from the very beginning. – Adriano Repetti Oct 03 '16 at 09:05
  • @AdrianoRepetti: On the WCF server, I don't see the point of mocking the service (since the service is what I want to test). On the WCF client (i.e., the service consumer), it does not make a difference whether the *server* internally uses an interface or not, since the WCF client uses the auto-generated proxy classes. – Heinzi Oct 03 '16 at 09:55
  • @Heinzi kind of. IMO it depends on the way you test your service. What I _usually_ do is to test the view of the implementation class as little as possible (because...well I don't want to make it public) and then test the interface. For interface testing I proceed in two steps: I _get_ an instance and test overall logic (like workflow, for example) and then get a service instance (obviously locally hosted) to test if all classes are properly serialized through service boundaries. – Adriano Repetti Oct 03 '16 at 10:09
  • Testing the implementation I may want to mock some methods to _simulate_ conditions (and delegate all the other calls). Plus, and more obvious, when I test the client I want to test both the logic (mocking interface) and overall system (directly using the service). Also note that when testing a server I try to test it as I am a client. Of course for a simple service you may just don't need this but I find it's much more easy to start with this architecture than to switch to it few weeks later. – Adriano Repetti Oct 03 '16 at 10:13

1 Answers1

3

Should I separate interface and implementation in WCF?

Yes.

...there's no obvious advantage of typing everything twice.

Setting aside the benefit which comes with the ability for clients to mock the service implementation (which Adriano calls out in his comment), a consumer can construct a fully operational channel with which to call the service, using just the interface type definition and nothing else.

In fact, it is generally accepted this is a superior way for a consumer to call a service. The Add Service Reference functionality is complex at best, adds another layer between you and a service, and will lead to difficulties when a service definition changes.

If you've already coupled your interface to your implementation then your consumers have no way of consuming your service cleanly, and are forced to use the visual studio mess which is WSDL + proxy generation that, far from being a prerequisite for a definitive contract, can actually create more problems than it solves.

Moreover, the advantages of separation are even bigger if you were to expose your operation over pure HTTP (instead of soap). In this instance, your consumers cannot add a service reference, so are completely dependent on you providing the service definition types (or at least some kind of schema, which, let's face it, will be much easier to maintain when you have separated the interface out).

Tenet 3 of the tenets of SOA states

Services share schema & contract, not class.

This is not just figurative but prescriptive; you should be decoupling your service's internal implementation from what is exposed on its surface.

Community
  • 1
  • 1
tom redfern
  • 30,562
  • 14
  • 91
  • 126
  • 1
    I agree, I'd also mention that the same implementation may provide multiple _versions_ of the same service (bad, I know, but it happens) with very few changes. – Adriano Repetti Oct 03 '16 at 14:51