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: Small functions
The Angular Style Guide defines this rule as follows:
Do define small functions
Consider limiting to no more than 75 lines.
💡 Positive Observations: Universally Useful
This rule is a rule to live by in software development!
Sometimes we will end up with large functions/methods/procedures, because the world isn't perfect 😭, but no one will ever recommend we create large functions.
Small functions tend to abide by the Single Responsibility Principle and can help with the Interface Segregation Principle.
If we don't do much in our functions, we decrease the number of dependencies we rely on, and make it easier to separate each function from the others. Small, easily composable pieces often result in a flexible architecture 💪🏿.
As with The Rule of One, the choice of 75 lines is a little arbitrary, but it's a good indicator for a code-smell 💩.
Personally, I would aim far lower than 75 lines, but this would likely result in more architecture and composition - something that might be off-topic for a style guide.
👓 What Needs Clarification: Functions Are Not Methods, But They Are Still Useful
In one code example, found in the Angular style guide, a plain JavaScript function is shown as part of the "bad code" to avoid.
In the "good code" solution, the function is replaced with a Service class method.
I don't think the intention here was to say JavaScript functions are inferior to class methods, but... this is the only use of the function
keyword in the entire style guide 😲!!
Looking closer at the example code, it becomes clear why the function was replaced with a Service class method.
The author wanted to take advantage of Dependency Injection and use the HttpClient to request data from an API 😅.
However, I think a point needs to be clarified here:
We should embrace using native JavaScript functions to encapsulate common operations, especially ones that don't mutate state and have few parameters (dependencies).
One common use case I find for JavaScript functions is when creating an ES Module that contains small, reusable functions which perform validation, data transformation, or object creation.
If these functions are "pure" (they produce no side effects and always return the same values for the same inputs), then they will be easy to test (maybe the easiest code to test in our apps).
If they are easy to test and we use them throughout our applications, this will increase our confidence in the quality of our code and logic 👍🏽.
📌 An Example
Sometimes we create Service classes with methods that do not access any internal state.
Here's an example:
@Injectable({ providedIn: 'root' })
export class UserService {
validateUser(user: User): boolean {
return user.id &&
user.username &&
user.enabled &&
user.hasPaidAccount
}
}
In the above code there is no use of the this
keyword.
Inside a class method, a lack of this
means that method can be changed into a JavaScript function.
But why would we want to use a function instead of a method 🤔?
Well, in this case, validateUser
only depends on 1 thing - the user: User
parameter passed to it.
We don't have a need to create an instance of UserService
, register the type with Angular's dependency injection system, or inject it into other classes.
Instead we could place validateUser
in an ES Module, export it, and then import it into other modules as needed 🧐.
It's also worth nothing that by not having access to the this
keyword, a function is easier to trust.
We know that it isn't changing the internal state of a class, but a class method can.
If a function does change application state, it can only change the state of the parameters passed in - but this is easily testable 🤗!
✨ Conclusion
It is kind of funny 😁 how this rule is named "Small functions" when the only use of actual functions in the style guide results in their removal!
To be clear, I'm not recommending that we replace all classes with functions - there are definite benefits to using classes, Angular's dependency injection system is powerful, and it works well with classes.
I do completely agree that we should consistently aim for small functions or methods in our applications.
I also think the style guide could either clarify that it's recommending "small methods", or add a couple examples of JavaScript functions being used in beneficial ways, and remind developers that classes are a good tool, but not the only tool!
As always, thanks for reading 🙏!
❓ Questions
What are your thoughts on "Small functions"?
Do you find yourself mostly writing classes in Angular applications, or do you also use JavaScript functions?
Does mixing the two cause confusion, or is some inconsistency ok when we use the right tool for the right job?
What do you think is a good goal for function/method length to keep our code maintainable?
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:
Top comments (0)