From a569c3077186234765f7024e498b363f3407f219 Mon Sep 17 00:00:00 2001 From: Benjamin Sigonneau Date: Sun, 1 Feb 2026 15:16:11 +0100 Subject: [PATCH] Improve README (finally) --- README.md | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 72005db..242039d 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,9 @@ endpoints : * `POST /items`: creates an item * `GET /items`: returns the list of items +This was a great opportunity for me to learn more about Clojure. Whatever the +result of the recruitment process, it was really fun working on this assignment! + ## Running and testing This project uses Leiningen. Assuming you already have Leiningen installed, @@ -31,13 +34,85 @@ The source code lies in `/src/yohoho` and is structured as follows: * `routes.clj`: API routes * `schemas.cls`: Malli schemas used for validation -## Library choices +## Library/tools choices -* `reitit`: for handling routes -* `jetty`: web server -* `muuntaja`: JSON handling -* `next.jdbc`: database interface (SQLite) -* `malli`: validation +Since this is just a small assignment, I sticked to simple and proven tools: + +* SQLite for the database (easy to setup, easy to use with `next.jdbc`) +* Leiningen for managing the project (it seems to be getting outdated in favor + of Clojure CLI Tools, but is still widely used and I could find more + documentation) +* Libraries : `reitit` for route handling + `malli` for validation + `muuntaja` + for handling json content. Thanks for the suggestions in the assignment! I + chose `reitit` because it seemed more complete/integrated than Compojure. + However, in the context of this simple assignment, Compojure may have been a + better choice (would have probably been easier to learn) +* Web server: `jetty` (seems to be pretty standard) + +## Comments + +Respect of the assignment: + +* The API features the `POST /items` and `GET /items` endpoints +* `POST /items` accepts a JSON payload, validates it and returns HTTP 400 is + validation fails +* `POST /items` persists data in SQLite +* `GET /items` returns the list of all items as JSON. +* The structure of the items is respected, although it just includes the bare + minimum (id, name, email). +* A data validation library is used (`malli`) +* Unit tests were written (although generated with the help of Claude Code) +* Integration tests were written (although generated with the help of Claude + Code too) +* The API is documented (OpenAPI `/openapi.json` + Swagger UI at `/doc`) + +Divergences from the assignment: + +* The `POST /items` do not take the id in the input. Instead, I prefer to let + the database generate a new id on its own. +* As a consequence, the `id` of an item is an integer, not a string. SQLite can + autogenerate/autoincrement only on a integer id. + +What was not part of the assignment: + +* `GET /ahoy` health check endpoint. As you may guess, this was my very first + endpoint as I was learning how to use `reitit`. I decided to keep it, because + a health check endpoint cannot hurt. +* `GET /item/:id` was included. This was quite easy to add, and also makes sense + since the `POST /items` endpoint follows standard practice of returning a + `Location` header for the newly created item. + +Security: + +* SQL injections: we should be ok since we are not using raw SQL statements in + `db.clj` (`next.jdbc` will use parametrized statements under the hood) +* `POST /items` input has validation +* See the "Desirable improvement" section for some missing security features + +## Desirable improvements + +This project is voluntarily kept simple. If it were to get deployed in +production, the following should be dealt with, in no particular order: + +* `GET /items`: add pagination +* Security: Add rate limiting +* Security: Add authentication/authorization +* Security: Add and configure CORS middleware +* Add logging +* TLS: it's fine that the API is accessible only through http, but it should be + deployed behind a reverse proxy to add TLS/https support. This is quite easy + to do with Apache, Nginx or Caddy. +* Database: use a migration system. This was definitely unnecessary for this + assignment, but should be used for a more serious project. Migratus seems to + be the de-facto library for this. +* Database: switch to a more serious database (PostgreSQL comes to mind), add + connection pooling, use transactions. +* Add metrics (request rate, response time, database connection + pool stats, etc.) and monitoring (eg. using Datadog). +* Configuration: add the ability to override deffault configuration using a + dotenv file and/or environment variables. +* Add a supervisor to ensure the API keeps running (could be as easy as using + systemd, or as complex as deploying with kubernetes) ## Documentation links