Decoupling the View from the Logic: Part 2 of 2 by Julian Flaks

In Part 1, EQengineered looked at the history of web applications and how the trend has been to move towards REST and SPA architectures. This approach provides a carefully defined separation between logic in the server-side and view code in the client side, and has become the normal approach in the industry. Contrary approaches emerge from time to time; Microsoft’s Blazor is one example of a framework trying to avoid JavaScript in favor of server side languages, and CMSs can complicate the situation where developer extensibility might not be the greatest priority. In general however, mixing up server-side capabilities with front-end concerns is a minority approach which tends to make software architects nervous.

Let us assume we have adopted REST endpoints and utilize a modern SPA. At this point, we might reasonably believe we are done with separation of concerns. The architectural decoupling in RESTful endpoints and a modern front end go a huge distance in separating out the logic, but there are still challenges to face to keep the separation pure. Let’s look at some of them.

Server side: Are you leaking innards to the front end?

Encapsulation should not stop at class definitions. For all parts of a system, think hard about how much information is an overshare. As a simple rule of thumb, if a detail is incidental to implementation, it might not be a great candidate for a DTO attribute. Identifiers are of course useful to share, and a part of the resource naming strategy implicit to REST; if anything, it can be a messy coupling if we try to share member object details as a hierarchy.

Be especially careful having the front end share back more of a complete picture of an object than it needs, and certainly be cautious of it ever sending back details it has no interest in, as that is an almost certain sign that back end concerns are being forced upon it. If in doubt, Command Query Request Separation is a way to pare back and reframe endpoints into exactly what is being desired.

Front end: Is logic separated from the view?

Moving away from the data representations being shared to and fro, there is still a lot to examine in the front-end before we can feel comfortable we have split view and logic. As front-ends have grown to embed more logic and represent more of the codebase, separation of view and logic has become important even within the browser. In the early days of Angular and React, components were an obvious way to break down complexity. But by splitting up along component boundaries, you can neglect the view separation. Components, which may be split up for aesthetic and user interaction reasons, can become the easiest place to communicate with a data source or react to data changes. 

The danger arises that the data and logic layer of the front-end becomes hard-coupled with the visual choices, and seemingly small changes to look and feel demand unexpected amounts of refactoring. The advent of global data stores in various forms can be seen as a fight back from this arbitrary splitting up of data. With the correct use of a Redux or similar solution, data (and at least to some degree, logic) can be given a home which is cross-cutting to the aesthetic divisions of pages and sub-page layout areas.

Are the Front-end and Back-end complete abstractions?

Ask yourself whether endpoints still make sense if you conceive a slightly different layout, or are they unnecessarily page centric. Compromises are a reality, but front ends are adept at pulling from more than one endpoint at once. At the same time, examine the abstractions involved, and if it is not readily clear why various calls are made or how the data is combined, you may have leaked logic to the front end.

Even more serious is the situation where understanding the data inside the back end becomes impossible, owing to too much logic shifting to the front end. It is tempting to design a back end to be resilient to change by using JSON structures with loose typing, but the reality is that if you go down that road for anything non trivial, you have created unstructured data and your back end is incapable of validating its integrity. Worse still is when the combination of back end and front end is the only way to understand the data, because neither can completely comprehend the data in flight, and the two are coupled tightly. Even beyond the application maintainability, such approaches have created a headache for anyone trying to perform meaningful analytics on the data.

Summary | Take Aways

Simply be vigilant with the approach. Many architectures appear clean in design, yet conceal details that deviate from intentions. It is easy to find teams defending server-side class names in DTOs, or view specific notations in stored entities, with convincing sounding arguments. So long as the reasoning confers some value that justifies tighter coupling, there may be an enlightened strategy where the incurred costs make sense. It is important that everybody understands the value and intent in decoupling, and one-off allowances should not be mistaken for a rational architectural approach.

Julian Flaks