Repository navigation
Technologies Microservices and Separation of concerns
The separation of concerns (SoC) is a description of how to segment entities/responsibilities. By considering who can best deal with a task, usually with greatest efficiency, least deviation from norm, and/or adherence to idealogical principal, you can best define who would be best to handle that task.
SoC is primarily used in application development, but is just a structural paradigm and can be applied to many facets of life. SoC can often be applied to business logic. Here are two examples of SoC: The first is a stretch but shows how the idea can be applied outside the programming world; the second is more of the traditional programming approach.
If Edu Tech Services decided we needed another full time member we'd need to build a job description, get approval for the position, do the hiring process and interviews, and train the person.
-
Building the description and deciding what person is needed in tech shouldn't be HR's responsibility, because they don't have the required knowledge to appropriately determine Tech's "need." HR might have input, but Hyuk, as would-be immediate supervisor for this person, is who should consult with his people on what is the best way to fulfill present needs. Tech much more capable at doing this task, so they are best for the job -- should be the ones doing it.
-
We're unable to approve the job ourselves (no matter how much we'd like to) because of the checks and balances put in place for units. Also, we don't know all that goes on in the school and if there are other initiatives that would prevent us from doing this action. This is best done by Hyuk, through his supervisor because she already has the rights to make those types of calls -- together they communicate with HR.
-
The Hiring Process has multiple steps, one of which is interviewing.
- Most of the hiring process cannot be done by non-HR. Posting Job Descriptions, doing on-boarding paperwork, and adding to payroll are tasks only HR can accomplish because no one else has access to payroll and has all the needed knowledge for what a new employee should know on day 1. They need to track the whole process, including the interviews.
- Interviews are most important, but HR isn't necessarily the best group to do it. To best interview technical people, a technical person is required. Hyuk's team should interview potentials. HR may monitor.
-
As for training the person, that has to be done by Hyuk and his team, because we're the only ones who have the knowledge.
Each task in the process is given to one or more people who are best suited to the task.
MVC is a software SoC paradigm that helps to structure what code parts are controlled by who -- and by who, often mean which person in the programming team. The paradigm attempts to outline what type of code goes into what file (often which directory) and can make it easier to develop and debug code.
- Model is a set of code to work with outside sources. These sources can be Databases, Filesystems, REST APIs, or anything else that isn't the application itself.
- Views are how the end user sees data. Usually they template out to HTML (or XML for mobile apps) and have little to know logical processing. They are intended to be simple as possible and they only show the available information in the way that is needed for the application.
- Controllers are the actors. They know about the models and the views. The right controller is called by a routing system and provided with the basic request information. The controller then accesses models, manipulates data, and eventually provides the data in a final state to the view.
Depending on the exact implementation of this paradigm there can be other pieces, for example: Libraries, Helpers, Components, etc. But the base is always this paradigm that Views show things, Models talk to the outside world, and Controllers thing/process.
While programming, it can help you decide how you want to start your code and when to break apart functions/tasks into another document/function/class. I find it helpful to first build the router and define which controllers will exist, then pick one and make its view, make the controller so it calls model stubs and provides the view with data, then fill out those model stubs to be real database calls. When I eventually have a question "where do I add x" I can answer it by asking if x talks to the database, displays data, or manipulates data for a view.
In debugging, I can look at the bug and start by asking myself if it is a display issue, a database issue or somewhere in between. That tells me where to start my search.
Microservices are (as the name suggests) very small services. A microservice does one thing and preferably only one thing attempting to keep a very small API. That one thing might be authenticating users, managing an outgoing email queue, accepting images for pre-processing, or any number of other possible tasks, but it is best to keep it as small as possible and only do the one thing that server is best at. Doing one thing doesn't mean it has only one function, as reading a user and writing a user are often best managed by the same server. Here's an example of a 0single function: a server managing outgoing email queues will be best at accepting an object which has an email body (HTML String) and list of recipients (Email String Array), but may not be the best place to store a templating engine or file storage.
The Microservices paradigm has come together as an opposition to the Monolithic server. The monolithic server is a single server that does everything. It may or may not have the database onboard, authenticates users, processes images users want to email, generates emails from templates, stores all the data, and enqueues outgoing emails -- it is the whole process in a single instance/machine. This is the classical way of constructing services.
The problems with monolithic architecture are aging machines and slow initial product development.
With every addition and customization to a body of code, it becomes more complicated and harder to effect change without also introducing 5 other bugs. Also, while new is not always better, new technologies come out every day and are being put through their paces to determine what they are best at and how they can simultaneously enhance and simplify the process.
When you have to design the whole machine at once, it is harder to make new servers because you start from nothing and build it all. There are a lot of connections to make in your code and a lot fo functions to test and they must all be perfect to stand up properly. This all takes time. Make a new version or overhaul takes just as long because you have to check the whole system.
Microservices attempts to fix these shortcomings.
With small services each change only affects one machine (as long as the API is consistent) and is more easily testable due to keeping a small API. Microservices can also be in completely different languages, therefor allowing them to be created in the language that best fits the task for the team. That also means that as new languages prove to do a task better, the service can be easily replaced with the new version of that service without overhauling the whole system.
As for time to deploy. The initial launch of the first application can vary. It might take less time or the same amount of time, but you have more options allowing you to potentially deploy sooner. Once the system is online, adding to the system is easier as each line effects less code. Making a second complete application is faster because the first and second application likely overlap in some areas. They may both authenticate the same users, process images similarly, and store sessions the same. In that case you can either have the two applications share those three microservices or stand up new instances of those microservices just for the new application -- either way, those are three services you don't need to re-invent.
The UCI WebAuth has 3 endpoints and 4 functions. It has:
-
GET /login-- display login page -
POST /login-- Do login with POST data, add session token to cookie, and forward to REDIRECT location or back to/login -
GET /check_webauth?id=xxx123-- in text, describe the status of tokenxxx123if it exists -
GET /logout-- delete session token from cookies.
Programming those four functions should be quick and when OIT wanted to add in DUO for multi-factor authentication, they only needed to add a step to the 2nd of those functions -- the API didn't change at all, so no/few outside websites relying on WebAuth had to make any changes to their code.
As mentioned above, it's best to keep microservice APIs simple, small. Using the SoC, you can evaluate the whole application and find portions that don't need to massively communicate with every other part of the application -- these are good parts to segment away into a new microservice. Another segment might be something you know will be shared regularly with other, future apps.
In every application I make, I have to write authentication such that it allows the user to login via OIT's WebAuth. It is a code I copy from place to place and improve with every application. It must
- ask if there is a session token on the user cookies, redirect to login if not
- check with OIT WebAuth if there is a valid session for that token, redirect to login if not
- Check if there is a valid user in our database for the session token, redirect to "unauthorized" if not
- store user data for use in the application later.
This segment of the code is the only segment to touch the permissioned users table in the database and is used in every application I have. By database standards it is rather slow as neither SQL nor MongoDB are the best technologies for this type of storage -- Redis and Key-Value MemCaching is best because I don't have any joins, I'm only storing WebAuth response with User information and providing them on request. This is a good candidate for separating as a microservice.
Its new concerns are dictated by what data it stores and its API. Any time I want to know if this-logged-in-user is allowed to do something, this service will know best and fastest. It is maybe not the best to ask about all users, this handle this user. It's not a bad place to handle all users, the question should be, "Is there a better place to handle all users." I am choosing to handle them in their own microservice, because I don't see sessions as being inherently linked with all users, but they could be.