Frontend Pattern — Atomic Business Components (ABC)
In this article, we are going to explore a pattern for frontend scalability. we are also going to explore the pros and cons of the ABC pattern.
Atomic Business Component
Reusable UI components can be shared across apps and they don’t carry any business logic them. But business UI components have business logic and data. Business UI components are created on top of reusable UI components.
Almost every Web application is one big monolithic business component.
Atomic Business Component is a pattern where the smallest part of the entire web application is created in such a manner so that,
- It doesn’t depend on the parent. It should work independently of the application or other components. In other words, It doesn’t depend on DOM or parent component hierarchy.
- It should take minimum sufficient parameters and mostly from URL.
100% loose coupling
in the ABC pattern, the entire application is built using multiple smaller business components. and each component can be loaded/unloaded/work independently with each other.
No EventBus or Communication between components
in the ABC pattern, components don’t talk to each other. We will explore later that how to have synchronization between different parts of the app/component.
No Centralised Custom Data+Logic Store
Many UI application architectures make a custom centralized data+logic store which becomes a centralized piece and couple entire web application.
In the ABC pattern, there is no such centralized stuff. each business component load/unload/work 100% independent of others. Think of every component as a mini-app itself.
Example
Take an example of the following screen from Github.
We can immediately think of at least 2 atomic business components.
- BranchCount component
- TagCount component
In order to build and render these two-component, the only input is required is the repo name that is facebook/react
BranchCount component will responsible for fetching data, rendering and subscribing changes of data, and re-rendering.
When it is loaded on the DOM, it will fetch the necessary data. It shouldn’t depend on the parent to give the exact number of branches.
GraphQL is an excellent choice to fetch data. In GraphQL, one can easily fetch data in any structure and any level of granularity.
// Correct way
<BranchCount repo="facebook/react"/>// Wrong way
<BranchCount count="102" icon="branch"/>
In fact, one should be able to load the above component using the following URL.
https://github.com/abc/branch-count?repo=facebook/react
In the ABC pattern, each component must be able to load via unique urls.
In fact, It is highly recommended to develop each such component in an isolated environment and once they are fully developed and tested, we should integrate them into the main application.
Metadata
in the ABC pattern, all the metadata, like CSS styles, language translations JSON, etc are present with the component itself.
In the future, if somebody removes a component, all its metadata also goes removed.
Benefits of ABC pattern
- scalability: highly scalable
- moveability: much easy to move any component from one place to another.
- lego-pattern: since components can be moved very easily, we can truly build applications like lego blocks.
- loose-coupling: components don’t depend on each other.
- removability: instead of using display:none, one can surely delete an old component without worry.
- replaceability: we can replace one component at a time without worrying about breaking the entire application.
- low-bandwidth: When designed with GraphQL, components only request minimum sufficient data.
Problems and Solution with ABC pattern
P0. Fetching data points at granular levels.
In the traditional REST world, creating API for each smallest portion will be problematic. GraphQL APIs come to the rescue. GraphQL APIs are not designed for particular UI components. We can query even the smallest data point using GraphQL APIs.
P1. Multiple components fetching the same data-points.
Two-component can query the same data point. It may result in multiple APIs call but Apollo Client 3 (AC3) provides an excellent mechanism to cache data from GraphQL APIs. Using AC3, we can solve this problem.
If two components require the same data points then one will be served from cached data. Components can bypass cache and request fresh data. In Apollo Client, components are not aware of the cache while making requests.
Take this example.
const { data } = await client.query({
query: gql`
query InitialGqlQuery($uid: String!) {
User(uid: $uid) {
_id
projects {
name
_id
}
}
}
`,
variables: {
uid: userId
}
});
console.warn('Data Received', data);
In the above code, the component doesn’t need to worry about that the data
is coming from a cache or a fresh network call. The component is simply requesting the data-points and it is a headache of AC3 to figure out how to serve data(from cache or a new network call).
P2. Reactivity & Communication
If one component updates some data-points then that change must reach the other parts of the application.
Again, Apollo Client solves this problem for us. In Apollo Client, we can subscribe to queries using client.watchQuery
. So whenever any data-point changes, other components will be automatically updated using Apollo Client.
FAQ
Q1 — Which framework or library (React/Angular/Vue) is best for ABC approach.
It doesn’t matter at all.
Only conditions are
- You are able to load/unload your component with unique URLs in the app itself.
- Component fetches their data and don’t depend on their parents.
- Components don’t depend on DOM or parent hierarchy to work.
- Keep as small as you can.
Q2 — Difference Between Micro Frontend and ABC pattern?
AFAIK, The micro frontend architecture is about loading multiple apps/pages that are built using different UI libraries like React/Vue. We can still develop web-app using ABC patterns and use micro-frontend architecture to combine multiple web apps.
Q3 — is Redux fall under the ABC pattern?
No. as explained earlier too, Redux provided a centralized coupled architecture for the entire app. It's a custom data layer.
on the Other hand, Apollo Client+GraphQL is excellent tech to build an ABC pattern web app.
Q4- I am using React or a similar component library. Am I using the ABC pattern?
Without necessary discipline, One can write full spaghetti code using React where the entire application is fully coupled and a huge number of “props & data & functions” is passed again and again to the entire component hierarchy.
ABC pattern clearly tells about not depends on any component and including parent itself.
Q5- How to test that a given component is following the ABC pattern?
If one is not able to load a given business component using a unique URL then it is not following the ABC pattern.
in the previous example, the BranchCount component was fully working using the following url.
https://github.com/abc/branch-count?repo=facebook/react
One can easily build a component loader that collects props from URL and load a given component with those props.
Q6- Can we combine multiple ‘atomic business component’ to make a bigger ‘atomic business component’
Yes, We should.
Downsides of this approach
- IMO, AC3 and GraphQL work best. If your backend is not GraphQL then implementing this pattern is hard.
- Enforcement in the entire team is difficult.
Conclusion
Apollo Client and GraphQL solve the biggest problems in the frontend world about data layer management. It's like a unified and generic data layer. Otherwise, We need to implement custom logic and build our own data layer using redux or similar libraries.
Because of Apollo Client and GraphQL, we can truly build web applications using Atomic Business Components (ABC) pattern.
There is no library or framework needed for the ABC pattern because it's an architecture pattern. One can use existing frameworks/libs like React/Angular/Vue etc. The team needs sufficient discipline to follow the pattern.
Let me know your thought on this.
If you like the article, please follow me at Twitter — https://twitter.com/nsisodiya