My future with Go for this 2023 🐹
¿Hablas español? Ver en español
Last year I focused on finding the ideal architecture and distribution for my projects, as a result of this my current template came out with which I start projects in Go, since it has a base already built that includes us: login with JWT, Documentation with Swagger, Metrics, Mock Generation, etc. You can review it in more detail at the following link template 2023.
This year I set out to improve modularity, in a few words I decided to divide my template into small packages that could reuse this because I usually have projects that are not only Web but also CLI and there are parts of my web template that I would like use as the Validator or the Session Manager. I could copy and paste the code to another project but…
This is the plan:
- Identify all possible packages within my template that may be reusable and applicable in another context.
- Develop a package that mimics its behavior and structure.
- Document and Test the package until reaching a minimum of 90% Coverage.
- At the end of the year update my new 2024 template that is 100 modular
Advantages of using our packages
1. Only one purpose
From now on the packages will serve their purpose and nothing more, this means that being in an isolated context when they are modified will not interfere with a bias of the project in which it is located
(Validator package in a web app) Well, in this spring we will add a function to validate the fields of this structure that will arrive as the body of the X function, let’s add it to the validator.
Although it is a validation, it already has a layer of bias, for example, what is the use of having that validation function in the validator package that will be used only for that specific structure, we better use the basic functions that the validator already has to validate the structure without compromising the basic function of the package.
package validator
import errors
func ValidateHeadersOfBuyShoesRequest(h *HeadersShoes) error{
if h.authorization!= "my secret 🤫 " {
return errors.New("Error validating the authorization")
}
}
Instead of contaminating the validator package with such a specific function, we will take advantage of how it is built in my template so that it is the structure that groups the validation rules.
package validator
type Validator interface {
Struct(s EvaluableStruct) error
}
type EvaluableStruct interface {
Validate(args...interface{}) error
}
type ValidatorImpl struct {}
func (v *ValidatorImpl) Struct(s EvaluableStruct) error {
// another logic for only structs
return s.validate()
}
package models
type HeadersShoesRequest struct {
Authorization string
ClientID int
}
// The validations are always close with the struct who validates
func (h *HeadersShoesRequest) Validate(args ...interface{}) error{
if err := validations.IsEquals(h.Authorization,args[0]); err != nil {
// use the generic error or be more specific for the example I will use the generic
return err
}
if err := validations.GreaterThan(ClientID,-1); err != nil {
return err
}
}
Considera que el paquete validations es parte del paquete validator
2. Test only one time
Try once I already lost count how many Tests I do that test things without exactly the same as in some other project, for example:
We need the session manager to also have the tests to validate that the session was saved correctly in projects A, B and C
Where is the DRY then? Even if it is in different projects by atomizing in small packages that clearly serve their purpose and do nothing more than what they promise, they allow us to have Tests written only once and therefore we will pay more attention to detail to make them of quality, our mind will only think about the functionality of the function, despite the redundancy, there will be no bias or external noise that confuses us in the purpose of the function because it is only the package 📦.
3. Easy to share
The ease of sharing packages between team members ends up generating a standard in how things are done since all your projects will be built on the same Lego blocks. Imagine something like that.
4. Easy to start a project
You start easier and less abrupt there will be less to ask. I will give you an example.
Hello Carlos, a new programmer joins the team on Monday, you can help him with the technical OnBoarding.
Welcome X your project is Y so I think to begin with you could bring the following packages to your project that will be useful: Session Manager, Validator, Logger, Authentication, etc. The documentation is in the same repositories.
We have just saved you probably a week of work on pure boilerplate and probably another extra week on just testing.
Not to mention that having a package that deals only with authentication allows one of the most critical and stressful parts I would say for someone joining the company would be reduced to using a Middleware that has already been programmed and is practically a “Plug and Play”
5. Isolate critical logic
It allows us to isolate critical business logic such as authentication in a single person responsible for ensuring the security of that package and being isolated from concentrating on what matters, which is to make it more secure.
6. Isolate changing business logic
It also allows us to isolate changing business logic, something very common in startups, what are parts of the business that are still in a state of testing and iterations? Let’s take the authentication package as an example again.
We have to add a new encryption to our keys tell all projects that use authentication that they should add the following rule X
Hello how is the addition of the new rule going? Project A,B has already been modified but they can’t be launched because project C which connects to A is still behind and we need to finish this before adding the new security rule.
Do you understand more or less what I mean? Now what would it look like if authentication was an isolated package, the talk would change a bit.
Tell the authentication package maintainer that we need to add a new rule
Hello, How is the addition of the new security rule going? Adding is finished, a release was made today and all the projects involved will create a branch of their most stable version in their project and add the update immediately
As always not everyone is pink
There is a high risk of falling into something that is very common in micro services, which is having 200 micro services and 5 people maintaining them, we could definitely have 200 packages and only 5 people maintaining them.
Another point to take into account is that we create an isolated package for each part of our project, I think that if a package is not useful in at least more than 60% of the projects, perhaps it is better to keep them in the projects
Unless you have plenty of hands then I would 100% go with another rule. Does this package solve a common problem in my business or is it a changing part of my business? If the answer is yes it is better to have it in a package.
- Not knowing where to start.
- Being tired of programming the same every time you start a new project.
And generating these atomic packages will give you the freedom to only choose the parts you need, personally I am a person who really likes to program Open Source things and this method helps me so that small parts of my templates can be used without having to use 100 of this.
This current year I will dedicate myself to atomizing all my repeating packages so that next year I can use the template built with the blocks I create this year and create a client that lets you choose parts of the template, improving the size of the project by 2024.
I leave you some links to the packages that I am already developing in case you want to collaborate, they are simple things, so it is ideal if you want to start in the world of open source:
And this is the link to my current template uses Fiber, Mongo and JWT authentication