Question

Assume I have 2 entities Foo and Bar as follows:

public class Foo
{
    public int FooID {get;set;}
    public string FooName {get;set;}
}

public class Bar
{
    public int BarID {get;set;}
    public string BarName {get;set;}
    public int FooID {get;set;}
}

For each entity will have its repository:

public class FooRepository
{
    public IEnumerable<Foo> getFoo()
    {
        //do something
    }
}

public class BarRepository
{
    public IEnumerable<Bar> getBar()
    {
        //do something
    }

    public IEnumerable<Bar> getBar(int FooID)
    {
        //get bar base on foo id
    }
}

Each of those repositories will have an associated service:

public class FooService
{
    //depend on Foo repository
}

public class BarService
{
    //depend on Bar repository
}

Now I want to make a function to see if a Foo is in used in Bar. I thought of 2 methods to implement this function:

Method 1:

public class BarService
{
    private BarRepository repository = new BarRepository();

    public bool isFooExisted(int FooID)
    {
        var bars = this.repository.getBar(FooID);
        return bars.Count > 0;
    }
}

Somehow, this is look like it is violating Single Responsible Principle since BarService is used to check for a Foo. So I came up with method 2:

Method 2:

public class BarService
{
    private BarRepository repository = new BarRepository();

    public IEnumerable<Bar> getBar(int FooID)
    {
        return this.repository.getBar(FooID);
    }
}

public class FooService
{
    private BarService service = new BarService();

    public bool isFooExisted(int FooID)
    {
        var bars = service.getBar(FooID);
        return bars.Count > 0;
    }
}

I wonder is it a good idea for services depend on each other like this. Please suggest me which one of those method above is good to follow or any other method will help

Was it helpful?

Solution

I personally would avoid services using other services because sooner or later you'll get a circular reference. Having the services not depend on each other also makes for looser coupling and ease of testability. So i would go for method 1.

The problem with this approach comes when you want to reuse functionality between services. In your case you can just defer calls to the respective repository, but in more complex cases you may need to add a domain object that contain common business logic that can be re-used in the different services. For example, if you had to have a complex isFooExisted method in both services, you might do something like this (note that I have changed your code to use dependency injection to make your code more testable):

public class BarService
{
    private FooEntity fooEntity;

    public BarService(IFooRepository repository)
    {
        this.fooEntity = new FooEntity(repository);
    }

    public IEnumerable<Foo> getFoo(int FooID)
    {
        return fooEntity.getFoo(FooID);
    }
}

public class FooService
{    
    private FooEntity fooEntity;

    public FooService(IFooRepository repository)
    {
        this.fooEntity = new FooEntity(repository);
    }

    public IEnumerable<Foo> getFoo(int FooID)
    {
        return fooEntity.getFoo(FooID);
    }
}

public class FooEntity
{
    private IFooRepository repository;

    public FooEntity(IFooRepository repository)
    {
        this.repository = repository;
    }

    public bool isFooExisted(int FooID)
    {
        /** Complex business logix **/
    }
}

And for the simple case I'd just use the same repository directly and not have the domain object:

public class BarService
{
    private IFooRepository repository;

    public BarService(IFooRepository repository)
    {
        this.repository = repository;
    }
    ...
}

public class FooService
{    
    private IFooRepository repository;

    public FooService(IFooRepository repository)
    {
        this.repository = repository;
    }
    ...
}

Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top