Introducing the Interaction, Data and View design pattern.
IDV = I + D + V
Every project I've been employed to work on so far I've taken on the responsibility for reorganising brownfield and designing the architecture for greenfield applications. The IDV pattern comes from my frustration of change. Not that I don't like change – I love what change brings. No, it's the fact change is hard.
Change should be cheap
I really believe this. Change happens and is required in business. Applications represent businesses. Applications need to be changed for business reasons. If change is inevitable, shouldn't we prepare for it? What would being prepared for change look like? Or, to put it another way. What does not being prepared for change look like?
- Things are tightly coupled
- Locked to vendors (concrete implementations everywhere)
- Leaky encapsulation
- Confusing or undocumented interfaces
Face it, it looks a mess and we've all been there.
Like I said, IDV came from a frustration of change caused by the problems listed above. So I have potential solutions. In fact I'd call them working solutions because I've developed and utilised them over time.
The main premise is the separation of concerns by introducing clear boundaries to your business and application logic. By using a small set of interfaces we can avoid a lot of these problems of change.
I say small set, it's purposefully a small set. The idea is that the interfaces you introduce will not change. So we define broad and generic method interfaces so these unchanging parts never cause a problem.
What does an unchanging interface look like?
An unchanging interface will be method based rather than class based so that we can switch implementations at anytime.
Method names will be generic enough not to hint any implementation details.
The only parameter will be a hash. This allows any and all kinds of information to be passed in. (At least in dynamically typed languages.)
The only returned value will also be a hash. This means anyone can consume the data returned. Hashes and scalar values should be the only values returned within the main hash.
A flexible unchanging interface means that communication between areas of your application can happen in a limited way. This means change to logic inside the interfaces are fully encapsulated and are less likely to cause problems in other areas of the application.
We do however need to decide where to draw these interface lines.
Separation of concerns
In order to decide where to implement these unchanging interfaces we need to understand the separation of concerns. We need to work out where to separate. The answer is in the name. We need to separate out the parts that aren't concerned with how the other parts do things.
How do most web frameworks split out application logic? MVC! MVC tells us that Model, View and Controller logic are separate concerns.
MVC fails with the unchanging interface criteria. Models in web application world often have many methods and are used in views and controllers. Controllers can have many actions and views have many methods and often mix logic with templates or logic in controllers. This makes for disaster because the interface of a class is the public methods it exposes. The more methods exposed the more weakness your application will have to the changes made in these methods.
MVC is a bastardised separation of concerns
So what areas is MVC trying to tackle? Uncle Bob tells us that the business logic should be wrapped in interface logic. So we have business logic, M. Snug in between the interface and business logic is a view layer for presenting the business data and logic, that's V. C is the controller layer which is basically the communication of the areas of the application to the interface by which the application is delivered.
I'd like to define these better. And not in some weird circle diagram. I'd still split it into three layers like MVC:
- The protocol for delivering the application
- The data layer for applying business logic to data
- The view layer for presentation
Or in other words IDV: Interaction, Data and View.
This isn't clearly defined enough yet though. Each one of these concerns have several concerns themselves. We'll discuss each section and their concerns briefly.
Interaction is the application itself. It is the delivery mechanism for the applications content. It is also the layer that communicates with the domain in order to produce the applications content. That's two concerns right there.
- Interaction with user over protocol communication
- Interaction with the business (domain) layer
Or in two simple terms Application and Controller.
I = A + C
Typicalling routing and protocol handling will be done in the application layer. This layer will then communicate with one or more controllers. The controllers will then interact with the data and view layers and produce a response which is then returned back to the application for delivery to the user.
I have written more about the interaction layer if you wish to find out more.
Data is the core business logic. It deals with asking business questions of data. It also handles the inserting, updating and deletion of business data. Along with this business logic it also handles the communication with the data sources of the application. Three concerns.
- Interaction with data sources
- Modelling of data for answering business questions
- Performing business actions on data
Or more simply Mapper, Model and Action.
D = Ma + Mo + A
Models and actions will be called by a controller. The controller will pass in mappers and other request information to the models and actions and pass their responses into the view layer or immediately return control to the application layer.
I have written more about the data layer if you wish to find out more.
View is the translation of business data into a presentation for the user. It handles the structure of data for presentation. It also handles the modelling of data for presentation. Along with these responsibilities it also needs to merge the modelled data into the structure. Three concerns just like data.
- Structuring data for presentation
- Modelling data for presentation
- Merging the structure and modelled data for presentation
Or more simply Template, Model and Template Engine.
V = T + M + TE
The controller will first pass data from the view layer and request into the view model. It will then use the template engine to merge this view model with a template. This data will then be formed into a response and passed back to the application layer.
I have written more about the view layer if you wish to find out more.
Using unchanging interfaces between each one of the sub concerns defined above will allow you to substitute each concern as per the Liskov substitution principle. Being able to switch out each component separately means they can be tested independently, parts can be replaced without affecting other sections of the application and you only have to introduce 8 types of interfaces to your entire application.
IDV = (A + C) (Ma + Mo + A) (T + M + TE)
This article was more theory than code examples so I apologise for that. You'll find in the links throughout code examples of each layer of IDV. If I tried to fit them all into this one article there would have been trouble.
Let me know what you think @LukeMorton.