You Need A Minimum of 3 Data Layers For UI Architecture

Today I’m going to explain why you need a minimum of 3 layers in your UI architecture. What you learn here is relevant to any UI framework (React, Angular or Vue). We are using simple JSX where we include markup examples, but the concepts are the same in the other solutions.

We will evaluate 3 strategies for UI architecture; the 1-layer, the 2-layer and finally our favourite; the 3-layer strategy.

1 Layer Model

In our 1-layer paradigm we simply map all of our persistent data structures (things we get from the API) directly into the view (using our framework component) and let the view do a lot of the processing.

// 1 layer
const authDto = api.get('authentication')
console.log(authDto.token) // 124

<div>
    user {authDto.users['current'].info['email']} is {(authDto.token) ? <>logged in</> || <>logged out</>}
</div>

To a beginner; code like this is enticing because it’s so ‘simple’. It gets the job done fast because of one reason; our brain.

You do not need to think of much except how to make the leap between data and view. You just unwrap one model, and then simply put it directly where you want it.

But hold on…

This code is really complex in the HTML. Because you are having to directly dig around using arrays inside the authDto object.

Most engineers with a few years of experience know that code like this doesn’t scale. It’s extremely brittle because of two reasons;

1) The view is not protected from the complexity of the data.
2) If the data ever changes; so does the view.

To remedy this, the engineer dials out to intermediary layers where they can map their persistent code to an object intended for the view. Sometimes they make this middle layer a ‘state’ repository using a tool like React-Redux.

2 Layer Model

The middle layer creates what we know as a ViewModel. Even when we don’t call it that, normally that’s what state containers produce.

They take out a lot of the complex logic we see in HTML and then flatten it ready for the view. We can then simplify our views and hide a lot of information in this second layer.

// 2 layer
const authDto = api.get('authentication')
console.log(authDto.token) // 124

const viewModel = reducer(authDto)

<div>
    user {viewModel.email} is {(viewModel.token) ? <>logged in</> || <>logged out</>}
</div>

This code is better because the HTML is simpler; but it still presents problems.

Although we don’t have the complexity of digging around in the authDto object in the HTML (and looking into its arrays). We still have other complexity; can you tell what it is?

Hope you guessed right; we have business logic!

That’s right, we have a very subtle business rule which says; if the token is available, then show the text ‘logged in’. If it isn’t then show ‘logged out’.

But hang on, why should we put rules like this into HTML? Well, we shouldn’t! Because;

  1. If the business rule changes so does the HTML.
  2. It’s really hard to mix concerns of flat HTML structure with complex business rules.
  3. We cannot test this code without using an excessive end-2-end test or difficult to write snapshot test.

We really need another layer.

3 Layer Model

This layer affords us a few final ‘flips of the switch’ to get from our data transfer layer to our ViewModel. It should take the business concerns out of the equation for us, we call this the Programmer's Model

// 3 layer
const authDto = api.get('authentication')
console.log(authDto.token) // 124

const programmersModel = reducer(authDto)

const viewModel = {}
if(programmersModel.token) {
    viewModel.message = "user" + viewModel.email + "is logged in"
} else {
    viewModel.message = "user" + viewModel.email + "is logged out"
}

<div>
    {viewModel.message}
</div>

You can see here that the Programmer's Model is a proxy model which intercepts between the authDto and the ViewModel. It’s going to let us run some business logic on it and then make sure our ViewModel is populated with exactly what it needs, instead of complex business information it doesn’t.

In our case we ‘take out’ the complexity behind the authentication rule which lets us produce dynamic text based on authentication state.

In the end the code between (line 7 and line 12) insulates us against the HTML complexity which was only designed to show different sentences in the first place; Madness!

The other benefit is that the Programmer's Model lets us communicate and ratify our business logic more easily with our teammates, because now we have it in one separate layer!

So… there we have the 3 layer (the most ideal) UI architecture which we teach in our UI Architecture Academy. By layering your code like this you can keep your UI views super simple which will help you scale your code infinitely.

Conclusion

The default behaviour for any UI architecture would be to use persistent data structures directly in the view itself.

Most engineers know this technique will give them problems. So, they introduce a second layer (sometimes using things like actions and reducers in tools like Redux).

But when their app becomes tangled, they don’t know why. Normally it’s because they mix the concerns of what they want to model in their code with what the view needs, meaning they have polluted ViewModels.

The missing link is to create a third model (the Programmer's Model) which they use to eliminate all the complex business rules which end up in the view.

In total we need at least 3 models in a UI app;

  • The Data Structure Model – which captures our persistent data from the API
  • The Programmer's Model – which holds business related concerns for calculation later on
  • The ViewModel – a very thin output which feeds off the Programmers model and forces the views to be simple

These 3 layers/models allow you to decouple from your persistent data (API), extend and flex a model which is communicable and understandable by you and your colleagues, and finally use a ViewModel which is optimised to make your view simple/dumb.

So remember when you next see only two layers or models in your UI app architecture, begin introducing one in the middle; the Programmer's Model.

Happy architecting ;-)


Author: Pete Heard

Pete is the founder of Logic Room. He designs the companies core material for JavaScript architecture, test automation and software team leadership.

LinkedIn

Want to learn 5 critical lessons for framework-agnostic JavaScript UI app design and structure?

Download our 28-page book exploring big picture ideas to help you create better architecture with any UI framework (inc. React, Angular or Vue).

Download
Close

50% Complete

Book Trial

Please fill out your details if you would like to trial our system.