Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

Sorry, you do not have permission to ask a question, You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please type your username.

Please type your E-Mail.

Please choose an appropriate title for the post.

Please choose the appropriate section so your post can be easily searched.

Please choose suitable Keywords Ex: post, video.

Browse

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Logo

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Navigation

  • Home
  • About Us
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • About Us
  • Contact Us
Home/ Questions/Q 3794

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise Latest Questions

Author
  • 61k
Author
Asked: November 26, 20242024-11-26T06:00:10+00:00 2024-11-26T06:00:10+00:00

Architects Delight: Enforcing Layers and Project Boundaries with Nx

  • 61k

Introduction

When I embarked on my journey as a software developer, I delved into the depths of software architecture. Renowned books such as “Clean Architecture” and “Domain-Driven Design (DDD)” provided valuable insights into concepts like project boundaries and software layers (both vertical and horizontal). Yet, what was sorely missing was a quick and efficient tool to enforce these principles.

Then, I discovered Nx, specifically its @nx/enforce-module-boundaries ESLint plugin, which has revolutionized how I enforce these boundaries.

The Hidden Side of the Iceberg

Interestingly, although the @nx/enforce-module-boundaries ELLint plugin is embedded in the generated code of every integrated Nx-Monorepo, it seems to fly under the radar when the conversation turns to Nx's merits, which are indeed numerous. Even Nx's video, “The Nx Iceberg,” doesn't mention it, despite its focus on the tool's lesser-known features.

Several authors, including Manfred Steyer, Lars Gyrup Brink Nielsen, and myself, have delved into this subject. Still, many developers using Nx aren't utilizing this feature as much as possible. That sparked me to write this article highlighting Nx's power in enforcing project boundaries.

What are Project Boundaries and Layers?

Before we delve into enforcing project boundaries, it's essential to understand what they are. These rules or principles dictate how different parts of our software interact.

For instance, software architects often use philosophies such as onion architecture and clean architecture to define horizontal layers. These layers are then grouped into vertical slices or boundaries using principles like the strategic design from Domain-Driven Design.

Without automated tools, though, maintaining these boundaries becomes tricky. Developers might inadvertently cross these boundaries, leading to issues with maintainability and scalability.

Creating Projects and Boundaries with Nx

Firstly, we must have projects and boundaries before we start enforcing boundaries restrictions. Nx simplifies this process with its generators that swiftly create applications and libraries. Here is a simple command to generate a library:

nx generate @nx/js:library feature-booking 
Enter fullscreen mode Exit fullscreen mode

But a main ingredient is missing; Nx project tags are crucial here. They act as written definitions of our boundaries. For instance:

// project.json { ...   "tags": ["bounded-context:booking", "type:feature"], ... } 
Enter fullscreen mode Exit fullscreen mode

In the current example, we define a vertical slice or vertical layer based on the bounded context containing the library: The booking bounded context. Not only that, but we also define a horizontal layer based on the type of the library: The feature type.

A Rectangle containing a smaller square. The rectangle represents the bounded context, the square represents the library. The rectangle has a caption: Booking, and the square another: feature. Both captions make reference to the level of the tags.

Additionally, we can use grouping folders with Nx to further streamline the structure. I believe there should be a direct connection between tags and grouping folders. I've discussed these patterns extensively in my article “Semantic Grouping Folders with Nx.”

Enforcing Project Boundaries with Nx

With our projects and boundaries in place, we can utilize the power of the Nx @nx/enforce-module-boundaries ESLint plugin to set restrictions between layers.

For example, if we want to restrict that, a library belonging to the booking bounded context can only import libraries from the same bounded context. Or in other words, if we want to enforce the vertical boundary defined by the bounded-context tags, we can do the following:

        "@nx/enforce-module-boundaries": [           "error",           {             "enforceBuildableLibDependency": true,             ...             "depConstraints": [               ...               {                 "sourceTag": "bounded-context:booking",                 "onlyDependOnLibsWithTags": ["bounded-context:booking"]               },               ...             ]           }         ] 
Enter fullscreen mode Exit fullscreen mode

Image description

The same can be done for our horizontal layers. In the following example, we will enforce the following:

  • libraries with type feature can only import libraries with type feature, domain, ui
  • libraries with type ui can only depend on libraries with type ui and domain
  • libraries with type domain can only depend on libraries with type domain.
        "@nx/enforce-module-boundaries": [           "error",           {             "enforceBuildableLibDependency": true,             ...             "depConstraints": [               ...               {                 "sourceTag": "type:feature",                 "onlyDependOnLibsWithTags": ["type:feature", "type:domain", "type:ui"]               },               {                 "sourceTag": "type:ui",                 "onlyDependOnLibsWithTags": ["type:domain", "type:ui"]               },               {                 "sourceTag": "type:domain",                 "onlyDependOnLibsWithTags": ["type:domain"]               },               ...             ]           }         ] 
Enter fullscreen mode Exit fullscreen mode

Image description

With these restrictions in place, if you try to import a library that breaks one of these enforced boundaries, you will get an ESLint error. Here is a hypothetical situation:

// File: libs/boundary/domain/types.ts import { Button } from '@my-org/ui'; 
Enter fullscreen mode Exit fullscreen mode

error  A project tagged with "type:domain" can only depend on libs tagged with "type:domain"  @nx/enforce-module-boundaries 
Enter fullscreen mode Exit fullscreen mode

This error message signifies that we've attempted to cross a boundary, thus helping us maintain the integrity of our architecture.

And this is not everything; we can even restrict external imports as described in the docs. I've found this. tool extremely useful when using technologies that look similar like React, Qwik and SolidJS; or even backend and frontend like Angular and NestJS.

Conclusion

Enforcing project boundaries and layers easily was a dream I thought was too much to ask.

Nx's @nx/enforce-module-boundaries ESLint plugin offers a powerful solution. The more we understand its potential and learn to utilize its power, the more we move towards creating robust, scalable, and maintainable software solutions. Nx is genuinely leading the way in the future of software architecture.

architecturemonoreponxwebdev
  • 0 0 Answers
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

Sidebar

Ask A Question

Stats

  • Questions 4k
  • Answers 0
  • Best Answers 0
  • Users 1k
  • Popular
  • Answers
  • Author

    How to ensure that all the routes on my Symfony ...

    • 0 Answers
  • Author

    Insights into Forms in Flask

    • 0 Answers
  • Author

    Kick Start Your Next Project With Holo Theme

    • 0 Answers

Top Members

Samantha Carter

Samantha Carter

  • 0 Questions
  • 20 Points
Begginer
Ella Lewis

Ella Lewis

  • 0 Questions
  • 20 Points
Begginer
Isaac Anderson

Isaac Anderson

  • 0 Questions
  • 20 Points
Begginer

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Querify Question Shop: Explore Expert Solutions and Unique Q&A Merchandise

Querify Question Shop: Explore, ask, and connect. Join our vibrant Q&A community today!

About Us

  • About Us
  • Contact Us
  • All Users

Legal Stuff

  • Terms of Use
  • Privacy Policy
  • Cookie Policy

Help

  • Knowledge Base
  • Support

Follow

© 2022 Querify Question. All Rights Reserved

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.