Your IDE helps if you help the IDE - example
Tags: javascript, beginners, cleancode, node
Published: 2021-11-24 15:49:48

I have written previously about a clean code angle I rarely read about: [writing code with the available coding tools in mind](https://dev.to/latobibor/how-spaghetti-code-comes-back-solving-the-wrong-class-of-problems-49bg).

This is a change in viewpoint.

> Instead of scraping together the easiest to write code possible you think about how much the coding tools (particularly your `IDE` or `typescript` transpiler) are going to be able to make use of it.

If this sounds alien to you I have found recently a seemingly innocent thing that can actually lead you to problems.

Let's say you want to start up a `koa` server using `routing-controllers` library. You have `controllers`, `middlewares`, `interceptors`...

Also you have two options: add these functions as an array or add the directories and `createKoaServer` function will look it up for you.

Now let's say you have an `errorInterceptor`.
```javascript
// 'interceptors/error-interceptor/index.js'

export function errorInterceptor() { /* ... */ }
```

And then you go with the option to specify the directories:
```javascript
import * as path from 'path';
import { createKoaServer } from 'routing-controllers';

const app = createKoaServer({
  controllers: [path.join(__dirname, 'controllers/**/index.js')],
  middlewares: [path.join(__dirname, 'middlewares/**/index.js')],
  interceptors: [path.join(__dirname, 'interceptors/**/index.js')]
});

export { app };
```

We really went _future-proof_ by loading all `middlewares`, `controllers` and `interceptors` right out of their damn directories?

All fine, but _later_ some other dev would come tracking down a problem: _"Maybe `errorInterceptor` is not running?"_ 🤔.

So they would go and use `Find Usages` option in their `IDE`.

...And it says _"No usages"_. Then they search for `errorInterceptor` and only find the definition.

_"Well then, it seems it really was dead code! Let's delete it then!"_

And then all hell breaks loose.

Or you don't delete it, you might be annoyed to have one file in one folder and you find it wasteful, so you just rename `index.js` -> `error-interceptor.js` and move it up one folder to `interceptors/error-interceptor.js`...

All these will break things and you won't know it until you press `Run` button.

### The **Pros** and **Cons**
**PRO:** We do not need to think about ever adding a new middleware/controller or cleaning it up.
**CONS:** Your IDE will say none of these are ever used, the `typescript` transpiler won't help you if you ever use the wrong format and so on... You have essentially turned off all automatic safe-guards. Only tests can save you.

Personally I find any **pre-runtime checks** very useful and if I have two solutions I would prefer the one that has more of them.

> Runtime is a "weird quantum state" where we do not know what is there until we get there: the more we push into this realm that less our coding tools will help us find the landmines before we step on them.

### What if we take the other option and pass the items ourselves?
The `error-interceptor/index.js` file stays where it is and - as an effort to preserve the "future-proof"-ness of the previous solution - let's create a new file in the `interceptors` folder:

```javascript
// `interceptors/index.js`
import { errorInterceptor } from './errorInterceptor/.';
import { otherInterceptor } from './otherInterceptor/.';

export const interceptors = [errorInterceptor, otherInterceptor, /* ... */];
```

Somewhere else in the file that creates the server:
```
import { createKoaServer } from 'routing-controllers';
import { interceptors } from './interceptors/.';

const app = createKoaServer({
  interceptors: interceptors,
  // controllers: controllers, 
  // middlewares: middlewares
});

export { app };
```
👍

#### **PRO**s and **CON**s
**PRO**s: 
- Our `IDE` and `typescript` will now know about the usages of our functions
- It can warn us when we delete/refactor
- If we move around the `controllers`/`middlewares`/`injectors` we can use our `IDE` to update the paths for us...

**CON**s:
- you might need to type a little (but not too much)

I think there is a clear winner here.

### _"But what if I have 50+ controllers?"_
In this case you also want to group them I guess into smaller folders, let's say:

```
\controllers
   \user-controllers
      \login
      \logout
      \...
      \index.js
   \product-controllers
      \add
      \remove
      \...
      \index.js
   index.js
```

In this solution `user-controllers\index.js` loads, groups into an array an exports all of the controllers from the folders:

```javascript
// controllers/user-controllers/index.js
import { login } from './login';]
// ...

export const userControllers = [login, logout, /* ... */];

// ------
// /controllers/index.js
import { userControllers } from './user-controllers';
import { productControllers } from './product-controllers';

export const controllers = [...userControllers, ...productControllers, /* ... */];
```

Finally where we create the server can stay simple while we boxed away really long imports/exports in neat, easily readable files.

### Summary
When you have options to choose from you should choose the solution that **works better with the coding tools** you have: you get back what you feed them. Feed them love and care and they are going to save you when you need them, feed them negligence and they won't help you.

🙃