Introduction GraphQL is a query language for APIs, providing a flexible and efficient alternative to REST. It was developed by Facebook in 2012 and open-sourced in 2015. Since then, it has gained immense popularity due to its ability to optimize data retrieval and offer greater control over the responses. In this blog post, we’ll learn the basics of GraphQL, its pros and cons, and then come up an example written in Go: we’ll go through schema design, code generation from schema with genql, and implementation of resolver functions....
Observability in Software Engineering Part 2
In the first part of this series, we introduced observability and discussed its significance, particularly in microservice architectures. Now, we shift our focus to the tools that will bring observability to life: Grafana and Prometheus. These are powerful platforms that allow us to visualize and monitor our systems effectively. In this post, we will introduce key observability concepts that one must understand before diving deeper into Grafana and Prometheus. Grafana Grafana is an open-source platform for monitoring and observability, primarily used to visualize metrics, logs, and traces through customizable dashboards....
Observability in Software Engineering Part 1
In today’s software development landscape, ensuring system reliability, performance, and scalability is crucial. With the increase in complexity of modern systems, traditional monitoring methods are no longer sufficient. Observability was introduced as a critical practice that allows engineers to gain deeper insights into their systems and diagnose issues effectively. This is the first post of a series about observability in software engineering. In this first post, we will explore what observability means, its historical evolution, its importance in modern architectures, and why observable systems outperform those without observability....
About hacky solutions
A strange, and maybe funny, phenomenon that I notice after 10 years working in this industry is that developers can get really offended when someone calls out their solution as a hack. I’ve observed this in different companies, even some people who I consider calm and composed can get their attitude changed once I tell them that their solution is hacky. People tend to be very civil as long as I politely criticize their work in a friendly manner, but once the word “hack” is said, it’s as if I was personally attacking them....
Facade Design Pattern
In the previous post, we converted an incompatible interface ino another that fits nicely with our existing design thanks to the adapter pattern. We were able to design a weapon system that allows composing different damage types to different weapons, and also able to incorporate a third party library to add a specific type of weapon damage. While the exising solution works, it’s not very clean due to a few reasons....
Adapter Design Pattern
In our previous post, we leveraged the decorator design pattern to implement a weapon system for our next video game. Thanks to the decorator pattern, we were able to provide additional damage types to our weapons without changing the weapons’ implementation. Adding a new weapon therefore is very easy, and so is adding a new damage type. In this post, we’ll cover a different kind of problem that can be solved by the adapter design pattern....
Decorator Design Pattern
The decorator design pattern lets us provide additional behavior to a type. This design pattern is extremely powerful when we want to provide extra functionalities without requiring changes to an existing type, helping us achieve the Open Closed principle. In this post we’ll examine how the decorator design pattern handles a hypothetical problem. The code will be written in Golang, but the idea should be simple enough to port to other programming languages....
Contextual Error Handling in Go
Go provides 2 native ways to instatiate an error value: errors.New that returns a string error value, very useful to create a simple sentinel error value like var errNotFound = errors.New("record not found"). fmt.Errorf that may return an error that wraps another error, and the wrapped error can be asserted against with errors.Is, or retrieved with errors.As. While both approaches are fine for simple programs, they lack depth when it comes to large systems because of:...
Interface Pollution
In this article, we’ll look at a very common mistake that Golang new comers make, especially when they come from a background of Object Oriented Programming (OOP) languages like Java or C#. What is interface pollution? Let’s look at some codes. package employee type Employee struct { Name string Credit int } type EmployeeRepository interface { Query(name string) *Employee } func NewEmployeeRepository() EmployeeRepository { return &database{} } type database struct {} // Query returns the first Employee that has a matching name....
Value and Pointer Semantic
“How do you decide that a variable should be a pointer, or a value?” and “How do you know when to use pointer receiver and value receiver of a method?” are among the most common questions I receive from Go new comers. Even though there is no offical rule that dictates which types should use pointer, and which types should use value, it’s worth to deep dive into the topic of pointer and value semantic in Go, which is what we’ll do in this article....