Onion, Hexagonal, Clean, or Fractal Architectures aim to organize how we deal with dependencies in our software architectures. But which one should we choose? After distilling the essence of each approach and comparing the advantages and challenges, I’ll show how to combine all of them into an approach to use evolutionary steps towards an architecture that fits your needs from day one until the software dies. You’ll see that layers and slices aren’t enough. A modularisation that fits the domain...
Evolution of Software Architectures
Evolutionary software architecture has gained much traction lately—at least in my bubble. It is one of my favourite topics, and I have presented and conducted workshops on it for over a decade. So, let me add a thought to the discussion:
The evolution of a software architecture has three dimensions:
Technical evolution,
conceptual evolution, and
the evolution of business capabilities
(Mis)estimation – why estimates tend to be wrong
Our Experience with Bi-temporal Event Sourcing
Bi-temporal event sourcing combines storing data as a sequence of events, which tell what has happened with the data, and the data has two associated points of time, one when the data entered the system and one when the data takes effect. This post is about our 8+ years of experience with bi-temporal event sourcing, along with code samples showing how to achieve this. Feel free to skip the code blocks and just read the conceptual parts. But you’ll miss the beauty of F# 😂 This post is part...
Myths about F#: Code without type annotations is hard to review! No, it’s a relief.
After one of my presentations about F#, we had a discussion about the effect of type inference, resulting in almost no type annotations, on code readability and reviewability. The concern was that it makes the code harder to understand, especially when reviewing code, for example, outside of an IDE (GitHub/Azure DevOps/… Pull Requests).
So is there a problem or not? Let’s see.
The caretaker model – our way of working
In this blog post, I describe the way we currently work as a team to deliver our product (TimeRocket) to our users and customers. This reflects our current understanding of working in an agile* way that matches our needs and skills. We are uncovering better ways of developing software by doing it and helping others do it. Manifesto for Agile Software Development (agilemanifesto.org) As the manifesto for Agile Software Development states, we continuously try to improve our way of working, so...
Today’s random F# code: one-line unit tests
Myths about F#: F#’s strict ordering is dumb! No, it’s great for taming dependencies.
In F#, you specify the order of files explicitly. Any code can only reference types, modules and functions that are higher up in the same file or in a file higher up in the file list. When starting with F#, this feels strange because most programming languages don’t rely on ordered files. Some call this feature even dumb.
Myths about F#: F# is slow! No, F# can be really fast.
Today’s random F# code: Using measures to give types more meaning
We use NodaTime in our application to deal with time. As you may remember, time is very important in our application – it’s a attendance time-tracking tool with duty planning and many more features. For example, we use Instant to model a point in time. But sometimes, we need a point in time with a granularity of minutes, not nanoseconds. Instead of introducing our own type to model an instant with minute granularity, we use an Instant with a measure. Let’s see how this works: