• Software
  • Cookbook
  • Software
  • Cookbook
  • Home
  • Rand
    • Minecraft Sucks
  • Docs
    • SPA Deployments in AWS
    • Minecraft Server Administration
    • Test Harness for Postgres Integrations
    • Enterprise REST API
  • Cookbook
    • Cookies
    • Muffins
    • Pasta

Enterprise REST API

Layered solution based on patterns established by Martin Fowler.

“Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice” - Christopher Alexander

Why would you want this?

Business software encodes business logic. That logic needs to be exposed (typically over http) to various agents. REST APIs have become a somewhat defacto solution, and Martin Fowler does a pretty good job of establishing a set of concerns. I like this.

Solution

Basically, the system is divided into layers allowing the developers to better reason about a single domain. For example, units of business logic are each defined as a service allowing them to be tested against known inputs by mocking the data-access layer below. The image represents the mental model, with requests coming in from the left, travelling through the layers ultimately arriving at the center (database) before returning some agreed upon data back up to the layer above in this case terminating the HTTP connection.

layer diagram

Understanding The Template

If unfamiliar, Patterns of Enterprise Application Architecture defines the three Primary Layers roughly as Presentation, Domain, and Data Source. The Primary Layers are meant to be further subdivided into more refined layers that may or may not subscribe to some Pattern.

This whole project represents the Domain Primary Layer, and its sub-layers implement a basic Transaction Script Pattern. From the text "A Transaction Script (110) is essentially a procedure that takes the input from the presentation, processes it with validations and calculations, stores data in the database, and invokes any operations from other systems".

Based on this, we'll define the sub-layers from left to right as:

Naming here is somewhat arbitrary so I've provided better definitions below.

   Interface

Various implementations for dealing with HTTP. Express and Lambda examples are currently provided for both server + serverless deployments. Describes routes and configures Middleware.

   Middleware

Early validation and request parsing. HTTP header configs. Error handling. Contextualizes the request to ensure the Controller can do work.

   Controller

Refined validation and transformations. Main responsibility is transforming user input in order to call a service.

   Service

The business logic. Will call repository functions based on the input recieved.

   Repository

A collection of operations available for a particular Model.

   Model

Programmatic representation of a Data Source.

Extending the Template

The benefits of a layered architecture are numerous, high on the list being testability. By isolating layers to their nearest neighbours we can easily spoof input and mock the layer below, testing each in turn achieving high levels of coverage and discrete "units".

The downsides of a layered architecture are more tedious. If I want to add a new Data Source and view it in the Presentation, I need to add the new bits to every layer in between. We should be liberal factoring code.

   Data Source

The database in the project is just a SQLite database in memory. It resets everytime you start the project which you can see by calling the POST /counter/increment/:id endpoint where :id is a valid v4 uuid.

   Interface

The project has examples for both Express and Lambda configurations.

   ORM

The DDL for the project is defined right in the database class declaration, and there is only a single model. To keep it simple the project takes no stance on how you should model your Data Source but an ORM may be a reasonable choice for you. My preference is db-migrate which concerns itself with migrations and nothing else. I write SQL files to create all of my tables and manually create the types. The Repository layer becomes a collection of queries and query building functions typically leveraging pg-format or something similar for sanitization.

Template Setup

   Clone the repository.
   Prerequisites
  • Node 18 or higher
   Install Dependencies
$ yarn
   Run Express Interface
$ yarn express
   Test
$ yarn test
Prev
Test Harness for Postgres Integrations