Designing a better architecture for a Node.js API

Thiago Pacheco on November 02, 2019

Some time ago I made a post about creating a Fullstack project with Node.js, React.js, and MongoDB. This is a very cool starter project that could ... [Read Full]
markdown guide
 
 

Oh the irony! "The rest if that"???
Don't be such a douche bud, especially when you can't do any better. That post is about programming, it's not a spelling bee or a grammar contest. Worse case, you can mention and correct the mistakes, so that he will learn.

You don't have to say that it's a waste of your precious time because nobody gives a damn, and it makes you look like a jerk.

 

I don't have much experience writing anything not even in my native language. I am just trying to share something that could be helpful for somebody.
If you could tell me what is wrong with the article I appreciate, that would help me and others that want to share something.

 

Thanks so much for this article Bro. and please keep up the good work.

Thank you very much Samson, I appreciate it! :)

 

It's the very reason why I use Grammarly 🚀. Grammarly is free if you only want to correct grammatical errors.

 

Is there a grammatical error in my sentence? 😂 The plugin says it is fine 😎

I'm pretty sure it's fine. To me, it's slightly strange when you say "it is" instead of "it's" and when you say "if you want only to" rather than "if you only want to". They're not actually wrong though.

 

Thank you for the suggestion, Grammarly is really amazing and I should have used that in the beginning.

 

Two Grammatical errors does not necessitate this comment, to be honest. Nor does it equal a lack of respect. I'm sure not everything you've ever written has been the height of the English language?

 

I didn't mean to be unkind. Just please get these things checked! :)

 

“I don’t want to read the rest if that, thanks.” Oh the irony.

 

Great article about how to start off a project and how to modularise your code. But it's not about architecting an API. This isn't architecture. Please don't call it architecture, you'll confuse people. If you want to talk about the architecture of an API, at the very least that would require a huge amount more background, a much more complex real-world based scenario, a lot of discussion, and a series of articles with diagrams.

 

Nonsense...so what is your definition of architecture then? Giving background and a real world example over and above what's written here would all of a sudden qualify this post of being worthy of being labelled a architecture discussion? Utter nonsense.

Good article on how to architect your node apps. Thanks Thiago.

 

Architecture isn't how to organise stuff. You don't tell your kid to "go upstairs and architect your room". Architecture is an altogether higher level discipline. As I said, it's a good article. But it's not about architecture.

There is no professional body (especially with regards to JS dev) that will define exactly what "architecture" is and isn't. For me, architecture is a very loose term that can mean many things, code structure being one of them. Personally, when I think "application architecture" then the data model is fundamental and most important - but the code structure is also a part of it (as is choice of technology etc).

I think we might actually agree (that architecture is a loose and general term), I just felt it unnecessarily pedantic to moan about the title of this post when it's perfectly "fine".

"Structuring your Node.js code in a better way" just doesn't have the same ring to it!

 

I disagree. That is one interpretation of an application architecture. However is not the only one. I wrote my Master Thesis on exploring the concept of software achitechture and among the conclusions is that, by necessity, the scope of "the architecture" is not always tangible or strict. It can (but more often is not) be defined for one single functionality, for the database, for the logging, or for every and any part of the application.
The tangible documentation of the architecture is usually referenced on older literature, but modern software solutions have extrapolated multiple layers of complexity and tend to be higher level, thus defining the architecture on a separate set of documents, ideas or mandates is less and less practical (where do we stop if we have an N number of references, do we specify those as well? do we use partial documentation of "obvious" dependencies? what if we need to take over one of those dependencies? where do we stop the abstractions? when is it more pragmatic to make an actual implementation that is self documenting?).
Often architecture is interpreted as "how to organize the project" and for many authors that means the way the project is literally organized on a file system is an implicit declaration of it's architecture. Under that construct, it is completely valid to say that this article defines the application's architecture in it's own realization.
The purpose of my thesis was to explicitly demystify and make the concept of architecture less esoteric, since is supposed to be a tool for a more concrete plan of realization of an application. Another conclusion is that things like a simple diagram could define an architecture and that any author can express it as detailed and using as many tools as the intention (which is express the organization for a purpose) require or was practically desired. Under those circumstances, declaring that this cannot be called architecture is up actually up to the author and whoever receives this information, if it helps clarify how the application works, then definitely serves as the architecture. The recipient of the information cancan request a more concrete definition of any of the parts (but I can hardly find a more concrete way than the code explained). Architecture in software serves the purpose of communication. The tools could be the discussion, articles or diagrams, but that on their own do not exclusively define the architecture.

 

Nice post
However your get() method in the Controller class refers to a method on the service instance also called get() which doesn't exist. Service class has getAll, insert, update and delete methods but not get

 

Thank you for seeing that Ben, I was trying to reduce the functions because the post does was very long but I've forgotten to remove this one too.
I've updated the post now.

 

Typically for architecture related posts, there's a high level diagram of what's happening. I don't see any here. Consider adding one 🙂.

 

Thank you for your suggestion, I am going to add that.

 

Hi can you help me test the API using insomia.
What would be my URL for POST?

Thanks in advance!

Yes done i've already did that, I also tried localhost:5000/api/getAll.

Im getting error below.

Cannot POST /api/post
Cannot GET /api/getAll

 

hey thanks in advance for this tutorial, but I download your repo from github and make this post with postman and dont works, stay Sending request.. and no work, dont return nothing, some advice could you give me ?

 

Hi, are you sending a JSON body in your POST request? Do any errors show up in your terminal?
If you could, show me how you are making the request, please.

 

Dont worry master, my bad because Im begginer and I have no installed mongoDB for that no show nothing,any error or any response, after I installed mongo all works like a charm;otherwise can you help me with other thing? please?, im trying to do this...
import Controller from './Controller';
import PostService from "./../services/PostService";
import RecordService from "./../services/RecordService";
import Post from "./../models/Post";
import Record from "./../models/Record";
const postService = new PostService(
new Post().getInstance()
);

const recordService = new RecordService(
new Record().getInstance()
);

class PostController extends Controller {

constructor(service) {
super(service);
}

async insert(req, res)
{
console.log("usando overwrite");
let response = await this.postService.insert(req.body);
console.log("creando record");
let response2 = await this.recordService.insert({"title":response.slung,"status":"created","post": response });
console.log("creado "+response2);
if (response.error) return res.status(response.statusCode).send(response);
return res.status(201).send(response);
}
}

export default new PostController(postService);

 

Great article but The first image of "Create the server" heading Line no 5 is "app.use(bodyParser.json())" while it should be "server.use(bodyParser.json())"
because there is no variable with name "app".
Thanks

 

That is totally right Aashir, thank you very much for reporting that. I just fixed the post :)

 

Bug: Failing to unlink a file will cause an unhandled rejection.

await new Promise((resolve, reject) => {
  fs.unlink(path, err => {
    if (err) reject(err)
    else resolve()
  })
})

Now the unlinking is awaited as well.

Additionally you don't need the Connection class. Just write the code at the top level.

 

Thank you for reporting that Adrian, actually this part wasn't supposed to be in the code.
I was going to add a file upload functionality too but I realized it would make this post very long and I forgot to remove it all.
And thank you for the solution too, I am going to add this in the next functionalities :)

 

I think express includes bodyParser by default as of 4.16.

 

That is true Sanna, I didn't know that. I am going to run some tests and I am probably going to change these lines on the post. Thank you!

 

Why do i need this structure ? i use normal functional approach.

 

Yes, I've being using a normal function approach for a long time too, but applying design patterns using class is really helpful and easy to replicate/add functionalities across your app, this will make your life easier especially on a big project.
For example, if you need to create a new endpoints with the same common functionalities as a CRUD like we did there you won't need to copy and paste code (respecting CLEAN code), you can just inherit all the functionality you have already created somewhere.

 

neither functional nor OO are normal. Those paradigms merely tools. The author chose to go OO but doesn't mean that a lot of the concepts can be used in the functional way.

 

Nice Article! Anw can you give reason which approach is better when using Class? Is it the export new Class or just make every function static? This is for the case Service and Controllers

 

Thank you Johannes, actually using static functions would be even better in these cases. I am thinking about changing the post with that.

Thank you for coming up with that! :)

 

Very good architecture to start with. You are awesome Sir.

 

Nothing more to add. Great post! You can address server.js in this post. You have mixed up variable name (using "app" instead of "server")

 

OMG you are right Yogesh! Thank you for reporting that. I already updated the post :)

 
 

So I am trying to get the model instance here, but I keep getting cannot overwrite feeds(a model I have) model once compiled. Any help!

 

I ran some tests some time ago and I realize that when you try to get the model multiple times this error could show up because we try to reinitialize the model.

So a quick fix for that is to add a custom function to your model to get only the model and not reinitialize all of it, like the example below:

getModel() {
return mongoose.model("your model name");
}

Let me know if that solves your problem. :)

 

Yes wanted to do this but realized that it will be repeatation of code so I added a functionality to the
getInstance (init =true) {
init && initScheme();
return mongoose.model("your model name");
}

This is way better, nice job man!
I am going to change the structure of this model soon.

 

I just thinking, i can be pros when read this post

code of conduct - report abuse