interface

The Answer To ‘Where Do Interfaces Live?’

Yesterday we looked at the puzzle of where we should place an interface to achieve a pluggable software architecture. We saw that the interface could go either into a high-level business logic component or a lower-level, database-specific data access component. I left the question unanswered but asked for you to write in your answers. 

Thank you to everyone who responded! Your level of engagement in contributing to excellent software engineering practices is admirable! 

Congratulations to Steve Buys from Xero for coming up with the correct answer and the best explanation. Well done, Steve! 

Today we’ll answer the question where we should place interfaces that provide component pluggability.

To keep it concrete, and thus easier to imagine, we’ll continue with the library management system example from yesterday.

We can ask ourselves a couple of questions to get closer to an answer:

  1. Should the high-level business logic component be dependent on the Mongo DB implementation details? 
  2. If we had to add another component containing a SQL Server implementation of IDatabase, then which of the two interface placements would be better suited?

Let’s try and answer Question 1 first.

It’s probably less than ideal to have the business logic component depend on the Mongo DB component. Suppose we placed IDatabase in LibrarySystem.MongoDB we would have to reference LibrarySystem.MongoDB from LibrarySystem.BusinessLogic. Well, unless we performed some late-binding shenanigans which we won’t and can therefore safely ignore.

We are aiming to engineer a solution for architectural pluggability—for easy extensibility and maintainability. If it was just about making “something work“, then we can arrange the dependencies any old way. Fingers crossed we don’t have to change the system design though! 

As we discovered in our exploration on stability, high-level business logic is naturally more stable than database detail. For example, if the database implementation changed from Mongo DB to SQL Server, then does the business workflow change? No, of course not. The database is a detail.

What about the other way around – the database access code depending on the business logic? Stability-wise that seems fair enough. The volatile component depending on the stable one. Really? The database depending on business logic? Well, it’s not the database per se; it’s specific data access logic which is very much in the know about business logic. It knows about the models in the business logic that it must convert to and from the corresponding data access-specific models. It would be very much aware of the data retrieval and persistence operations that the business logic can perform. 

OK, the answer to Question 1 is in support of IDatabase residing in the business logic component.

What about Question 2? Which arrangement makes more architectural sense if we had a LibrarySystem.SqlServer component?

The SQL Server component would contain an implementation of IDatabase. For the sake of pluggability we would want all the SQL Server related classes to live in their own component, right? It would be weird to have SQL Server classes in a component dedicated to MongoDB and named LibrarySystem.MongoDB! No, SQL Server classes get a separate component: LibrarySystem.SqlServer

Now, if interface IDatabase was located in LibrarySystem.MongoDB, then LibrarySystem.SqlServer would have to reference LibrarySystem.MongoDB. What?!? You’re kidding. Yes, that is a bit weird. So not happening. Not on our watch, right? 

Could we redefine a copy of IDatabase in LibrarySystem.SqlServer? This seems like an idea that has legs, but unfortunately it would be a different type and have a different namespace. We would have two different IDatabase interfaces. We don’t want that. 

So, if we insist on putting IDatabase into the Mongo DB component, our only option would be to reference the Mongo DB component from the SQL Server component:

That image looks so wrong; SQL Server depending on Mongo DB. Not good.

On the other hand, if interface IDatabase resided within the business logic component, then our picture looks like this:

That looks much better. Both LibrarySystem.MongoDB and LibrarySystem.SqlServer are just siblings to one another. There exists no dependency between them. We could deploy the system with the Mongo DB component or the SQL Server component.

OK, I’ve been going on for too long—time to wrap up.

Interfaces that enable component pluggability should be placed away from the components that contain the implementers. 

What we have discovered today is related to the idea of how adapters enable pluggable architecture.

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply