Functional DI in Nodejs for .Net developers
TL;DR=> Don’t have time :)? Checkout this repository. Here you’ll find a comparison between dotnet core and nodejs using dependency injection of the same api.
Have a minute to spare? Let’s check it out together :)!
Background
I started my software development career using C#. During the first 7 years I had different roles but I was always involved with mainly Object-Oriented-Programming and .Net stack (C#+WebApi, Visual-Studio, SQL, Azure, …).
During those years, I felt OOP with .Net was paradise. I couldn’t understand why anybody wouldn’t choose .Net for their application. You want to build a web-api? No problem! Here you have a template that is ready to run. You are creating packages? Nuget is for you. You are a game-developer? Easy, here you have Unity to easily create video-games…
Almost everything was provided out-of-the-box. Easy to setup and run. But, at some point, once my understanding began to grow I started to wonder:
- Why is not everybody using .Net?
- What is exactly happening inside those boilerplate that Microsoft provides?
Then, I had a revelation: Microsoft was doing a great job by hiding the complexity but it was affecting negatively my software-development knowledge and skills. I was not able to do things without Visual Studio :O !
From that point, I decided to better know my tools and also explo re other programming languages. I realized that having all those other languages must meant there was more ways of solving problems and .Net was blinding me about them.
I decided to learn about languages like Javascript and Python and I don’t know you but I only learn by doing … I joined MigraCode (https://migracode.openculturalcenter.org/) an NGO that teaches programming to refugees. It was amazing! All the curriculum is javascript-based. I became main instructor of the back end modules (NodeJs, Postgresql, …) and had to learn everything from scratch and fast.
Also, at that moment I started a new job as DevOps engineer at Ohpen (https://ohpen.com/) and certainly my knowledge was being pushed by my teammates.
The main discussion
At Ohpen our main stack is .Net and we love it :) ! It serves well to create performant web apis with many endpoints. When I started there we were developing serverless apis (apis supported by Apigateway and Lambda in AWS) and some migration was required. At that point, discussions started about different languages and how they compare.
In my case, I strongly advocate for interpreted languages like NodeJs and Python. They are easy to start with and are lightweight by definition (greatly reducing cold-starts). This is great but the team wasn’t sure that NodeJs had the capabilities from .Net in terms of structuring the code. In fact, one of our main concerns was how to manage dependency-injection with NodeJs (even some of us said that it couldn’t be done :O! Fools …). Here we have a list of the most common sentences that were said and my response to them:
- NodeJs allows you to sum bananas with apples:
So? What is the issue there? Javascript is not a strongly typed language like C#. In my opinion, this is beneficial when you are isolating (and deploying) your code as functions. Also, as a developer you should properly test your code so you are sure that you are not “summing bananas with apples”!
- When the complexity of the project increases, NodeJs fails to provide structure:
Hmmm, … maybe. But, do we need “complex” projects now that we are embracing serverless? Why do we need our projects to be complex? In my opinion, writting our bussiness logic as functions should be the least resistance path with the least amount of code.
- OOP is the way to go. Functional programming doesn’t allow proper dependency injection… because there is only functions, so no abstractions.
First, although NodeJs has a strong functional component, you can still code using OOP practices. In fact, you can go with both approaches! And my favorite is FP since allows for the least amount of code.
At that point I realized that we were so used to only work with OOP in .Net and the team saw javascript+FP (Functional-Programming) as something to be scared about. So, I decided to prove myself that NodeJs was (more than) capable of managing dependency injection as good as .Net.
The comparison
I decided to build an API in three different ways:
- Asp.Net core API with C# using OOP.
- Code the same API using NodeJs+Express and OOP.
- Again, using NodeJs+Express and FP.
Asp.Net core
The project in .Net is quite straight-forward. Has a DotnetController.cs (https://github.com/EduardBargues/content-functional-dependency-injection-in-nodejs/blob/main/dotnet/DotnetController.cs) with a couple of dependencies injected using the constructor.
The same happens for the service. It has some dependencies that are injected in the constructor and Asp.Net core takes care to manage them once registered in your Startup.cs (https://github.com/EduardBargues/content-functional-dependency-injection-in-nodejs/blob/main/dotnet/Startup.cs) class.
Asp.Net core abstracts the burden to instantiate and inject implementations on each constructor.
OOP NodeJs
There are many equivalent packages in NodeJs equivalent to Asp.Net but I decided to go with the simplest approach in NodeJs. This is how it looks:
The closest thing to the controller in Express is the index.js (https://github.com/EduardBargues/content-functional-dependency-injection-in-nodejs/blob/main/nodejs-di/index.js) file. Here you see a single endpoint routed to the Api object using the getUser method.
For the sake of completeness, let me show you also the api.js (https://github.com/EduardBargues/content-functional-dependency-injection-in-nodejs/blob/main/nodejs-di/api.js) and service.js (https://github.com/EduardBargues/content-functional-dependency-injection-in-nodejs/blob/main/nodejs-di/service.js) files.
As you can see, the Api class is playing the role of the Startup.cs from Asp.Net core. In the Api constructor, everything is injected and all dependencies are setup. Then each class receives it’s dependencies in the constructor and uses them inside it’s methods.
FP NodeJs
So far, we’ve seen OOP using both Asp.Net core and NodeJs, but what about FP? Let’s give it a go!
The approach I want to follow is:
Each *.js file will export a single function that receives some dependencies. This function, when invoked, will provide the actual set of functions that contain the implementation.
Okay, that sounds weird … Let’s see it with examples :) ! First, the index.js (https://github.com/EduardBargues/content-functional-dependency-injection-in-nodejs/blob/main/nodejs-functional-di/index.js) hasn’t changed much. The only important difference is how the api.js module is consumed. Notice that no constructor is being called. Instead, the api.js module exposes a function and it is simply executed to obtain an json object with a getUserHandler method.
The api.js file (https://github.com/EduardBargues/content-functional-dependency-injection-in-nodejs/blob/main/nodejs-functional-di/api.js) only exposes a single function with no dependencies (no inputs) and returns a specific implementation in the form of a json object with one method getUserHandler.
The service.js (https://github.com/EduardBargues/content-functional-dependency-injection-in-nodejs/blob/main/nodejs-functional-di/service.js) file follows the same approach: one single function that receives it’s dependencies and returns the set of functions with the actual implementation.
Conclusions
So, we developed a REST api following both OOP and FP with C# and NodeJs. If you check the repository and the whole code, you might (would love you don’t :P!) agree with me on the following conclusions:
C# vs NodeJs
- NodeJs/Javascript allows to add the same business value with less lines of code compared to .Net/C#.
- C# includes interfaces which is something interpreted based languages lack. This gives explicit consistency in large projects where many developers are involved since forces them to “code against interfaces, not implementations”.
- C#, together with Asp.Net core, gives a great out of the box solution for dependency injection in OOP but lacks the equivalent on FP (as far as I know).
- NodeJs is much more flexible. This can be seen as an advantage and disadvantage since due to the dynamic type nature of javascript one can do great things or break them easily.
OOP vs FP
- OOP is the way most developers are comfortable with.
- In my opinion, OOP comes with a lot of problems and provides great solutions for each one of them. But, wouldn’t be better to simply not having those problems :)?
- FP pushes the “less-code” paradigm and allows to have the same functional api with less lines of code.
- FP allows you to focus on what really matter. Also, provides an (not intuitive at first) easy way to make your code expressive and elegant.
Personally, I find FP a great way of coding. It simplifies everything :) ! Maybe even too much? What do you think? Agree with me? #HappyCoding!