Clean Code Architecture With Node.js and TypeScript
This architecture is created by Robert C. Martin (Uncle Bob). Like most architectures, it also aims to make the application more flexible to inevitable changes in client requirements.
Each circle (ring) represents an isolated layer in the application. The dependency direction is from the outside in. Meaning entities don’t know about use-cases, use-cases don’t know about controllers and controllers don’t know about external interfaces. Let’s see each layer briefly.
Entities — Refers to business rules and usually represented as plain classes.
Use Cases — This is where our application business logic lives.
Controllers — “ This layer is a set of adapters that convert data from the format most convenient for the use cases and entities to the format most convenient for some external agency such as the Database or the Web.” — Robert C. Martin
Frameworks — “This layer is where all the details go. The Web is a detail. The database is a detail. We keep these things on the outside where they can do little harm ” — Robert C. Martin
In this section, we’ll build a simple rest API that creates, updates, read and delete course with typescript.
Our API needs to support the following use cases
- Create Course
- Delete Course
- Fetch Courses
- Update Courses
- Fetch Single Course
This Layer depends on the repository meaning we can mock the repository for testing, this is a huge advantage.
The controller is an adapter and we don’t want any business logic here, only data formatting logic.
This layer includes all our specific implementations, such as the database. In our API we used memory storage but since other’s layers don’t depend on this layer it can easily be changed to use MongoDB or other options.
Our use cases depend on contracts instead of implementation. These contracts need to be satisfied via dependency injection at runtime.
In this series of articles, we’ve tried to see what is clean code architecture and how to implement it with TypeScirpt decoupling our logic from frameworks. This way we are able to write robust code that is easily testable and flexible.
Full code can be found here.