Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Domain modelling - Implement an interface of properties or POCO?

I'm prototyping a tool that will import files via a SOAP api to an web based application and have modelled what I'm trying to import via C# interfaces so I can wrap the web app's model data in something I can deal with.

public interface IBankAccount
{
    string AccountNumber { get; set; }
    ICurrency Currency { get; set; }
    IEntity Entity { get; set; }
    BankAccountType Type { get; set; }
}

internal class BankAccount
{
    private readonly SomeExternalImplementation bankAccount;

    BankAccount(SomeExternalImplementation bankAccount)
    {
        this.bankAccount = bankAccount;
    }

    // Property implementations
}

I then have a repository that returns collections of IBankAccount or whatever and a factory class to create BankAccounts for me should I need them.

My question is, it this approach going to cause me a lot of pain down the line and would it be better to create POCOs? I want to put all of this in a separate assembly and have a complete separation of data access and business logic, simply because I'm dealing with a moving target here regarding where the data will be stored online.

like image 612
Neil M Avatar asked Feb 02 '11 10:02

Neil M


1 Answers

This is exactly the approach I use and I've never had any problems with it. In my design, anything that comes out of the data access layer is abstracted as an interface (I refer to them as data transport contracts). In my domain model I then have static methods to create business entities from those data transport objects..

interface IFooData
{
    int FooId { get; set; }
}

public class FooEntity
{
    static public FooEntity FromDataTransport(IFooData data)
    {
        return new FooEntity(data.FooId, ...);
    }
}

It comes in quite handy where your domain model entities gather their data from multiple data contracts:

public class CompositeEntity
{
    static public CompositeEntity FromDataTransport(IFooData fooData, IBarData barData)
    {
        ...
    }
}

In contrast to your design, I don't provide factories to create concrete implementations of the data transport contracts, but rather provide delegates to write the values and let the repository worry about creating the concrete objects

public class FooDataRepository
{
    public IFooData Insert(Action<IFooData> insertSequence)
    {
        var record = new ConcreteFoo();

        insertSequence.Invoke(record as IFooData);

        this.DataContext.Foos.InsertOnSubmit(record); // Assuming LinqSql in this case..

        return record as IFooData;
    }
}

usage:

IFooData newFoo = FooRepository.Insert(f =>
    {
        f.Name = "New Foo";
    });

Although a factory implementation is an equally elegant solution in my opinion. To answer your question, In my experience of a very similar approach I've never come up against any major problems, and I think you're on the right track here :)

like image 144
MattDavey Avatar answered Nov 13 '22 00:11

MattDavey