Why We Built Drash
Tags: deno, drash, typescript, webdev
Published: 2020-07-11 12:50:15

Hi, my name is Eric Crooks. I'm one of the founders of Drash. In this article, I talk about what Drash is and why I decided to build it with one of my colleagues. Before diving into this article, know that all statements made are by me and all opinions are my own.

## Table of Contents

* [What is Drash?](#what-is-drash)
* [Why was Drash built?](#why-was-drash-built)
    * [Problem 1: Syntax](#problem-1-syntax)
    * [Problem 2: Debugging](#problem-2-debugging)
    * [Solutions to the problems](#solution-to-the-problems)

## What is Drash?

[Drash](https://drash.land/drash) is a REST microframework for Deno's HTTP server. It has zero dependencies outside of Deno's Standard Modules. It is designed to help you build your projects quickly -- APIs, SPAs, etc. 

## Why was Drash built?

Before Deno, I used Node and Express. Express was great, but I found issues with the development experience. Mainly, I had issues with the syntax and the time it took to debug issues. More code meant an exponential increase in duplicated code and debugging time. I wasn't a fan of that fact.

### Problem 1: Syntax

Take a look at the code below. You might be familiar with the syntax.

```javascript
app.get('/', function (req, res) {
  res.send('GET request received')
})

app.post('/', function (req, res) {
  res.send('POST request received')
})

app.put('/', function (req, res) {
  res.send('PUT request received')
})

app.delete('/', function (req, res) {
  res.send('DELETE request received')
})
```

This syntax is great for small applications. It's not so great for larger applications. I found that a large Express application comes at cost. That cost is the degradation of the developer's experience when writing code. The above code looks great, is easy to write, and helps you get started quickly. However, look at how much code is duplicated.

* The `req` and `res` objects are passed in multiple times for each route you define
* The `/` route is defined multiple times
* The `app` object is used multiple times

This led me to ask myself the following:

* Why can't the callback function that is passed into the route handler have the `req` and `res` objects readily available using `this.req` and `this.res`?
* Why do I have to keep using `app.`?
* Why do I have to define the `/` route one time for each HTTP method?

I'm lazy and don't want to have to write something multiple times if I don't have to. What I wanted was something like this:

```javascript
app.route('/')
  .get(() => {
    this.res.send('GET request received')
  })
  .post(() => {
    this.res.send('POST request received')
  })
  .put(() => {
    this.res.send('PUT request received')
  })
  .delete(() => {
    this.res.send('DELETE request received')
  })
```

That syntax looks much better in my opinion and it's easy to write. You take the `app` object, define a route, and define the allowed HTTP methods for that route.

### Problem 2: Debugging

In a larger Express application, your filesystem might be split up so that your front-end and back-end are organized in a way to help you identify where code lives. For example, your filesystem might look like the following:

```
app/
|-- assets/
|   |-- js/
|       |-- api.js
|       |-- another-js-file.js
|
|-- views/
|   |-- index.html
|   |-- another-view-file.html
|
|-- src/
|   |-- controllers/
|   |   |-- home-controller.js
|   |   |-- user-controller.js
|   |   |-- order-controller.js
|   |
|   |-- services/
|   |   |-- user-service.js
|   |   |-- order-service.js
|   |
|   |-- routes.js
|
|-- app.js
|-- package.json
```

Let's take the above example code and see why debugging is an issue with it. Inside of `api.js`, we see the following code and there's an issue with it:

```javascript
axios.get("/users/1")
  .then((response) => {
    // code to handle the response
  })
  .catch((error) => {
    // code to handle the error
  });
```

For some reason, the back-end isn't returning what's expected. So let's take a look at the back-end. All we know is `/users/1` is the route we need to start with. So let's go to our `routes.js` file and see what controller is mapped to the route. We see the following:

```javascript
app.get('/users/:id', UserControllerGet);
app.post('/users/:id', UserControllerPost);
app.put('/users/:id', UserControllerPut);
app.delete('/users/:id', UserControllerDelete);
```

Ok, now we know that the `UserControllerGet` function is mapped to the `GET /users/:id` route. This looks promising because `/users/:id` matches the front-end's API call to `/users/1`. Let's go to the `UserControllerGet`:

```javascript
function UserControllerGet(req, res) {
  res.send(userService.getUserDetails(req.params));
}
```

Now we're at the `UserControllerGet` function and see that the response being created comes from `userService.getUserDetails()`. So let's go to that file. Actually, let's not. This is too much sifting through code just to figure out where issues are occurring.

This debugging process led me to ask myself the following:

* Do I have to go through this process every time I debug something? I have to look at the front-end API call, match the route to one of the routes defined in the routes file, and then go from there?
* Why can't I just assume `/users/*` maps to a single `UserController` file and look in that file?

What I wanted was to remove the routes file completely and have:

```javascript
// File: user-controller.js

app.route("/users/:id")
  .get(() => {
    this.res.send(userService.getUserDetails(req.params));
  })
  .post(() => {
    // POST code
  })
  .put(() => {
    // PUT code
  })
  .delete(() => {
    // DELETE code
  })
```

Again, you take the `app` object, define a route, and define the allowed HTTP methods for that route -- all in a single file.

So, how would I solve the syntax issues? How would I solve the debugging issues? Should I rewrite my code to make it work the way I want to? I mean, Express is unopinionated, so I could do that, but why not just create something that makes more sense? Why go with controllers? Why can't we go with [resource](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Identifying_resources_on_the_Web)-based logic? Some frameworks (e.g., Laravel) use resources and they kind of make sense. I had so many questions and in the end I decided to plan out a new framework with my colleague: Drash.

### Solution to the problems

Instead of having `app.get()`, I figured it'd make sense to have a class with HTTP verbs ...

```typescript
export class MyController {

  public GET() { ... }

  public POST() { ... }

  public PUT() { ... }

  public DELETE() { ... }
}
```

... and then you'd plug this into your application in some way. I wasn't sure at the time, but I figured it'd look something like:

```typescript
import { MyController } from "/path/to/my_controller.ts";

const app = new App({
  controllers: [MyController]
})
```

What about the route definitions? Where do those go? I figured it'd be best to have the controller be in charge of the routes clients can use to target the controller. Like so:


```typescript
export class MyController {

  public paths = [
    "/my-controller",
    "/my-controller/:some_param"
  ];

  public GET() { ... }

  public POST() { ... }

  public PUT() { ... }

  public DELETE() { ... }
}
```

With "resources" in the back of my mind and its definition, I figured the controller should just be named a resource. This is how they do it in Tonic (the PHP microframework). Everything in Tonic is a resource. Resources are PHP classes; and resources define their own paths. So now we have something like this:

```typescript
export class MyResource {

  public paths = [
    "/my-resource",
    "/my-resource/:some_param"
  ];

  public GET() { ... }

  public POST() { ... }

  public PUT() { ... }

  public DELETE() { ... }
}
```

This looks great! Also, it solves the debugging issue. If I had a front-end that called `/my-resource/something`, I would already know to go `MyResource` because the URI should be mapped to a `MyResource` resource. Same thing goes for a `/users` API call. `/users` should map to a `UsersResource`.

What about the `req` and `res` objects? I figured it'd be best to instantiate a resource class and pass in the `req` and `res` objects in its constructor. That would give all of the resource class' methods access to the `req` and `res` objects without having to pass them in like in Express. This would also mean a `BaseResource` class would need to be used so that the resource classes that developers define wouldn't require the constructor. So, now we have something like this:

```typescript
// File: base_resource.ts

export class BaseResource {
  public resource;
  public response;
  constructor(request, response) {
    this.request = request;
    this.response = response;
  }
}
```

```typescript
// File: my_resource.ts

import { BaseResource } from "/path/to/base_resource.ts";

export class MyResource extends BaseResource {

  public paths = [
    "/my-resource",
    "/my-resource/:some_param"
  ];

  public GET() {
    this.request.doSomething();
    this.response.doSomething();
  }

  public POST() { ... }

  public PUT() { ... }

  public DELETE() { ... }
}
```

You might notice the change of the `req` and `res` names to `request` and `response`. I believe we should be explicit in our code so that newcomers don't question things like variable names.

After a few months of developing around the definition of [resources](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Identifying_resources_on_the_Web) with the syntax being the first thing considered (for a better developer experience), Drash was born. Originally, it was developed with an Express-like syntax, but maintaining that was a nightmare. This was especially true when trying to handle `this.request` and `this.response` in chained functions. So, Drash was forced to be different, and I think that's ok because most of its logic is backed by definitions in the MDN.

Hope you enjoyed reading this! I figured it'd be nice to give some insight into Drash.

-- Eric