I am working on a project that generates an API with the possibility of doing CRUD operations based on a high-level description of the resources that the user would like to have in an application. In the process of generating the code, multiple steps have to be taken (for some context, I am generating Python code from Python with Jinja2):
- Generating code that handles the connection with the database
- Generating Dockerfiles
- Generating Pydantic Models for the input resources
- Generating classes that link the application to a database using SQLAlchemy models
- Generating methods that facilitate CRUD operations on the database's tables
- Generating the API code
Almost all of the operations depend on the input from the user but are not directly linked in any way, so they could even be executed in parallel.
Researching for ways of how to properly handle sequential operations I have found the Chain of Responsibility pattern, but it does not really apply in my situation as I have to execute all of the steps regardless of the user input (as long as it's a valid input).
I have also thought of something like the Strategy pattern for each generation process, but I'm having a hard time deciding if any of these patterns is a right fit for my situation.
Currently I have structured my code in the following way:
- I received the input and check for several conditions to be met (validations)
- I process the input and change it dynamically to adjust it for the following steps
- I execute the following steps in a procedural manner, one after the other.
r = RelationshipHandler(Input(**res).resources)
r.execute()
resources = [resource.dict() for resource in r.resources]
generate_connection()
generate_db_create_code(resources)
generate_docker_compose()
generate_pydantic_models(resources)
generate_sqlalchemy_classes(resources)
generate_model_code(resources)
generate_fastapi_code(resources)
All of these operations are executed by an orchestator/choreographer - which would basically imply that I'm at least using an extremely simple version of the Choreography pattern (more common in the context of microservices).
My question is: how are situations like this handled in general? What patterns or best practices would make the code be more clean/readable/logical and easier to maintain?
I am aware that there might be multiple ways of handling situations like the described one, I am just trying to find other, more elevated ways of solving the same problem.