In this series we look at some of the rules in Angular's Style Guide that might need clarification or alteration as we grow our applications and our understanding 🧠 of the framework.
📐 The Rule in Question: Rule Of One
The Angular Style Guide defines this rule as follows:
Do define one thing, such as a service or component, per file.
Consider limiting files to 400 lines of code.
This rule is definitely great advice. It aligns with the Single Responsibility Principle, and motivates us to think about what purpose a component or service in our application really serves.
Choosing 400 lines, as the maximum length per file, is slightly arbitrary, but we should choose some number as a guide post.
Anything that crosses this line is a code smell - not necessarily wrong, but worth further investigation!
Creating multiple components in a single file could make one or both hard to find (at least one class won't match the file name), and as the style guide mentions, the more code in a file, the higher the chance for version control conflicts.
I think this rule is a good starting point, and at the beginning of an application's development there's no reason not to follow it.
This rule has good intentions and is a great suggestion for services and components.
However, most Angular applications are going to include more types than just services and components.
It's common, in a growing or mature code base, to see the following types of things in addition to components and services:
- Domain model classes
- Interface definitions to match API requests / responses
- Type aliases of both of the above, to better match the domain language
- Enum definitions
- Typescript union types
- Custom RxJs operators
- Factory functions for non-class data structures
- Utility functions for validation or transformation
- Classes managed outside Angular's dependency injection system
Do all of these need to be in separate files as well?
Since these types are closely related to each other and the state management code that uses them, it makes sense to co-locate them (keep them close in our project).
I think this rule is somewhat influenced by well-known Object Oriented programming languages, like C# and Java, where the type-per-file pattern is well established.
I really like this quote from Kent Beck (as noted by Mark Seemann):
Following the "Rule of One" and seeing an increase in the number of files in a project isn't inherently a bad thing!
That said, co-location is also a goal that's worth pursuing - especially for code that is closely related.
I think the "Rule of One" should clearly state the it is a recommendation for Angular types (Components, Directives, Injectables, NgModules, ect...), but we should be free to structure our non-Angular code as the project demands.
As always, thanks for reading 🙏!
What are your thoughts on the "Rule of One"?
Have any of your apps included the things I listed above, like domain models, Enum definitions, or custom RxJs operators?
Have you ever found the need to move beyond the "Rule of One" for non-Angular code in your Angular application? What about for Angular specific things?
Leave a comment below!
Normally, I'm blogging about Kentico, a content management system I love to use.
We've put together a list over on Kentico's GitHub account of developer resources. Go check it out!
If you are looking for additional Kentico content, checkout the Kentico tag here on DEV:
Or my Kentico blog series: