Angular Tutorial: Separation of Concerns using ES7 Decorators
Tags: angular, javascript, typescript, tutorial
Published: 2018-02-10 22:39:50

---
title: "Angular Tutorial: Separation of Concerns using ES7 Decorators"
published: true
tags: angular,javascript,typescript,tutorial
canonical_url: https://hackernoon.com/angular-tutorial-separation-of-concerns-using-es7-decorators-ed6c9756265
---

This tutorial is intended to create a simple Angular app which drives a “common issue in OOP paradigm which is code duplication and hidden patterns usually found in real world that can be solved using Inversion of Control techniques and allowing us to perform _declarative programming_.

#### Resources (what this article is&nbsp;about):

- [https://github.com/k1r0s/angular2-srp-showcase/tree/master](https://github.com/k1r0s/angular2-srp-showcase/tree/master)
- [https://github.com/k1r0s/angular2-srp-showcase/tree/normal-oop](https://github.com/k1r0s/angular2-srp-showcase/tree/normal-oop)

### The App

- The app should load a list of **users** (authors) in its home&nbsp;page.
- If a list element is clicked a dialog should be presented
- That dialog should have a brief[1] about the selected user and two&nbsp;buttons
- One button should close the&nbsp;dialog
- Other button should load user specific â€˜post&nbsp;page’
- Clicking on an user from â€˜South Elvis’ will trigger a random exception
- Exception should be cached, an error dialog[2] should be presented
- Post page should render selected user’s specific&nbsp; **posts**

[1] User dialog format/content isn’t part of tutorial’s scope

[2] Error dialog format/content isn’t part of tutorial’s scope

Rules

- Each time we perform an ajax request we must show a loading&nbsp;dialog
- All ajax request should be stored for cache&nbsp;purposes

Technical details

Users (writers) resource is placed here: [https://jsonplaceholder.typicode.com/ **users**](https://jsonplaceholder.typicode.com/users)

Posts resource is placed here: [https://jsonplaceholder.typicode.com/ **posts**](https://jsonplaceholder.typicode.com/posts)

### Let’s start

You can follow these instructions, step by&nbsp;step.

**Prepare your workspace**

- $ git clone https://github.com/k1r0s/angular2-srp-showcase.git
- $ git checkout normal-oop
- $ npm&nbsp;install

**Run the&nbsp;code**

- $ npm&nbsp;start
- browse localhost:4200

**Read the&nbsp;code**

Okay so lets start by openingsrc/app/components/writers/writers.component.ts&nbsp;. This component has the following responsibilities:

- Invoke a service to fetch&nbsp;users
- Render users&nbsp;list
- Listen clicks on users&nbsp;list
- Invoke a service to store users request result and the selected user to be loaded on â€˜posts&nbsp;screen’
- Invoke a service to build a dialog to render selected&nbsp;user
- Handle an exception if selected user is from â€˜South&nbsp;Elvis’

Now lets look over src/app/components/user-posts/user-posts.component.ts&nbsp;. This one has the following responsibilities:

- Grab selected user from&nbsp;cache
- Invoke a service to fetch user’s specific&nbsp;posts
- Render a post&nbsp;list
- Invoke a service to store posts request result for that specific&nbsp;user

### Common OOP drives repetition:

In OOP, each method is an **action or verb** domain related. 

Cross Cutting Concerns are pieces of code that brings nothing to understand what this **action** is really doing by mixing infrastructure concerns with domain concerns.

```javascript
  // stuff that matters
  
  // this stuff only represents "SHOW A DIALOG, DOMAIN SPEAKING"
  // 
  this.dialogRef = this.dialogFactory.open( 
    dialogThatNeedsToBeShowed,
    { data: dialogsRequiredData }
  )
  
  // stuff that matters
```

Let’s see the code at [https://github.com/k1r0s/angular2-srp-showcase/blob/normal-oop/src/app/components/writers/writers.component.ts#L41](https://github.com/k1r0s/angular2-aop-showcase/blob/normal-oop/src/app/components/writers/writers.component.ts#L41)

{% gist https://gist.github.com/k1r0s/53678cc2b33280bfa8fd1a9c4098e530 %}

Most of times a method body that should describe a business action is entangled with code that does not describe at all that action. Like opening a dialog, capturing exceptions, subscribe to close events,&nbsp;etc.

{% gist https://gist.github.com/k1r0s/339b59aaee434c61c95f4d8b54d732b9 %}

In OOP we try to separate concerns by declaring classes that are responsible to manage outdoor interactions that describe **what business wants to happen (domain speaking)**. Usually that classes invoke other classes that describe **how things should be fulfited.**

A common issue in OOP paradigm is that, to replicate a behavior, code must be replicated too. Sometimes class extension isn’t enough because your behavior doesn’t always occur in the same spot or you simply don’t have enough time to change whole app arquitecture. For example, a log service has to be invoked at the end of some method calls printing method’s arguments and result but that implementation isn’t important at all in terms of domain problem **meaning that code is polluting your app**. Can you deal with logs calls with class extension? nope.

What about projects with 12 developers coding **the same behavior with different implementation?** That’s hidden patterns. For example when a developer is used to add a feature similar or identical a previous one most of them will seek that previous implementation on the code base to look â€˜how to deal with the same problem’ or simply paste that code in their feature changing some variables related with the context of that specific screen or feature, while some developers will implement their own code to solve the same problem. We don’t care about which implementation is the best. Different implementations for the same problem drives bugs, code is harder to mantain, etc. An easy solution to deal with this are **interface definition** that all developers must agree. But still duplication spreads.

Authentication, Ajax resolution, UX action invocation, exception handling… almost anything that isn’t related with business logic its likely to be invoked in several places and that implementations can pollute your domain&nbsp;logic.

### Examples

Lets back to writers component

What is really doing writers.component.ts at _setup&nbsp;_?

[Reading the code we may conclude&nbsp;that:](https://github.com/k1r0s/angular2-aop-showcase/blob/normal-oop/src/app/components/writers/writers.component.ts#L78)

- Is reading from cache if resource was already fulfilled (if so list is assigned) and all steps below are&nbsp;skipped
- If that cache is empty: We must show a loading dialog[2] and we fetch users&nbsp;resource
- Then we should store that resource on cache by calling a&nbsp;service
- Then we should hide loading&nbsp;dialog
- Then we should asign the list to be rendered by the component

Many concerns take place as this code gets executed. In terms of domain this is simply **fetch and render users list**. There are a few domain rules that apply on this, **catch resources, show a loading dialog while requesting a resource** …

That behavior also gets replicated on user-posts.component.ts&nbsp;. But on this case there is a domain concern before: _grab the selected user from&nbsp;cache_.

**There is a way to code that implementation abstracting us from component’s specific domain?&nbsp;Yes!**

We already defined some interfaces that writers.component.ts and user-posts.component.ts share: LoadingDialog, ResourceContainer\<T\>, LoadingDialog, CacheContainer&nbsp;. We also assure that there are no _hidden patterns._

- Both components have to fetch some resource when&nbsp;created
- Both components have to show a loading dialog at&nbsp;anytime
- Both have to write/read from cache something

Hence we can achieve this on both components:

![https://cdn-images-1.medium.com/max/1024/1*CI1uqNuWpcd5HIzPFX0m4Q.png](https://cdn-images-1.medium.com/max/1024/1*CI1uqNuWpcd5HIzPFX0m4Q.png)

Note that the same behavior needs to be invoked in different spots and with different context/arguments.

[writers.component.ts (code)](https://github.com/k1r0s/angular2-aop-showcase/blob/master/src/app/components/writers/writers.component.ts)

[user-posts.component.ts (code)](https://github.com/k1r0s/angular2-aop-showcase/blob/master/src/app/components/user-posts/user-posts.component.ts)

And this works, trust me [(running example)](https://angular2-kaop.firebaseapp.com).

> Tip `argsDriverIndex` param for `@ArgsCacheReader` its just a specification of which method **arguments** index will be used as a **serialized key** to read/write from cache. This means that user-posts.component.ts will access cache having first fetchPosts argument. Therefore it will not call the same resource twice.

Is important to know that these decorators can be imported everywhere and are completly standalone (that depends on you). Meaning that you can remove some of them without messing callstack **while in common OOP implementations you face side&nbsp;effects**.

### Conclusion

Method and class Decorators are a powerful tool against repetition and, it also provides a needed abstraction layer needed in modern applications. We have cleared infrastructure code from our component by using declarative programing whichs aims&nbsp;for:

_“Remove side effects by describing_ **what _the program must accomplish in terms of the_** [**_problem domain_**](https://en.wikipedia.org/wiki/Problem_domain)_, rather than describe_ how _to accomplish it as a sequence of the programming language_ [_primitives_](https://en.wikipedia.org/wiki/Language_primitive)_”._

Our code is clear as water and easy to&nbsp;mantain.

We have to understand that **we have created a strong association with two components** which can become very different in the near future. So if our abstraction is somehow deprecated, we must remove this decorator from that component which no longer match a pattern (interface), paste its implementation and code the difference.

### Bonus

#### Why Decorators?

Decorators are bread and butter in modern libraries like Angular, [Vue (addon)](https://github.com/vuejs/vue-class-component), also in backend, for instance [Nest framework](https://github.com/nestjs/nest) provides a lot of built in decorators to enhace your dev experience, improve readability, separate concerns.. etc.

Decorators are nice because provide you a language feature that allows you to add/remove/manage rich implementations without messing in language primitives.

Maybe in the near future decorators will be used as “standalone plugins which can be downloaded and plugged in your code providing features ([example](https://www.npmjs.com/package/decorator-log)).

For instance, Angular’s @Component decorator is a neat way to register your class as a web component into angular boilerplate. So why you wont define some for your own&nbsp;needs?

#### How to @ in Typescript/Babel?

_Babel does not support interfaces to deal with_ **_hidden patterns_** _, but_ [_it supports method and class decorators_](http://babeljs.io/docs/plugins/transform-decorators/)_._

Currently **if you need to write a function that needs to be called before specific constructor in some classes** you need to deal with [ES7 decorators API](https://github.com/wycats/javascript-decorators) which is well explained in [TS&nbsp;docs](https://www.typescriptlang.org/docs/handbook/decorators.html).

I created a [library](https://github.com/k1r0s/kaop-ts/) that makes very easy define your own method/class decorators. It will allow you to _change, extend, modify the behavior of methods and constructors non-invasively_. Of course this tutorial example was made using that&nbsp;library.

Give a&nbsp;try!

* * *


_This post was originally published on [medium.com](https://hackernoon.com/angular-tutorial-separation-of-concerns-using-es7-decorators-ed6c9756265)_