Modern Frontend Architecture 102

Bilel Msekni
Vue.js Developers
Published in
4 min readJul 29, 2019

Understanding what matters, away from javascript fatigue and framework wars

In the first part of this serie, we revealed how modern web Apps are made of different building blocks, each fulfilling a specific role like core, features, etc. In this article, we take a deeper look inside features to understand its challenges. Without further ado, here is the second part.

Update: The third part is already out ! (Click here to check it out)

A feature is a collection of components laid out on the same branch of the tree.

These components need to communicate with each other to deliver the desired business value. For example, when a user selects an item from a list, its details should be fetched then displayed on another component.

Because the shape of the branch is unpredictable, the communication flow can be in any direction and can follow unconventional patterns. This is dangerous as it clouds the judgment of where to put data fetching code, user interaction logic, etc. It may even lead to components with mixed concerns.

Mixing concerns doesn’t only violate many principles of Software Craftsmanship but also makes understanding features tedious. Code debugging becomes necessary, thus causing frustration and inefficiency.

Component communication inside a feature

So, the first challenge is: 👊

Clarify component responsibilities by organizing them into two categories:

  • Presentational component (aka dumb component): As its name states, its sole role is to display UI and to interact with users. It is not aware of the domain it is used in, nor it contains any business logic thus making it highly reusable. The list component is a good example. It knows how to display its items and how to interact with users but isn’t aware of how these items were fetched nor of who is interested in user events.
  • Container component (aka smart component): Because a presentational component lacks context, a container component serve as its context provider. It knows how to get the data to be passed down to presentational component and also how to handle user events. This make it aware of its functional domain, thus ideal host for business logic but also makes it harder to reuse.
Communication between Container and Presentational components

PS: Some frameworks like React promote one way communication by passing callback functions along with the data. This doesn’t contradict with the fact that containers will be passing down data and will be handling user events.

Although communication between container and presentational components follows a standard pattern, the data flow between different containers or even features is still unclear. They need to share, to read and to update data across the App. This is well known as the state management.

So, the second challenge is: 🔥

Determine who’s responsible for managing the App state and for protecting it from inconsistency.

Although the solutions invented to solve this problem differ on the technical level, they are based on a common simple concept.

Because the state can be updated and read by any part of the App, its management shouldn’t be the responsibility of any of them.

Instead, a single global entity will be in charge of managing the App state. Because it’s global, it is the only source of truth therefore protecting the state from inconsistency and making the App easier to understand.

State management through a global entity

This shifts state management responsibility away from container components by transforming them into a business logic layer linking between state and presentational components.

Communication flow between feature layers

This promotes separation of concerns where every layer has a single role:

  • State: Manages the App state and guarantees its consistency.
  • Business logic: Contains business logic and provides context for presentational components.
  • UI: Displays UI and interacts with users.

This also has an impact on code structure too if we want the developers to quickly find their way inside the App code.

AppRepo

├──/Overview
| ├──/Components
| ├──/ListComponent
│ └──/ChartComponent
| ├──/State

The state folder will contain everything related to the state of the feature. It forms together with other feature states, the entirety of the App state.

App state is composed of feature states

In this article, we saw how a feature can be broken into layers to normalize the communication flow and clarify component responsibilities.

In the next article, we will explore the mecanics of the state layer and understand its impacts on components in specific and the App in general.

Stay tuned and don’t forget to 👏😅!

PS: Catch up with the first article of this serie here !

--

--