2009-05-22

Data, objects and abstractions – Are there more to DIP?

If we define the following:

Data is just raw data, with no context and no logic associated.

Objects contains both data and behavior that operates on that state.

Abstractions defines behavior by naming, with out any details of how the desired behavior is implemented.

 

A common definition of DIP states that:

High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.

That keeps the objects from referencing each other, creating low coupling = a good thing :-)

In C# code following DIP, there is often an “IFooBar” and a “FooBar”. So we have a 1 to 1 between abstractions and object classes. I never really liked it, I don't know why it just don't feels right. Another side effect is that objects that depend on the abstraction can now be unit tested, but often we need to mock the abstraction. In my opinion this leads to hard-to-read and brittle tests.

Is there a simple alternative?

So if objects should not depend upon other object and an abstraction is not desirable, what should the dependency be?

Data

It just like messaging between systems, only this is inside an system. Instead of having a direct dependency to the “CustomerRepository” or having to create a “ICustomerRepository”, just depend on a Customer or a Customer[], nice and simple. This assumes that the Customer is data, and not a object or abstraction.

Move as much if/else/switch/loop code to object classes that depend on and creates data, that way they are easily read, tested and understood. As close to the user action (button click etc. – I call them “Controllers”), get the data needed(possible from a database), pass it to or create the objects, and then take action based on the data result(SubmitChanges to the database, send the MailMessage or what not). These “Controllers” are hard to test and need mocking because of all the database work, mail sending etc., so here classic DIP applies. The Controllers should have a minimum of conditional statements (if) and the few if statements needed should not be nested. This is extremely procedural in nature, and is easy to read.

 

Sometimes we actually need an abstraction, and by all means make one. But code reads better when it just data flowing through logic.