Previously I talked about how any system can talk to any other system using an API, in Poller’s case, using WebApi. Each area of functionality can be accessed through a controller, e.g. Client Controller, Agency Controller, Polling Controller, etc.
Each controller is only the entrypoint for that area, they only receive the request, direct where it should go and, if necessary, send a response back. In Poller, a JSON formatted request is received and interpreted into code that the business layer can understand and consume. For example, the web application wants to Add a new client, it will Post a JSON that contains the name, email and phone number for the client (see below).
Now, the controller needs to send that information to the Business Layer (BL), to do so it needs to convert that JSON into an object – code that the application can understand – and call the necessary area, in this example, Add Client. Since the controller sent the object into the Add Client function of the Client Business Layer, the latter will consume that object: validate the information, calculate any fields (for example, how many days has this client been a member), then save the information to the database.
Because we care about this thing called “separation of concerts”, we don’t want to save the information in the AddClient function where we validated or did calculations, we want to call the layer that focuses on interacting with the database, by convention called Client Repository. Think of a Repository as the connection to the database.
Saving to the database is the next beast to talk about. Without going too deep into how the data is organized, I’ll just mention that tables store data. There are many ways to get data in and out from a database, using stored procedures, inline SQL or using Object Relational Mapping (ORM). I decided to use a micro-ORM called Dapper. What Dapper does is connect data to objects (similar to how JSON gets converted into an object). Long story short, we have to now convert the object into language that the database understands. Once the save is successful, the repository sends a successful message to the BL, that message is relayed by the BL to the controller, and finally sent to the client.
All that applies in the same way to any other controller like Agency. If I want to edit an Agency, I submit an request to edit to the Agency controller with a JSON that has the information I want to edit, the controller will call the Agency BL to validate and calculate, then the BL will call the Agency Repository to actually save the edited , the send the status message back.
There might be controllers that don’t actually need a Repository. Take for example the Polling Controller. This controller, when triggered, will use the Polling Business Layer to poll the specified site for information. Since the information is unique to a client, it could be more beneficial to send the result back to the calling application, or, the Polling BL can actually use another Business Layer to update something else.
Let’s say that we are polling how many clients the Agency has from an internal site, the Polling BL makes a call and gets the number of clients, then it can casl the Agency BL to update the number of clients. This is where separation of concerns really helps, the Polling BL only cares about getting information, once it has that, it calls the Business Layer that cares about updating the Agency without having to worry about validating or calculating anything.
This calling chain sounds overkill, why should we divide? Having this separation makes each part easier to work on. Some advantages: if we’re not changing any inputs or outputs, we can easily refactor or improve for performance, we can test individual layers by using mock data, it can be reused if the system evolves.
Leave a Reply