API Implementation

Let's imagine ...

You are a developer in a startup company that wants to create a web application for doctor's office.

Always begin with users needs

Let's imagine we did some user research with doctors, and we learned that their first basic needs are:

When a patient comes to their office for the first time, they need to be able to:

  • Create a new patient record
  • Update the patient record
  • Delete the patient record
  • Search for a patient by one or several criteria (name, surname, date of birth, social security number)
  • List all patients

Let's create the associated User Story and Acceptance tests

User Story

As a doctor Thomas
I want to keep records of my patients
So that I can access them later

Acceptance Criteria

Behavior Driven Development

Acceptance Criteria

Gherkin Syntax

Example:

Feature: Patient management

Scenario: Create a patient
Given I am a doctor Thomas  
When I create a patient John Doe with the social security number 123456789012345  
Then I should be able to find it in the list of patients

We will not implement those tests because this is beyond the scope of this training.
However, this is a good practice to at least define them, to help us understand the business domain.

Design the API Spec

We would start by designing our API, this way the development of the Frontend and Backend can be done simultaneously.
It also allows us to discuss and refine our understanding of the business domain.
If during implementation, it needs to be changed, it is possible, but it needs to be discussed with every one involved.
We already did this last time using Apicurio.

Let's implement the API in our backend using Python

Pre-requisite:

  • An IDE of your choice (Pycharm, VSCode, ...)
  • Python installed on your machine
  • virtualenv installed on your machine

Let's bootstrap a virtual environment

In python, it is good practice to work with virtual environments in order to isolate the dependencies of each project.

  • Go to the directory of the project we already created.
  • Create a virtual environment: virtualenv -p python3 myenv
  • Activate the virtual environment: source myenv/bin/activate
  • You can later install dependencies: for example: pip install flask or pip install -r requirements.txt

Notes:

  • The virtual environment is not pushed to git, so you will need to recreate it on each machine you work on.
  • Some IDEs can create and manage virtual environments for you.

Let's implement the API in our backend using Python

Project structure

As discussed previously, the project structure should be organized by your business domains.
Therefore, we could for example have a patients directory.

/
├── patients

Hexagonal Architecture

hexagonal architecture

  • The idea is to separate the business logic from the technical details.
  • The mose important thing is that the dependencies are always pointing inwards.

Hexagonal Architecture

When doing hexagonal architecture, we can have the following structure:

/
├── patients
│   ├── application // User Side
│   ├── domain // Business logic
│   ├── infrastructure // Storage, external services, ...

Start by implementing the domain, from the point of view of the caller

We always try to put ourselves in the shoes of the caller, and start by implementing the domain from his point of view.

In our case, the caller is the application layer, so we will start by implementing the PatientService class, inside the application directory.

Test Driven Development

tdd cycle

  • Write a test (that fails)
  • Implement the code to make the test pass. And only the code to make the test pass.
  • Refactor the code
  • Repeat

Bootstrap

You can find the bootstrap of the project here.
The creation of new Patients is already implemented, you can use it as a reference to implement the other features.

Note: This is not a perfect implementation of the hexagonal architecture, but it is a good start.

Assignment

You should implement the REST API spec we designed previously.

  • Create a new patient
  • Update a patient
  • Delete a patient
  • Get a patient by id
  • Search patients by criteria
  • List all patients
  • List all patients with pagination

Push your work to the repository previously created.

Bonus

Document your API using Swagger (OpenAPI)

``` / ├── patients │ ├── application // User Side │ │ ├── __init__.py │ │ ├── patient_resource.py │ │ ├── patient_service.py │ ├── domain // Business logic │ │ ├── __init__.py │ │ ├── patient.py │ ├── infrastructure // Storage, external services, ... │ │ ├── __init__.py │ │ ├── patient_repository_memory.py │ │ ├── patient_repository_mongodb.py │ ├── __init__.py ├── __init__.py ├── main.py ├── requirements.txt ```