Portabilité et maintenabilité des fonctions ServerLess

Photo by Luca Bravo on Unsplash

Je pense qu’il est important de limiter l’adhérence pour assurer la portabilité du code, simplifier sa maintenabilité et garantir sa testabilité.

Comme vous le verrez ci-après, la structure minimale d’une fonction pour chaque provider est relativement simple.

Structure d’une Azure Function:

import json
import azure.functions as func

def main(req: func.HttpRequest) -> func.HttpResponse:
body = req.get_json()
return func.HttpResponse(json.dumps(body), status_code=200, mimetype="application/json")

Structure d’une fonction AWS Lambda:

import jsondef handler(event, context):
body = event.get('body')
return dict(
statusCode=200,
headers={"Content-Type": "application/json"},
body=json.dumps(body)
)

Structure d’une Google Function :

import jsondef echo_http(request):
body = request.get_json(silent=True)
return json.dumps(body), 200, {'Content-Type': 'application/json'}

Nous allons développer un exemple de fonction Azure qui sera exécutée lors d’un appel HTTP et sera chargée de consommer un web-service externe.

import json
import requests
import azure.functions as func

def main(req: func.HttpRequest) -> func.HttpResponse:
body = req.get_json()
search_id = body.get('id')
url = f"https://jsonplaceholder.typicode.com/posts/{search_id}"
resp = requests.get(url)
data = json.dumps(resp.json())
return func.HttpResponse(data, status_code=200, mimetype="application/json")

Avec l’exemple ci-dessus, si je veux tester unitairement la partie métier de mon code, c’est à dire, la consommation d’un web-service externe, je suis obligé de tester la totalité de la fonction Azure.

Maintenant, nous allons déplacer le code métier dans une librairie externe et charger cette librairie dans la fonction Azure. (Les librairies métiers, hors contexte du serverless devraient se trouver dans un projet externe indépendant avec un cycle de vie différent)

# libs/web_consume.pyimport json
import requests
def get_post(search_id: str) -> str:
body = req.get_json()
search_id = body.get('id')
url = f"https://jsonplaceholder.typicode.com/posts/{search_id}"
resp = requests.get(url)
return json.dumps(resp.json())

Adaptons maintenant notre fonction pour utiliser cette librairie:

import azure.functions as func
from libs.web_consume import get_post
def main(req: func.HttpRequest) -> func.HttpResponse:
body = req.get_json()
search_id = body.get('id')
data = get_post(search_id)
return func.HttpResponse(data, status_code=200, mimetype="application/json")

Qu’avons nous gagner en sortant la partie métier du code ?

  • Je peux réutiliser le module web_consume.py dans une autre fonction Azure mais aussi dans AWS Lambda ou Google Functions.
  • Je peux tester la fonction get_post() indépendament d’Azure Function

Nous n’avons survolé que des fonctions serverless, liés au protocole HTTP mais si nous prenons des exemples avec des évènements liés à une queue AWS SQS ou une entrée Azure CosmoDB, limiter l’adhérence est plus difficile mais pas impossible.

Dans un prochain article qui sera orienté sur les tests unitaires de fonctions Azure, nous pourrons mettre en pratique ce découplage avec des exemples d’utilisation de queues de messages.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store