1

Today at work a colleague was looking at a piece of module I had written a month ago as a reference implementation.
I had written a WCF service which a Windows service was consuming.
I have a single operation exposed as below.

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    void PerformASpecificTask(int randomNumber);
}

I have a similar interface in a separate assembly and I refer to this contract in a different assembly which implements this above interface,
similar to how one would implement any WCF service contracts. I have the interface in a separate assembly because I can distribute the dll with the interface alone to the clients (Windows service in my case).

public class MyService : Contract.IMyService
{

    private readonly Domain.ISomeDomainNameHereDataProvider _domainDataProvider;
    private readonly Domain.ADomainService _aDomainService;

    public MyService(Domain.ISomeDomainNameHereDataProvider domainDataProvider, 
        Domain.ADomainService aDomainService)
    {
        _domainDataProvider = domainDataProvider;
        _aDomainService = aDomainService;
    }

    public void PerformASpecificTask(int randomNumber)
    {
        var myRequiredData = _domainDataProvider.GetMyRequiredData(randomNumber);
        myRequiredData.ForEach(data => _aDomainService.DoSomething(data));
        _domainDataProvider.SaveMyChanges(myRequiredData);
    }
}

Here ADomainService is a class which lives in an assembly named Domain and this class uses another WCF service internally,
the proxy of which is injeccted during its instantiation.
ISomeDomainNameHereDataProvider is a interface I have in the Domain assembly I also have another interface IDataAccess in the Domain assembly.
IDataAccess is implemented in my DAL assembly.

Implementation of `ISomeDomainNameHereDataProvider` is in the same `Domain` assembly
and an implementation of `IDataAccess` which lies in `DAL` is injected to it. So `ISomeDomainNameHereDataProvider` makes use of `IDataAccess` to access the data or to be specific sql-server in this case.
Please note I didn't define `IDataAccess` in a separate assembly of its own, as this work was a small task and my `Domain` would be only one consuming it.

Now coming to the question, this colleague calls me and question why is your service talking to `DAL` directly and not using the `Domain` layer. His reasoning was my implementation of an interface defined in `Domain` came from `DAL`.
He went to say your service has business logic and it violates `open-close` and `single-responsibility` prinicple,
I take pride in my work and explanned I don't violate the principles and all my classes have only one responsibility and open-close is not a rule and does not apply in this usecase at hand.

I also tried reasoning for this requirement I have to get some data, perform some operation with the data and then save it back and you need a place to co-ordinate all this and my service class does that and that is the responsibility of my service. He wouldn't agree and started talking about requirements changes, etc. I tried reasoning another solution would have been to move the code I have in my service implementation to a different class and that class would have the same code and he wouldn't agree.
Am I missing something ?
Please let me know what you think of the above solution and events ?
I could only think, he comes from a `MVC` background and thinks of the service class akin to a 'Controller'. `Controller` anyway would delegate the calls to a service layer and all the code I have in my service implementation would remain?

I have read this How accurate is "Business logic should be in a service, not in a model"? and would still require you opinions on my solution above.

Vignesh.N
  • 151
  • 7
  • 1
    You and your friend are probably over-thinking this. My initial impression is that the whole thing is already over-engineered and your friend doesn't know what he's talking about. But there's no way to know for sure without some concrete, specific implementation to talk about; `FooBar` examples aren't really going to cut it here. – Robert Harvey Oct 06 '16 at 19:12
  • @Robert Harvey I agree that this might be too much, but few things can change, like I might end up adding more methods to the service contract and would like to have data access and accessing other service outside of this class. – Vignesh.N Oct 06 '16 at 19:17

1 Answers1

1

As I see your friend have reasons to say that you have business logic in the web service.
These lines is business logic

var myRequiredData = _domainDataProvider.GetMyRequiredData(randomNumber);
myRequiredData.ForEach(data => _aDomainService.DoSomething(data));
_domainDataProvider.SaveMyChanges(myRequiredData);

In the code above your service need to know about how "get" data, how "handle" it and how "save" it.

Think about web service as about IO device/driver, which execute only input/output without knowing about what data is.

Web service can maybe execute some converting data before sending to internal service or before sending to "outside word"

If structure of your small application is - WebService - Domain - Data layer

Following Dependency inversion principle: - WebService depend on abstractions

interface IServiceProcessData
{
    void ProcessData(DataModel data);
}
  • Domain layer implement abstractions provided by top layer(Web Service) Domain layer define own abstractions for data processing

    interface IDataAccessService { void LoadDataById(int id); void SaveData(DataModel data); }

  • Data layer implement abstractions provided by Domain layer

Then your Web Service will look like this:

public void PerformASpecificTask(DataModel data)
{
  //Check preconditions
  _DomainService.ProcessData(data); 
}

And of course somewhere in WebService "main" method you composite all implementations together

Fabio
  • 3,086
  • 1
  • 17
  • 25
  • for me that fits the definition of a `Controller` than a `Service` and by that I mean this "web service as about IO device/driver, which execute only input/output without knowing about what data is" – Vignesh.N Oct 06 '16 at 19:26
  • 1
    Controllers don't generally contain business logic. – Robert Harvey Oct 06 '16 at 19:27
  • @RobertHarvey yes – Vignesh.N Oct 06 '16 at 19:31
  • 1
    Your `web service` is just IO device. Consider WCF is same as WPF or Windows Forms do you put your business logic there? Imagine if next week you need provide ASP.NET Web API service with exactly same logic. With your approach you will need to copy code from WCF service to the Web API service. – Fabio Oct 06 '16 at 19:39
  • @Fabio If I need to Web API, I will inject this service I have to the controller and the controller method would delegate call to the service. And I don't see what you have posted is different from what I already have. – Vignesh.N Oct 07 '16 at 07:41
  • @Vignesh.N if you will inject service as it is now you will going to copy that three lines to the Web API. which "creates" code duplication. – Fabio Jan 05 '17 at 05:57
  • @Fabio no those three lines are inside an implementation of `IMyService` and I would be injecting that implementation to the new WebAPI Controller. – Vignesh.N Jan 05 '17 at 11:14