mardi 14 février 2017

Simplifying composition interfaces in C#

In the code I am working on I have a structure where some portions of the code depend on the current software session. Software session contains multiple helper objects which are dependency injected by composition.

One example is IRepository injected to it, which contains access to the data repository. And the IRepository contains a DatabaseContext which writes to a database, via IDbContext again which is injected.

SoftwareSession is the only injected common infrastructure for accessing all the way to the database, acting as a gateway. This means when I want to write an object to database, for instance WriteCar I will have to implement 3 interfaces, 2 functions delegating to composed objects and 1 function with implementation. It is clarified in the code fragment below.

This means when I want to refactor, move code, add functionality or change function signatures I will always have to change 6 places for one function.

I think this provides the best environment for improving testability and it follows best practices where software session wraps access to repository and repository wraps access to data contexts - yet I still am questioning if we can have some better way of writing it once, or do I have a misunderstanding of some concept in the code below?

What is the architecturally more maintainable way of implementing this? Maybe even using some clever way of lambdas or delegates to reduce the amount of code written for each new functionality? Or even some tools to ease generation of this code from some kind of templating mechanism using Visual Studio, Resharper, etc?

Please let me know if I am having some confusion of concepts here. I know some my colleagues have similar views, in which case it may be helpful to clarify misunderstandings of others as well.

public class SoftwareSession : ISoftwareSession
{
    ...
    IRepository repository;
    public void WriteCar(Car car){
        repository.WriteCar(car);
    }
    ...
}

public interface ISoftwareSession{
    ...
    void WriteCar(Car car);
    ...
}


public class Repository : IRepository{
    ...
    IDbContext context;
    public void WriteCar(Car car){
        context.WriteCar(car);
    }
    ...        
}

public interface IRepository{
    ...
    void WriteCar(Car car);
    ...
}

public class MyDbContext : IDbContext{
    ...
    public void WriteCar(Car car){
       //The Actual Implementation here.
        ...
    }
    ...
}

public interface IDbContext{
    ...
    void WriteCar(Car car);
    ...
}

Aucun commentaire:

Enregistrer un commentaire