Jiri Sedlacek 17/11/2024
- This is not a post about statically or dynamically typed programming languages. This is also not a post about eventually consistent systems. This post is about classic transactional software systems and how they decay over time and how.
- Every software has inherent complexity that comes from solving the problem it needs to solve. Yet you can break it down to Static Complexity and Dynamic Complexity.
- I will show you how they relate to each other. I will show you why keeping Dynamic Complexity low leads to more readable and maintainable code.
- I will start by defining Static Complexity - it's the number of EXPLICIT relationships among objects in your database model. In real life this would be number of foreign keys and constraints in your database.
- Explicit foreign keys make it easy to understand the order in which objects can be created.
- What I have seen over and over is that Static Complexity goes DOWN over time. As new features are added under pressure people resort to denormalized models.
- As Static Complexity goes down it is compensated with Dynamic Complexity - it's the number of constraints in application code that control the order of things. Since the DB model is denormalized - and thus can hold corrupt state - there is only application code preventing it from happening. It's code like this:
def create_order_line(product_id, order_id):
# These checks would be automatic with FKs
if not Order.exists(order_id):
raise Error("Order must exist first")
if not Product.exists(product_id):
raise Error("Product must exist first")
...
- You can say such code is a code smell of a bad DB model.
- Dynamic complexity is about the conceptual difficulty of understanding "what must happen before what".
- As the number of application code rules that control order of events increases the code becomes less and less readable and maintainable. Dynamic Complexity increases.
- A programmer must find all the places in codebase that control order of updates instead of looking at one definition of DB model. This approach does not scale well in large organizations.
- To counteract this trajectory organizations can turn Dynamic Complexity into Static One. Having the confidence that DB model will protect itself from bad states there does not need to be so many application level rules.
- But sometimes the Dynamic Complexity is so high that noone even dares to think about refactoring. The point of this post is to highlight the relationship between DB model and the difficulty to read and change code. You need to keep dynamic complexity at bay - while you can.
I thank Matej Bosak for feedback on early versions of this article.