Best Practices in Angular

André Braga
ITNEXT
Published in
8 min readMay 29, 2018

--

This is a simple introduction to the best practices you can apply to your Angular project. Note that these best practices can be applied to other languages, but our focus in this article will be Angular with TypeScript.

What are best practices and readable code? This is not a science and my opinion can be different from yours. The aim of this article is to provide you with information and some tips which allow you to decide the best approach in each scenario. These tips received a lot of good feedback from conferences, colleagues, and clients. Thus, I hope I can help you.

Let’s start with a question that you should answer with total sincerity. Do your code reviews look like this?

If so, how do you make your code easier to read?

Simple! You only need to follow some advice that this article will give you. Again, this is the way I work and I love it. You can have a different opinion than me and be totally valid as well. So, let’s actually start this time. 😊

Angular CLI

The Angular CLI is the best way to build Angular Applications. To install it globally, run the following command:

The CLI has scaffolding (aka schematics) tools for creating new projects and generating new code for you. However, this isn’t the main benefit. The main benefit of the CLI is the way it automates the build pipeline for both live development with ng serve, as well as for production code that you would ship down to browsers with ng build -prod.

LIFT Principle

Let’s take a look at the LIFT principle is.

This principle helps you to find code quickly. So, if you don’t use this principle, ask yourself: How quickly can you open and work in all of the files that you need in order to build a feature? My advice: Respect and use LIFT.

Meaningful Names

It’s very important that you give good names to methods, variables, and parameters.

This example of code shows that it’s hard to read and understand this method’s behavior. But if you look to the next example you note that it’s easier.

5 seconds rule

If you can’t understand in 5 seconds you probably need a refactor. Relax, I know that you are thinking that I am crazy, but when I say 5 seconds is a figure of speech. The goal is understanding that your code needs to be easy to get for everyone.

Organization for readability

  • The most important stuff goes first.
  • Properties followed by methods.
  • Grouped and sorted.
  • Consistent naming and spelling matter.
  • One item per file
    One file must have only one component and the same is valid for services or directives.
  • Single Principle Responsibility
    Single class or module should only have a single responsibility.
  • Symbol naming
    Properties and methods must be camel case (e.g. currentUser).
    → Classes (components, services, directives…) must be upper camel case, called Pascal case (e.g. UserComponent).
    → Components and services should have the respective suffix on the name.

UserComponent

UserService

→ Imports

External imports come first

Give a blank line before the import files from own app

This give us an easy way to identify the external and app files

  • Small Functions
    Small functions are better to read and faster to understand the purpose. If your function has more than 10 lines you need to ask yourself if it would be better to break it into smaller functions. This might be hard to do, but unfortunately in the real world, we see a lot of huge functions that are hard to read due to the size and complexity. In my opinion, this is an important practice that everyone should follow.

Provide clarity through code first

  • Self-describing code
  • Replace magic strings with constants (code reuse)
  • Explain in code, not in comments
  • Comments must be readable and maintained
  • Avoid comments when:
    Explains “What” the code does.
    → Outdated and incorrect (wrong comments are worse than no comments).
    → Instead, have a well-named function.
    → THE CODE NEVER LIES, COMMENTS SOMETIMES DO.
  • Use comments when:
    Explain “Why” you do that.
    → Explaining consequences.
    → API Docs.

Angular components best practice

  • Prefixing your components is recommended. If you use Angular CLI to create the component, by default the CLI will prefix your component like this: selector: ‘app-component-name’. You can decide if you keep the ‘app’ as a prefix or change it to the name of the project. If you are using a Feature module section, you can use the name of each feature module to distinguish each component by prefix. For example, if your project name is ‘DIGITALSTORE’ you can put ‘ds’ as prefix. (‘ds-component-name’).
  • Separating the HTML, CSS and TypeScript files is also a good practice. This allows us to have more organized and readable files.
  • Inputs
    → You can declare the input decorator inside of component decorator, near the selector, template, etc. But this is not advisable. The best practice here is to declare it inside of the class and at the beginning like this.

→ For the output decorator, the rule is exactly the same.

  • Delegating complex logic to services
    We want our components to be as simple as possible. This means if our component needs to do some complex logic we need to decide if that logic belongs to the component or not. If we are talking about one or two lines of logic, maybe it’s ok to leave it in the component. In my opinion, the components doesn’t have the responsibility to perform the complex logic. We can leave this to a service, so that our component works like a postman who receives a package and knows it has to send it to someone without needing to know the content of the package. This is a final decision that you need to make in your own app.
  • Component member sequence
    Public methods must be declared before private ones. This is easier to read or find, because in this way we can prevent private methods from getting lost in the middle of lots of public methods. Note that by default all methods are public, so to declare private methods you need to write the private keyword before the name of the method.
  • Implementing life cycle hook interface
    We must declare the life cycle hook interfaces to alert us if we are not using the interface that we declare. For example, when we use the ngOnInit if we declare the implementation like this:

then if we do not create this we will receive an alert telling us that we are missing the ngOnInit:

Angular Services Best Practices

  • Make services as injectable
    This is necessary only when a service injects another service, but is recommended to use every time, because you never know when the service will need to inject another one (dependency injection) and it will be hard to remember that we decided not to use the injectable decorator.

→ We can use the @Inject inside of the constructor and remove the global @Injectable but this is not recommended unless it is needed. For example, if the service that you are injecting is not using the service datatype as this service. This requirement is rare and usually we will not need this. The recommendation is to use @Injectable always. Also, we will need more code because we will need to do this for all the parameters.

  • Using services for data retrieval
    Like we talked above, you should use the Single Principle Responsibility. Our component must call a service to get some data. For example, we can directly call an API in the component… ok the code is simple, but to respect this principle it’s a best practice to put this logic in a service. The service can call an API, localStorage, or also a dummy structure that helps us during development, but for our component this should be transparent. If we need to update the call in our service, the component remains the same. The component shouldn’t have to think how to get the data and it shouldn’t have to know if the data comes from an API or localStorage. The responsibility of the component is only to know that he had the necessity to call the service. The service has the duty to know where and how to get the data. So, please, avoid the temptation to call the API directly on your component.

Conclusion

To improve the performance of your app I recommend that you consider the use of Ahead-of-time compilation, lazy loading, and paying attention to bundle sizes. In my next articles I will go deeper into these, so stay tuned!

--

--