What are DTOs and their significance?
Published: 2024-06-20 19:49:51

What's up amazing people 👋

I just wanted to talk a lil bit about the concept of DTOs in programming and how they might be useful and significant in your code.

So, what is a DTO? Well, it stands for Data Transfer Object. It is basically defining an interface for various types of data transfers within a system. Some examples are: typescript interfaces which we use in our typescript code, mongoose schemas, etc.

DTOs make it easier to identify the flow of data between functions, services, modules and components of our application. Having the structure of data clear makes it easier to understand code, apply validations on data, identify unintentional flow of sensitive information and easier to document the code.


Let's take an example of our simple Node.js application and implement a simple API controller first without using DTO and then using DTOs. Later we will compare both of the strategies.

### Basic API example without using DTO

```js
const express = require("express");
const app = express();

// controller without using DTO
async function getUserData(req, res) {
	const username = req.query.username;
	const key = req.query.key;
	if (!username || !key) {
		return res.json({ success: false, info: "Invalid parameters!" });
	}

	// process user data
	// may be from your database
	// like db.get(users, {username})
	const userData = {
		name: "XYZ",
		age: "23",
		// ... more data
	};

	return res.json({ success: true, data: userData });
}

// route
app.get("/user", getUserData);

app.listen(5000, () => console.log("SERVER LISTENING ON 5000"));
```


This is a very basic API implementation in Nodejs using express, right?

### Let's try implementing the same with a DTO object.

```js
const express = require("express");
const app = express();

class UsernameQueryDTO {
	username;
	key;
	constructor(query) {
		this.username = query.username;
		this.key = query.key;
	}
	isValid() {
		if (
			!this.username ||
			this.username.length < 5 ||
			!this.key ||
			this.key != "your_secret_key"
		) {
			return false;
		}
		return true;
	}
	get() {
		return { username: this.username };
	}
}

// controller using our DTO object
async function getUserData(req, res) {
	const query = (new UsernameQueryDTO(req.query)).get();
	if (!query.isValid())
		return res.json({ success: false, info: "Invalid parameters!" });

	// process user data
	// may be from your database
	// like db.get(users, {username: query.username})
	const userData = {
		name: "XYZ",
		age: "23",
		// ... more data
	};

	return res.json({ success: true, data: userData });
}

// route
app.get("/user", getUserData);

app.listen(5000, () => console.log("SERVER LISTENING ON 5000"));
```
You can clearly see now we are easily able to:

- define validations. 🤨
- see the structure of incoming data. 📊
- determine sensitive data such as secret key is filtered beforehand (you can see our get function only returns the username). 🔒
- understand the flow of data and document the APIs more effectively as we already have the data defined. 📏

I hope you got the point now !! 
Now I leave it up to you as a task to define a DTO class for the response object as well and post it in the comments 💬.

That was it guys, Thankyou for reading the blog and if you like my work you can follow me here 😃

See you next week with a new blog :)