tag:blog.wolksoftware.com,2014:/feedWolk Software Engineering2018-07-29T09:18:05-07:00Wolk Software Limitedhttp://blog.wolksoftware.comSvbtle.comtag:blog.wolksoftware.com,2014:Post/implementing-solid-and-the-onion-architecture-in-node-js-with-typescript-and-inversifyjs2018-07-29T09:18:05-07:002018-07-29T09:18:05-07:00Implementing SOLID and the onion architecture in Node.js with TypeScript and InversifyJS<p>In this article, we are going to describe an architecture known as the onion architecture. The onion architecture is a software application architecture that adheres to the SOLID principles. It uses the dependency injection principle extensively, and it is profoundly influenced by the Domain Driven Design (DDD) principles and some functional programming principles.</p>
<h1 id="prerequisites_1">
<a class="head_anchor" href="#prerequisites_1"> </a>Prerequisites</h1>
<p>The following section describes some software design principles and design patterns that we must learn to be able to understand the onion architecture.</p>
<h2 id="the-separation-of-concerns-soc-principle_2">
<a class="head_anchor" href="#the-separation-of-concerns-soc-principle_2"> </a>The separation of concerns (SoC) principle</h2>
<p>Concerns are the different aspects of software functionality. For instance, the “business logic” of software is a concern, and the interface through which a person uses this logic is another concern.</p>
<p>The separation of concerns is keeping the code for each of these concerns separated. Changing the interface should not require changing the business logic code, and vice versa.</p>
<h2 id="the-solid-principles_2">
<a class="head_anchor" href="#the-solid-principles_2"> </a>The SOLID principles</h2>
<p>SOLID is an acronym that stands for the following five principles:</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/awux83emfqr6x9dzfdss.png" alt=""></p>
<h3 id="single-responsibility-principle_3">
<a class="head_anchor" href="#single-responsibility-principle_3"> </a>Single responsibility principle</h3><blockquote class="large">
<p>A class should have only a single responsibility</p>
</blockquote>
<p>The most effective way to break applications is to create GOD classes. </p>
<blockquote class="large">
<p>A God class is a class that knows too much or does too much. The God object is an example of an anti-pattern.</p>
</blockquote>
<p>God classes keep track of a lot of information and have several responsibilities. One code change will most likely affect other parts of the class and therefore indirectly all other classes that use it. That, in turn, leads to an even bigger maintenance mess since no one dares to do any changes other than adding new functionality to it.</p>
<p>The following example is a TypeScript class that defines a Person; this class should not include email validation because that is not related to a person behavior:</p>
<pre><code class="prettyprint lang-ts">class Person {
public name : string;
public surname : string;
public email : string;
constructor(name : string, surname : string, email : string){
this.surname = surname;
this.name = name;
if(this.validateEmail(email)) {
this.email = email;
}
else {
throw new Error("Invalid email!");
}
}
validateEmail(email : string) {
var re = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
return re.test(email);
}
greet() {
alert("Hi!");
}
}
</code></pre>
<p>We can improve the class above by removing the responsibility of email validation from the Person class and creating a new Email class that will have that responsibility:</p>
<pre><code class="prettyprint lang-ts">class Email {
public email : string;
constructor(email : string){
if(this.validateEmail(email)) {
this.email = email;
}
else {
throw new Error("Invalid email!");
}
}
validateEmail(email : string) {
var re = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
return re.test(email);
}
}
class Person {
public name : string;
public surname : string;
public email : Email;
constructor(name : string, surname : string, email : Email){
this.email = email;
this.name = name;
this.surname = surname;
}
greet() {
alert("Hi!");
}
}
</code></pre>
<p>Making sure that a class has a single responsibility makes it per default also easier to see what it does and how you can extend/improve it.</p>
<h3 id="openclose-principle_3">
<a class="head_anchor" href="#openclose-principle_3"> </a>Open/close principle</h3><blockquote class="large">
<p>Software entities should be open for extension, but closed for modification.</p>
</blockquote>
<p>The following code snippet is an example of a piece of code that doesn’t adhere to the open/close principle:</p>
<pre><code class="prettyprint lang-ts">class Rectangle {
public width: number;
public height: number;
}
class Circle {
public radius: number;
}
function getArea(shapes: (Rectangle|Circle)[]) {
return shapes.reduce(
(previous, current) =&gt; {
if (current instanceof Rectangle) {
return current.width * current.height;
} else if (current instanceof Circle) {
return current.radius * current.radius * Math.PI;
} else {
throw new Error("Unknown shape!")
}
},
0
);
}
</code></pre>
<p>The preceding code snippet allows us to calculate the area of two shapes (Rectangle and Circle). If we try to add support for a new kind of shape we will be extending our program. We can certainly add support for a new shape (our application is open for extension), the problem is that to do so we will need to modify the getArea function, which means that our application is also open for modification.</p>
<p>The solution to this problem is to take advantage of polymorphism in object-oriented programming as demonstrated by the following code snippet:</p>
<pre><code class="prettyprint lang-ts">interface Shape {
area(): number;
}
class Rectangle implements Shape {
public width: number;
public height: number;
public area() {
return this.width * this.height;
}
}
class Circle implements Shape {
public radius: number;
public area() {
return this.radius * this.radius * Math.PI;
}
}
function getArea(shapes: Shape[]) {
return shapes.reduce(
(previous, current) =&gt; previous + current.area(),
0
);
}
</code></pre>
<p>The new solution allows us to add support for a new shape (open for extension) without modifying the existing source code (closed for modification).</p>
<h3 id="liskov-substitution-principle_3">
<a class="head_anchor" href="#liskov-substitution-principle_3"> </a>Liskov substitution principle</h3><blockquote class="large">
<p>Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.</p>
</blockquote>
<p>The Liskov substitution principle also encourages us to take advantage of polymorphism in object-oriented programming. In the preceding example:</p>
<pre><code class="prettyprint lang-ts">function getArea(shapes: Shape[]) {
return shapes.reduce(
(previous, current) =&gt; previous + current.area(),
0
);
}
</code></pre>
<p>We used the interface <code class="prettyprint">Shape</code> to ensure that our program is open for extension but closed for modification. The Liskov substitution principle tells us that we should be able to pass any subtype of <code class="prettyprint">Shape</code> to the <code class="prettyprint">getArea</code> function without altering the correctness of that program. In static programming languages like TypeScript, the compiler will check for us the correct implementation of a subtype (e.g., if an implementation of <code class="prettyprint">Shape</code> is missing the <code class="prettyprint">area</code> method we will get a compilation error). This means that we will not need to do any manual work to ensure that our application adheres to the Liskov substitution principle.</p>
<h3 id="interface-segregation-principle_3">
<a class="head_anchor" href="#interface-segregation-principle_3"> </a>Interface segregation principle</h3><blockquote class="large">
<p>Many client-specific interfaces are better than one general-purpose interface.</p>
</blockquote>
<p>The interface segregation principle helps us prevent violations of the single responsibility principle and the separation of concerns principle.<br>
Let’s imagine that you have two domain entities: Rectangle and Circle. You have been using these entities in your domain services to calculate their area, and it was working very well, but now you need to be able to serialize them in one of your infrastructure layers. We could solve the problem by adding an extra method to the Shape interface:</p>
<pre><code class="prettyprint lang-ts">interface Shape {
area(): number;
serialize(): string;
}
class Rectangle implements Shape {
public width: number;
public height: number;
public area() {
return this.width * this.height;
}
public serialize() {
return JSON.stringify(this);
}
}
class Circle implements Shape {
public radius: number;
public area() {
return this.radius * this.radius * Math.PI;
}
public serialize() {
return JSON.stringify(this);
}
}
</code></pre>
<p>Our domain layer needs the area method (from the <code class="prettyprint">Shape</code> interface), but it doesn’t need to know anything about serialization:</p>
<pre><code class="prettyprint lang-ts">function getArea(shapes: Shape[]) {
return shapes.reduce(
(previous, current) =&gt; previous + current.area(),
0
);
}
</code></pre>
<p>Our infrastructure layer needs the serialize method (from the <code class="prettyprint">Shape</code> interface), but it doesn’t need to know anything about the area:</p>
<pre><code class="prettyprint lang-ts">// ...
return rectangle.serialize();
</code></pre>
<p>The problem is that adding a method named serialize to the Shape interface is a violation of the SoC principle and the single responsibility principles. The Shape is a business concern and being serializable is an infrastructure concern. We shouldn’t mix these two concerns in the same interface.</p>
<p>The Interface segregation principle tells us that many client-specific interfaces are better than one general-purpose interface, which means that we should split our interfaces:</p>
<pre><code class="prettyprint lang-ts">interface RectangleInterface {
width: number;
height: number;
}
interface CircleInterface {
radius: number;
}
interface Shape {
area(): number;
}
interface Serializable {
serialize(): string;
}
</code></pre>
<p>Using the new interfaces, we are implementing our domain layer in a way that is completely isolated from infrastructure concerns like serialization:</p>
<pre><code class="prettyprint lang-ts">class Rectangle implements RectangleInterface, Shape {
public width: number;
public height: number;
public area() {
return this.width * this.height;
}
}
class Circle implements CircleInterface, Shape {
public radius: number;
public area() {
return this.radius * this.radius * Math.PI;
}
}
function getArea(shapes: Shape[]) {
return shapes.reduce(
(previous, current) =&gt; previous + current.area(),
0
);
}
</code></pre>
<p>In the infrastructure layer we can use a new set of entities that deal with serialization:</p>
<pre><code class="prettyprint lang-ts">class RectangleDTO implements RectangleInterface, Serializable {
public width: number;
public height: number;
public serialize() {
return JSON.stringify(this);
}
}
class CircleDTO implements CircleInterface, Serializable {
public radius: number;
public serialize() {
return JSON.stringify(this);
}
}
</code></pre>
<p>Using multiple interfaces instead of one general-purpose interface has helped us to prevent a violation of the SoC principle (the business layer doesn’t know anything about serialization) and the Single responsibility principle (we don’t have a class God class that knows about both the serialization and the calculation of the area).</p>
<p>We can argue that <code class="prettyprint">RectangleDTO</code> and rectangle <code class="prettyprint">Rectangle</code> are almost identical and they are a violation of the “Don’t repeat yourself” (DRY) principle. I don’t think it is the case because while they look the same, they are related to two different concerns. When two pieces of code look alike, it doesn’t always mean that they are the same thing.</p>
<p>Also, even if they are a violation of the DRY principle, we would have to choose between violating the DRY principle or the SOLID principles. I believe that the DRY principle is less important than the SOLID principles and I would, therefore “repeat myself” in this particular case.</p>
<h3 id="dependency-inversion-principle_3">
<a class="head_anchor" href="#dependency-inversion-principle_3"> </a>Dependency inversion principle</h3><blockquote class="large">
<p>One should depend upon abstractions, [not] concretions.</p>
</blockquote>
<p>The dependency inversion principle tells us that we should always try to have dependencies on interfaces, not classes. It is important to mention that dependency inversion and dependency injection are NOT the same thing.</p>
<p>It is unfortunate that the dependency inversion principle is represented by the D in SOLID. It is always the last principle explained, but it is the most important principle in SOLID. Without the dependency inversion principle, most of the other SOLID principles are not possible. If we go back and revisit all the previously explained principles we will realize that the usage of interfaces is one of the most fundamental elements in each of the principles: </p>
<ul>
<li><p>Depending on an interface that follows the interface segregation principle allows us to isolate a layer from the implementation details of another layer (SoC principle) and helps us to prevent violations of the single responsibility principle. </p></li>
<li><p>Depending on an interface also allows us to replace an implementation with another (Liskov substitution principle).</p></li>
<li><p>Depending on an interface enables us to write applications that are open for extension but close for modification (Open/close principle).</p></li>
</ul>
<p>Implementing the SOLID principles in a programming language that doesn’t support interfaces or in a programming paradigm that doesn’t support polymorphism is very unnatural. For example, implementing the SOLID principles in JavaScript ES5 or even ES6 feels very unnatural. However, in TypeScript, it feels as natural as it can be.</p>
<h2 id="the-modelviewcontroller-mvc-design-pattern_2">
<a class="head_anchor" href="#the-modelviewcontroller-mvc-design-pattern_2"> </a>The model-view-controller (MVC) design pattern</h2>
<p>The MVC design pattern separates an application into three main components: the model, the view, and the controller.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/yl84y5ypxi0i1pfzc7hb.png" alt=""></p>
<h3 id="model_3">
<a class="head_anchor" href="#model_3"> </a>Model</h3>
<p>Model objects are the parts of the application that implement the logic for the application’s data domain. Often, model objects retrieve and store model state in a database. For example, a Product object might retrieve information from a database, operate on it, and then write updated information back to a Products table in a SQL Server database.</p>
<p>In small applications, the model is often a conceptual separation instead of a physical one. For example, if the application only reads a dataset and sends it to the view, the application does not have a physical model layer and associated classes. In that case, the dataset takes on the role of a model object.</p>
<h3 id="view_3">
<a class="head_anchor" href="#view_3"> </a>View</h3>
<p>Views are the components that display the application’s user interface (UI). Typically, this UI is created from the model data. An example would be an edit view of a Products table that displays text boxes, drop-down lists, and checks boxes based on the current state of a Product object.</p>
<h3 id="controller_3">
<a class="head_anchor" href="#controller_3"> </a>Controller</h3>
<p>Controllers are the components that handle user interaction, work with the model, and ultimately select a view to render that displays UI. In an MVC application, the view only displays information; the controller handles and responds to user input and interaction. For example, the controller processes query-string values and passes these values to the model, which in turn might use these values to query the database.</p>
<p>The MVC pattern helps you create applications that separate the different aspects of the application (input logic, business logic, and UI logic) while providing a loose coupling between these elements. The pattern specifies where each kind of logic should be located in the application. The UI logic belongs in the view. Input logic belongs in the controller. Business logic resides in the model. This separation helps you manage complexity when you build an application because it enables you to focus on one aspect of the implementation at a time. For example, you can focus on the view without depending on the business logic.</p>
<p>The loose coupling between the three main components of an MVC application also promotes parallel development. For example, one developer can work on the view, a second developer can work on the controller logic, and a third developer can focus on the business logic in the model. The Model-View-Controller (MVC) design pattern is an excellent example of separating these concerns for better software maintainability.</p>
<h2 id="the-repository-and-the-data-mapper-design-pat_2">
<a class="head_anchor" href="#the-repository-and-the-data-mapper-design-pat_2"> </a>The repository and the data mapper design patterns</h2>
<p>The MVC pattern helps us to decouple the input logic, business logic, and UI logic. However, the model is responsible for too many things. We can use a repository pattern to separate the logic that retrieves the data and maps it to the entity model from the business logic that acts on the model. The business logic should be agnostic to the type of data that comprises the data source layer. For example, the data source layer can be a database, a static file or a Web service.</p>
<p>The repository mediates between the data source layer and the business layers of the application. It queries the data source for the data, maps the data from the data source to a business entity, and persists changes in the business entity to the data source. A repository separates the business logic from the interactions with the underlying data source. The separation between the data and business tiers has three benefits:</p>
<ul>
<li>It centralizes the data logic or Web service access logic.</li>
<li>It provides a substitution point for the unit tests.</li>
<li>It provides a flexible architecture that can be adapted as the overall design of - the application evolves.</li>
</ul>
<p>The repository creates queries on the client’s behalf. The repository returns a matching set of entities that satisfy the query. The repository also persists new or changed entities. The following diagram shows the interactions of the repository with the client and the data source.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/l2e1xo4vm9deyy403p78.png" alt=""></p>
<p>Repositories are bridges between data and operations that are in different domains. A common case is mapping from a domain where data is weakly typed, such as a database, into a domain where objects are strongly typed, such as a domain entity model. </p>
<p>A repository issues the appropriate queries to the data source, and then it maps the result sets to the externally exposed business entities. Repositories often use the Data Mapper pattern to translate between representations. </p>
<p>Repositories remove dependencies that the calling clients have on specific technologies. For example, if a client calls a catalog repository to retrieve some product data, it only needs to use the catalog repository interface. For example, the client does not need to know if the product information is retrieved with SQL queries to a database or Collaborative Application Markup Language (CAML) queries to a SharePoint list. Isolating these types of dependences provides flexibility to evolve implementations.</p>
<h2 id="the-onion-architecture_2">
<a class="head_anchor" href="#the-onion-architecture_2"> </a>The onion architecture</h2>
<p>The onion architecture divides the application into circular layers (like an onion):</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/6y0l99fwf5vtfgqq3eva.png" alt=""></p>
<p>The central layer is the domain model. As we move towards the outer layers, we can see the domain services, the application services and, finally, the test, infrastructure, and UI layers.</p>
<p>In DDD, the center of everything is what is known as “the domain” The domain is composed of two main components:</p>
<ul>
<li>Domain model</li>
<li>Domain services</li>
</ul>
<p>In functional programming, one of the main architecture principles is to push side-effects to the boundaries of the application. The onion architecture also follows this principle. The application core (domain services and domain model) should be free of side effects and implementation details, which means that there should be no references to things like data persistence (e.g., SQL) or data transportation (e.g., HTTP) implementation details.</p>
<p>The domain model and domain services don’t know anything about databases, protocols, cache or any other implementation-specific concern. The application core is only concerned about the characteristics and rules of the business. The external layers (infrastructure, test and user interface) are the ones that interact with the system resources (Network, Storage, etc.) and is where side-effects are isolated and kept away from the application core.</p>
<p>The separation between layers is achieved via the usage of interfaces and the application of the dependency inversion principle: Components should depend upon abstractions (interfaces) not concretions (classes). For example, one of the infrastructure layers is the HTTP layer which is mainly composed of controllers. A controller named <code class="prettyprint">AircraftController</code> can have a dependency on an interface named AircraftRepository:</p>
<pre><code class="prettyprint lang-ts">import { inject } from "inversify";
import { response, controller, httpGet } from "inversify-express-utils";
import * as express from "express";
import { AircraftRepository } from "@domain/interfaces";
import { Aircraft } from "@domain/entitites/aircraft";
import { TYPE } from "@domain/types";
@controller("/api/v1/aircraft")
export class AircraftController {
@inject(TYPE.AircraftRepository) private readonly _aircraftRepository: AircraftRepository;
@httpGet("/")
public async get(@response() res: express.Response) {
try {
return await this._aircraftRepository.readAll();
} catch (e) {
res.status(500).send({ error: "Internal server error" });
}
}
// ...
}
</code></pre>
<p><code class="prettyprint">AircraftController</code> is part of the infrastructure layer and its main responsibility is dealing with HTTP related concerns and delegate work to the <code class="prettyprint">AircraftRepository</code> The <code class="prettyprint">AircraftRepository</code> implementation should be completely unaware of any HTTP concern. At this point, our dependency graph looks as follows:</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/3mjknbo44vtstqvyk0vx.png" alt=""></p>
<p>The arrows in the diagram have different meanings the “comp” arrow defines that <code class="prettyprint">AircraftRepository</code> is a property of <code class="prettyprint">AircraftController</code> (composition). The “ref” arrow defines that <code class="prettyprint">AircraftController</code> has a reference or dependency on <code class="prettyprint">Aircraft</code>.</p>
<p>The <code class="prettyprint">AircraftRepository</code> interface is part of the domain services while the <code class="prettyprint">AircraftController</code> and <code class="prettyprint">AircraftRepository</code> implementation are part of the infrastructure layer:</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/l5390ozl9u253sue5dps.png" alt=""></p>
<p>This means that we have a reference from one of the outer layers (infrastructure) to one of the inside layers (domain services). In the onion architecture we are only allowed to reference from the outer layers to the inner layers and not the other way around:</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/2i73srvbean7nitmf8up.png" alt=""></p>
<p>We use the <code class="prettyprint">AircraftRepository</code> interface to decouple the domain layer from the infrastructure layer at design time. However, at runtime, the two layers must be somehow connected. This “connection” between interfaces and implementation is managed by InversifyJS. InversifyJS allow use to declare dependencies to be injected using the <code class="prettyprint">@inject</code> decorator. At design time, we can declare that we wish to inject an implementation of an interface:</p>
<pre><code class="prettyprint lang-ts">@inject(TYPE.AircraftRepository) private readonly _aircraftRepository: AircraftRepository;
</code></pre>
<p>At runtime, InversifyJS will use its configuration to inject an actual implementation:</p>
<pre><code class="prettyprint lang-ts">container.bind&lt;AircraftRepository&gt;(TYPE.AircraftRepository).to(AircraftRepositoryImpl);
</code></pre>
<p>We will now take a look at the <code class="prettyprint">AircratRepository</code> and <code class="prettyprint">Repository&lt;T&gt;</code> interfaces which is part of the domain services layer.</p>
<pre><code class="prettyprint lang-ts">import { Aircraft } from "@domain/entitites/aircraft";
export interface Repository&lt;T&gt; {
readAll(): Promise&lt;T[]&gt;;
readOneById(id: string): Promise&lt;T&gt;;
// ...
}
export interface AircraftRepository extends Repository&lt;Aircraft&gt; {
// Add custom methods here ...
}
</code></pre>
<p>At this point, our dependency graph looks as follows: </p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/5bumjhjmjmeamndjabmy.png" alt=""></p>
<p>We now need to implement the <code class="prettyprint">Repository&lt;T&gt;</code> interface and the <code class="prettyprint">AircraftRepository</code> interface:</p>
<ul>
<li><p><code class="prettyprint">Repository&lt;T&gt;</code> is going to be implemented by a class named <code class="prettyprint">GenericRepositoryImpl&lt;D, E&gt;</code></p></li>
<li><p><code class="prettyprint">AircraftRepository</code> is going to be implemented by a class named <code class="prettyprint">AircraftRepositoryImpl</code>.</p></li>
</ul>
<p>Let’s start by implementing <code class="prettyprint">Repository&lt;T&gt;</code>:</p>
<pre><code class="prettyprint lang-ts">import { injectable, unmanaged } from "inversify";
import { Repository } from "@domain/interfaces";
import { EntityDataMapper } from "@dal/interfaces";
import { Repository as TypeOrmRepository } from "typeorm";
@injectable()
export class GenericRepositoryImpl&lt;TDomainEntity, TDalEntity&gt; implements Repository&lt;TDomainEntity&gt; {
private readonly _repository: TypeOrmRepository&lt;TDalEntity&gt;;
private readonly _dataMapper: EntityDataMapper&lt;TDomainEntity, TDalEntity&gt;;
public constructor(
@unmanaged() repository: TypeOrmRepository&lt;TDalEntity&gt;,
@unmanaged() dataMapper: EntityDataMapper&lt;TDomainEntity, TDalEntity&gt;
) {
this._repository = repository;
this._dataMapper = dataMapper;
}
public async readAll() {
const entities = await this._repository.readAll();
return entities.map((e) =&gt; this._dataMapper.toDomain(e));
}
public async readOneById(id: string) {
const entity = await this._repository.readOne({ id });
return this._dataMapper.toDomain(entity);
}
// ...
}
</code></pre>
<p>This particular <code class="prettyprint">Repository&lt;T&gt;</code> implementation expects an <code class="prettyprint">EntityDataMapper</code> and a <code class="prettyprint">TypeOrmRepository</code> to be injected via its constructor. Then it uses both dependencies to read from the database and map the results to domain entities.</p>
<p>We also need the <code class="prettyprint">EntityDataMapper</code> interface:</p>
<pre><code class="prettyprint lang-ts">export interface EntityDataMapper&lt;Domain, Entity&gt; {
toDomain(entity: Entity): Domain;
toDalEntity(domain: Domain): Entity;
}
</code></pre>
<p>And the <code class="prettyprint">EntityDataMapper</code> implementation:</p>
<pre><code class="prettyprint lang-ts">import { toDateOrNull, toLocalDateOrNull } from "@lib/universal/utils/date_utils";
import { Aircraft } from "@domain/entitites/aircraft";
import { AircraftEntity } from "@dal/entities/aircraft";
import { EntityDataMapper } from "@dal/interfaces";
export class AircraftDataMapper implements EntityDataMapper&lt;Aircraft, AircraftEntity&gt; {
public toDomain(entity: AircraftEntity): Aircraft {
// ...
}
public toDalEntity(mortgage: Aircraft): AircraftEntity {
// ...
}
}
</code></pre>
<p>We use the <code class="prettyprint">EntityDataMapper</code> to map from the entities returned by the <code class="prettyprint">TypeOrmRepository</code> to our domain entities. At this point, our dependency graph looks as follows:</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/1kvlt30aqebjreb6x5ax.png" alt=""></p>
<p>We can finally implement <code class="prettyprint">AircraftRepository</code>:</p>
<pre><code class="prettyprint lang-ts">
import { inject, injectable } from "inversify";
import { Repository as TypeOrmRepository } from "typeorm";
import { AircraftRepository } from "@domain/interfaces";
import { Aircraft } from "@domain/entitites/aircraft";
import { GenericRepositoryImpl } from "@dal/generic_repository";
import { AircraftEntity } from "@dal/entities/aircraft";
import { AircraftDataMapper } from "@dal/data_mappers/aircraft";
import { TYPE } from "@dal/types";
@injectable()
export class AircraftRepositoryImpl
extends GenericRepositoryImpl&lt;Aircraft, AircraftEntity&gt;
implements AircraftRepository {
public constructor(
@inject(TYPE.TypeOrmRepositoryOfAircraftEntity) repository: TypeOrmRepository&lt;AircraftEntity&gt;
) {
super(repository, new AircraftDataMapper())
}
// Add custom methods here ...
}
</code></pre>
<p>At this point, we are done, and our dependency graph looks as follows:</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/4p6c8t9bbimoreb85kd2.png" alt=""></p>
<p>The preceding diagram uses colors to identify concretions (classes, blue) and abstractions (interfaces, orange):</p>
<p>The following diagram uses colors to identify a component that belongs to the domain layer (green) and components that belong to the infrastructure layer (blue):</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/152j7cxu3trb2e4cha5y.png" alt=""></p>
<p>This architecture has worked very well for me in large enterprise software projects over the last ten years. I also ended up breaking up some colossal monolithic onions into microservices that follow the same architecture. I like to say that when we have microservices that implement the onion architecture, we have a “bag of onions”.</p>
<p>I hope you enjoyed the article! Please let me know your thoughts via Twitter at <a href="https://twitter.com/RemoHJansen">@RemoHJansen</a>.</p>
tag:blog.wolksoftware.com,2014:Post/a-look-ahead-web-development-predictions2018-07-29T09:16:49-07:002018-07-29T09:16:49-07:00A Look Ahead: Web Development Predictions<p>In this post, I would like to share some predictions about the world of web development. Making predictions is dangerous because there are high chances that they will be wrong. However, I enjoy thinking about the future because it is exciting and it can help us to identify potential future career opportunities. Remember that all innovations start as a fantasy. </p>
<p>Over the past couple of years, I’ve been reading some blog post and announcements as well as observed some of the breakthrough technologies in the world of web development, DevOps and cloud computing spaces and I’m starting to being able to envision how the world of web development could look like in a decade from now. These are some of the most significant changes in the world of web development that I can envision right now. Please note that these predictions are not based on formal research, and it is just pure speculation.</p>
<h1 id="infrastructure-will-no-longer-be-a-concern_1">
<a class="head_anchor" href="#infrastructure-will-no-longer-be-a-concern_1"> </a>Infrastructure will no longer be a concern</h1>
<p>Cloud computing has been around us for a little bit over a decade now. Amazon launched AWS in 2006 and Microsoft launched Azure in 2010. I don’t know if you remember the hype around cloud computing when it started to be a thing but its promise was the following:</p>
<blockquote class="large">
<p>Scale the IT function up or down immediately to meet the near real-time needs of any large organization.</p>
<ul>
<li>
<a href="https://www.forbes.com/2010/06/30/pharmaceuticals-mobile-salesforcecom-technology-cloud-computing.html"><em>“Cloud Computing’s Great Promise”</em></a> by Forbes.com </li>
</ul>
</blockquote>
<p>The promise of cloud computing has been somehow true from the beginning, but I feel that it is only now, thanks to the arrival of serverless technologies and more than ten years later that it is becoming a fulfilled promise. One of the significant milestones during this journey has been the arrival of container technologies such as Docker and container orchestration technologies such as Kubernetes. </p>
<p>The container technology take its name from the <a href="https://en.wikipedia.org/wiki/Intermodal_container">Intermodal container</a> used by the shipping industry. I would like you to stop thinking about web development and cloud computing for a second and think about the implications of the arrival of intermodal containers. </p>
<p>Before the arrival of the Intermodal containers, all sort of things with different shapes and weights had to be loaded, accommodated and unloaded by hand. It took an insane amount of time and human effort to move objects from one location to another. The Intermodal containers allowed things to be loaded into a container and then they could be transferred using one unique standard shape across different modes of transport (from a ship to a rail to a truck) without unloading and reloading their cargo. The use of standardized steel shipping containers began during the late 1940s and early 1950s. Soon after, the ships, the trucks, the trains and cranes where all adapted to optimize the accommodation of containers. As a result, today the world’s busiest trading port (Shangai) handles 32 million of containers a year carrying 736 million tonnes of goods around the globe. Intermodal containers enabled a level of productivity never seen before.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/t78y6v2bsaaac6qnes8i.jpg" alt=""> </p>
<p>The most impressive part of this story is that the Intermodal container revolution is not over yet. The arrival of IoT and AI is going to make the shipping process even more efficient. The entire shipping chain could someday be 100% autonomous. The trucks, the cranes, ships, and trains could all use the data provided by IoT sensors and the algorithms powered by AI to transport containers around the world without the intervention of one single human being. While this may sound like science fiction, all the technology required to achieve such a scenario is available today. </p>
<p>Let’s go now back to the world of web development and cloud computing. We already have containers, and we have container orchestration tools. We are also starting to have some container orchestration tools that are 100% managed by the cloud providers, which means that we don’t need to think about container orchestration at all. We also have some serverless technologies like <a href="https://aws.amazon.com/lambda/">AWS Lambda</a> y <a href="https://azure.microsoft.com/en-us/services/functions/">Azure functions</a> and some managed distributed databases like <a href="https://azure.microsoft.com/en-us/services/cosmos-db/">Azure Cosmo DB</a>. It feels to me like managing servers is quickly becoming a thing of the past just like loading and unloading stuff by hand did when the Intermodal container revolutionized the shipping industry.</p>
<p>The next step for the Intermodal container revolution is also the next step for the cloud computing revolution. It is easy to imagine that IoT and AI are going to have a very significant impact on cloud infrastructure management. For example, a cluster could be scaled based on predictions powered by IoT and AI and failures in servers could also be predicted before they happen. The combination of serverless technologies, IoT and AI are going to allow us to create applications that can scale and that will be incredibly resilient and cost-effective, and developers will not even need to think about these problems. Infrastructure will stop being a concern for all of us, and we will be able to focus 100% of our time in the business needs and our users instead of waisting an interminable number of hours dealing with infrastructure-related concerns.</p>
<p>Today, there is a high demand for professionals that know how to implement large-scale distributed systems but in the future, they could be in low demand. As organizations increase their focus on the users needs instead of infrastructure concerns, the demand for technical skills will decrease and the demand for soft skills will increase.</p>
<h1 id="semantic_1">
<a class="head_anchor" href="#semantic_1"> </a>Semantic</h1>
<p>A semantic web is a web where all information is categorized and stored in such a way that a computer can understand it as well as a human. The idea of the semantic web has been around for quite a long time, but I don’t think it has taken off yet. However, I do believe that it is going to happen at some point because the semantic web is becoming more relevant as the AI technologies improve.</p>
<p>In the future, systems and services will need to be able to understand each other and communicate with each other without the intervention of a human. For example, we should be able to ask for a wide variety of services to a virtual assistant like Cortana, Siri or Alexa. The virtual assistant technologies should then be able to communicate with a vast number of systems implemented by third-party providers such as Uber or Dominos. At some point, it will become essential for these systems to be able to discover and understand each other automatically. The semantic web will play a big role in this.</p>
<h1 id="aiassisted-development-amp-ux_1">
<a class="head_anchor" href="#aiassisted-development-amp-ux_1"> </a>AI-assisted development &amp; UX</h1>
<p>Our development tools are going to incorporate assistance powered by AI. For example, Guess.js is a library that can help us to reduce the losing times in our website by predicting user workflows and pre-fetching resources.</p>
<blockquote class="large">
<p>Libraries &amp; tools for enabling Machine Learning driven user-experiences on the web.</p>
<ul>
<li><a href="https://github.com/guess-js/guess">Guess.js</a></li>
</ul>
</blockquote>
<p>Microsoft has also recently showcased an AI-assisted development tool named IntelliCode:</p>
<blockquote>
<p><strong>IntelliCode</strong> generates recommendations by using a machine-learning model that is trained on thousands of public codebases – today it uses over 2000 GitHub repositories that each has more than 100 stars to ensure that you’re benefiting from best practices. The model is used in your IDE along with your local code context to provide .NET related APIs that are likely to be the most relevant for you given the line of code you’re writing. We’ll be growing and improving the model over time, so the recommendations will get better as we progress.</p>
<ul>
<li>
<a href="https://blogs.msdn.microsoft.com/visualstudio/2018/05/07/introducing-visual-studio-intellicode/"><em>“Introducing Visual Studio IntelliCode”</em> </a> by Microsoft</li>
</ul>
</blockquote>
<p>These are just two examples, but there will be many more to come. Working with the help of AI will become the norm.</p>
<h1 id="decentralized_1">
<a class="head_anchor" href="#decentralized_1"> </a>Decentralized</h1>
<p>Another significant trend will be the decentralization of specific services. I don’t believe that every service will become decentralized, but I’m sure that a lot of them will. As more people become aware of the implications of our sensitive data being own and managed by companies such as Facebook, the idea of using a decentralized service will become more and more appealing. Also, it seems like a lot of political leaders seems to have a keen interest in controlling the contents that are available on the internet. For example, Teresa May, the British Prime Minister, has been advocating for a regulated internet a good while. Decentralized systems will be a way to scape these regulations.</p>
<h1 id="compiled-javascript-is-here-to-stay_1">
<a class="head_anchor" href="#compiled-javascript-is-here-to-stay_1"> </a>Compiled JavaScript is here to stay</h1>
<p>Using a compiler while developing JavaScript will become more and more mainstream. I believe that the leader right now is TypeScript, but even if TypeScript goes away, it will only because it has been replaced by another compiler. Compilers can help us to detect some problems earlier and to don’t have to worry about low-level details of our compilation target. However, compilers can also automatically optimize certain aspects of our code and generate metadata that can be consumed by other development tools. This metadata is crucial because we can say that it enables other tools to understand certain aspects of our code. For example, the metadata can be used to allow a dependency injection library to be able to understand the dependencies in our application. In a certain way, we can say that the metadata helps our code to be “semantic”.I can imagine that in the future someone out there is going to have a crazy idea of connecting a compiler to some AI technologies to create tools that will be able to reduce the build times, optimize our code even more and detect even more issues automatically. AI will power a new generation of compilers and a new generation of tools with the help of the compiler-generated metadata.</p>
<h1 id="summary_1">
<a class="head_anchor" href="#summary_1"> </a>Summary</h1>
<p>In summary, AI technologies are going to be a big deal. Big corporations are aware of this as they demonstrate by their investments in AI technologies. AWS, Microsoft, and Google are all betting hard into AI.</p>
<p>We heard a lot of things in the press about the breakthrough in AI applied to the human-to-machine interaction, but I believe that the most significant impact in the world of web development is going to take place in the machine-to-machine communications. For example, in the interactions between our applications and the cloud services that host them will be managed and enhanced by AI. </p>
<p>I hope you enjoyed this post! Do you agree with my predictions? What are your predictions? Please share your thoughts and ideas via Twitter at <a href="https://twitter.com/RemoHJansen">@RemoHJansen</a> </p>
tag:blog.wolksoftware.com,2014:Post/my-new-book-has-just-been-released-here-is-how-i-did-it-and-how-you-can-do-the-same2018-07-29T09:14:59-07:002018-07-29T09:14:59-07:00My new book has just been released! Here is how I did it and how you can do the same<p>My new book, <strong>Learning TypeScript 2.x</strong>, has just been released!</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/tb1e0z9bbsmzx3pidp0s.jpg" alt=""></p>
<p>I’m not going to talk about the book contents in this post because you can learn everything about it at <a href="http://www.learningtypescript.com/">www.learningtypescript.com</a>. However, I would like to talk about the behind the scenes process of how this book became a reality.</p>
<p>In this article I’m going to answer the following questions:</p>
<ul>
<li><p>How did I end up writing a technical book?</p></li>
<li><p>What is involved in writing a technical book?</p></li>
<li><p>Is the effort of writing a technical book worth?</p></li>
<li><p>How can you write a technical book?</p></li>
</ul>
<p>I decided to write this post because I think it could be useful for some aspiring authors. Let’s get started!</p>
<h1 id="how-did-i-end-up-writing-a-technical-book_1">
<a class="head_anchor" href="#how-did-i-end-up-writing-a-technical-book_1"> </a>How did I end up writing a technical book?</h1>
<p>In this section, I will try to provide you with some background information that explains how I ended up being highly involved with TypeScript and receiving an offer to write a technical book about it.</p>
<h3 id="my-first-javascript-steps_3">
<a class="head_anchor" href="#my-first-javascript-steps_3"> </a>My first JavaScript steps</h3>
<p>I consider myself very lucky because early in my career I got a job at a company that had an extensive holiday booking system powered by JavaScript. I had spent the first couple years of my career working on PHP, Java, and C# web applications and this application was entirely different from anything that I had seen at the time. The application loaded “widgets” (a combination of HTML, CSS, and JSON) on demand using AJAX calls. It was basically a single-page web application (SPA) with “web components” however it was a couple of years before SPAs became mainstream.</p>
<p>The application worked very well. However, we regularly experienced some common JavaScript issues like:</p>
<ul>
<li><p>Problems caused by the “this” operator pointing to the wrong thing</p></li>
<li><p>Type coercion issues like adding to numbers that were actually strings</p></li>
<li><p>Scope issues caused by the lack of block scope</p></li>
</ul>
<p>This application gave me an early exposure to large JavaScript applications with client-side rendering. I found this “new” way of building web applications fascinating and I enjoyed working with JavaScript a lot, so I decided to focus on learning more about SPAs and JavaScript.</p>
<p>After some time, I got a new job, and this time I was going to work on a greenfield project. I had more room for choices, and I wanted to try to solve some of the problems that I had experienced in my previous project. I decided to build an SPA with “widgets” just like before but with two significant changes:</p>
<ul>
<li><p>I decided to use a JavaScript module loader for the very first time (Require.js).</p></li>
<li><p>I also decided to use CoffeeScript because I liked the idea of not having to worry about lexically bind the value of “this” by hand thanks to the usage of arrow functions.</p></li>
</ul>
<h3 id="coffeescript-didn39t-work-for-me_3">
<a class="head_anchor" href="#coffeescript-didn39t-work-for-me_3"> </a>CoffeeScript didn’t work for me</h3>
<p>Af first, CoffeeScript did help to a certain extent but it never fully solved all my problems. However, after a few months CoffeeScript became a problem. I found that debugging some issues was becoming more and more complicated as our code base got bigger. It was also quite hard to find developers with previous experience with CoffeeScript. So I ended up removing CoffeeScript and going back to vanilla JavaScript with Require.js and AMD modules.</p>
<h3 id="typescript-came-to-the-rescue_3">
<a class="head_anchor" href="#typescript-came-to-the-rescue_3"> </a>TypeScript came to the rescue</h3>
<p>It was only a couple of months later when Microsoft showed TypeScript for the very first time. TypeScript didn’t manage to get a lot of interest from the web community initially. I think this was because Microsoft had a bad reputation within the web development community. Many saw TypeScript as something completely different from JavaScript because when TypeScript was announced most people were unaware of the details of the ES6 specification. When they saw a code sample with classes in TypeScript, they thought that it was TypeScript while, in reality, it was ES6. As a result, they felt that Microsoft was not trying to improve the ecosystem but to replace it with a new ecosystem while the reality is that Microsoft was quite visionary!</p>
<p>I was aware of the mistakes of Microsoft in the past, but I was also familiar with the good side of Microsoft. I had some experience with C#, and Visual Studio and the developer experience od these tools was simply amazing. On top of this, I was already a fan of Anders Helsberg (the father of C# and TypeScript), and while JavaScript and frontend development are my passions, my adventures in the backend with C# made me miss and envy the type safety of C#. Finally, TypeScript was announced as an Open Source project able to run on Windows, Mac, and Linux, which might seem like something obvious today, but back on the day, it was pretty unusual for Microsoft. </p>
<p>I started to use TypeScript as soon as the first preview was released and it was a pretty exciting announcement for me. It was able to solve some of the problems that I experienced in the past, it was open source, and it improved the existing ecosystem as opposed to trying to replace it. It just ticked all my boxes. </p>
<h3 id="being-an-early-adopter-paid-off_3">
<a class="head_anchor" href="#being-an-early-adopter-paid-off_3"> </a>Being an early adopter paid off</h3>
<p>I started to learn more about TypeScript, I wrote a few of blog post about it, and I highlighted it as one of my skills on Linkedin.com. Then, one day I got an email from Packt Publishing. They told me that they were looking for technical reviewers for an upcoming TypeScript book. </p>
<p>Packt Publishing found me because I highlighted TypeScript as one of my skills on Linkedin.com. Today thousands of people have TypeScript as one of their skills on Linkedin.com, but a few years ago there was only a small number of early adopters. I’m sure that this significantly increased my chances of being contacted by a book publisher. Before this event, I didn’t care too much about Linkedin.com, but ever since then I learned a valuable lesson: </p>
<p>If you want to increase the chances of great things happening to you, you will need to work hard, but you will also need to let the world know what are you working on.</p>
<p>I thought that being a technical reviewer was a fantastic opportunity. I always wanted to write a technical book. It was one of my lifetime goals, but I thought that it was completely out of my reach and many years ahead of me so I saw becoming a technical reviewer as something that could help me to get there faster. </p>
<p>I was not expecting it, but I ended up being offered the opportunity to be an author straight after my first job as a technical reviewer.</p>
<h3 id="typescript-becames-mainstream_3">
<a class="head_anchor" href="#typescript-becames-mainstream_3"> </a>TypeScript becames mainstream</h3>
<p>The first edition of Learning TypeScript was published just a couple of months before TypeScript became mainstream. </p>
<p>Over time the web development community became aware of the new ES6 features, the size of the average JavaScript application grew exponentially, and Microsoft started to embrace open source. However, it was only when the Angular team at Google announced that they were going to adopt TypeScript that it became mainstream.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/fm1s8gw5fw8pg9xrq3pc.png" alt="Google trends chart for TypeScript"></p>
<p>I think the fact that Google adopted it helped the community to trust TypeScript and start to see it as what it really is: a truly open source technology that adheres to open standards.</p>
<h1 id="what-is-involved-in-writing-a-technical-book_1">
<a class="head_anchor" href="#what-is-involved-in-writing-a-technical-book_1"> </a>What is involved in writing a technical book?</h1>
<p>In this section, I’m going to try to describe the process of writing a book and the amount of work that is involved in it.</p>
<h3 id="there-is-a-rocky-road-ahead-of-you_3">
<a class="head_anchor" href="#there-is-a-rocky-road-ahead-of-you_3"> </a>There is a rocky road ahead of you</h3>
<p>Everyone can write a book; you don’t need to be a genius. However, you are going to need time, patience and perseverance. For example, the Manning Publications website says that you are going to need:</p>
<blockquote class="large">
<p>Time and writing skills, or at least the time and will to acquire them.</p>
</blockquote>
<p>While the Wrox website says the following:</p>
<blockquote class="large">
<p>If you’re a programmer and you’re interested in writing for Wrox — even if you’ve never written anything before — feel free to contact us. We’ll be more than happy to take you on as an author if you know the technology inside out. Wrox authors aren’t writers by trade — they’re programmers, and our unique editorial process will get the best out of you.</p>
</blockquote>
<p>I believe that time is and perseverance or will are the essential skills. I would also like to point out that I think that you are not going to be able to do it alone.</p>
<p>The book sales will generate some direct additional income for you. I cannot say the exact figures here because they are under an NDA. However, I can say that you can make enough money to go on an exotic holiday but not enough money to buy a car or pay your mortgage.</p>
<p>You are most likely going to need to keep your fulltime job to be able to pay your bills, which means that you are only going to have time to write in the evening after work and during the weekends. You probably also have other responsibilities outside of work which will take even more of your time. I don’t know how others deal with this lack of time, but in my case, I went to bed very late and didn’t sleep very well for months.</p>
<p>You will feel tired, and you are not going to spend as much time as you would like with your family and friends.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/o4gtttdpeje0tx19t7ma.jpg" alt="A cartoon that tries to represent expectations (easy path) and reality (difficult path) "></p>
<p>As you can imagine this is hard and this is why I think that you are not going to be able to do it alone. In my case, it only worked out because I had the support of my family and friends.</p>
<p>My advice about this is to be prepared. Expect a long, exhausting road ahead of you. It is going to be a big sacrifice for you and for the people that care about you. Troy Hunt has <a href="https://www.troyhunt.com/how-i-optimised-my-life-to-make-my-job/">some good advice</a> about this kind of sacrifice:</p>
<blockquote>
<p>So many times I hear people who want to get more involved in the sorts of things I’ve been doing say “I can’t, my wife / husband / kids would go nuts”. That’s a perfectly fine position for the significant other to take and by no means is that a bad thing when that’s your shared vision. It’s when one party continually wants to head in a direction that the other doesn’t support that things get tricky.</p>
<p>I had many years of working my arse off at all hours in order to reach this point and that put a lot of pressure on my wife. We have two small kids and she was working in a pretty high-level job until recently too; my drive and ambition became her responsibility as well. And she supported me – almost unquestioningly – because ultimately, we share the same vision of how we want to live. It took many years for that effort to bear any fruit beyond my own personal sense of satisfaction which whilst important, doesn’t do a lot for the family as a whole. It’s only been over the last 18 months that she (and the kids, for that matter) have seen a return in a way in which we all benefit. Obviously, an important part of that is financial, but it also translates into flexibility which means more time with the kids, more holidays and more generally just doing what we want, when we went. It’s been her sacrifice as much as it has been mine.</p>
<p>And now I’m helping her to do the same, at least insofar as focusing on her public profile and building independence from corporate life in the way we’ve both previously known it. If you appreciate what I’ve been able to do over the years, tweet her a quick thanks because boy does she deserve it!</p>
<p>Tip: Talk to your significant other about where you want to invest your time and how that benefits you collectively. Don’t do this and don’t let it come between you; agree on where you’re heading together.</p>
</blockquote><h3 id="the-writing-process_3">
<a class="head_anchor" href="#the-writing-process_3"> </a>The writing process</h3>
<p>The process of writing a book is intense and long, but it is not complicated. </p>
<ol>
<li><p><strong>Create an outline</strong>: In my case, the process started by ordering all the existing TypeScript books in the market (at the time there was only a couple of them). I created a list of the content covered by each of the books, the parts that I enjoyed, the parts that I did not enjoy and the missing parts. Then I used all this information to put together the initial outline. Creating an outline that progressively introduces the contents is crucial. The outline must be approved by the editor before you can move to the next phase.</p></li>
<li><p><strong>Planning phase</strong>: In this phase, you need to come up with estimates for each chapter and create a calendar with the delivery date for each chapter. In my case, writing the initial draft of a chapter took between two and three weeks.</p></li>
<li><p><strong>Initial draft phase</strong>: Once you have the outline, you can start writing the chapters. Each chapter must go through an initial QA check from the book editor. The chapter then enters the technical review phase.</p></li>
<li><p><strong>Technical review phase</strong>: While you write the next chapter, a group of technical reviewers with different levels of expertise and different backgrounds will read the chapter and let you know how they feel about it.</p></li>
<li><p><strong>Pre-final phase</strong>: Once you finish all the chapters, you will have to incorporate the feedback from the technical reviewers to the chapter, and it will enter the pre-final phase. At this point, you have your last chance to upgrade the outdated content and fix any remaining issues.</p></li>
<li><p><strong>Final phase</strong>: You will then get the final version, and if you are happy with it, it will be sent to print.</p></li>
</ol>
<p>Unfortunately, the review process needs to be quite fast because some technologies evolve at a very fast pace. For example, TypeScript is released every two months. If it takes you two months to review all the chapters, your book will be outdated before it is released.</p>
<p>This whole process (from outline to release) took me eleven months for the first edition and another extra eleven months for the second edition.</p>
<p>I found the reviews and content upgrades to be harder than writing the initial drafts. My advice about this is to try to don’t panic. Your book is never going to be fully updated and entirely perfect. Work hard, try your best and enjoy the journey.</p>
<h1 id="is-the-effort-of-writing-a-technical-book-wor_1">
<a class="head_anchor" href="#is-the-effort-of-writing-a-technical-book-wor_1"> </a>Is the effort of writing a technical book worth?</h1>
<p>In this section, I’m going to try to explain all the benefits that I have experienced as a result of becoming an author.</p>
<h3 id="the-direct-financial-benefits-are-not-great_3">
<a class="head_anchor" href="#the-direct-financial-benefits-are-not-great_3"> </a>The direct financial benefits are not great</h3>
<p>As I said earlier, from the economic point of view it is not really worth it. If you divide the income generate directly from the book sales by the number of hours that you are going to put into the book you will find out that the pay per hour is not great. However, the book will provide you with some significant indirect benefits (including indirect financial benefits).</p>
<h3 id="you-will-learn-a-lot_3">
<a class="head_anchor" href="#you-will-learn-a-lot_3"> </a>You will learn a lot</h3>
<p>There are things that you understand and use every day. However, if you write about them and try to come up with an easy explanation, you will realize that you don’t understand some of these things as good as you though and as a result, you will end up doing some more reading and having a better understanding.</p>
<p>You will also have to go deeper into detail because a technical book is a more formal medium than our emails, slack chats and blogs posts. This will lead you to learn some low-level details that you could afford to ignore before. As a result, you will learn a lot, and this knowledge will also help you to get a better job.</p>
<h3 id="it-will-help-you-to-get-involved-in-oss_3">
<a class="head_anchor" href="#it-will-help-you-to-get-involved-in-oss_3"> </a>It will help you to get involved in OSS</h3>
<p>While I was working on both of the editions of my book something unexpected happened. Besides writing a book, another thing that I always wanted to do was to contribute to an open source. I knew how to contribute (using Git, GitHub…) but I never felt that I had an idea worthy of being released as open source. However, I had an idea while I was writing the first edition (InversifyJS) and another idea while I was working on the second edition (TsUML).</p>
<p>I believe that this happened because when you write a book, you have to think about the future. You need to keep an eye on the product roadmap and ensure that your book will be up to date when it is released. </p>
<p>For example, I started to write a chapter about decorators before this feature was added to TypeScript. I wrote the chapter using some public design notes that were available online at the time. It was then when I had the idea of creating and IoC container powered by decorators and for the very first time I wasn’t too late. I searched online for it, and Angular was planning something similar, but nothing was available at the time, so I started working on what became InversifyJS. Today InversifyJS has over two million downloads on npm.</p>
<h3 id="it-will-help-you-to-be-more-confident_3">
<a class="head_anchor" href="#it-will-help-you-to-be-more-confident_3"> </a>It will help you to be more confident</h3>
<p>Another thing that happened to me was that the book somehow helped me to overcome my impostor syndrome. I was not afraid anymore about doing things like sharing my thoughts with the community at blog posts, local user groups or conferences and I decided to start the Dublin TypeScript meetup.</p>
<p>Overcoming my impostor syndrome was for me the best benefit provided by the book and eventually led me to become a Microsoft MVP.</p>
<h3 id="the-indirect-financial-benefits-are-great_3">
<a class="head_anchor" href="#the-indirect-financial-benefits-are-great_3"> </a>The indirect financial benefits are great</h3>
<p>The income generated directly by the book sales will most likely not be great. However, the indirect benefits such us learning or getting involved in OSS and the community will help you to become a better professional.</p>
<p>Having a book, some OSS projects and conference talks in your CV will help you to stand out and get a better job. This means that the book will lead you to some great financial benefits not directly related to the book sales.</p>
<h1 id="how-can-you-write-a-technical-book_1">
<a class="head_anchor" href="#how-can-you-write-a-technical-book_1"> </a>How can you write a technical book?</h1>
<p>I was not expecting to be offered to publish a book so soon. I thought that it was a privilege reserved only for very well-known engineers like John Resig, Camille Fournier, Jon Skeet or Martin Fowler but I was wrong.</p>
<p>The reality is that a lot of times these very well-known engineers are too busy to write a book, or they don’t want to do it because writing a book is a very exhausting activity.</p>
<p>In fact, there is a high demand for technical authors and not many authors available. </p>
<p>I believe that the lack of authors is not caused by a lack of skills it is more a lack of confidence. Just like me, I’m sure that many other engineers would like to write a book and would do a fantastic job if they had an opportunity but they don’t feel ready. This is just another instance of the infamous impostor syndrome.</p>
<h3 id="being-an-early-adopter-of-technologies_3">
<a class="head_anchor" href="#being-an-early-adopter-of-technologies_3"> </a>Being an early adopter of technologies</h3>
<p>Becoming an early adopter is not always an option. Some critical solutions cannot rely on immature technologies. However, nothing is stopping you from trying something new on your next hobby project.</p>
<p>Being an early adopter of open source technologies will help you to identify potential ways to improve the technology and fix issues, which will give you clear opportunities to contribute to the project.</p>
<h3 id="sharing-your-experiences_3">
<a class="head_anchor" href="#sharing-your-experiences_3"> </a>Sharing your experiences</h3>
<p>Being an early adopter is only the first step. Do you need to let the world know how is it going for you? How can we get started with this technology? What are the benefits of this technology? Which patterns have you noticed to be effective? When you are an early adopter, this kind of things are not available online, but you will create them. </p>
<p>If a publisher wants to release a book a few years later, your name will most likely come up on his google searches. You need to let the world know what are you working on and what interest you. That is the only way that they will be able to find you and contact you if they have an opportunity for you.</p>
<h3 id="becoming-a-technical-reviewer_3">
<a class="head_anchor" href="#becoming-a-technical-reviewer_3"> </a>Becoming a technical reviewer</h3>
<p>You can become a technical reviewer right now. Trust me; you can contribute to a book right now.</p>
<blockquote class="large">
<p>If you don’t feel you’re ready to become a Wrox author, or you’d like to be involved but just don’t have the time to dedicate to writing a book, you have some alternatives. You can become a technical editor, using your programming knowledge to review and validate a book’s technical material. Your feedback would play a very important role in the quality of the final book.</p>
</blockquote>
<p>Even if you are a junior developer, you can be a technical reviewer. The book will most likely be read by other junior developers so having your input will help the author to ensure that the book is suitable for the less experienced sector of the public.</p>
<p>You can become a technical reviewer by contacting the publishing companies. Here are some examples:</p>
<ul>
<li><p><a href="https://www.packtpub.com/books/info/packt/contact-us">Packtpub</a></p></li>
<li><p><a href="https://www.apress.com/gp/services/tech-review">Apress</a></p></li>
<li><p><a href="https://www.manning.com/manuscript-reviews">Manning</a></p></li>
<li><p><a href="http://www.wrox.com/WileyCDA/Section/id-105073.html">Wrox</a></p></li>
</ul>
<h3 id="becoming-an-author_3">
<a class="head_anchor" href="#becoming-an-author_3"> </a>Becoming an author</h3>
<p>I highly recommend working as a technical reviewer first because it will help you to get familiar with the process. As I said earlier you don’t need to be a genius or to have amazing writing skills. All you need is:</p>
<blockquote class="large">
<p>Time and will to acquire them (writing skills).</p>
<p>If you’re a programmer and you’re interested in writing for Wrox — <strong>even if you’ve never written anything before</strong> — feel free to contact us. We’ll be more than happy to take you on as an author if you know the technology inside out. Wrox <strong>authors aren’t writers by trade</strong> — they’re programmers, and our unique editorial process will get the best out of you.</p>
</blockquote>
<p>The recipe for success is time + will + support from your family and friends.</p>
<p>Trust me; you have way more chances than you think. The publishing companies are having a hard time finding authors:</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/1mg9do6lbrk5j3oo25eu.jpeg" alt="A recruitment advert for technical authors in one of the Packt Publishing books"></p>
<p>You can become an author by contacting the publishing companies. Here are some examples:</p>
<ul>
<li><p><a href="https://www.packtpub.com/books/info/packt/contact-us">Packtpub</a></p></li>
<li><p><a href="https://www.apress.com/gp/write-for-us">Apress</a></p></li>
<li><p><a href="https://www.manning.com/write-for-us">Manning</a></p></li>
<li><p><a href="http://www.wrox.com/WileyCDA/Section/id-105073.html">Wrox</a></p></li>
</ul>
<p>Maybe you are wondering which publishing company you should approach first. I cannot provide you with much advice because I have only worked with Packt Publishing but my experience with them has been enjoyable and I would happily work with then again in the future.</p>
<h1 id="summary_1">
<a class="head_anchor" href="#summary_1"> </a>Summary</h1>
<p>Writing a book takes a lot of time and effort. It is a big commitment but overall it also a very positive experience. If you have ever dreamed about publishing your own technical book, don’t be afraid, contact the publishing companies and give it a go. You can do it!</p>
<p>Did you enjoy this article? Do you have any questions? Please let me know at <a href="https://twitter.com/RemoHJansen">@RemoHJansen</a>.</p>
<p>Thanks for reading!</p>
tag:blog.wolksoftware.com,2014:Post/the-most-important-practical-lesson-that-javascript-has-taught-us2018-01-29T01:43:20-08:002018-01-29T01:43:20-08:00The most important practical lesson that JavaScript has taught us<p>The incredible rise in popularity that JavaScript has experienced over the last decade has been spectacular. According to the yearly developer survey by StackOverflow <a href="https://insights.stackoverflow.com/survey/2017">[1]</a>, JavaScript is today the most popular programming language in the world:</p>
<p><img src="https://svbtleusercontent.com/h8ojppccedhaq_small.png" alt=""></p>
<p>JavaScript also leads the ranks in other studies and surveys like the quarterly Programming Language Rankings by Redmonk <a href="http://redmonk.com/sogrady/2017/06/08/language-rankings-6-17/">[2]</a> or the 2018 Developer Skills Report by HackerRank <a href="https://research.hackerrank.com/developer-skills/2018/">[3]</a>:</p>
<p><img src="https://svbtleusercontent.com/9cjam0o4rodlfg_small.png" alt=""></p>
<p><img src="https://svbtleusercontent.com/6arkkhxzowutla_small.png" alt=""></p>
<p>The success of JavaScript has been so spectacular that we even have a “law” about it <a href="https://en.wikipedia.org/wiki/Jeff_Atwood">[4]</a>:</p>
<blockquote class="large">
<p>Any application that can be written in JavaScript, will eventually be written in JavaScript.</p>
</blockquote>
<p>However, the success of JavaScript has not been free of detractors. JavaScript has been the source of inspiration for some well-known jokes:</p>
<p><img src="https://svbtleusercontent.com/cgddjt9nrsautg.jpg" alt=""></p>
<p>JavaScript has been the focus of a lot of negative criticism, It has even been described by some as “a phenomenon of mass psychosis” <a href="https://hackernoon.com/the-javascript-phenomenon-is-a-mass-psychosis-57adebb09359">[5]</a>:</p>
<blockquote class="large">
<p>JavaScript programmers have been mind-fucked into thinking that JavaScript is a good programming language. The president speaks of “mass psychosis” and “crowd thinking” but I’ve used the analogy of Stockholm syndrome and cult psychology. Think Patty Hearst and Scientology.</p>
</blockquote>
<p>However, all these negative comments don’t seem to have been able to stop it from becoming extraordinarily successful. So, I’ve been asking myself one question for some time: Why? Why is JavaScript so successful?</p>
<h1 id="accessibility-matters_1">
<a class="head_anchor" href="#accessibility-matters_1"> </a>Accessibility matters</h1>
<p>If we could explain the success of JavaScript with just one word what would it be? The answer is <strong>Accessibility</strong>.</p>
<p>I think about “accessibility” as the design of products, devices, services, or environments for people who experience disabilities. However, according to the Oxford Dictionaries, the terms accessibility has a broader meaning <a href="https://en.oxforddictionaries.com/definition/accessibility">[6]</a>:</p>
<blockquote class="large">
<h3 id="accessibility_3">
<a class="head_anchor" href="#accessibility_3"> </a>accessibility</h3>
<h4 id="kssblti_4">
<a class="head_anchor" href="#kssblti_4"> </a>/əksɛsɪˈbɪlɪti/</h4>
<p>noun</p>
<ul>
<li>the quality of being able to be reached or entered.</li>
<li>the quality of being easy to obtain or use.</li>
<li>the quality of being easily understood or appreciated.</li>
</ul>
</blockquote>
<p>Please don’t get me wrong, I’m not trying to rest importance to the design of products for people who experience disabilities. It is extremely important to be empathic and ensure that when we create something, it can also be enjoyed by people who experience disabilities.</p>
<p>I was recently reading the book Homo Deus: A Brief History of Tomorrow by Yuval Noah Harari and he argues that what enabled humans to conquer the world wasn’t a unique possession of consciousness because animals have that too in varying degrees. What was unique was our ability to cooperate in very large numbers. </p>
<blockquote class="large">
<p>Side Note: If you find this idea interesting, you will probably enjoy reading Homo Deus or watching the TED talk “Why humans run the world” <a href="https://www.youtube.com/watch?v=nzj7Wg4DAbs">[7]</a>.</p>
</blockquote>
<p>When large numbers of humans collaborate we are able to achieve great things. The larger the group, the greater the achievements. If we want to be able to guess how much something is going to evolve and progress, all we need to do is to measure how big is the community around that something. Accessibility is what has made possible the growth of the JavaScript community and the community is what has made possible its progress and evolution.</p>
<p>The most important lesson that the success of JavaScript has taught us is that when building a product, application, service, framework, library or whatever; we will achieve better results if we focus our efforts trying to build something accessible for everyone. It doesn’t matter if at the beginning we are creating something that lacks features or if it is not as fast as we would like it to be, or if it cannot scale as much as we would like. If our product is accessible, the community around it will grow and the community will then foster the creativity and innovation required to sustain long-term success.</p>
<p>It is also important to reflect on the fact that this is a lesson that can be applied to many different kinds of organizations. Open source projects, startups, research collectives, and governments are just some of them.</p>
<h2 id="focusing-on-accessibility_2">
<a class="head_anchor" href="#focusing-on-accessibility_2"> </a>Focusing on accessibility</h2>
<p>At this point, our main question should be: How can we focus on accessibility?</p>
<p>My first suggestion is to practice wishful programming. Wishful programming <a href="https://blog.thesoftwarecraft.com/2013/11/wishful-programming.html">[8]</a> is a very powerful programming practice that can help us to create accessible APIs. However, many programmers are unaware of it:</p>
<blockquote class="large">
<p>Write some code that uses a component before we implement the component. This helps to discover what functions and data we need, and following this discovery will lead us to more simple and useful APIs.</p>
</blockquote>
<p>When we practice wishful programming, we focus our efforts on the creation of simple and useful APIs. We can achieve this by asking ourselves what is the easier and minimal way to allow someone to try, install, use, understand, extend something before we implement it.</p>
<p>My second suggestion is to try to ensure that our community is also accessible, as opposed to just our product. We can achieve this by promoting diversity and inclusiveness.</p>
<p><a href="http://blog.wolksoftware.com/feed">Don’t forget to subscribe</a> if you don’t want to miss it out future articles!</p>
<blockquote class="large">
<p>Note: This post was originally posted at <a href="https://dev.to/remojansen/the-most-important-lesson-that-the-success-of-javascript-has-taught-us-4ike">https://dev.to/remojansen/the-most-important-lesson-that-the-success-of-javascript-has-taught-us-4ike</a></p>
</blockquote>tag:blog.wolksoftware.com,2014:Post/learn-how-to-contribute-to-the-typescript-compiler-on-github-through-a-real-world-example2018-01-20T09:04:21-08:002018-01-20T09:04:21-08:00Learn how to contribute to the TypeScript compiler on GitHub through a real-world example<p>A few days ago I managed to send my first PR to the TypeScript project on GitHub. This is something that I’ve been trying to do for a very long time but unfortunately, it felt way too complicated for me.</p>
<p>I decided to write this post because I’m 100% sure that there are a lot of people out there feeling just like me. I’m going to try to describe how I personally found a way to contribute. My goal is to hopefully help others to contribute as well.</p>
<p>Please note that I’m not an expert in the TypeScript compiler internals. Please correct me using the comments below if I say is wrong.</p>
<h2 id="prerequisites_2">
<a class="head_anchor" href="#prerequisites_2"> </a>Prerequisites</h2>
<p>I’m going to assume a few things in this article:</p>
<ul>
<li>You understand <a href="https://git-scm.com/">Git</a> and have already installed it on your machine.</li>
<li>You understand <a href="https://www.typescriptlang.org/index.html">TypeScript</a> and have been using it for a while.</li>
<li>You understand the <a href="https://guides.github.com/introduction/flow/">GitHub Flow</a> and you already have a <a href="https://github.com/">GitHub</a> account.</li>
</ul>
<h2 id="a-realworld-example_2">
<a class="head_anchor" href="#a-realworld-example_2"> </a>A real-world example</h2>
<p>I’m going to use a real-world issue and its contribution as a reference during this post. Please refer to the following links if you want to see the original issue and contribution:</p>
<ul>
<li>The <a href="https://github.com/Microsoft/TypeScript/issues/20026">original issue</a> on GitHub.</li>
<li>The <a href="https://github.com/Microsoft/TypeScript/commit/73e3e8d790410c982ea80fd786cb046b0b861989">original contribution</a> on GitHub</li>
</ul>
<h2 id="about-the-learning-curve_2">
<a class="head_anchor" href="#about-the-learning-curve_2"> </a>About the learning curve</h2>
<p>As I’ve already said, contributing to TypeScript is something that I’ve been trying to do for a very long time but unfortunately, it felt way too complicated for me. In this section, I’m going to try to describe my own personal learning journey.</p>
<p>I personally believe that contributing to an open source project like TypeScript is not something that we can achieve in just a few days. There is a long learning curve ahead of us but everybody can contribute with the right amount of effort and perseverance.</p>
<p>My own personal learning curve started a few years ago when I created my first GitHub account and I started to work on my own side projects. These projects were just learning exercises and demo apps but it helped me to get familiar with GitHub and Git.</p>
<p>Back then I had a strong interest in TypeScript and I was writing <a href="https://www.amazon.co.uk/Learning-TypeScript-Remo-H-Jansen/dp/1783985542/">a book about it</a>. This lead me to visit a lot the TypeScript roadmap, the TypeScript issues and other TypeScript projects like DefinitelyTyped on GitHub. I read hundreds of issues, PR, and comments over an extended period of time. </p>
<p>After some time, I started contributing to <a href="https://github.com/DefinitelyTyped/DefinitelyTyped">DefinitelyTyped</a>. I started by reporting issues but I ended up sending some PRs. <br>
My very first PRs were documentation changes, dependencies upgrades, and some very simple bug fixes. Eventually, I ended up creating new type definitions and documenting my experience in <a href="http://blog.wolksoftware.com/contributing-to-definitelytyped">another article</a>.</p>
<p>Using both TypeScript and GitHub lead me to understand TypeScript, Git, and GitHub very well but I was still unable to contribute the TypeScript compiler. The main problem was that I was working on some libraries like <a href="https://github.com/inversify/InversifyJS">InversifyJS</a> and some web applications with React and Node.js but these projects are very different from the TypeScript compiler.</p>
<h3 id="how-can-i-learn-about-the-typescript-compiler_3">
<a class="head_anchor" href="#how-can-i-learn-about-the-typescript-compiler_3"> </a>How can I learn about the TypeScript compiler?</h3>
<p>Contributing to a compiler can be a bit scary at first because a compiler sounds like a very advanced computer science topic for someone like me (I don’t have a CS degree). </p>
<p>However, we are lucky because the TypeScript compiler is actually a “very simple” compiler because it doesn’t need to deal with things like hardware architecture or memory management (The JavaScript runtime takes care of these things). If you always wanted to learn how a compiler works, contributing to TypeScript is actually a very friendly way to do so.</p>
<p>I personally started to learn about compiler by watching many <a href="https://en.wikipedia.org/wiki/Anders_Hejlsberg">Anders Hejlsberg</a> interviews online. He always talks about things like “rewriting the TypeScript emitter as a tree-based transformation emitter”. I didn’t get everything he said at first but listening to his interviews over the years have led me to gain some basic knowledge about the architecture of the TypeScript compiler.</p>
<p>I watched a lot of videos and read a lot of documents. I don’t remember all of them but these are the ones that stuck in my memory:</p>
<ul>
<li>
<a href="https://www.youtube.com/watch?v=Nlqv6NtBXcA">Syntaxation</a> by Douglas Crockford describes how to implement a parser from scratch and provides a very good understanding of what is an abstract syntax tree (AST) and how it is generated.</li>
<li>
<a href="https://www.youtube.com/watch?v=WkJagE7b5U0">Hidden Gems of TypeScript compiler</a> by Vincent Ogloblinsky describes how the TypeScript compiler works in a very clear and practical way.</li>
<li>
<a href="https://www.youtube.com/watch?v=jBddlEWNsps">Anders Hejlsberg @ Build 2017</a> is one of the many Anders Hejlsberg interviews about TypeScript.</li>
<li>
<a href="https://channel9.msdn.com/Blogs/Seth-Juarez/Anders-Hejlsberg-on-Modern-Compiler-Construction">Modern Compiler Construction</a> by Anders Hejlsberg provides some interesting insights about the TypeScript compiler but it doesn’t too much into implementation details.</li>
<li><a href="https://dev.to/vaidehijoshi/grammatically-rooting-oneself-with-parse-trees-16a">Grammatically Rooting Oneself With Parse Trees</a></li>
<li><a href="https://github.com/Microsoft/TypeScript/wiki/Architectural-Overview">Architectural Overview</a></li>
<li><a href="https://github.com/Microsoft/TypeScript/wiki/Compiler-Internals">Compiler Internals</a></li>
<li>
<a href="https://basarat.gitbooks.io/typescript/docs/compiler/overview.html">TypeScript Compiler Internals</a> by <a href="https://twitter.com/basarat">Basarat Ali Syed</a>.</li>
<li>“TypeScript Contributors” and “Building Tools for TypeScript” sections in the <a href="https://github.com/Microsoft/TypeScript/wiki">TypeScript wiki</a>.</li>
</ul>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/z0j7yplnkwpyciqqhmff.png" alt="wiki"></p>
<p>About a year ago I did <a href="https://github.com/remojansen/TsUML">a small experiment</a> in a hackathon at the Global Microsoft MVP summit in Redmond. I tried to create an extension to transform TypeScript code into a UML diagram. </p>
<p>I never fully finished the experiment but it was my first direct contact with the TypeScript AST and language service tools. I found this small experiment very useful and I would recommend playing with the language services as a learning exercise.</p>
<p>Once you manage to understand the different phases of the compilation process and what each one of them does, you should be ready to start trying to pick an issue.</p>
<h2 id="how-can-i-find-something-to-do_2">
<a class="head_anchor" href="#how-can-i-find-something-to-do_2"> </a>How can I find something to do?</h2>
<p>The TypeScript project managers have created a milestone for <a href="https://github.com/Microsoft/TypeScript/milestone/2">issues that are recommended for the community</a>. Some of this issues are labeled as <a href="https://github.com/Microsoft/TypeScript/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22">“good first issue”</a>. You should try to go through this issues and find one that you can understand.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/6bcjsdg00nlrva2bulij.png" alt="milestone"></p>
<h3 id="what-can-i-do-if-everything-seems-too-complic_3">
<a class="head_anchor" href="#what-can-i-do-if-everything-seems-too-complic_3"> </a>What can I do if everything seems too complicated?</h3>
<p>I visited the community milestone a lot of times for many months and I left it disappointed many times because I didn’t feel able to help. I continued learning and visiting this page until one day I saw an issue that felt like something that I could do.</p>
<p>After your first PR your level of confidence will grow a lot and it won’t be long until you find your next opportunity for a new PR.</p>
<h2 id="about-issue-20026_2">
<a class="head_anchor" href="#about-issue-20026_2"> </a>About issue #20026</h2>
<p>The issue that I selected for my very first contribution was the issue number <a href="https://github.com/Microsoft/TypeScript/issues/20026">#20026</a>. </p>
<p>In this particular issue, someone suggested that when we try to invoke a <code class="prettyprint">null</code> or <code class="prettyprint">undefined</code> variable:</p>
<pre><code class="prettyprint lang-ts">null()
</code></pre>
<p>We get an <code class="prettyprint">Object is possibly 'null'</code> error. This error is not very user friendly and it would be much better if the one of the following errors was used instead:</p>
<pre><code class="prettyprint">Cannot invoke an object which is possibly 'null'.
Cannot invoke an object which is possibly 'undefined'.
Cannot invoke an object which is possibly 'null' or 'undefined'.
</code></pre>
<p>I was able to understand the requirement of the issue and also I thought that I would be able to find where the error <code class="prettyprint">Object is possibly 'null'</code> is thrown and change it for one of the others errors when the expression is a <code class="prettyprint">function</code> call. </p>
<p>For the first time, I found an issue that didn’t sound too complicated so I decided to give it a go.</p>
<h2 id="how-can-i-contribute_2">
<a class="head_anchor" href="#how-can-i-contribute_2"> </a>How can I contribute?</h2>
<p>After finding an issue of our interest we can start working on it. We need to go through the following steps:</p>
<ol>
<li>Setting up the project</li>
<li>Implementing and testing your change</li>
<li>Sending a PR</li>
</ol>
<h3 id="1setting-up-the-project_3">
<a class="head_anchor" href="#1setting-up-the-project_3"> </a>1.Setting up the project</h3>
<ul>
<li>
<p>Create a fork of the TypeScript project.</p>
<blockquote class="large">
<p>Please refer to the <a href="https://help.github.com/articles/fork-a-repo/">GitHub documentation</a> if you need additional help about how to fork a repository.</p>
</blockquote>
</li>
<li>
<p>Clone your fork</p>
<pre><code class="prettyprint lang-sh">git clone https://github.com/YOUR_GITHUB_USER_NAME_GOES_HERE/TypeScript.git
</code></pre>
<blockquote class="large">
<p>Please refer to the <a href="https://help.github.com/articles/cloning-a-repository/">GitHub documentation</a> if you need additional help about how to clone a repository.</p>
</blockquote>
</li>
<li>
<p>Install jake (requires <a href="https://nodejs.org/en/download/">node.js</a>) </p>
<pre><code class="prettyprint lang-sh">npm install -g jake
</code></pre>
</li>
<li>
<p>Install the project dependencies</p>
<pre><code class="prettyprint lang-sh">npm install
</code></pre>
</li>
<li>
<p>Run the tests</p>
<pre><code class="prettyprint lang-sh">jake runtests-parallel
</code></pre>
</li>
</ul>
<p>If all the tests worked successfully you should be ready to start working on your contribution.</p>
<p>I recommend you to work on a new branch. In my case a created an branch with the name of the issue that I was working on:</p>
<pre><code class="prettyprint">git checkout -b issue-20026
</code></pre>
<h3 id="2-implementing-and-testing-your-change_3">
<a class="head_anchor" href="#2-implementing-and-testing-your-change_3"> </a>2. Implementing and testing your change</h3>
<p>Our first PR will most likely be a bug fix, not a new feature. The best way to fix a bug is to start by writing a test that reproduces the bug. </p>
<p>So I started by trying to find the existing tests. I opened the <code class="prettyprint">tests</code> folder but I was unable to find something that looked like a unit test.</p>
<p>The TypeScript tests are a bit strange because they use Mocha in a very abstracted way. We don’t need to write test fixtures or tests cases, instead we write a TypeScript code snippet which is expected to work in certain way or to throw a certain compilation error. The testing tools will then generate some outputs and a test case will be created automatically for each of these outputs.</p>
<p>In order to write a test, we need to create a new file under the tests folder (<code class="prettyprint">/tests/cases/compiler/</code>) with a unique name. The <code class="prettyprint">CONTRIBUTING.md</code> file provides some advice about the name uniqueness:</p>
<blockquote class="large">
<p>Note that filenames here must be distinct from all other compiler test case names, so you may have to work a bit to find a unique name if it’s something common.</p>
</blockquote>
<p>The file should contain the TypeScript code that you wish to test. In my case, I created a file named <a href="https://github.com/Microsoft/TypeScript/blob/73e3e8d790410c982ea80fd786cb046b0b861989/tests/cases/compiler/nullableFunctionError.ts"><code class="prettyprint">nullableFunctionError.ts</code></a>.</p>
<h4 id="testscasescompilernullablefunctionerrorts_4">
<a class="head_anchor" href="#testscasescompilernullablefunctionerrorts_4"> </a>/tests/cases/compiler/nullableFunctionError.ts</h4>
<p>My <code class="prettyprint">nullableFunctionError.ts</code> contains the following TypeScript code:</p>
<pre><code class="prettyprint lang-ts">// @strictNullChecks: true
null();
undefined();
let f: null | undefined;
f();
</code></pre>
<p>The preceding code snippet uses three function calls: <code class="prettyprint">null();</code>, <code class="prettyprint">undefined();</code> and <code class="prettyprint">f();</code>. Each of these calls should trigger each of the new errors expected by the issue #20026.</p>
<p>As you may have already noticed, the code snippet doesn’t contain any kind of assertion. The TypeScript project uses the previous compilation output as the tests assertion. </p>
<p>We can execute the test using the following command to execute a test:</p>
<pre><code class="prettyprint">jake runtests tests=nullableFunctionError
</code></pre>
<p>The TypeScript compiler will then generate the following files as output:</p>
<ul>
<li><code class="prettyprint">nullableFunctionError.errors.txt</code></li>
<li><code class="prettyprint">nullableFunctionError.js</code></li>
<li><code class="prettyprint">nullableFunctionError.symbols</code></li>
<li><code class="prettyprint">nullableFunctionError.types</code></li>
</ul>
<p>These files are stored in source control under the <code class="prettyprint">/tests/baselines/reference/</code> directory. When the tests are executed, the files are re-generated under the <code class="prettyprint">/tests/baselines/local/</code> directory. The files under both directories are then compared to check if the compiler behaviour has changed.</p>
<p>You can use the following command to compare the two versions:</p>
<pre><code class="prettyprint">jake diff
</code></pre>
<p>And the following command to accept the changes:</p>
<pre><code class="prettyprint">jake baseline-accept
</code></pre>
<p>Because this is a new test, there are not previous versions of the files and we need to accept the new files using <code class="prettyprint">jake baseline-accept</code>.</p>
<p>Don’t worry too much about using <code class="prettyprint">jake baseline-accept</code> by mistake because you will be able to rollback the changes using Git if you need to do so.</p>
<p>In my case, the <code class="prettyprint">nullableFunctionError.errors.txt</code> contained the following content:</p>
<pre><code class="prettyprint">tests/cases/compiler/nullableFunctionError.ts(1,1): error TS2531: Object is possibly 'null'.
tests/cases/compiler/nullableFunctionError.ts(2,1): error TS2531: Object is possibly 'null'.
tests/cases/compiler/nullableFunctionError.ts(4,1): error TS2531: Object is possibly 'null'.
==== tests/cases/compiler/nullableFunctionError.ts (3 errors) ====
null();
~~~~
!!! error TS2721: Object is possibly 'null'.
undefined();
~~~~~~~~~
!!! error TS2722: Object is possibly 'null'.
let f: null | undefined;
f();
~
!!! error TS2723: Object is possibly 'null'.
</code></pre>
<p>As we can see the three errors are <code class="prettyprint">Object is possibly 'null'.</code> but they should be:</p>
<pre><code class="prettyprint">Cannot invoke an object which is possibly 'null'.
Cannot invoke an object which is possibly 'undefined'.
Cannot invoke an object which is possibly 'null' or 'undefined'.
</code></pre>
<p>This was correct because I didn’t change anything in the TypeScript compiler. At this point, I needed to figure out what needed to be changed so the correct errors were displayed. </p>
<p>I already had a test in place and I would be able to know if my changes were correct by checking the contents of the <code class="prettyprint">nullableFunctionError.errors.txt</code> file. Also, there was already <a href="https://travis-ci.org/Microsoft/TypeScript/jobs/326657578#L628">58656 existing tests</a> that will let me know if I changed something else by mistake. This is a very obvious example of the benefits of <a href="https://en.wikipedia.org/wiki/Test-driven_development">TDD</a>.</p>
<h3 id="srccompilerdiagnosticmessagesjson_3">
<a class="head_anchor" href="#srccompilerdiagnosticmessagesjson_3"> </a>/src/compiler/diagnosticMessages.json</h3>
<p>The first thing I tried to do was to figure out where the current error message was coming from. I ended up adding three new errors to a file named <a href="https://github.com/Microsoft/TypeScript/blob/73e3e8d790410c982ea80fd786cb046b0b861989/src/compiler/diagnosticMessages.json">diagnosticMessages.json</a>:</p>
<pre><code class="prettyprint lang-js">"Cannot invoke an object which is possibly 'null'.": {
"category": "Error",
"code": 2721
},
"Cannot invoke an object which is possibly 'undefined'.": {
"category": "Error",
"code": 2722
},
"Cannot invoke an object which is possibly 'null' or 'undefined'.": {
"category": "Error",
"code": 2723
},
</code></pre>
<h3 id="srccompilercheckerts_3">
<a class="head_anchor" href="#srccompilercheckerts_3"> </a>/src/compiler/checker.ts</h3>
<p>The next step was to throw the new three errors that I created in the <code class="prettyprint">diagnosticMessages.json</code> file. </p>
<p>This step was an intense learning exercise because I had very little domain knowledge about the TypeScript compiler. My only option was to try to gain some knowledge through trial, error, and experimentation.</p>
<p>I managed to figured out that I could run all the tests using the following command:</p>
<pre><code class="prettyprint">jake runtests-parallel
</code></pre>
<p>I could also run just my test using the following command:</p>
<pre><code class="prettyprint">jake runtests tests=nullableFunctionError
</code></pre>
<p>I could also debug my tests using the following command and the chrome debugging tools:</p>
<pre><code class="prettyprint">jake runtests-browser tests=nullableFunctionError browser=chrome
</code></pre>
<p>I found all this information in the <code class="prettyprint">CONTRIBUTING.md</code> file.</p>
<p>Because the errors were type errors, I was able to guess that I should implement some changes in the checker. </p>
<p>Once more, I started by searching were the <code class="prettyprint">TS2723: Object is possibly 'null'</code> error was used within the type checker. I ended up looking at the <code class="prettyprint">checkNonNullType</code> and the <code class="prettyprint">checkNonNullExpression</code> functions.</p>
<p>The three new errors are only relevant for function calls but the function <code class="prettyprint">checkNonNullType</code> was used in many cases, not only for function calls. </p>
<p>After some time experimenting, I figured out that I need to pass the three new errors as optional arguments to <code class="prettyprint">checkNonNullExpression</code> and pass them to <code class="prettyprint">checkNonNullType</code>:</p>
<pre><code class="prettyprint lang-ts">function checkNonNullExpression(
node: Expression | QualifiedName,
nullDiagnostic?: DiagnosticMessage,
undefinedDiagnostic?: DiagnosticMessage,
nullOrUndefinedDiagnostic?: DiagnosticMessage,
) {
return checkNonNullType(
checkExpression(node),
node,
nullDiagnostic,
undefinedDiagnostic,
nullOrUndefinedDiagnostic
);
}
</code></pre>
<p>The <code class="prettyprint">checkNonNullType</code> would then also take the three new errors as optional arguments and use them when appropriate:</p>
<pre><code class="prettyprint lang-ts">function checkNonNullType(
type: Type,
node: Node,
nullDiagnostic?: DiagnosticMessage,
undefinedDiagnostic?: DiagnosticMessage,
nullOrUndefinedDiagnostic?: DiagnosticMessage
): Type {
const kind = (strictNullChecks ? getFalsyFlags(type) : type.flags) &amp; TypeFlags.Nullable;
if (kind) {
error(node, kind &amp; TypeFlags.Undefined ? kind &amp; TypeFlags.Null ?
(nullOrUndefinedDiagnostic || Diagnostics.Object_is_possibly_null_or_undefined) :
(undefinedDiagnostic || Diagnostics.Object_is_possibly_undefined) :
(nullDiagnostic || Diagnostics.Object_is_possibly_null)
);
const t = getNonNullableType(type);
return t.flags &amp; (TypeFlags.Nullable | TypeFlags.Never) ? unknownType : t;
}
return type;
}
</code></pre>
<p>The final change was to provide the three new errors as arguments <code class="prettyprint">checkNonNullExpression</code> when a function call was used. I tried to search for things like <code class="prettyprint">invoke</code> or <code class="prettyprint">call</code> in the source code I managed to figure out that the <code class="prettyprint">resolveCallExpression</code> function was what I was looking for.</p>
<pre><code class="prettyprint lang-ts">function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[]): Signature {
// ...
const funcType = checkNonNullExpression(
node.expression,
Diagnostics.Cannot_invoke_an_object_which_is_possibly_null,
Diagnostics.Cannot_invoke_an_object_which_is_possibly_undefined,
Diagnostics.Cannot_invoke_an_object_which_is_possibly_null_or_undefined
);
// ...
</code></pre>
<p>I executed the tests and I found unexpected results because my tests was not executed using non-nullable types. I figured this out thanks to the chrome debugger. The code that lead me to identify the problem can be found in the <code class="prettyprint">checkNonNullType</code> function:</p>
<pre><code class="prettyprint lang-ts">const kind = (strictNullChecks ? getFalsyFlags(type) : type.flags) &amp; TypeFlags.Nullable;
</code></pre>
<p>I found how to enable non-nullable files in the <code class="prettyprint">CONTRIBUTING.md</code> file:</p>
<blockquote class="large">
<p>These files support metadata tags in the format // @metaDataName: value. The supported names and values are the same as those supported in the compiler itself.</p>
</blockquote>
<p>The solution was to add the flag <code class="prettyprint">// @strictNullChecks: true</code> to the test file <code class="prettyprint">nullableFunctionError.ts</code>. I executed the tests once more and the following files were generated as expected.</p>
<h4 id="testscasescompilernullablefunctionerrorerrors_4">
<a class="head_anchor" href="#testscasescompilernullablefunctionerrorerrors_4"> </a>/tests/cases/compiler/nullableFunctionError.errors.txt</h4>
<p>Contains a list of the errors detected by the compiler. This time the errors were correct:</p>
<pre><code class="prettyprint lang-txt">tests/cases/compiler/nullableFunctionError.ts(1,1): error TS2721: Cannot invoke an object which is possibly 'null'.
tests/cases/compiler/nullableFunctionError.ts(2,1): error TS2722: Cannot invoke an object which is possibly 'undefined'.
tests/cases/compiler/nullableFunctionError.ts(4,1): error TS2723: Cannot invoke an object which is possibly 'null' or 'undefined'.
==== tests/cases/compiler/nullableFunctionError.ts (3 errors) ====
null();
~~~~
!!! error TS2721: Cannot invoke an object which is possibly 'null'.
undefined();
~~~~~~~~~
!!! error TS2722: Cannot invoke an object which is possibly 'undefined'.
let f: null | undefined;
f();
~
!!! error TS2723: Cannot invoke an object which is possibly 'null' or 'undefined'.
</code></pre>
<h4 id="testscasescompilernullablefunctionerrorjs_4">
<a class="head_anchor" href="#testscasescompilernullablefunctionerrorjs_4"> </a>/tests/cases/compiler/nullableFunctionError.js</h4>
<p>Contains the input (TypeScript) and the output (JavaScript) code:</p>
<pre><code class="prettyprint lang-js">//// [nullableFunctionError.ts]
null();
undefined();
let f: null | undefined;
f();
//// [nullableFunctionError.js]
null();
undefined();
var f;
f();
</code></pre>
<h4 id="testscasescompilernullablefunctionerrorsymbol_4">
<a class="head_anchor" href="#testscasescompilernullablefunctionerrorsymbol_4"> </a>/tests/cases/compiler/nullableFunctionError.symbols</h4>
<p>Contains a list of the Symbols created by the compiler:</p>
<pre><code class="prettyprint lang-txt">=== tests/cases/compiler/nullableFunctionError.ts ===
null();
undefined();
&gt;undefined : Symbol(undefined)
let f: null | undefined;
&gt;f : Symbol(f, Decl(nullableFunctionError.ts, 2, 3))
f();
&gt;f : Symbol(f, Decl(nullableFunctionError.ts, 2, 3))
</code></pre>
<h4 id="testscasescompilernullablefunctionerrortypes_4">
<a class="head_anchor" href="#testscasescompilernullablefunctionerrortypes_4"> </a>/tests/cases/compiler/nullableFunctionError.types</h4>
<p>Contains a list of the types detected by the compiler:</p>
<pre><code class="prettyprint lang-txt">=== tests/cases/compiler/nullableFunctionError.ts ===
null();
&gt;null() : any
&gt;null : null
undefined();
&gt;undefined() : any
&gt;undefined : undefined
let f: null | undefined;
&gt;f : null | undefined
&gt;null : null
f();
&gt;f() : any
&gt;f : null | undefined
</code></pre>
<h3 id="3-sending-a-pr_3">
<a class="head_anchor" href="#3-sending-a-pr_3"> </a>3. Sending a PR</h3>
<p>At this point, I was almost ready to finish my PR. I accepted the new baseline files:</p>
<pre><code class="prettyprint">jake baseline-accept
</code></pre>
<p>And I executed all the existing test:</p>
<pre><code class="prettyprint">jake runtests-parallel
</code></pre>
<p>If your tests passed locally, it is highly likely that you will not experience any issues in the CI build.</p>
<p><img src="https://thepracticaldev.s3.amazonaws.com/i/f2owuvtd3paw8juj64fe.png" alt="ci"></p>
<p>If you experience any issues the TypeScript team should be able to help you, don’t be afraid to ask for help!</p>
<p>Please refer to the <a href="https://help.github.com/articles/creating-a-pull-request/">GitHub documentation</a> if you need additional help about how to create a PR.</p>
<h4 id="signing-the-cla_4">
<a class="head_anchor" href="#signing-the-cla_4"> </a>Signing the CLA</h4>
<p>The TypeScript projects requires contributors to sign a Contribution License Agreement (CLA).</p>
<p>The <code class="prettyprint">CONTRIBUTING.md</code> file contains some guidelines about this:</p>
<blockquote class="large">
<p>You will need to complete a Contributor License Agreement (CLA). Briefly, this agreement testifies that you are granting us permission to use the submitted change according to the terms of the project’s license and that the work being submitted is under appropriate copyright. Please submit a Contributor License Agreement (CLA) before submitting a pull request. You may visit <a href="https://cla.microsoft.com">https://cla.microsoft.com</a> to sign digitally.</p>
</blockquote><h2 id="summary_2">
<a class="head_anchor" href="#summary_2"> </a>Summary</h2>
<p>In this article, we have learned how we can contribute to TypeScript on GitHub through a real-world example. </p>
<p>I hope you enjoyed this post and it will help you to send your first PR to the TypeScript project.</p>
<p>Happy coding!</p>
<blockquote class="large">
<p>Note: This post was originally posted at <a href="https://dev.to/remojansen/learn-how-to-contribute-to-the-typescript-compiler-on-github-through-a-real-world-example-4df0">https://dev.to/remojansen/learn-how-to-contribute-to-the-typescript-compiler-on-github-through-a-real-world-example-4df0</a></p>
</blockquote>tag:blog.wolksoftware.com,2014:Post/dependency-injection-in-typescript-applications-powered-by-inversifyjs2018-01-20T09:03:48-08:002018-01-20T09:03:48-08:00Dependency injection in TypeScript applications powered by InversifyJS<h2 id="about_2">
<a class="head_anchor" href="#about_2"> </a>About</h2>
<p>InversifyJS is a lightweight inversion of control (IoC) container for TypeScript and JavaScript apps. InversifyJS uses annotations to identify and inject its dependencies.</p>
<p>The InversifyJS API had been influenced by Ninject and Angular and encourages the usage of the best OOP and IoC practices.</p>
<p>InversifyJS has been developed with 4 main goals:</p>
<ol>
<li><p>Allow JavaScript developers to write code that adheres to <a href="https://dev.to/samueleresca/solid-principles-using-typescript">the SOLID principles</a>.</p></li>
<li><p>Facilitate and encourage the adherence to the best OOP and IoC practices.</p></li>
<li><p>Add as little runtime overhead as possible.</p></li>
<li><p>Provide a state of the art development experience.</p></li>
</ol>
<h2 id="motivation-and-background_2">
<a class="head_anchor" href="#motivation-and-background_2"> </a>Motivation and background</h2>
<p>Now that ECMAScript 2015 version of JavaScript supports classes and that TypeScript brings static types to JavaScript application, the SOLID principles have become more relevant than ever before in the development of JavaScript applications.</p>
<p>InversifyJS was created as a result of the need for tools to enable TypeScript developers to implement an application that adheres to the SOLID principles.</p>
<p>A couple of years ago I was working on some TypeScript applications and I felt that there was a need for an IoC container with great support for TypeScript. At the time there were some IoC containers available for JavaScript applications but none of them were able to provide a developer experience as rich as I was expecting so I decided to try to develop something that would suit my needs.</p>
<h2 id="adoption_2">
<a class="head_anchor" href="#adoption_2"> </a>Adoption</h2>
<p>The first commit to the InversifyJS core library took place the 7th of Apr 2015 and the version 1.0.0 was released on npm 10 days later. The version 2.0.0 was released the 11th of Sep 2016, after a year of development. The most recent release (4.2.0 at the time in which this article was published) was published in July 2017. </p>
<p>Since the first release, the project has earned over 1300 stars on GitHub, over 30 contributors and <a href="https://npm-stat.com/charts.html?package=inversify">almost 40K monthly downloads on npm</a>.</p>
<p><img src="https://user-images.githubusercontent.com/10656223/27908410-909e892c-6243-11e7-9e1d-afa16806737d.png" alt="ddztwqixcaaqrgo"></p>
<p>The most important things for us is that the feedback from our users has been very possitive:</p>
<p><img src="https://user-images.githubusercontent.com/10656223/27908418-9de1c9d2-6243-11e7-9848-e36f3502e538.png" alt="selection_011"><br>
<img src="https://user-images.githubusercontent.com/10656223/27908416-9dde39d4-6243-11e7-8274-170e4a158e5f.png" alt="selection_012"><br>
<img src="https://user-images.githubusercontent.com/10656223/27908419-9de37ae8-6243-11e7-8136-0b28e8ba83aa.png" alt="selection_014"><br>
<img src="https://user-images.githubusercontent.com/10656223/27908420-9de4317c-6243-11e7-8586-1322e6371df4.png" alt="selection_016"><br>
<img src="https://user-images.githubusercontent.com/10656223/27908421-9de671ee-6243-11e7-9ab1-ee3cb9509b17.png" alt="selection_017"><br>
<img src="https://user-images.githubusercontent.com/10656223/27953854-49eb84a4-6305-11e7-99db-c5363c5ff5d1.png" alt="selection_018"></p>
<p>Thanks a lot to all our users!</p>
<h2 id="getting-started_2">
<a class="head_anchor" href="#getting-started_2"> </a>Getting Started</h2>
<p>In this tutorial, we are going to showcase how InversifyJS works using Node.js. InversifyJS can be used with JavaScript and TypeScript but it is recommended to use TypeScript for the best developer experience.</p>
<p>To get started you will need Node.js. You can download the Node.js binary for your operating system from <a href="https://nodejs.org/en/download/">the official downloads page</a>.</p>
<p>Once you install Node.js, you will need to install TypeScript. TypeScript can be installed using the npm command which is the default Node.js package manager:</p>
<pre><code class="prettyprint">$ npm install -g typescript@2.4.1
</code></pre>
<p>If both Node.js and TypeScript have been installed, you should be able to check the installed versions using the following commands.</p>
<pre><code class="prettyprint">$ node -v
$ tsc -v
</code></pre>
<p>At the time in which this article was published, the latest version of Node.js and TypeScript released were 8.1.0 and 2.4.1 respectively.</p>
<p>At this point, you should be ready to create a new project. We need to create a new folder named “inversify-nodejs-demo” and create a package.json file inside it. We can achieve this by using the npm init command as follows:</p>
<pre><code class="prettyprint">$ mkdir inversify-nodejs-demo
$ cd inversify-nodejs-demo
$ npm init --yes
</code></pre>
<p>The preceding commands should generate a file named “package.json” under the “inversify-nodejs-demo”. We can then install the “inversify” and “reflect-metadata” packages using the Node.js package manager:</p>
<pre><code class="prettyprint">$ npm install --save inversify@4.2.0
$ npm install --save reflect-metadata@0.1.10
</code></pre>
<p>The “reflect-metadata” module is a polyfill for the reflect metadata API which is required by InversifyJS.</p>
<p>We also need to create a file named “tsconfig.json”. This file contains the configuration for the TypeScript compiler. We can create a “tsconfig.json” file using the following command:</p>
<pre><code class="prettyprint">$ tsc -init
</code></pre>
<p>You can then copy the following into the generated “tsconfig.json”:</p>
<pre><code class="prettyprint lang-js">{
"compilerOptions": {
"lib": ["es6"],
"module": "commonjs",
"target": "es5",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
</code></pre>
<p>The preceding configuration file contains some compilations required by InversifyJS. At this point, we are ready to write a small demo. Let’s create a new TypeScript file named “index.ts”:</p>
<pre><code class="prettyprint">$ touch index.ts
</code></pre>
<p>Let’s copy the following TypeScript code into the “index.ts” file:</p>
<pre><code class="prettyprint lang-ts">import "reflect-metadata";
import { interfaces, injectable, inject, Container } from "inversify";
// 1. Declare interfaces
interface Warrior {
fight(): string;
sneak(): string;
}
interface Weapon {
hit(): string;
}
interface ThrowableWeapon {
throw(): string;
}
// 2. Declare types
const TYPES = {
Warrior: Symbol("Warrior"),
Weapon: Symbol("Weapon"),
ThrowableWeapon: Symbol("ThrowableWeapon")
};
// 3. Declare classes
@injectable()
class Katana implements Weapon {
public hit() {
return "cut!";
}
}
@injectable()
class Shuriken implements ThrowableWeapon {
public throw() {
return "hit!";
}
}
@injectable()
class Ninja implements Warrior {
private _katana: Weapon;
private _shuriken: ThrowableWeapon;
public constructor(
@inject(TYPES.Weapon) katana: Weapon,
@inject(TYPES.ThrowableWeapon) shuriken: ThrowableWeapon
) {
this._katana = katana;
this._shuriken = shuriken;
}
public fight() { return this._katana.hit(); };
public sneak() { return this._shuriken.throw(); };
}
// 4. Create instance of Container &amp; declare type bindings
const myContainer = new Container();
myContainer.bind&lt;Warrior&gt;(TYPES.Warrior).to(Ninja);
myContainer.bind&lt;Weapon&gt;(TYPES.Weapon).to(Katana);
myContainer.bind&lt;ThrowableWeapon&gt;(TYPES.ThrowableWeapon).to(Shuriken);
// 5. Resolve Warrior type
const ninja = myContainer.get&lt;Warrior&gt;(TYPES.Warrior);
// 6. Check “Katana” and “Shuriken” has been injected into “Ninja”
console.log(ninja.fight()); // "cut!"
console.log(ninja.sneak()); // "hit!"
</code></pre>
<p>The preceding file performs the following of tasks:</p>
<ol>
<li><p>Import the required dependencies “reflect-metadata” and “inversify”.</p></li>
<li><p>Declare some interfaces and some types. Types are unique identifiers used to represent interfaces at runtime. We need these unique identifiers because TypeScript is compiled into JavaScript and JavaScript does not have support for static types like interfaces. We use types to identify which types need to be injected into a class.</p></li>
<li><p>Declare some classes that implement the interfaces that we previously declared. These classes will be instantiated by the IoC container and for that reasons they require to be decorated using the “@injectable” decorator. We also need to use the “@inject” decorator to indicate which types need to be injected into a class.</p></li>
<li><p>Declare an instance of the “Container” class and then declares some type bindings. A type binding is a dictionary entry that links an abstraction (type) with an implementation (concrete class).</p></li>
<li><p>Use the IoC container instance previously declared to resolve the “Warrior” type. We declared a type binding between the “Warrior” type and the “Ninja” class so we can expect the IoC container to return an instance of the “Ninja” class. Because the “Ninja” class has a dependency on the “Weapon” and “ThrowableWapon” types and we declared some bindings for those types we can expect instances of the “Katana” and “Shuriken” classes to be instantiated and injected into the “Ninja” class.</p></li>
<li><p>Use the “log” method from the “console” object to check that instances of the Katana” and “Shuriken” has been correctly injected into the “Ninja” instance.</p></li>
</ol>
<p>Before running the preceding TypeScript code snippet, we need to compile it into JavaScript. We can use the “tsc” (TypeScript compiler) command and the project option “-p” to use the compilation options that we previously defined in the “tsconfig.json” file:</p>
<pre><code class="prettyprint">$ tsc -p tsconfig.json
</code></pre>
<p>The preceding command should generate a file named “index.js” under the current directory. We can then run the generated JavaScript file using Node.js</p>
<pre><code class="prettyprint">$ node index.js
</code></pre>
<p>If everything went well we should see the following text displayed in the console:</p>
<pre><code class="prettyprint">cut!
hit!
</code></pre>
<p>If we follow the source code we can see how this text comes from methods in the “Katana” and “Shuriken” classes which are invoked through the “Ninja” class. This proves that the “Katana” and “Shuriken” classes have been successfully injected into the “Ninja” class.</p>
<h2 id="inversifyjs-in-realworld-nodejs-applications_2">
<a class="head_anchor" href="#inversifyjs-in-realworld-nodejs-applications_2"> </a>InversifyJS in real-world Node.js applications (inversify-express-utils)</h2>
<p>What we just saw in the previous section of this article is a basic demo of the core InversifyJS API. When we implement a real world enterprise Node.js application using TypeScript and InversifyJS with Express.js we will end up writing some code that looks as follows:</p>
<pre><code class="prettyprint lang-ts">import * as express from "express";
import { response, requestParams, controller, httpGet, httpPost, httpPut } from "inversify-express-utils";
import { injectable, inject } from "inversify";
import { interfaces } from "./interfaces";
import { Type } from "./types";
import { authorize } from "./middleware";
import { Feature } from "./features";
@injectable()
@controller(
"/api/user"
authorize({ feature: Feature.UserManagement })
)
class UserController {
@inject(Type.UserRepository) private readonly _userRepository: interfaces.UserRepository;
@inject(Type.Logger) private readonly _logger: interfaces.Logger;
@httpGet("/")
public async get(
@request() req: express.Request,
@response() res: express.Response
) {
try {
this._logger.info(`HTTP ${req.method} ${req.url}`);
return await this._userRepository.readAll();
} catch (e) {
this._logger.error(`HTTP ERROR ${req.method} ${req.url}`, e);
res.status(500).json([]);
}
}
@httpGet("/:email")
public async getByEmail(
@requestParams("email") email: string,
@request() req: express.Request,
@response() res: express.Response
) {
try {
this._logger.info(`HTTP ${req.method} ${req.url}`);
return await this._userRepository.readAll({ where: { email: email } });
} catch (e) {
this._logger.error(`HTTP ERROR ${req.method} ${req.url}`, e);
res.status(500).json([]);
}
}
}
</code></pre>
<p>As we can see in the preceding code snippet, the <code class="prettyprint">inversify-express-utils</code> package allows us to implement routing, dependency injection and even apply some Express.js middleware using a very declarative and developer-friendly API. This is the kind of developer experience that we want to enable thanks to InversifyJS and TypeScript.</p>
<h2 id="features-amp-tools_2">
<a class="head_anchor" href="#features-amp-tools_2"> </a>Features &amp; Tools</h2>
<p>The core InversifyJS has a rich API and supports many use cases and features including support for classes, support for Symbols, container API, controlling the scope of the dependencies, injecting a constant or dynamic value, create your own tag decorators, named bindings, circular dependencies</p>
<p>In top of an extensive list of features, we also want to provide developers with a great user experience and we are working on a serie for side-projects to facilitate the integration of InversifyJS with multiple frameworks and to provide developers with a great development experience: </p>
<ul>
<li><a href="https://github.com/inversify/inversify-binding-decorators">inversify-binding-decorators</a></li>
<li><a href="https://github.com/inversify/inversify-inject-decorators">inversify-inject-decorators</a></li>
<li><a href="https://github.com/inversify/inversify-express-utils">inversify-express-utils</a></li>
<li><a href="https://github.com/inversify/inversify-restify-utils">inversify-restify-utils</a></li>
<li><a href="https://github.com/inversify/inversify-">inversify-vanillajs-helpers</a></li>
<li><a href="https://www.npmjs.com/package/inversify-tracer">inversify-tracer</a></li>
<li><a href="https://github.com/inversify/inversify-logger-middleware">inversify-logger-middleware</a></li>
<li><a href="https://github.com/inversify/inversify-devtools">inversify-devtools (WIP)</a></li>
<li><a href="https://www.npmjs.com/package/inversify-express-doc">inversify-express-doc</a></li>
</ul>
<h2 id="future-development_2">
<a class="head_anchor" href="#future-development_2"> </a>Future development</h2>
<p>The main focus of the InverisfyJS project is the core library. We want to continue listening to the needs of the users of the library and keep adding new features to support those use cases. We also want to ensure that we provide users with utilities to facilitate the integration of InversifyJS with whatever framework they are using.</p>
<h2 id="summary_2">
<a class="head_anchor" href="#summary_2"> </a>Summary</h2>
<p>InversifyJS is a dependency injection library with a rich set of features and a rich ecosystem. If you wish to learn more about InversifyJS please refer to the following links:</p>
<ul>
<li><a href="https://github.com/inversify/InversifyJS/">The official InversifyJS repository</a></li>
<li><a href="https://twitter.com/inversifyjs">InversifyJS on Twitter</a></li>
<li><a href="https://twitter.com/RemoHJansen">Remo H. Jansen on Twitter</a></li>
</ul>
<blockquote class="large">
<p>Note: This post was originally posted at <a href="https://dev.to/remojansen/dependency-injection-in-typescript-applications-powered-by-inversifyjs">https://dev.to/remojansen/dependency-injection-in-typescript-applications-powered-by-inversifyjs</a></p>
</blockquote>tag:blog.wolksoftware.com,2014:Post/contributing-to-definitelytyped2016-10-15T18:53:38-07:002016-10-15T18:53:38-07:00How to create your own TypeScript type definition files (.d.ts) and contribute to DefinitelyTyped on GitHub<h1 id="learn-how-to-create-your-own-type-definition_1">
<a class="head_anchor" href="#learn-how-to-create-your-own-type-definition_1"> </a>Learn how to create your own type definition files and how to contribute to the TypeScript community at <a href="https://github.com/DefinitelyTyped/DefinitelyTyped">DefinitelyTyped</a>
</h1><h1 id="helping-your-community-is-awesome_1">
<a class="head_anchor" href="#helping-your-community-is-awesome_1"> </a>Helping your community is AWESOME</h1>
<p>It is Saturday evening and it’s raining a lot in Ireland. So I decided to spend some time on Twitter looking for interesting TypeScript news. Over the last year I’ve been using the <a href="https://twitter.com/DubTypeScript">@DubTypeScript</a> account to share TypeScript news. This is the official account of the <a href="https://www.meetup.com/Dublin-TypeScript-Meetup/">Dublin TypeScript Meetup</a> which is based in Dublin (Ireland) and is organized by myself.</p>
<p>I was searching for interesting tweets when I found the following one:</p>
<p><a href="https://svbtleusercontent.com/igfvtxkaloztsa.png"><img src="https://svbtleusercontent.com/igfvtxkaloztsa_small.png" alt="Screen Shot 2016-10-15 at 19.19.45.png"></a></p>
<p>When I saw this tweet I was automatically thrilled because it is AWESOME when you find an opportunity to help the community like this. </p>
<p>I really think it is sad that only a small percentage of all the software engineers out there contribute to open source. Contributing to open source is not easy for newcomers but I have seen a lot of initiatives to try to improve this over the past year. Initiatives among which I would like to highlight the Hoodie efforts:</p>
<blockquote class="large">
<p>Hoodie aims to be one of open source’s most diverse and inclusive communities - <a href="https://opensource.com/life/16/2/hoodie-open-source-community">opensource.com</a></p>
</blockquote>
<p>And the <a href="https://yourfirstpr.github.io/">“Your First PR”</a> initiative:</p>
<blockquote class="large">
<p>Your First PR helps you get started contributing to Open Source by showcasing great starter issues on Github and elsewhere. - <a href="https://yourfirstpr.github.io/">Your First PR</a></p>
</blockquote>
<p>You may not believe me until you try it yourself but working on open source will make you a happier person. You might be working on an awesome project at work, in an amazing company with an amazing salary but nothing will fulfil you as much as helping others. Helping others will give you a sense of purpose that no salary or pension will ever be able to give you.</p>
<p>Working on open source has also helped me a lot in my professional career. It has allowed me to gain access to amazing opportunities like writing a <a href="http://amzn.to/2dYiLEY">technical book</a>.</p>
<p><a href="https://svbtleusercontent.com/q3ejbhgt5s3pw.png"><img src="https://svbtleusercontent.com/q3ejbhgt5s3pw_small.png" alt="learning_typescript.png"></a></p>
<p>Or having the honor of being awarded with the Microsoft Most Valuable Professional (MVP) award:</p>
<p><a href="https://svbtleusercontent.com/3bnvciwfchqmha.jpeg"><img src="https://svbtleusercontent.com/3bnvciwfchqmha_small.jpeg" alt="mvp.jpeg"></a></p>
<p>In summary, contributing to open source will not only make you a happier person. It will also help you to become a better professional.</p>
<p>In this article I’m going to explain how to create type definitions for an open source npm module. Please note that I’m assuming that you are familiar with TypeScript, Git and npm but you don’t need to be familiar with GitHub or React.</p>
<h1 id="writing-your-own-type-definitions-files_1">
<a class="head_anchor" href="#writing-your-own-type-definitions-files_1"> </a>Writing your own type definitions files</h1>
<p>To create our own type definitions, we need to see the source code of the npm module for which we are trying to create type definitions. </p>
<p>In this post we are working on the type definitions for the <code class="prettyprint">react-side-effect</code> npm module. It is easy to find the source code doing a quick search on Google but, the way I do it, is by heading to <a href="https://www.npmjs.com/package/react-side-effect">the module page on npmjs.com</a>. </p>
<p>Once you find the module on npmjs.com, you will be able to find a link to its GitHub repository on the right-hand side of the page:</p>
<p><a href="https://svbtleusercontent.com/kcv7svvpgmobxq.png"><img src="https://svbtleusercontent.com/kcv7svvpgmobxq_small.png" alt="Screen Shot 2016-10-15 at 22.01.50.png"></a></p>
<p>Follow the link to GitHub and try to find the <code class="prettyprint">package.json</code> file using the file explorer. We then need find the <code class="prettyprint">main</code> field in the <code class="prettyprint">package.json</code> file:</p>
<p><a href="https://svbtleusercontent.com/u69we1s8qskarg.png"><img src="https://svbtleusercontent.com/u69we1s8qskarg_small.png" alt="Screen Shot 2016-10-15 at 22.04.00.png"></a></p>
<p>In 99% percent of the libraries, the main file is the <code class="prettyprint">/src/index.js</code> file but, if that is not the case, the <code class="prettyprint">package.json</code> file can help you to identify the main file.</p>
<p>Head to the main file to see its source code. In this case, the main file can be found <a href="https://github.com/gaearon/react-side-effect/blob/master/src/index.js">here</a>. </p>
<p>Wait a second, I just noticed something. This source code was created by <a href="https://twitter.com/dan_abramov">Dan Abramov</a>! This means that we are about to be able to learn from the source code one of the most popular software developers within the React and the JavaScript community. This is an example of the kind of amazing opportunities that you will encounter if you work on open source. You will be able to learn from some of the best software engineers in the world and even get to know them for free!</p>
<p>Once you find the source code, the first thing that we need to do, is to identify if this library was created using ES5 or ES6. We can usually identify the version of JavaScript being used by looking at the module imports. Then try identify which modules are imported (dependencies) and which elements are exported (public interface):</p>
<p><a href="https://svbtleusercontent.com/0dxwhp2sjmhoeg.png"><img src="https://svbtleusercontent.com/0dxwhp2sjmhoeg_small.png" alt="Screen Shot 2016-10-15 at 22.24.34.png"></a></p>
<p>It looks like this module depends on 2 other modules:</p>
<ul>
<li>
<code class="prettyprint">Component</code> is imported from <code class="prettyprint">react</code>
</li>
<li>
<code class="prettyprint">ExecutionEnvironment</code> and <code class="prettyprint">shallowEqual</code> is imported from <code class="prettyprint">fbjs</code>
</li>
</ul>
<p>When I search for the <code class="prettyprint">ExecutionEnvironment</code> and <code class="prettyprint">shallowEqual</code> variables in the source code, I can see that <code class="prettyprint">ExecutionEnvironment</code> and <code class="prettyprint">shallowEqual</code> are used internally and are not exported by <code class="prettyprint">react-side-effect</code>.</p>
<p>The module exports a function named <code class="prettyprint">withSideEffect</code>, which the function takes 3 arguments named:</p>
<ul>
<li><code class="prettyprint">reducePropsToState</code></li>
<li><code class="prettyprint">handleStateChangeOnClient</code></li>
<li><code class="prettyprint">mapStateOnServer</code></li>
</ul>
<p>The library is written in JavaScript so we don’t know the types of these 3 arguments.</p>
<p><a href="https://svbtleusercontent.com/jxqnwfto52ow.png"><img src="https://svbtleusercontent.com/jxqnwfto52ow_small.png" alt="Screen Shot 2016-10-15 at 23.11.08.png"></a></p>
<p>At this point we can start creating our type definition file:</p>
<pre><code class="prettyprint">declare module "react-side-effect" {
function withSideEffect(
reducePropsToState: any,
handleStateChangeOnClient: any,
mapStateOnServer: any
): any;
export = withSideEffect;
}
</code></pre>
<p>I can also see that the <code class="prettyprint">withSideEffect</code> function returns another function named <code class="prettyprint">wrap</code>, which takes an argument named <code class="prettyprint">WrappedComponent</code>. Once more we don’t know the type of this argument but by looking at its name and a <code class="prettyprint">typeof</code> check we can guess that it is a React Component.</p>
<p><a href="https://svbtleusercontent.com/gveozdp66ybq.png"><img src="https://svbtleusercontent.com/gveozdp66ybq_small.png" alt="Screen Shot 2016-10-15 at 23.10.48.png"></a></p>
<p>The <code class="prettyprint">Warp</code> function returns a React component named <code class="prettyprint">SideEffect</code>.</p>
<p><a href="https://svbtleusercontent.com/w0ptu1rhjywg.png"><img src="https://svbtleusercontent.com/w0ptu1rhjywg_small.png" alt="Screen Shot 2016-10-15 at 23.11.48.png"></a></p>
<p><a href="https://svbtleusercontent.com/6uduuajx1r7ag.png"><img src="https://svbtleusercontent.com/6uduuajx1r7ag_small.png" alt="Screen Shot 2016-10-15 at 23.11.39.png"></a>.</p>
<p>The last thing that we need to find out is the types of the arguments. This is the most complicated part. In this case I’m lucky because I’m familiar with React and the library is well documented.</p>
<p>The <code class="prettyprint">handleStateChangeOnClient</code> and <code class="prettyprint">mapStateOnServer</code> arguments are functions that expect an object <code class="prettyprint">state</code> as its only argument.</p>
<p><a href="https://svbtleusercontent.com/z0ggfv16tjilq.png"><img src="https://svbtleusercontent.com/z0ggfv16tjilq_small.png" alt="Screen Shot 2016-10-15 at 23.34.24.png"></a></p>
<p>Because I’m familiar with React I know that the state can take any from so I used the type <code class="prettyprint">any</code>.</p>
<p>Later I noticed that <code class="prettyprint">reducePropsToState</code> actually takes an array as argument:</p>
<p><a href="https://svbtleusercontent.com/gie78cbp2v4gca.png"><img src="https://svbtleusercontent.com/gie78cbp2v4gca_small.png" alt="Screen Shot 2016-10-16 at 02.47.23.png"></a></p>
<p>At this point I updated the type definitions:</p>
<pre><code class="prettyprint">declare module "react-side-effect" {
import React = __React;
function withSideEffect(
reducePropsToState: (propsList: any[]) =&gt; any,
handleStateChangeOnClient: (state: any) =&gt; any,
mapStateOnServer: (state: any) =&gt; any
): (WrappedComponent: React.Component&lt;any, any&gt;) =&gt; React.Component&lt;any, any&gt;;
export = withSideEffect;
}
</code></pre>
<p>Note that I have used <code class="prettyprint">export =</code> because that is what I can <a href="https://github.com/gaearon/react-side-effect/blob/eb25efece753108b083f9c2c1be8e650712810d0/src/index.js#L5">see</a> in the library’s source code. Sometimes you will see <code class="prettyprint">export default x</code> or <code class="prettyprint">export { x }</code> you need to ensure that your type definitions file use the same kind of export that is used in the library.</p>
<p>Now that we have the initial type definitions ready, we are going to try to add them to DefinitelyTyped.</p>
<h1 id="contributing-to-definitelytyped-on-github_1">
<a class="head_anchor" href="#contributing-to-definitelytyped-on-github_1"> </a>Contributing to DefinitelyTyped on GitHub</h1>
<p>To contribute to DefinitelyTyped you need to visit the official repository at <a href="https://github.com/DefinitelyTyped/DefinitelyTyped">https://github.com/DefinitelyTyped/DefinitelyTyped</a>. </p>
<p>Once you are in the page you need to fork the repository (you will need to be logged in). You can fork the repository by clicking on the top right “fork” icon:</p>
<p><a href="https://svbtleusercontent.com/nxtf4okbyoj4aq.png"><img src="https://svbtleusercontent.com/nxtf4okbyoj4aq_small.png" alt="Screen Shot 2016-10-15 at 19.54.50.png"></a></p>
<p>After forking the repository, you will be redirected to the page of your fork. You need to find the HTTPS URL to clone your fork:</p>
<p><a href="https://svbtleusercontent.com/dt2hktepz3dyw.png"><img src="https://svbtleusercontent.com/dt2hktepz3dyw_small.png" alt="Screen Shot 2016-10-15 at 19.57.32.png"></a></p>
<p>Once you have the clone URL, you can clone the repository using the terminal or console of your operating system. </p>
<pre><code class="prettyprint">$ git clone https://github.com/YOUR_USER_NAME/DefinitelyTyped.git
</code></pre>
<p>When the repository has been cloned you need to move into the newly created folder:</p>
<pre><code class="prettyprint">$ cd DefinitelyTyped
</code></pre>
<p>We are going to add a new type definition file so we can say that we are going to work on a new feature. We are going to create a new branch:</p>
<pre><code class="prettyprint">$ git checkout -b react-side-effect
</code></pre>
<p>We need to install the dependencies of this project:</p>
<pre><code class="prettyprint">$ npm install
</code></pre>
<p>We can then create a new folder:</p>
<pre><code class="prettyprint">$ mkdir react-side-effect
</code></pre>
<p>A new file for our type definitions:</p>
<pre><code class="prettyprint">$ touch react-side-effect/react-side-effect.d.ts
</code></pre>
<p>And a new file for the test of the type definitions:</p>
<pre><code class="prettyprint">$ touch react-side-effect/react-side-effect-tests.ts
</code></pre>
<p>We can copy our initial type definitions into the <code class="prettyprint">react-side-effect.d.ts</code> file that we just created. I copied it and added some comments required by DefinitelyTyped:</p>
<pre><code class="prettyprint">// Type definitions for react-side-effect v1.0.2
// Project: https://github.com/gaearon/react-side-effect
// Definitions by: Remo H. Jansen &lt;https://github.com/remojansen/&gt;
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/// &lt;reference path="../react/react.d.ts"/&gt;
declare module "react-side-effect" {
import React = __React;
function withSideEffect(
reducePropsToState: (propsList: any[]) =&gt; any,
handleStateChangeOnClient: (state: any) =&gt; any,
mapStateOnServer: (state: any) =&gt; any
): (WrappedComponent: React.Component&lt;any, any&gt;) =&gt; React.Component&lt;any, any&gt;;
export = withSideEffect;
}
</code></pre>
<p>To create the test, I just to copied <a href="https://github.com/gaearon/react-side-effect#usage">one of the examples</a> from the <code class="prettyprint">react-side-effect</code> documentation. The example is written in JavaScript but can be migrated to TypeScript with ease:</p>
<pre><code class="prettyprint">/// &lt;reference path="react-side-effect.d.ts" /&gt;
import * as React from "react";
import * as withSideEffect from "react-side-effect";
interface DocumentTitleProps {
title: string
}
class DocumentTitle extends React.Component&lt;DocumentTitleProps, any&gt; {
public render() {
if (this.props.children) {
return React.Children.only(this.props.children);
} else {
return null;
}
}
}
function reducePropsToState(propsList: any[]) {
var innermostProps = propsList[propsList.length - 1];
if (innermostProps) {
return innermostProps.title;
}
}
function handleStateChangeOnClient(title: string) {
document.title = title || "";
}
let DocumentTitleWithSideEffects = withSideEffect(
reducePropsToState,
handleStateChangeOnClient
)(DocumentTitle);
export default DocumentTitleWithSideEffects;
</code></pre>
<p>If we search in the DefinitelyTyped repository documents, we will be able to find the <a href="http://definitelytyped.org/guides/contributing.html#tests">instructions</a> to test our changes before sending a pull request:</p>
<pre><code class="prettyprint">$ npm test
</code></pre>
<p>When I executed the tests I encountered two issues:</p>
<pre><code class="prettyprint">import * as withSideEffect from "react-side-effect";
</code></pre>
<p>Was throwing:</p>
<blockquote class="large">
<p>[ts] Module ‘“react-side-effect”’ resolves to a non-module entity and cannot be imported using this construct.</p>
</blockquote>
<p>I was able to fix it adding a <code class="prettyprint">namespace</code>. I found <a href="https://github.com/Microsoft/TypeScript/issues/5073">the solution</a> after a quick search online:</p>
<pre><code class="prettyprint">declare module "react-side-effect" {
import React = __React;
function withSideEffect(
reducePropsToState: (propsList: any[]) =&gt; any,
handleStateChangeOnClient: (state: any) =&gt; any,
mapStateOnServer: (state: any) =&gt; any
): (WrappedComponent: React.Component&lt;any, any&gt;) =&gt; React.Component&lt;any, any&gt;;
namespace withSideEffect {} // https://github.com/Microsoft/TypeScript/issues/5073
export = withSideEffect;
}
</code></pre>
<p>The second problem was that:</p>
<pre><code class="prettyprint">let DocumentTitleWithSideEffects = withSideEffect(
reducePropsToState,
handleStateChangeOnClient
)(DocumentTitle);
</code></pre>
<p>Was throwing:</p>
<blockquote class="large">
<p>[ts] Argument of type ‘typeof DocumentTitle’ is not assignable to parameter of type ‘Component’.<br>
Property ‘setState’ is missing in type ‘typeof DocumentTitle’.</p>
</blockquote>
<p>I was able to fix this issue by going through the type definitions of other similar react libraries. I found <a href="https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/redux-form/redux-form.d.ts#L279-L283">the solution</a> in the <code class="prettyprint">redux-forms</code> type definitions:</p>
<pre><code class="prettyprint">// Type definitions for react-side-effect v1.0.2
// Project: https://github.com/gaearon/react-side-effect
// Definitions by: Remo H. Jansen &lt;https://github.com/remojansen/&gt;
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/// &lt;reference path="../react/react.d.ts"/&gt;
declare module "react-side-effect" {
import React = __React;
function withSideEffect(
reducePropsToState: (propsList: any[]) =&gt; any,
handleStateChangeOnClient: (state: any) =&gt; any,
mapStateOnServer?: (state: any) =&gt; any
): ClassDecorator;
class ElementClass extends React.Component&lt;any, any&gt; {}
interface ClassDecorator {
&lt;T extends (typeof ElementClass)&gt;(component:T): T;
}
namespace withSideEffect {} // https://github.com/Microsoft/TypeScript/issues/5073
export = withSideEffect;
}
</code></pre>
<p>We are ready to send our changes to our fork. Let’s add the new folder to source control:</p>
<pre><code class="prettyprint">$ git add react-side-effect
</code></pre>
<p>Then check which files are ready to be committed:</p>
<pre><code class="prettyprint">$ git status
</code></pre>
<p>The files seem to be correct:</p>
<pre><code class="prettyprint">new file: react-side-effect/react-side-effect-tests.ts
new file: react-side-effect/react-side-effect.d.ts
</code></pre>
<p>We can now commit the changes:</p>
<pre><code class="prettyprint">$ git commit -m "Added type definitions for react-side-effect"
</code></pre>
<p>To finish, let’s push the changes to a new branch in our fork:</p>
<pre><code class="prettyprint">$ git push origin react-side-effect
</code></pre>
<p>If you head to the page of your fork on GitHub you will see a notice box which allows you to create a pull request (PR) for your changes:</p>
<p><a href="https://svbtleusercontent.com/dqxcjfw68t3uyg.png"><img src="https://svbtleusercontent.com/dqxcjfw68t3uyg_small.png" alt="Screen Shot 2016-10-16 at 01.34.55.png"></a></p>
<p>After creating the PR a the DefinitelyTyped continuous integration process will be triggered. The CI process will run the tests just like you have done in your local machine so it should be fine.</p>
<p>This time the CI process has been successful ??</p>
<p><a href="https://svbtleusercontent.com/kd5bzyijmrzvw.png"><img src="https://svbtleusercontent.com/kd5bzyijmrzvw_small.png" alt="Screen Shot 2016-10-16 at 01.50.11.png"></a></p>
<p>If your PR fails during the CI process, you will need to check the Travis CI logs. You can access the logs by clicking on “Show all checks” and then clicking on “Details”. If you need help you will be abel to use the comments section in the PR and the DefinitelyTyped time will try their best to help you.</p>
<h1 id="summary_1">
<a class="head_anchor" href="#summary_1"> </a>Summary</h1>
<p>We have learned how to create our own type definition files and how to share them with the open source community. </p>
<p>There is a process that you can follow:</p>
<ol>
<li>Identify imports and exports of a given module.</li>
<li>Identify types of the exported function (arguments and return).</li>
<li>Create initial <code class="prettyprint">.d.ts</code> file.</li>
<li>Create test using a example from the module docs.</li>
<li>Run test locally and fix issues.</li>
<li>Send PR to DefinitelyTyped.</li>
</ol>
<p>Creating type definitions files is not a trivial task but it is a positive experience:</p>
<ul>
<li>We get to review code created by people like Dan Abramov.</li>
<li>We learn how to solve issues like <a href="https://github.com/Microsoft/TypeScript/issues/5073">#5073</a>.</li>
<li>We learn about new libraries.</li>
<li>We will make at least one person <a href="https://twitter.com/kevin_mees/status/787252967388934144">happy</a>.</li>
</ul>
<p><a href="https://svbtleusercontent.com/kklqmz0sdkghw.png"><img src="https://svbtleusercontent.com/kklqmz0sdkghw_small.png" alt="Screen Shot 2016-10-16 at 02.08.30.png"></a></p>
<p>You can find more resources about the creation of type definitions at <a href="https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html">www.typescriptlang.org</a> and <a href="http://definitelytyped.org/guides/creating.html">definitelytyped.org</a>.</p>
<p>Please feel free to share thoughts about this article with us via <a href="https://twitter.com/WolkSoftwareLtd">@WolkSoftwareLtd</a>.</p>
<p><a href="http://blog.wolksoftware.com/feed">Don’t forget to subscribe</a> if you don’t want to miss it out future articles!</p>
tag:blog.wolksoftware.com,2014:Post/the-rise-of-functional-programming-and-the-death-of-angularjs2016-08-16T00:00:11-07:002016-08-16T00:00:11-07:00The rise of functional programming &amp; the decline of Angular 2.0<h1 id="learn-why-we-believe-that-the-rise-of-functio_1">
<a class="head_anchor" href="#learn-why-we-believe-that-the-rise-of-functio_1"> </a>Learn why we believe that the rise of functional programming (FP) will prevent Angular 2.0 from being as successful as its predecessor.</h1>
<p><a href="https://svbtleusercontent.com/qbpckf6fq8xrq.png"><img src="https://svbtleusercontent.com/qbpckf6fq8xrq_small.png" alt="hbnratu2blpova.png"></a></p>
<p>Angular 2.0 RC.5 was <a href="https://github.com/angular/angular/blob/master/CHANGELOG.md#200-rc5-2016-08-09">just released last week</a> and is now really close the long-awaited 2.0 release.</p>
<p>After the success of Angular 1.0, it is normal to expect a huge success for Angular 2.0. However, we feel that there are reasons to believe that Angular 2.0 will not be as successful as its predecessor.</p>
<p>We believe this because we have been observing the front-end development trends and <strong>we have noticed a significant shift within the JavaScript community</strong>. </p>
<p>Let’s learn what this “shift” is about.</p>
<blockquote class="large">
<p>Note: JavaScript transpilers like Babel, TypeScript or Elm are out of the scope of this article. But you should really <a href="http://elm-lang.org/try">try Elm</a>.</p>
</blockquote><h1 id="a-little-bit-of-history_1">
<a class="head_anchor" href="#a-little-bit-of-history_1"> </a>A little bit of history</h1>
<p>JavaScript is a multi-paradigm programming language. On its early days, it was mostly used as a scripting programming language. As the complexity of front-end application increased, <strong>the JavaScript community shifted towards a more object-oriented (prototype-based) style</strong>.</p>
<p>We can take a look to the API of many of the early single-page application (SPA) frameworks like <a href="http://backbonejs.org/#Model-extend">Backbone.js</a> to observe that they were heavily based on inheritance:</p>
<pre><code class="prettyprint">var Note = Backbone.Model.extend({
initialize: function() { ... },
author: function() { ... },
coordinates: function() { ... },
allowedToEdit: function(account) {
return true;
}
});
</code></pre>
<p>At the time ES6 wasn’t around and many developers demanded a class-based object-oriented API. After some time the class-based API became a reality:</p>
<blockquote class="large">
<p>JavaScript classes are introduced in ECMAScript 6 and are syntactical sugar over JavaScript’s existing prototype-based inheritance. The class syntax is not introducing a new object-oriented inheritance model to JavaScript. JavaScript classes provide a much simpler and clearer syntax to create objects and deal with inheritance. <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes">MDN</a></p>
</blockquote>
<p>However, when the class-based API arrived it was already too late and many influential developers didn’t want it anymore:</p>
<ul>
<li><p><a href="https://medium.com/javascript-scene/how-to-fix-the-es6-class-keyword-2d42bb3f4caf">ES6 classes are a virus</a>. </p></li>
<li><p><a href="https://github.com/joshburgess/not-awesome-es6-classes/">ES6 classes are not awesome</a>. </p></li>
<li><p><a href="https://medium.com/@dan_abramov/how-to-use-classes-and-sleep-at-night-9af8de78ccb4">How to use classes and still sleep at night</a>.</p></li>
</ul>
<p>Why? What happened between the arrival of the first SPA frameworks and the arrival of ES6? </p>
<p>The answer is simple: <strong>the JavaScript community is shifting towards a more functional programming style</strong>.</p>
<h1 id="the-rise-of-functional-programming_1">
<a class="head_anchor" href="#the-rise-of-functional-programming_1"> </a>The rise of functional programming</h1>
<p>Functional programming has its roots in lambda calculus, a formal system developed in the 1930s. </p>
<p>FP is a “scary topic” because languages (especially purely functional ones) have largely been emphasised in academia rather than in commercial software development. However this is changing. JavaScript is a very accessible programming language and, as a result, FP in JavaScript is much more accessible than learning <a href="https://www.haskell.org/">Haskell</a>.</p>
<p>Many developers with a background on FP languages have started to work on SPA frameworks and today we can enjoy libraries like React, Redux, Cycle.js, MobX, Ramda or Immutable.js in our JavaScript applications. Some of these libraries have a more FP style API than others but they all share one thing: <strong>they try avoid OOP style on their APIs</strong>. </p>
<p>When we say “OOP style” we are referring to:</p>
<ul>
<li>Inheritance over composition</li>
<li>Internal class state</li>
<li>Imperative state mutations</li>
</ul>
<p>We all know that it is better to use composition over inheritance but when a framework gives you a classes that you can extend it means that the framework promotes inheritance over composition. Angular 2.0 is a bit “weird” because it seems to <strong>prefer the decorator pattern over inheritance</strong>. However the decorator pattern <a href="http://www.programmerinterview.com/index.php/design-pattern-questions/decorator-pattern-versus-inheritance/">should not be not necessary in non-dynamic situations</a>.</p>
<p>Some elements of the React API promote inheritance over composition. For example, we can extend the <code class="prettyprint">React.Component</code> class:</p>
<pre><code class="prettyprint">import React from 'react';
class Contacts extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
&lt;div&gt;&lt;/div&gt;
);
}
}
export default Contacts;
</code></pre>
<p>Dan Abramov <a href="https://medium.com/@dan_abramov/how-to-use-classes-and-sleep-at-night-9af8de78ccb4#.iva4sjvvp">shared his disagreement</a> about APIs that favor inheritance over composition:</p>
<blockquote class="large">
<p><strong>Don’t expect people to use your classes</strong>. Even if you choose to provide your classes as a public API, prefer duck typing when accepting inputs. Instead of instanceof checks, assert the existence of the methods you plan to use, and trust the user to do the right thing. This will make userland extensions and later tweaks easier, as well as eliminate the issues with iframes and different JavaScript execution contexts.</p>
</blockquote>
<p>The React community is aware of the benefits of FP and new elements with a strong FP influence have been introduced into its API. For example, React.14 introduced a simpler way to define components called <strong>stateless functional components</strong> which introduced <a href="https://medium.com/@housecor/react-stateless-functional-components-nine-wins-you-might-have-overlooked-997b0d933dbc#.kzxd1g4ry">many benefits over its inheritance-based alternative</a>.</p>
<p>Angular 2.0 uses RxJS with is a <strong>functional reactive programming (FRP) library</strong>. Reactive programming is not functional programming. Reactive programming is programming with asynchronous data streams (observables). </p>
<p>RxJS is reactive because it allows you to work with observables but is also functional because it includes an amazing toolbox of functions to combine, create and filter any of those streams. <a href="https://gist.github.com/staltz/868e7e9bc2a7b8c1f754#what-is-reactive-programming">“That’s where the "functional” magic kicks in"</a>. We also have Cycle.js which is a framework highly influenced by FRP.</p>
<p>The official Angular 2.0 literature contains some reference to RxJS but it doesn’t emphasises enough in the ideas and benefits of reactive programming or mention the RxJS FP elements like the composition of observables. RxJS is used for things like fetching data from the server but not to do thing like user handling user input:</p>
<pre><code class="prettyprint">// SOURCE: https://angular.io/docs/ts/latest/guide/user-input.html
@Component({
selector: 'click-me',
template: `
&lt;button (click)="onClickMe()"&gt;Click me!&lt;/button&gt;
{{clickMessage}}`
})
export class ClickMeComponent {
clickMessage = '';
onClickMe() {
this.clickMessage = 'You are my hero!';
}
}
</code></pre>
<p>Other frameworks like Cycle.js do a much more intensive usage of reactive data streams:</p>
<pre><code class="prettyprint">function ClickMeComponent({DOM}) {
const msg$ = DOM.select('.btn')
.events('click')
.map(ev =&gt; 'You are my hero!')
.startWith('');
return {
DOM: msg$.map(clickMessage =&gt;
div([
button('.btn', 'Click me!'),
clickMessage
])
)
};
}
</code></pre>
<p>The angular.io docs are also full of examples of internal class state and imperative state mutations. We understand that many of this examples are very basic and using internal state simplifies the learning process but it feels quite different from reading the docs and examples of other libraries which strongly recommend following FP ideas like pure functions or immutability quite more often. You can of course use Angular 2.0 with these FP ideas but words like “pure”, “immutable”, “state”, “mutation”, “composition”, “reactive” or “observable” are much less common in the official Angular 2.0 literature than in the official Redux, React, RxJS or Cycle.js literature. This has lead us to think that the culture of Angular 2.0 as a community is much less aligned towards FP and FRP than the culture of other communities.</p>
<p>Many developers with an OOP background have been using libraries like React and Redux and slowly have been starting to understand the core FP principles:</p>
<blockquote class="large">
<p><strong>How much of functional programming can I learn by learning AngularJS?</strong> </p>
<p>Little to none. But, if you pick up React/Redux, you’ll actually encounter key functional concepts at the core of what you learn. Namely pure functions and immutability. - <a href="https://www.quora.com/How-much-of-functional-programming-can-I-learn-by-learning-AngularJS">Quora</a></p>
</blockquote>
<p>Understanding the basics about FP is is leading many developers to be eager to learn more about FP in JavaScript.</p>
<p><a href="https://svbtleusercontent.com/n5dyftkhmexpg.png"><img src="https://svbtleusercontent.com/n5dyftkhmexpg_small.png" alt="fp.png"></a></p>
<p>As developers learn more about FP we can observe the emergence of many libraries with a strong FP style like Cycle.js or Ramda and <strong>we believe that the shifting of the JavaScript community towards FP has just started</strong>.</p>
<h1 id="how-can-the-rise-of-fp-influence-the-success_1">
<a class="head_anchor" href="#how-can-the-rise-of-fp-influence-the-success_1"> </a>How can the rise of FP influence the success of Angular 2.0?</h1>
<p>We believe that the Angular 2,0 API is highly influenced by OOP ideas and goes against the shifting of the JavaScript community towards FP that we have been explaining in this article.</p>
<p>Angular 2.0 is being advertised as a framework that gives you everything. However, some developers are using Angular 2.0 with Redux because after experiencing the benefits of FP in React they just simply don’t want to deal with an API with a strong OOP style. They like more the idea of triggering actions (pure functions) that will invoke a reducer (pure function) in Redux than invoking a method in a Service class in Angular 2.0:</p>
<pre><code class="prettyprint">// SOURCE: https://angular.io/docs/ts/latest/tutorial/toh-pt6.html
import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
import { Hero } from './hero';
@Injectable()
export class HeroService {
private heroesUrl = 'app/heroes'; // URL to web api
constructor(private http: Http) { }
getHeroes() {
return this.http.get(this.heroesUrl)
.toPromise()
.then(response =&gt; response.json().data as Hero[])
.catch(this.handleError);
}
getHero(id: number) {
return this.getHeroes()
.then(heroes =&gt; heroes.find(hero =&gt; hero.id === id));
}
save(hero: Hero): Promise&lt;Hero&gt; {
if (hero.id) {
return this.put(hero);
}
return this.post(hero);
}
delete(hero: Hero) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let url = `${this.heroesUrl}/${hero.id}`;
return this.http
.delete(url, {headers: headers})
.toPromise()
.catch(this.handleError);
}
// Add new Hero
private post(hero: Hero): Promise&lt;Hero&gt; {
let headers = new Headers({
'Content-Type': 'application/json'});
return this.http
.post(this.heroesUrl, JSON.stringify(hero), {headers: headers})
.toPromise()
.then(res =&gt; res.json().data)
.catch(this.handleError);
}
// Update existing Hero
private put(hero: Hero) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let url = `${this.heroesUrl}/${hero.id}`;
return this.http
.put(url, JSON.stringify(hero), {headers: headers})
.toPromise()
.then(() =&gt; hero)
.catch(this.handleError);
}
private handleError(error: any) {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
</code></pre>
<p>We can use the Angular 2.0 components (even though they are not stateless functional components) together with some other libraries (like Redux or RxJS) to make Angular 2.0 feel “more functional”.</p>
<p><a href="https://svbtleusercontent.com/lavjoo6cdcmaka.png"><img src="https://svbtleusercontent.com/lavjoo6cdcmaka_small.png" alt="arrow-right-310628_640.png"></a></p>
<blockquote class="large">
<p>Note: Notice that we placed Redux closer to FP than React. Also notice how React on its own is closer to OOP than FP. If you use React with Redux you will be “closer to FP then OOP”. In a similar way, if you use Angular 2.0 with Redux and RxJS it will move a lot towards FP but we see Angular 2.0 closer to OOP than React that’s why it is located on the very far right. Also note that we are comparing FP influences in this diagram not reactive programming influences.</p>
</blockquote>
<p>Why we need such a powerful framework then? Would it not be better to simply use a very light weight component library with Redux? This is something that is even <a href="http://riotjs.com/">happening to React components</a>.</p>
<p><strong>We believe that the “sweet spot” is somewhere between OOP and FP, maybe somewhere a bit closer to FP than OOP</strong> but maybe the right thing to do is to <a href="http://dl.acm.org/ft_gateway.cfm?id=2611829&amp;ftid=1452158&amp;dwn=1">go fully functional</a>. We have not tried to go pure functional yet but is something that we would like to experiment soon.</p>
<p>We are looking forward to find out what will bring us: </p>
<blockquote class="large">
<p>The aftermath of the “functional web frontend tsunami” React and friends brought about - <a href="http://futurice.com/blog/elm-in-the-real-world">Futurice</a></p>
</blockquote><h1 id="update_1">
<a class="head_anchor" href="#update_1"> </a>Update</h1>
<p>One week after publishing this article <a href="https://github.com/bodil/eslint-config-cleanjs">eslint-config-cleanjs</a> was released on GitHub. This open-source project provide us with an eslint config which reduces JS to a pure functional language.</p>
<p><a href="https://svbtleusercontent.com/sho2mkllivzukq.jpg"><img src="https://svbtleusercontent.com/sho2mkllivzukq_small.jpg" alt="CrGpyuMWEAAG-A-.jpg"></a></p>
<p><a href="https://svbtleusercontent.com/rfghfxmuoyavfa.jpg"><img src="https://svbtleusercontent.com/rfghfxmuoyavfa_small.jpg" alt="CrGqI1pWcAATmmu.jpg"></a></p>
<p>You can already find some <a href="https://medium.com/javascript-inside/the-elegance-of-react-ebc21a2dcd19#.28s1nbvb3">examples online</a>:</p>
<blockquote class="large">
<p>The examples have been written using eslint-config-cleanjs, to <strong>enforce a more functional style, which includes no-this and no-classes rules</strong>.</p>
</blockquote>
<p>Frameworks with a strong functional programming influence like Cycle.js apps can pass the lint test easily:</p>
<p><a href="https://svbtleusercontent.com/ml3ammxt296ug.png"><img src="https://svbtleusercontent.com/ml3ammxt296ug_small.png" alt="Untitled.png"></a></p>
<p>The fact that this project exists is for us one more sign of the increasing interest of the JavaScript community in Functional Programming.</p>
<h1 id="summary_1">
<a class="head_anchor" href="#summary_1"> </a>Summary</h1>
<p>We believe that the Angular 2,0 API is less influenced by FP ideas than its competitors. This goes against the shifting of the JavaScript community towards FP that we have been explaining in this article.</p>
<p>As more and more people learn about functional programming techniques and try frameworks and libraries like React, Cycle.js, Redux, MobX, RxJS or Ramda they will be more likely to try to avoid classes, inheritance, imperative programming and other OOP elements as much as they can. This leads us to believe that the rise of FP within the JavaScript community will prevent Angular 2.0 from being as successful as its predecessor.</p>
<p>If you want to learn more about functional programming in JavaScript, a good way to get started is to use React with Redux and read some books:</p>
<ul>
<li><a href="http://amzn.to/2bcpOrF">Functional Programming in JavaScript by Dan Mantyla</a></li>
<li><a href="http://amzn.to/2aQVBuF">Functional Programming in JavaScript by Luis Atencio</a></li>
<li><a href="http://amzn.to/2baIRkO">Reactive Programming with RxJS by Sergi Mansilla</a></li>
</ul>
<p>Then you can introduce immutable.js and RxJS into your React applications and finally give a try to Cycle.js and Ramda.</p>
<p>Please feel free to share thoughts about this article with us via <a href="https://twitter.com/WolkSoftwareLtd">@WolkSoftwareLtd</a>.</p>
<p><a href="http://blog.wolksoftware.com/feed">Don’t forget to subscribe</a> if you don’t want to miss it out future articles!</p>
tag:blog.wolksoftware.com,2014:Post/dependency-injection-in-react-powered-inversifyjs2016-07-27T09:01:34-07:002016-07-27T09:01:34-07:00Dependency injection in React powered by InversifyJS<h3 id="most-of-the-solutions-for-dependency-injectio_3">
<a class="head_anchor" href="#most-of-the-solutions-for-dependency-injectio_3"> </a>Most of the solutions for dependency injection (DI) in React components are based on context. The famous connect function and the Provider there use the context. However, the React development team recommends avoiding the usage of the context. In this article we will learn how we can use InversifyJS as a context-free solution for DI in React applications.</h3><h2 id="introduction_2">
<a class="head_anchor" href="#introduction_2"> </a>Introduction</h2>
<p>A few weeks ago, an user in Twitter asked <a href="https://twitter.com/mweststrate">Michel Weststrate</a> (the author of <a href="https://github.com/mobxjs/mobx">MobX</a>) the following:</p>
<p><a href="https://svbtleusercontent.com/igizyurohpaqa.png"><img src="https://svbtleusercontent.com/igizyurohpaqa_small.png" alt="Untitled.png"></a></p>
<p>His <a href="https://twitter.com/mweststrate/status/750267384926208000">answer</a> was the following:</p>
<p><a href="https://svbtleusercontent.com/oevogoskckagja.png"><img src="https://svbtleusercontent.com/oevogoskckagja_small.png" alt="Untitled2.png"></a></p>
<p>Later, the popular repository react-in-patterns <a href="https://github.com/krasimir/react-in-patterns/blob/master/patterns/dependency-injection/README.md">documented</a> the most common dependency injection patterns in React applications but some developers <a href="https://twitter.com/hugoccampos/status/756180622368993280">mentioned</a> InversifyJS once more:</p>
<p><a href="https://svbtleusercontent.com/akfgzq3idczw.png"><img src="https://svbtleusercontent.com/akfgzq3idczw_small.png" alt="Untitled.png"></a></p>
<p>I was surprised after reading the following in react-in-patterns:</p>
<blockquote class="large">
<p>Most of the solutions for dependency injection in React components are based on context. I think that it’s good to know what happens under the hood. As the time of this writing one of the most popular ways for building React apps involves Redux. The famous connect function and the Provider there use the context.</p>
</blockquote>
<p>I was surprised because, based on the <a href="https://facebook.github.io/react/docs/context.html">React docs</a>, we should try to avoid using context:</p>
<blockquote>
<p>Context is an advanced and experimental feature. The API is likely to change in future releases.<br>
Most applications will never need to use context. Especially if you are just getting started with React, you likely do not want to use context. Using context will make your code harder to understand because it makes the data flow less clear. It is similar to using global variables to pass state through your application.</p>
<p><strong>If you have to use context, use it sparingly.</strong></p>
<p>Regardless of whether you’re building an application or a library, try to isolate your use of context to a small area and avoid using the context API directly when possible so that it’s easier to upgrade when the API changes.</p>
</blockquote>
<p>In this article we are going to learn how we can use an IoC container to inject a value into React components without passing it explicitly through each component and without using the React context.</p>
<p>We are going to use <a href="https://github.com/inversify/InversifyJS">InversifyJS</a> as IoC container and <a href="https://github.com/Microsoft/TypeScript">TypeScript</a> as programming language. We are using InversifyJS because it works in both Node.js and web browsers. This is an important feature because some React applications use server-side rendering. We are also using TypeScript because it is the recommended by InversifyJS.</p>
<h1 id="about-the-integration-of-ioc-containers-with_1">
<a class="head_anchor" href="#about-the-integration-of-ioc-containers-with_1"> </a>About the integration of IoC containers with React</h1>
<p>InversifyJS supports two kinds of injections:</p>
<ul>
<li>Constructor injection</li>
<li>Property injection</li>
</ul>
<p>In order to use “constructor injection” the IoC container needs to be able to create the instances of the classes. In React the components sometimes are just functions (not classes) and we can’t delegate the creation of the instances of the components to the IoC container. This means that <strong>constructor injection powered by IoC containers don’t play nicely with React</strong></p>
<p>However, <strong>property injection works nicely</strong> if what we want is to pass dependencies to components without passing them explicitly through each component. Let’s take a look to a basic example.</p>
<h1 id="show-me-the-code_1">
<a class="head_anchor" href="#show-me-the-code_1"> </a>Show me the code!</h1>
<p>We need to start by configuring the IoC container. In InversifyJs we need to create a dictionary that maps a type identifier with a type. The dictionary entries are known as “type bindings”. </p>
<p>In this case, we use a binding to map the identifier <code class="prettyprint">UserStore</code> to the class <code class="prettyprint">UserStore</code>. This time the identifier is the Class but InversifyJS also allow you to use <code class="prettyprint">Symbols</code> or string literals as identifiers. Symbols or string literals are required when we use interfaces.</p>
<pre><code class="prettyprint lang-ts">import { Kernel, makePropertyInjectDecorator } from "inversify";
import { UserStore } from "./store/user";
import "reflect-metadata";
let kernel = new Kernel();
kernel.bind&lt;UserStore&gt;(UserStore).to(UserStore);
let pInject = makePropertyInjectDecorator(kernel);
export { kernel, pInject };
</code></pre>
<p>We also need to generate a decorator using the function <code class="prettyprint">makePropertyInjectDecorator</code>. </p>
<p>The generated <code class="prettyprint">pInject</code> decorator allow us to flag the properties of a class that we want to be injected:</p>
<pre><code class="prettyprint lang-ts">import { pInject } from "./utils/di";
import { UserStore } from "./store/user";
class User extends React.Component&lt;any, any&gt; {
@pInject(UserStore)
private userStore: UserStore;
public render() {
return (
&lt;h1&gt;{this.userStore.pageTitle}&lt;/h1&gt;
);
}
}
</code></pre>
<p>Injected properties are lazy evaluated. This means that the value of the <code class="prettyprint">userStore</code> property is only set after we try to access it for the first time.</p>
<h2 id="update-12082016_2">
<a class="head_anchor" href="#update-12082016_2"> </a>Update 12/08/2016</h2>
<p>Please note that in the future releases of InversifyJS the function <code class="prettyprint">makePropertyInjectDecorator</code> will be removed. It will be provided by its own module: <a href="https://github.com/inversify/inversify-inject-decorators"><strong>inversify-inject-decorators</strong></a>.</p>
<p><strong>The <code class="prettyprint">lazyInject</code> decorator is the equivalent to the previously known as <code class="prettyprint">pInject</code> decorator.</strong></p>
<pre><code class="prettyprint">import getDecorators from "inversify-inject-decorators";
import { Kernel } from "inversify";
import { UserStore } from "./store/user";
import "reflect-metadata";
let kernel = new Kernel();
kernel.bind&lt;UserStore&gt;(UserStore).to(UserStore);
let {
lazyInject,
lazyInjectNamed,
lazyInjectTagged,
lazyMultiInject
} = getDecorators(kernel);
export {
kernel,
lazyInject,
lazyInjectNamed,
lazyInjectTagged,
lazyMultiInject
};
</code></pre>
<h1 id="summary_1">
<a class="head_anchor" href="#summary_1"> </a>Summary</h1>
<p>The main advantage of using an IoC container like InversifyJS is that <strong>we are not using the context</strong>!</p>
<p>InversifyJS is also great for testing because you can declare a new binding to inject a mock or stub instead of a real value:</p>
<pre><code class="prettyprint lang-ts">kernel.bind&lt;UserStore&gt;(UserStore).toConstantValue({
pageTitle: "Some text for testing..."
});
</code></pre>
<p>You can find some real use cases of InversifyJS with React <a href="https://github.com/Mercateo/dwatch/blob/master/app/src/components/site/LocaleSwitcher.tsx#L12">here</a> and <a href="https://github.com/Mercateo/dwatch/blob/master/app/src/components/site/Header.tsx#L14">here</a>. You can learn more about InversifyJS <a href="https://github.com/inversify/InversifyJS">here</a>.</p>
<p>Please feel free to share thoughts about this article with us via <a href="https://twitter.com/OweR_ReLoaDeD">@OweR_ReLoaDeD</a>, <a href="https://twitter.com/inversifyjs">@InversifyJS</a> and <a href="https://twitter.com/WolkSoftwareLtd">@WolkSoftwareLtd</a>.</p>
<p><a href="http://blog.wolksoftware.com/feed">Don’t forget to subscribe</a> if you don’t want to miss it out future articles!</p>
tag:blog.wolksoftware.com,2014:Post/inversifyjs-2-0-0-release-candidate2016-06-27T00:00:16-07:002016-06-27T00:00:16-07:00Announcing InversifyJS 2.0.0 Release Candidate ?<p><strong>Learn what’s new in InversifyJS 2.0.0 and what can you expect to see in the future of this powerful lightweight IoC container for JavaScript and Node.js apps powered by TypeScript</strong></p>
<p><a href="https://svbtleusercontent.com/uge3nfaiwwrqda.jpg"><img src="https://svbtleusercontent.com/uge3nfaiwwrqda_small.jpg" alt="687474703a2f2f692e696d6775722e636f6d2f303473443733522e6a7067.jpg"></a></p>
<p>As many of the readers of this blog already know, over the past year and a half we have been working on <a href="https://github.com/inversify/InversifyJS">InversifyJS</a>. </p>
<blockquote class="large">
<p>InversifyJS is a powerful lightweight IoC container for JavaScript and Node.js written in TypeScript.</p>
</blockquote>
<p>Last march we announced that we were working on InversifyJS 2.0. Today we are happy to announce that InversifyJS 2.0 release candidate is <a href="https://www.npmjs.com/package/inversify">available on npm</a>.</p>
<p>In this post we are going to learn about the following:</p>
<ul>
<li><strong>Setting up InversifyJS 2.0 with TypeScript</strong></li>
<li><strong>The InversifyJS 2.0 API</strong></li>
<li><strong>The InversifyJS 2.0 features</strong></li>
<li><strong>The InversifyJS ecosystem</strong></li>
<li><strong>The InversifyJS community</strong></li>
</ul>
<p>Let’s get started!</p>
<h1 id="setting-up-inversifyjs-20-with-typescript_1">
<a class="head_anchor" href="#setting-up-inversifyjs-20-with-typescript_1"> </a>Setting up InversifyJS 2.0 with TypeScript</h1>
<pre><code class="prettyprint">$ npm install inversify@2.0.0-beta.5 reflect-metadata --save
$ npm install inversify-dts --save-dev
</code></pre>
<pre><code class="prettyprint">{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
</code></pre>
<p>Please refer to the InversifyJS <a href="https://github.com/inversify/InversifyJS#installation">installation guide</a> for more details.</p>
<h1 id="the-inversifyjs-20-api_1">
<a class="head_anchor" href="#the-inversifyjs-20-api_1"> </a>The InversifyJS 2.0 API</h1>
<p>The InversifyJS API has changed a lot over the last couple of months, so let’s take a look to the final syntax.</p>
<p>The following example is not the most basic example but it is a good example to showcase the power of InversifyJS.</p>
<p>The first thing we need to do is to import <code class="prettyprint">reflect-metadata</code>, the <code class="prettyprint">injectable</code>, <code class="prettyprint">named</code> and <code class="prettyprint">inject</code> decorators and the <code class="prettyprint">Kernel</code> class from ImversifyJS and the required TypeScript type definitions:</p>
<pre><code class="prettyprint">/// &lt;reference path="./node_modules/inversify-dts/inversify/inversify.d.ts" /&gt;
/// &lt;reference path="./node_modules/reflect-metadata/reflect-metadata.d.ts" /&gt;
import { Kernel, injectable, inject, named } from "inversify";
import "reflect-metadata";
</code></pre>
<p>Then we can declare some interfaces:</p>
<pre><code class="prettyprint">interface Warrior {
fight(): string;
}
interface Weapon{
use(): string;
}
interface Battlefield{
warrior1: Warrior;
warrior2: Warrior;
}
</code></pre>
<p>We are also going to declare some <code class="prettyprint">Symbols</code> and tags. These are constants that are used as IDs and metadata. Because the constants are strings literals it is better to declare them just once in the whole application and that is what we are doing here:</p>
<pre><code class="prettyprint">let TYPES = {
Warrior: Symbol("Warrior"),
Weapon: Symbol("Weapon"),
Battlefield: Symbol("Battlefield")
};
let TAGS = {
ninja: "ninja",
samurai: "samurai"
};
</code></pre>
<p>We can then implement the interfaces. In this case we are going to declare two implementations of the <code class="prettyprint">Weapon</code> interface:</p>
<pre><code class="prettyprint">@injectable()
class Katana implements Weapon {
public use() {
return "Used Katana!";
}
}
@injectable()
class Shuriken implements Weapon {
public use() {
return "Used Shuriken!";
}
}
</code></pre>
<p>One implementation of the <code class="prettyprint">Warrior</code> interface:</p>
<pre><code class="prettyprint">@injectable()
class Warrior implements Warrior {
private _weapon: Weapon;
public constructor(
@inject(TYPES.Weapon) weapon: Weapon
) {
this._weapon = weapon;
}
public fight() { return this._weapon.use(); };
}
</code></pre>
<p>One implementation of the <code class="prettyprint">Battlefield</code> interface:</p>
<pre><code class="prettyprint">@injectable()
class Battlefield implements Battlefield {
public warrior1: Warrior;
public warrior2: Warrior;
public constructor(
@inject(TYPES.Warrior) @named(TAGS.ninja) warrior1: Warrior,
@inject(TYPES.Warrior) @named(TAGS.samurai) warrior2: Warrior
) {
this.warrior1 = warrior1;
this.warrior2 = warrior2;
}
}
</code></pre>
<p>We need to annotate all these classes with the <code class="prettyprint">injectable</code> decorator and if the class has dependencies we also need to use the <code class="prettyprint">inject</code> decorator to declare the type of the dependency.</p>
<p>Now that our entities are ready, we can create an instance of the InversifyJS kernel.</p>
<p>We then need to declare some bindings. A binding is a map between an interface and an implementation of that type. A binding can also have constraints. Constraints allow us to limit the binding to a context. In this case we are going to declare the following constraints:</p>
<ul>
<li>When an instance of <code class="prettyprint">Weapon</code> is needed, return a <code class="prettyprint">Katana</code> if its parent (<code class="prettyprint">Warrior</code>) is named “samurai”.</li>
<li>When an instance of <code class="prettyprint">Weapon</code> is needed, return a <code class="prettyprint">Shuriken</code> if its parent (<code class="prettyprint">Warrior</code>) is named “ninja”.</li>
</ul>
<pre><code class="prettyprint">var kernel = new Kernel();
kernel.bind&lt;Weapon&gt;(TYPES.Weapon)
.to(Katana)
.whenParentNamed(TAGS.samurai);
kernel.bind&lt;Weapon&gt;(TYPES.Weapon)
.to(Shuriken)
.whenParentNamed(TAGS.ninja);
kernel.bind&lt;Warrior&gt;(TYPES.Warrior)
.to(Warrior);
kernel.bind&lt;Battlefield&gt;(TYPES.Battlefield)
.to(Battlefield);
</code></pre>
<p>At this point we can request an instance of <code class="prettyprint">Battlefield</code> and the InversifyJS Kernel will be able to resolve</p>
<pre><code class="prettyprint">let battlefield = kernel.get&lt;Battlefield&gt;(TYPES.Battlefield);
battlefield.warrior1.fight(); // &gt; "Used Shuriken!"
battlefield.warrior2.fight(); // &gt; "Used Katana!"
</code></pre>
<h1 id="the-inversifyjs-20-features_1">
<a class="head_anchor" href="#the-inversifyjs-20-features_1"> </a>The InversifyJS 2.0 features</h1>
<p>InversifyJS 2.0 is really powerful and its list of features is very extensive:</p>
<ul>
<li>NodeJS and Browser support.</li>
<li>ES6 and ES5 support.</li>
<li>TypeScript and JavaScript support.</li>
<li><a href="https://github.com/inversify/InversifyJS#declaring-kernel-modules">Kernel modules</a></li>
<li><a href>Kernel middleware</a></li>
<li><a href="https://github.com/inversify/InversifyJS#kernel-snapshots">Kernel snapshot</a></li>
<li><a href="https://github.com/inversify/InversifyJS#middleware">Kernel middleware</a></li>
<li>
<a href="https://github.com/inversify/InversifyJS#kernel-children">Kernel children</a> (Hierarchical DI systems)</li>
<li><a href="https://github.com/inversify/InversifyJS#kernelgetall-kernelgetnamed--kernelgettagged">Kernel.getAll(), Kernel.getNamed() &amp; Kernel.getTagged()</a></li>
<li>Use <a href="https://github.com/inversify/InversifyJS#support-for-classes">classes</a>, string literals or <a href="https://github.com/inversify/InversifyJS#support-for-symbols">Symbols</a> as dependency identifiers</li>
<li><a href="https://github.com/inversify/InversifyJS#controlling-the-scope-of-the-dependencies">Singleton &amp; Transient scope</a></li>
<li><a href="https://github.com/inversify/InversifyJS#property-injection">Property Injection</a></li>
<li><a href="https://github.com/inversify/InversifyJS#injecting-a-constant-or-dynamic-value">Injection of constant and dynamic values</a></li>
<li><a href="https://github.com/inversify/InversifyJS#injecting-a-class-constructor">Injection of class constructors</a></li>
<li><a href="https://github.com/inversify/InversifyJS#injecting-a-factory">Injection of factories</a></li>
<li><a href="https://github.com/inversify/InversifyJS#auto-factory">Auto factory</a></li>
<li>
<a href="https://github.com/inversify/InversifyJS#injecting-a-provider-asynchronous-factory">Injection of providers</a> (async factory)</li>
<li>
<a href="https://github.com/inversify/InversifyJS#activation-handler">Activation handlers</a> (used to inject proxies)</li>
<li><a href="https://github.com/inversify/InversifyJS#multi-injection">Multi injections</a></li>
<li><a href="https://github.com/inversify/InversifyJS#tagged-bindings">Tagged bindings</a></li>
<li><a href="https://github.com/inversify/InversifyJS#create-your-own-tag-decorators">Custom tag decorators</a></li>
<li><a href="https://github.com/inversify/InversifyJS#named-bindings">Named bindings</a></li>
<li><a href="https://github.com/inversify/InversifyJS#contextual-bindings--targetname">Contextual bindings</a></li>
<li>
<a href="https://github.com/inversify/InversifyJS#circular-dependencies">Friendly exceptions</a> (e.g. Circular dependencies)</li>
</ul>
<p>You can visit <a href="https://github.com/inversify/InversifyJS">GitHub</a> or <a href="http://inversify.io/">www.inversify.io</a> to learn more about these features.</p>
<h1 id="the-inversifyjs-ecosystem_1">
<a class="head_anchor" href="#the-inversifyjs-ecosystem_1"> </a>The InversifyJS ecosystem</h1>
<p>I believe that InversifyJS is great but we think that being great is not enough. I want to provide the community with an awesome library and awesome ecosystem of extensions and development tools. Let’s take a look to some of them.</p>
<h3 id="the-inversifybindingdecorators-project_3">
<a class="head_anchor" href="#the-inversifybindingdecorators-project_3"> </a>The inversify-binding-decorators project</h3>
<p>There is an alternative binding syntax that uses decorators. Instead of writing:</p>
<pre><code class="prettyprint">import { injectable, Kernel } from "inversify";
import "reflect-metadata";
@injectable()
class Katana implements Weapon {
public hit() {
return "cut!";
}
}
@injectable()
class Shuriken implements ThrowableWeapon {
public throw() {
return "hit!";
}
}
var kernel = new Kernel();
kernel.bind&lt;Weapon&gt;("Weapon").to(Katana);
kernel.bind&lt;ThrowableWeapon&gt;("ThrowableWeapon").to(Shuriken);
</code></pre>
<p>We can write the following:</p>
<pre><code class="prettyprint">import { injectable, Kernel } from "inversify";
import makeProvideDecorator from "inversify-binding-decorators";
import "reflect-metadata";
var kernel = new Kernel();
let provide = makeProvideDecorator(kernel);
@provide("Weapon")
class Katana implements Weapon {
public hit() {
return "cut!";
}
}
@provide("ThrowableWeapon")
class Shuriken implements ThrowableWeapon {
public throw() {
return "hit!";
}
}
</code></pre>
<p>The inversify-binding-decorators project also allows us to declare contextual constraints using decorators:</p>
<pre><code class="prettyprint">@provide("Weapon").whenTargetTagged("throwable", false).done();
class Katana implements Weapon {
public hit() {
return "cut!";
}
}
</code></pre>
<p>You can learn more about this project on <a href="https://github.com/inversify/inversify-binding-decorators">GitHub</a>.</p>
<h3 id="the-inversifyloggermiddleware-project_3">
<a class="head_anchor" href="#the-inversifyloggermiddleware-project_3"> </a>The inversify-logger-middleware project</h3>
<p>This project provides you with a configurable console logging middleware:</p>
<p><a href="https://svbtleusercontent.com/xslrfmbpxcoba.png"><img src="https://svbtleusercontent.com/xslrfmbpxcoba_small.png" alt="687474703a2f2f692e696d6775722e636f6d2f6946416f67726f2e706e67.png"></a></p>
<p>This middle ware can help you to identify issues and to have a better understanding of the object composition.</p>
<p>You can learn more about this project on <a href="https://github.com/inversify/inversify-logger-middleware">GitHub</a>.</p>
<h3 id="the-inversifydevtools-project-coming-soon_3">
<a class="head_anchor" href="#the-inversifydevtools-project-coming-soon_3"> </a>The inversify-devtools project [Coming Soon]</h3>
<p>This project provides InversifyJS developers with a browser extension that helps you to work with InversifyJS in front-end applications.</p>
<p><a href="https://svbtleusercontent.com/unt1mgubrmpwla.png"><img src="https://svbtleusercontent.com/unt1mgubrmpwla_small.png" alt="1.png"></a></p>
<p><a href="https://svbtleusercontent.com/pyw985rdwvxvgq.png"><img src="https://svbtleusercontent.com/pyw985rdwvxvgq_small.png" alt="2.png"></a></p>
<p><a href="https://svbtleusercontent.com/2nvzcs28zrrieg.png"><img src="https://svbtleusercontent.com/2nvzcs28zrrieg_small.png" alt="3.png"></a></p>
<p>You can learn more about this project on <a href="https://github.com/inversify/inversify-devtools">GitHub</a>.</p>
<h3 id="the-inversifyexpressutils-project_3">
<a class="head_anchor" href="#the-inversifyexpressutils-project_3"> </a>The inversify-express-utils project</h3>
<p>This projects provides some utilities for the development of Node.js application with Express.</p>
<p><a href="https://svbtleusercontent.com/dinvsmxyqgwgyw.png"><img src="https://svbtleusercontent.com/dinvsmxyqgwgyw_small.png" alt="Untitled.png"></a></p>
<p>You can learn more at <a href="https://github.com/inversify/inversify-express-utils">GiiHub</a>.</p>
<h3 id="other-projects_3">
<a class="head_anchor" href="#other-projects_3"> </a>Other projects</h3>
<p>The list of projects does not end here! Check out the InversifyJS <a href="https://github.com/inversify/InversifyJS/blob/master/wiki/ecosystem.md">ecosystem page on GitHub</a> to learn about other projects.</p>
<h1 id="the-inversifyjs-community_1">
<a class="head_anchor" href="#the-inversifyjs-community_1"> </a>The InversifyJS community</h1>
<p>The InversifyJS community is still relatively small but it has been growing steadily over the last few months. There are <a href="http://registry.npmjs.org/-/_view/dependedUpon?group_level=3&amp;startkey=%5B%22inversify%22%5D&amp;endkey=%5B%22inversify%22%2C%7B%7D%5D&amp;skip=0&amp;limit=1000">other libraries and frameworks</a> depending on it already.</p>
<p><a href="https://svbtleusercontent.com/qevoxzfh3qiqaw.png"><img src="https://svbtleusercontent.com/qevoxzfh3qiqaw_small.png" alt="Untitled.png"></a></p>
<p>Thanks a lot to all the <a href="https://github.com/inversify/InversifyJS/graphs/contributors">contributors</a>, all the developers out there using InversifyJS and all those that help us to spread the word by sharing content about InversifyJS online. Without your feedback and support this project would not be possible.</p>
<h1 id="the-future-of-inversifyjs_1">
<a class="head_anchor" href="#the-future-of-inversifyjs_1"> </a>The future of InversifyJS</h1>
<p>Now that the core library is stable we will focus on improving documentations and examples. We will also work in development tools so you guys can enjoy a state of the art development experience.</p>
<p>There are two major features that we are planning to try to implement and I believe are worth mention here:</p>
<ul>
<li>
<a href="https://github.com/inversify/InversifyJS/issues/199">Support for hierarchical dependency inversion</a>.</li>
<li>
<a href="https://github.com/inversify/InversifyJS/issues/218">Support for custom scopes</a>.</li>
</ul>
<p>The best way to be updated is to <a href="https://github.com/inversify/InversifyJS/issues">check the issues page on GitHub</a>.</p>
<h1 id="summary_1">
<a class="head_anchor" href="#summary_1"> </a>Summary</h1>
<p>I’ve been working on InversifyJS for over a year and it has been an amazing experience.</p>
<p>I believe that InversifyJS a lot of potential and we are just getting started. I hope that the community will continue to grow and I can’t wait to see what amazing stuff the people will build with it.</p>
<p>Please try InversifyJS and let us know what do you think. We want to define a road map based on the real needs of real users and the only way we can do that is if you let us know what you need and what you don’t like.</p>
<p>Remember that you can visit <a href="http://inversify.io/">http://inversify.io/</a> or the <a href="https://github.com/inversify/InversifyJS">GitHub repo</a> to learn more about InversifyJS.</p>
<p>Please feel free to let us know your thoughts about this article with us via <a href="https://twitter.com/OweR_ReLoaDeD">@OweR_ReLoaDeD</a>, <a href="https://twitter.com/WolkSoftwareLtd">@WolkSoftwareLtd</a> and <a href="https://twitter.com/inversifyjs">@InversifyJS</a>.</p>
<p><a href="http://blog.wolksoftware.com/feed">Don’t forget to subscribe</a> if you don’t want to miss it out future articles!</p>