Controller-Service-Repository Pattern #63
Replies: 2 comments 6 replies
-
@TylerMatteo how closely does this follow what you had in mind? (After we get these responsibilities sorted out, we can refactor the existing code. And once we have the code refactored, we can start to implement tests of each component) |
Beta Was this translation helpful? Give feedback.
-
Adding for posterity - I stumbled up on this SO thread that I think summarizes thoughts on what sort of exceptions ought to go at which layer of the architecture: https://softwareengineering.stackexchange.com/questions/393307/where-would-you-handle-exceptions-controller-service-repository. This doesn't necessarily describe the approach we're taking now, just documenting the research. |
Beta Was this translation helpful? Give feedback.
-
Description
We are generally moving toward a controller-service-repository pattern. However, we may have different understandings of where to draw the lines between each of these components. This discussion will give a brief overview on the responsibilities of each component and then go through an example endpoint, detailing where to draw the lines between each component.
Discussion strategy
This top-level comment will hold the latest consensus among the participants. As comments are added, this comment will be updated to reflect the changed consensus
Architecture overview
Controllers
Controllers are responsible for routing traffic. They accept incoming routes and inspect the http methods used on that route. Based on these routes, they match the request to the necessary service. Based on the result of the service function, they also return the appropriate response- to include the appropriate status code and body.
Repositories
Repositories are responsible for interacting with databases. Transactions and queries should be held within the repository. In drizzle, we can also create prepared statements with placeholders to improve performance.
Services
Services handle the "business logic" of the application. They often coordinate requests from controllers with results from repositories. If a repository response needs to be formatted to meet an api-specific structure, it should be transformed in the service
Endpoint
The
tax-lots/<bbl>/geojson
andtax-lots/<bbl>/zoning-districts
endpoints provide an opportunities to explore how these responsibilitiestax-lots/<bbl>/geojson
tax-lots/<bbl>/geojson
accepts a get method and 10 character url parameter (the bbl). The controller will listen for these two pieces of information. It will call the appropriate service function with the bbl parameter. The service will check the bbl is valid. If it is invalid, the service will throw an error that will bubble up to the controller. The control will detect this error and return a corresponding 400 error response. If it is valid, the service will then call the repository.The repository will make a request to the database. If an error occurs during the request, the repository will catch and rethrow an error that will bubble up to the service. The service will also rethrow an error. Finally, the controller will catch this error and return a corresponding 500.
If the repository successfully makes its request, it will return the data as-is (no transformations). If there are no rows in the response, the service will throw an error. The controller will catch the error and return a corresponding 404. If there is a row in the response, the service will structure the raw response to meet the required format and then return it to the controller. The controller will return the data as the body of a 200 response.
The spatial data requires two operations during its processing- a database
ST_AsGeoJSON
and a JSJSON.parse
. The repository will contain theST_AsGeoJSON
. The service will apply theJSON.parse
tax-lots/<bbl>/zoning-districts
tax-lots/<bbl>/zoning-districts
accepts a get method and 10 character url parameter (the bbl). The controller will listen for these two pieces of information. It will call the appropriate service function with the bbl parameter. The service will check the bbl is valid. If it is invalid, the service will throw an error that will bubble up to the controller. The control will detect this error and return a corresponding 400 error response. If it is valid, the service will then call the repository.The service will make up to two calls to the database. The first call is a check of whether the selected tax lot exists. If the repository returns an empty response, the service will throw an error. The controller will catch the error and return a 404. If the repository returns a response with data, the service will then make a subsequent call to the repository to get the zoning district data. The repository will return the zoning district data as is. The service will format the data, such as taking the array and placing it into an object ie)
{ zoningDistricts: Array<zoningDistrict> }
.If at any point the database throws an error, the repository will throw an error. The Service will catch this error and rethrow it to the controller. The controller will catch it and return a corresponding 500 error.
Beta Was this translation helpful? Give feedback.
All reactions