I have been working on an application for Ordbogen.com. Here I have tried to specialize myself in two different areas. Those two are:
Software Architecture including Clean Architecture and Microservice Architecture
Full stack web development in .NET Core and Vue.js
These areas are the areas I have been focused on, and tried to implement into the project we have made for Ordbogen.com.
The application is fairly simple. It’s an human driven Google translate, called Ordsome. By human driven we mean, people who voluntarily answer on translations, and ask for some text to be translated. The main idea was to eliminate the sometimes bad translations made by Google translate.
It was also the idea, that the application should be extendable. Therefore the back-end should be able to communicate with whatever front-end Ordbogen found attractive.
Our Product owners at Ordbogen consists of three different mobile app developers, with experience in Swift to Kotlin. Since they are app developers the found it very attractive to implement ‘Optical character recognition’ known as OCR, which read text directly through the camera lens.
We found a middle ground, where we would be able to develop web applications and mobile applications under the same domain.
The domain consisted of two main conceptual classes. Answer and Request. The request contains the text to be translated. The answer will contain the text translated.
A simple UML diagram could be made from this.
This is the core of the program, and very simple. However, the amount of functionality and thought to make this open for extension, can make this a very complex domain.
My thoughts and development progress
I wanted to make an application using Microservice architecture, where each service is build upon the principles of Clean Code / Clean Architecture to achieve a strong separation between the services and also within the services. These services should communicate internally and should not have a reference to each other. Outwards communication should happen through an API-gateway through different endpoints.
The goal for each service was to obtain a structure as follows:
- WebApi (presentation)
- Infrastructure (persistence logic)
- EntityFrameworkCore DbContext
- Entity configurations
- Application (business logic execution)
- Command/Query handlers and validators
- Domain (business entities and interfaces)
- Domain entities (ex. answer and request)
In .NET Core each application must have a startup file to be configured. However, this Startup file can be split up to different static methods. This is called the Options pattern. Makes it easier to maintain your startup file - which for each service is nearly the same. Therefore each service depend on a CrossCuttingConcerns library consisting of different shared options and classes. Each service also has their own database (SQL server), consisting of their own tables and relations.
The main structure looks like this:
Pros and cons of these architectural decisions
Here is some listed pros and cons I have experienced developing with these architectures:
- Require more initial effort.
- High learning curve - not as intuitive.
- You need an dependency injection framework (.NET Core comes with this out of the box)
- Need of DevOps - if you don’t have this, communication between the different teams working on the different services can go bad.
- Harder to test.
- Poorer performance - microservice needs to communicate through a network.
- Security - all the services and the network must be secure and not just a single application.
- Bigger chance of failure - not a single team working on the same application.
- Complex for small applications.
- Nice separation of concerns.
- Testable - straight forward to test. Just go through each layer.
- Easy to add new functionality, since it is nicely organized.
- Easier to debug, when using debugging tools.
- When working in teams adding functionality is easier, and requires less communication, since you just do as the flow
- Each service is ideally tech stack independent. Communication is only through protocols and APIs.
- CI/CD independently each microservice - every microservice can ideally have their own repo.
- Independently scale-able.
- Easy to setup and use containerization and cloud computing.
In the next part we will dig into one of the services I have created for Ordsome, and show how I managed to implement the Clean Architecture into the API.