Improve README (finally)
This commit is contained in:
87
README.md
87
README.md
@@ -9,6 +9,9 @@ endpoints :
|
|||||||
* `POST /items`: creates an item
|
* `POST /items`: creates an item
|
||||||
* `GET /items`: returns the list of items
|
* `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
|
## Running and testing
|
||||||
|
|
||||||
This project uses Leiningen. Assuming you already have Leiningen installed,
|
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
|
* `routes.clj`: API routes
|
||||||
* `schemas.cls`: Malli schemas used for validation
|
* `schemas.cls`: Malli schemas used for validation
|
||||||
|
|
||||||
## Library choices
|
## Library/tools choices
|
||||||
|
|
||||||
* `reitit`: for handling routes
|
Since this is just a small assignment, I sticked to simple and proven tools:
|
||||||
* `jetty`: web server
|
|
||||||
* `muuntaja`: JSON handling
|
* SQLite for the database (easy to setup, easy to use with `next.jdbc`)
|
||||||
* `next.jdbc`: database interface (SQLite)
|
* Leiningen for managing the project (it seems to be getting outdated in favor
|
||||||
* `malli`: validation
|
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
|
## Documentation links
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user