There are challenges to overcome when building new applications

Building new, frontend applications presents some key challenges that must be overcome to ensure they deliver what the user expects from them. They need the flexibility to add new features, the scalability to grow the project or add new developers to it, and the intuitive capability for developers to locate and implement fixes and incorporate new elements.

We can define a few architectural characteristics (-ilities) for these requirements, for example:

  • Scalability
  • Flexibility
  • Modularity
  • Readability
  • Simplicity

Each characteristic matches with a requirement discussed above. For instance, scalability matches with growing the project or bringing new developers to it. Flexibility, readability and simplicity match with adding new features or bug fixes. Modularity matches with giving semantic information to developers to know where they need to go and what are the software boundaries.

Now we’re able to start designing the project and architecture style.

Check out the react-example to see a simple demo project using the following principles and ideas addressed in the post.

Using a modular architecture

For scalability, flexibility and modularity, we can use a modular architecture to define the boundaries of the subdomains in the project. By using a modular architecture we have a domain-partitioned project structure where we can see the boundaries between each subdomain.

technical partitioned

domain partitioned

Here we can bring inspirations from domain-driven design, feature-based architecture, vertical slice architecture and screaming architecture (along with a range of other styles).

Adding logical layers

Next, still focusing on flexibility, we should put some logical layers into the project — each layer will carry a single responsibility and make the code evolution simpler. In this case, we’ll define these three layers:

  • Application
    • Containers
    • Interfaces
  • Infrastructure
  • Shared

Application layer

In the application layer (a.k.a subdomains) will reside all logic related to the application itself. For example:

  • Data management
  • API requests
  • UI components
  • All the pages for the application
  • Routes of the application

Etc…

application layer

Copy to Clipboard

Container layer

The container nested layer is related to dependency injection. Its responsibility is to provide concrete implementations for the abstractions and each business capability should have a single container.

Copy to Clipboard

All the code examples will be written using React, as it’s the most popular frontend library as of now (you can use any other library or framework, though).

Copy to Clipboard

Interface layer

The interface nested layer is related to defining the markup and the UI for the application pages — it’s where all the HTML (JSX/TSX) code goes. Each page needs to have a single container attached to it, as it’s a one-to-one relationship.

Copy to Clipboard
Copy to Clipboard

Pay attention to the products-catalog/routes.js file, you have to import and attach only containers for the routes.

Copy to Clipboard

Infrastructure layer

In the infrastructure layer, we’ll include all the necessary details on how abstractions should work and perform their actions. For example, handling API requests (using REST or GraphQL), store management, application theme logic, navigation handling and other things.

Copy to Clipboard
Copy to Clipboard

Shared layer

Finally, the shared layer will contain elements that are used across the entire application, usually global abstractions such as UI/business components, utils, global types and interfaces, helpers, translations, enums, layouts, and more.

Copy to Clipboard

We should create ADR (Architecture Decision Record) document files to specify the reason for each definition, but this is a topic for another blog post — in the meantime, if you want information on creating ADR document files, I recommend you read this article. Below we can see a landscape of all these requirements being resolved by each characteristic.

Copy to Clipboard

Although the code examples were written using React, this architecture style is technology agnostic — by this I mean, libraries and frameworks. The style can be used by React, Angular, Vue, Svelte, Next, Nuxt, Gatsby, SvelteKit, Angular Universal, etc…

Conclusion

There’s no silver bullet to resolve all the problems and challenges we face when we’re building and shipping software. Instead, we need to focus on decreasing the complexity to better handle problems like the ones I’ve covered in this blog post.

By making the project semantic, using a nice folder structure with a separation of responsibilities, incorporating well-defined context boundaries, applying modularization and adding logic layers to handle different concerns we’re able to scale any software project.

References

Share Me

Related Reading

Newsletter

Don’t miss a beat

Get all the latest NearForm news, from technology to design. Sign up for our newsletter.

Follow us for more information on this and other topics.