Angular best practises, or what goes wrong when designing an Angular application

Hola a todos!

A new day and a new blog post. There are thousands of tutorials out there on how to implement Angular apps. But when you get into a situation where you need to think of a nice architecture for a B2B application, tutorials and blog posts get rear. Actually that situation is clear because of the fact that to be a good software architect you need experience on real world scenarios. However, as I saw some typical errors in the past many times in the different projects I was working on, I thought that it would be a good idea to talk about those architectural errors and how to solve them typically.

This blog post need some kind of basic Angular knowhow because I will not explain basic Angular things in detail but before jumping into some best practises for Angular, first things first, a quick recap what this framework is about. With Angular you have a rich typescript based frontend framework that enables you to create web applications in a structured way. Therefore Angular provides the following main parts (I know, this description is a very short one but I would like to focus on the architectural perspective in this post):

  • Components
    Components are parts of the application. A component can be anything, from a small button to a complex side made out of different components.
  • Services
    In services you capture business logic. So services are typically used to hold data for the app, communicate to backend services or to manipulate data.
  • Modules
    Modules are combined components and there needed services. So you can understand a module as a group of components.

Best Practise #1: Use base components

Let’s start with components and how to structure them. In most applications you get some requirements that are the same all over the whole application. For instance, if you display data somewhere (which is pretty likeable) mostly you need to add some data tables or data grid. First error that I see very often is the not using of specific components for an element in the UI.

Let me show that by a quick example:
It is very likely that users need to input data into your app. To do that you need some input fields. In Angular creating input fields is obviously very easy, something like the following:

<input class="form-check-input" id="textInput" [(ngModel)]="textVariable" type="text">
<label class="form-check-label" for="textInput">
  Enter text
</label>

Nothing spectacular so far. In a business application you will need plenty of such input fields. If you are implementing it everytime in above way you probably going to end up with different ways of implenting the input field, one may have a placeholder, one may have no id, one may not even have a databinding but is storing the data by a (change) event. So it will be very difficult to be maintained in the future. It is also likely that you get problems when you get a new requirement for all instances of inputs, something like “We need a check on the length of inputs of text fields” because then you need to go over every single instance which is timeconsuming.

A better way is using whenever possible base components that are used by the application. Creating such a base component, is of course, not always straight forward as the component should be used by different scenarious. But this effort will count out later when your app’s complexity increases. By creating a base component You will also capsulate a frontend library from the rest of the app, that means you are able to switch it when neccessary by only adopting one class instead of many classes.

When designing the component you should think of what the needed inputs and outputs of a component are. A textfield needs some kind of configuration (label, placeholder,…) and should emit changes to the parent so that it is possible to use the entered text somewhere. A button might have some event that is sent to the parent when clicked. The most important thing here is that you are documenting the inputs and outputs of the base component.

One example of a framework that supports the kind of capsulation that I explaned is storybook. It has documentation features but also it enables you to preview single components and their behaviour.

Best Practise #2: Do not forget about object oriented programming (OOP) when implementing components

Yeah, OOP is definetively something you had learnt in the past. But during the work we do and especially during stressful situations we tend to forget about the basic principles of software engineering. One is to think about how to solve the problem before you start doing something. Another one is the use of object oriented design patters.

Components cover some kind of logic. Often you need some injected classes all over the whole application (for instance a logger which is needed everywhere). In some applications you also need some kind of setup before the component is rendered. To cover such a requirement it is very recommendable to use a base class which is extended by the different components in the app.

My example should describe the mentioned best practice by using a simple logger which is used everytime to log when a component is created. This should just explain the concept, in business applications you are more likely to load a some user information or initiate services but you can use the base component concept for these problems too.

// what to avoid
@Component({
  selector: 'app-somecomponenta',
  templateUrl: './somecomponenta.component.html',
  styleUrls: ['./somecomponenta.component.page.scss'],
})
export class SomeComponentA implements OnInit {
   constructor(private logger: MyLogger) {}

   ngOnInit() {

     this.logger.log('Component was created');
  }
}

@Component({
  selector: 'app-somecomponentb',
  templateUrl: './somecomponentb.component.html',
  styleUrls: ['./somecomponentb.component.page.scss'],
})
export class SomeComponentB implements OnInit {
   constructor(private logger: MyLogger) {}

   ngOnInit() {

     this.logger.log('Component was created');
  }
}

The better way to do it is creating a base component. To create the logger instance I use the Injector class. By doing that I avoid problems when we need to extend the base class later by other injected services because in such a case you would need to change all constructors of implementations of the base class which is not a good idea.

export abstract class BaseComponent implements OnInit {
     protected logger: MyLogger;
     constructor(injector: Injector) {
        this.logger = injector.get(MyLogger);
     }

     ngOnInit() {
        this.logger.log('Component was created');
        this.componentCreated();
     }

    abstract componentCreated(): void;
}

@Component({
  selector: 'app-somecomponenta',
  templateUrl: './somecomponenta.component.html',
  styleUrls: ['./somecomponenta.component.page.scss'],
})
export class SomeComponentA extends BaseComponent {
   constructor(injector: MyLogger) {
      super(injector);
   }

   componentCreated() {

     // custom implementation to set everything up
  }
}

@Component({
  selector: 'app-somecomponentb',
  templateUrl: './somecomponentb.component.html',
  styleUrls: ['./somecomponentb.component.page.scss'],
})
export class SomeComponentB extends BaseComponent {
   constructor(injector: MyLogger) {
      super(injector);
   }

   ngOnInit() {

     // custom implementation to set everything up
  }
}

Best Practise #3: Use and documentate a clear application structure

Angular provides a structured way of creating apps. But still there are many possabilities to create components, modules and their dependencies. So in the beginning of the app is very important to specify how the code of the app should be structured. You need to think of where you put base components, model classes, services and how to create pages with different components. You also have to think of how you are grouping the components in modules. A clear structure will help new developers get in the project faster and also you will find an implementation faster if you have a clear structure.

One pattern that I use very often is the following:

  • Base module
    In this directory I put in everything which is used by many/all components. For instance if you are not using libaries the global logger should be put in somewhere. This module can be importated by other modules.
  • Basic component modules
    For all basic component implementations (button, datagrid, input field, etc.) I would recommend to create a module for each. That will enable you to import only components you will need in the app and so you will be able to make a page loaded faster.
  • A module per menu
    In your app you will have a variety of menues. A good pattern is to create a module for every main screen you have. This screen can, of course, contain a variety of components (lists, detail views, popups, etc.). But grouping all of them is definetivly a good idea. If you are using the Router it is actually essential to use that pattern.
  • Services and data model classes
    Placing services is most of the times a bit more complicated. This is because the same service might be used by a variety of screens. But also, some services might be assigned to exactly one component. So, for services there is no “right or false” but I think it is a good idea to create the service near to the place where it is needed. For instance, if a component is using the service you might end up better if the service is next to the component.
    The same applies to model classes. If you have a shopping list component the shopping list item should be located in the same module.

Best Practise #4: Create small components

Components can end up with many lines of code. Sometimes you have many functionalities it must cover, sometimes you need to put everything together. But big sourcecode classes are difficult to understand, difficult to be tested and more difficult to be fixed when something goes wrong.

Therefore I recommend to make sure that a component don’t get too complex. As I explaned already, use your understanding of OOP to create components with a specifc purpose. Many programmers are complaining about legacy source code basis which are difficult to be maintained, but do not forget to keep attention on not also creating such a legacy code base for future software developers. Angular provides everything to create a clear structure but still you can end up in a big mess.

To create smaller components there are severall possabilites. One is to split the component into serverall small components. For instance, it does not make a lot of sense to put into a component the menu together with all its popup dialogs. It is better to create a component for each popup dialog. That will increase readability of the code and maybe you find out that you can reuse a dialog from somewhere else by doing that practise.

Another option to reduce the amount of code lines is to create service classes for a component. That is a good idea if your component has lot of logic it must cover. One example where I implemented such a thing is a datagrid which is on the one hand displaying data sets but is also performing the data requests. In such a scenario it is an idea to split the code logic into ui logic and business logic, so to create a service that handles the user interaction, create a class that handles the data requests and let the component only display it. You can use the MVVM pattern to design such kind of components.

Important to know is that you are using the same pattern all over an application. If you use one pattern for problem A and another one for another problem it will be difficult to understand what is going on in the component.

Best Practise #5: Create a unit test base libarary

As I explaned in my article about TDD (TDD sucks), testing is complex and needs time. But it is important to provide a good software quality. To make it easier to create a test a good approach is to provide a library which supports developers to create unit tests. One example would be a method which can be used to create the setup for components. Another method could provide all the things we need to provide for jasmine.js to be able to setup the component (change detection etc.). The main goal here is to make testing easier. That totally depends on the case but you should make your and your collegues life easier by adding such implementations to your project.

Best Practise #6: Use one css framework, not all of them

With Angular you get many css frameworks which are doing most of the work for you. That is fantastic! But not every css framework provides a solution for every job. Many times unexperienced developers are then googling for the next framework that provides the solution. Nothing wrong with that, but a library should only be choosen by criteria and not by intention. A new library brings in new functionalities but it also brings in a new bundle size, so a bigger application. That means that your application will take longer to load which means that the user experience is being decreased. Also, if you have different libraries providing the same feature (for instance a handsome button) developers are going to use both libraries which means that the user gets not one type of button but two. That will again, decrease the user experience.

If you want to create an application that should be used on android devices like a native app, use the material design libarary, if you create a rich business application use PrimeNg or KendoUi but do not mix them.

Best Practise #7: Create a base service which is used to perform HTTP requests

In applications you need to communicate to some sort of backend. Normally you need to perform REST requests to do that. Angular provides a base http client but this http client can be used in different ways. Also you may need to add some common headers in all of your REST calls. Most of the time error handlings or caching must also be done everytime a REST call is made. Therefore it is generally a good practice to create a base class which is always used to communicate with rest endpoints.

One very simple example would be the following:

@Injectable()
export class GenericRestConsumer {
    private baseUrl: string;

    constructor( protected httpClient: HttpClient) {
      this.baseUrl = environment.baseUrl;
    }

    /**
     * Will perform a get request.
     * @param path the path to be used.
     */
    get<T>(path: string) {
        const headers = this.setStandardHeaders();
        const url = this.baseUrl + path;
        return this.httpClient.get<T>(url, { headers: headers });
    }

   setStandardHeaders(apiType: TypeOfAPI): HttpHeaders {
      // Some standard headers that must be set all the time
      const headers: HttpHeaders = new HttpHeaders({
          // ....
      }
     );
     return headers;
   }
}

As you see from my example, this class is implemented in a generic way so that many different components can use it to do get calls. By doing that your application is going to get clearer and more understandable. Also you will decrease the amount of bugs produced by forgetting to set some headers and so one.

Best Practise #8: The same procedure as every year… use Angular libraries

When you create severall Angular apps your will soon recognise that you get over the same problem again and again. To prevent copying code from project A to project B and to be able to use some kind of central versioning it is essential to use Angular libaries.

Such libaries can contain of base components, base services (like the generic one) or some combination of both. Before creating the library please make sure to think about what you want to achieve with it. Libaries will provide functionalities over different projects but you might end up a bit more frustrated when you need to change something in the library as you need to do more steps (compiling the library, uploading it to a npm registry).

By using libraries you will get more encapsulation from base tasks. That enables you and your collegues to focus on the actual project.

Conclusion

As I described with some examples there are many ways with that you can increase the quality of your Angular software architecture. Even thought Angular provides a very structured way of how you would implement something it is still essential to think of how you can structure the software you write. By a good and a well documented architecture you and your developer collegues will have a better life in the future when you need to write new software parts.

What do you think about Angular architecture? What are your suggestions how to improve Angular code? Do you have any best practises you like to use when implementing an Angular app?

Some reasons why I think you should consider using Angular in your next project

Hola a todos 😉

Today I really want to talk about a topic I am really enthuasiastic about – and this topic is Angular. Since released in September 2016 many applications started to use this framework. And today I would like to talk about my experiences using the framework in the past years. So maybe you are asking now, why the hell should I read another blog post about that framework? Maybe I can give you a reason. When I came to my current company 3 years ago we started a new project. I have used Angular.js in my recent projects and also I have used React. So first we were sure that using Angular.js is a good idea, why not, it is easy to use (remember the good old days when nothing more was neccessary than including a script and you have a whole framework with you) and there was a hell of a big community out there. But at this time there was already lot of discussions out there in the internet that the new Angular, Angular 2 has many advantages. And that was why I started googling it. Very fast I could find out how this framework works because there are so many explanations out there and Google is also doing a fantastic job from documentations perspective. That was why we started using it and since this time we actually never had any problems with that framewok.

As already described in my introduction, the biggest advantage of using Angular is that it has a big community out there and there are so many ways of learning the framework and getting support using it. Google is doing a fantastic job with their tour of heroes ( https://angular.io/tutorial ) which is explaining the important aspects of Angular very fast. On Stackoverflow there are over 200.000 questions meaning that there is a very active community. And in my mind having many ways of getting information about a framework is one of the most important aspects in modern software development. Nothing is worse than googling an error you have for hours and hours and not finding a solution.

The next good aspect is something that many people don’t like about Angular. It is the strictness of the framework. I know, we all are Software developers and we don’t like too many rules. Especially as web developers we really like the web as it is. We produce code and the browsers are doing the best to correctly run it. That is beatiful. But as projects are growing it is good to have rules – or at least to have some rules. Different software developers are creating code differently. They may use different libraries, they may use different ways of solving problems. Sometimes that is good because it is a way of getting new ideas. But sometimes it is just a big hell of a mess. Hands in the air if you have had any bad experience debugging good old spaghetti style code that was produced by somebody. Angular has solved this issue by providing many features that are normally solved by different libraries. For instance it is including its own HTTP client, it is having a routing functionality and it has all packaging tools included by default. Also it is using typescript which is very recommendable to not run into typical javascript errors produced by somebody that don’t have a clue about that language.

Packaging is something that we as software developers really don’t like to think about. The code should run and the web application should be as small as possible, that is the most important goal. Thank god, today this is something we don’t need to think about since there are tools providing that functionality. Angular is providing those tools and you can run them just by using the angular cli. By the last update of Angular 9 the team also solved a problem that many developers had – that the production bundle is way too big. And also Angular is providing tools to deploy the application directly, so no more worries about copying something to a web server or creating a script that is doing that for you. Check out https://angular.io/guide/deployment for more information.

Ok now some good points but what are the disadvantages? Of course there are also some. As Angular is a framework that can only be used as a whole or not you have to consider that it is developed by Google and if you are using it you are dependent on Google and their developers. I am not one of this guys with their tiny foil hat that are warning you about that company since I think they are providing fantastic features but you have to think about that before using it. If Google wants you to pay for the framework at some time you have to pay them because you are depending on that framework. But isn’t that the same with every framework? No matter if you are using React, Vue.js or some other framework. Either you have to use some library that somebody created or you have to use good old fashioned javascript and DOM functionality and do everything by yourself. But than you will need more time creating things that somebody has already created to get something that somebody else has finished two months ago.

Managing CSS is a problem for many software developers. Creating some nice UI can be pretty different. Today creating a web app is not only focused on providing good functionality but it also needs to focus on good design and usability. So what we are normally are doing is searching for a nice CSS framework and then we are hoping that we don’t have to change too many parts of it. As Angular is a framework with many restrictions searching for UI libraries was used to be difficult, especially in the beginning time of the framework. But that is not the case now. Many UI libraries are providing Angular components out of the box, so you can choose whatever framework you like. If you want to use the styles that are used in every Android phone use Material ( https://material.angular.io/ ). If you more a bootstrap guy you can use ng-bootstrap ( https://ng-bootstrap.github.io/#/home ). PrimeNg also provides nice UIs ( https://primefaces.org/primeng/#/ ).

Now since you still reading I finally can start with the boring part – which is unit testing… 😉 Angular provides everything by its cli to use jasmine testing framework. For those who don’t know it, it is a framework that is nothing more than a whole framework for testing using nothing more than javascript. The Angular cli is creating by default a test by each component or service, so everytime you create a new part of your application also a new test is created. Writing jasmine unit tests is very easy, actually it is so easy that I prefer using unit testing to start an onboarding process with a new employee since you can write tests without understanding a big application. And if you are using WebStorm or vscode you can start the tests without knowing all the cli commandos. I think that is something that is really great because so many times it is a valid excuse for developers that creating tests is so time consuming and so there is no time for it. But creating unit tests provides security for changes in our application as they are telling you if the behaviour is still valid or not. And if a framework is providing you such features by default it is definetivly worth giving it a chance.

I already talked about growing projects that are getting bigger and bigger. At some point it makes sence to create some small libraries that provide functionality with a specified interface. You could create a libarary that provides some base components so that nobody in your company needs to worry about these, you may also want to create a library with all the functionality to create REST calls. Angular is giving you all the tooling you need to do that. Libaries are small projects in a project that are created with the cli. A library can be handled like a normal Angular project. You can write components in it, you can test your components in it and when you are finished you can simply deploy that library and include it. See https://angular.io/guide/creating-libraries how to create libraries in your Angular project.

Google describes its framework as “One framework.
Mobile & desktop”. So one code base for all platforms, sounds like a dream doesn’t it? And so it is, but not by default. What is is meant by one framework is that every platform is able to open web applications. And as we still want to have mobile applications as applications that are available in our app stores this is not enought. I know, somebody out there is right now screaming around because of that point. There are ways to create APKs with Angular code. And yes, calm down, I come to that in a second. But first I would like to start with PWAs. PWA is a technology that provides your web application with functionality that is normally only useable by native applications – so very short, it is awesome. For instance your web application can be used offline or you can use the mobile camera with the app. Maybe you now think, holy shit, that means I have to think about many things like storing all the application data somewhere to be offline available. And also I will not be able to use the dino game of Google Chrome, which is the best inventation that has ever been made by humanity (isn’t that the case?). But here is the good news, not many applications are using PWA technology (which is actually not a good news) and if you want to use PWA it is very easy. Angular CLI provides you commandos to use different functionality. You just need to use the command ng add @angular/pwa and you are able to start. Check out that post to get more information ( https://angular.io/guide/service-worker-getting-started ).

But now, finally, how can we create installable mobile applications with Angular. And here is the good news, there are many ways. One option is to use Ionic ( https://ionicframework.com/docs/). In ionic you build web apps that are then bundled into an installable native app that includes a browser that then is able to display the app. A big advantage of using such a technology that the same code base is usable by a desktop application too (which may be a web app or a desktop app with Electron).

As you see, Angular is a framework that has many advantages. Of course, not everything is good but in my mind it is a framework you should think about when you are in the position of choosing a technology for a new project. What are your experiences with Angular? Do you think that it is a pretty cool framework or do you think that it is too complicated?