Description
This can be solved in a very readably way by calling the implementation.py functions from storage.py. This way the exception handling only need to be written once. This also allows for computed arguments for the implementations.py functions as well as using their return data, which may or may not be needed. But this is apparently bad practice, thus it is a problem.
Consider the following example, where a User
can have multiple Project
s, which in turn can have one or multiple Goal
s. When returning a goal, we have to check that the Project
and User
ids provided exist and are correct. Sure, you can maybe skip doing this with project id and just use user id, but this problem will anyway, one way or another occur when creating, editing or deleting Goal
s. The implementation.py
file will then look something like below. Note that the handling of the exceptions are rewritten, because when we're getting Project
we need to check that the user is correct, and when getting a Goal
, we need to check that the Project
and User
exist or are correct.
def get_project(project_id: int, user_id: int) -> models.Project:
try:
with get_connection() as con:
storage.get_goal(con, project_id, user_id)
except ProjectNotFoundException:
raise ...
except UserNotCorrectException:
raise ...
def get_goal(goal_id: int, project_id: int, user_id: int) -> models.Goal:
try:
with get_connection() as con:
storage.get_goal(con, goal_id, project_id, user_id)
except GoalNotFoundException:
raise ...
except ProjectNotFoundException:
raise ...
except UserNotCorrectException:
raise ...
We might solve this by calling the implementation functions from the router.py
file as exemplified below. But this will get messy if we want to use the return data to avoid querying the database multiple times for the same thing. This is however, probably best practice when possible for now.
@router.get(
'/project/{project_id}/goal/get/{goal_id}/',
summary='Returns a goal based on id',
response_model=models.Goal,
)
def get_goal(goal_id: int, project_id: int, user: User = Depends(get_current_active_user)) -> models.Goal:
impl.get_project(project_id, user.id)
return impl.get_goal(goal_id)
Might be possible to solve by modifying get_connection()
.