Have you noticed that sometimes you need to write a lot of test code only to verify some very specific part of production logic?
When I come across this myself my first reaction is to hide all these uninteresting details. For example, by introducing factory methods or builders in test code. Often this is indeed good enough. However, before cleaning up the test this way it is good to think if it’s not the production code that needs some cleanup.
Tests that have low focus factor are a sign of badly designed production code.
Focus factor here is the ratio…
The term legacy is used quite broadly in software engineering. Typically it’s used to refer to a system or technology any reasonable person should avoid as much as possible. However, if we go deeper into trying to understand what legacy in software means we can uncover some more interesting insights.
In Merriam-Webster dictionary legacy is defined as:
something transmitted by or received from an ancestor or predecessor or from the past
As legacy is something transmitted by an ancestor it means that it has some value (or at least had for the ancestors). Similarly having a legacy system means it’s…
The biggest problem with ticket management systems like Jira is that they are too powerful. Having a backlog of 300+ items is no problem. Whenever some new topic is raised we always have an answer — “let’s create a ticket”. And then forget about it.
With 300+ items on the backlog majority of the tickets will stay there forever or until we throw the whole list away and start over again. This outcome does not differ no matter how much time we have invested into “backlog grooming sessions”.
As a parent I often face the challenge of having to explain the hidden dangers of unhealthy life habits. Interestingly, I have realised that the way we tend to treat our own health and the health of our software have a lot in common.
Eating unhealthy food and no regular exercising will lead to worse health. Unfortunately this will not happen immediately — especially if you are young. The side effects of such habits may take long time to appear. This makes it quite hard to fight against these habits early on. Just like with software systems we don’t usually…
Previously I wrote about avoiding nulls using
Optional method return value. In this post I will focus on modelling optionality in an object internal state in cases where
NullObject is not suitable. This means when implementing the basic building blocks for internal state of Value Objects and Entities or working with data structures instead of behaviour.
If we keep our classes small then this is a much smaller problem than having nulls passed around between objects. Still, the more of the actual domain constraints we are able to convey in our static code structure the better. …
Let’s say we want to implement a service that handles the process of placing an order. This order goes through multiple stages during its lifetime. Initially it is pending, then goes to confirmed and paid. Finally it ends up as either completed or canceled.
Now going to implementation it seems obvious that we need a class named
Order. Simplest way to model the states that it goes through is having an
There are different things that we can do with an
Order in each of its states. For example, in pending state we can change any details (e.g…
Null Object and Optional are both ways to avoid nulls. In the following post we will compare these two approaches to see when one or the other is more suitable.
Null Object pattern is nice as it hides away the special case of not having a value for something. So ideally we should be able to avoid all ifs for null checks. This works nicely when we can replace normal behavior with a noop implementation. However, it does not work so well when we need to access some data on the object.
For example, we have a Customer class like…
In this post we will look into using port level tests to make microservice testing experience faster/more pleasant. As a nice side effect we will also improve our application design.
This post contains some Spring specifics but the idea itself should be applicable to any similar framework.
Having clear test categorisation with explicit guidelines is very valuable within a team/service. This way we can avoid amorphous tests that follow random patterns and are hard to read.
There are many ways how to categorise tests. …
Entity services are services that are modelled around data instead of behavior. It’s an antipattern when implementing “Service” classes in a single monolith. Entity services are even worse in microservices architecture where they inevitably lead to distributed monolith.
One way how to avoid such entity services is intentional naming. Naming is very powerful way how we can direct our thinking and create positive constraints for software designs. If we want to build services that are formed around behavior and not data then we should also name them using verbs or processes instead of nouns.
Name services using verbs instead of…
There are two kinds of dependencies between services: data dependency and behavior dependency. We have a data dependency when we need to find out what is the address of customer X. We have a behaviour dependency when we need to ask if customer Y is eligible for our customer loyalty program.
In both cases using asynchronous communication enables building more autonomous services. Just like it is desirable to build organisation out of autonomous units it is also valuable to build our software system out of autonomous components. …
I enjoy (functional) art sometimes referred to as software development. Have been creating software for more than 10 years.