Short Note on Abstractions
As I continue exploring abstractions and trying to understand their proper nature, I'd like to share some thoughts.
In my previous post on this topic, we found a good definition of abstraction - it's creating a mapping from the concrete "messy" world into a clean mathematical representation. When this mapping is "built" correctly, we get a new semantic level where we can reason about the system precisely while maintaining the connection with reality.
DSL naturally follows from correct mapping between concrete and abstract levels, serving as a tool for working in this abstract space
Here's an interesting example from infrastructure code: imagine a (really) complex distributed system with many services and high SLA requirements, running on Kubernetes with all the tools you love.
We can rise above the level of specific Kubernetes manifests (and Kubernetes itself, because we're not interested in Kubernetes per se, but rather in our system that lives in it) to a higher semantic level - let's call it `SystemState`.
Our SystemState could define a formal model of the entire system and its components consistency model.
It might describe:
Service versions
Cluster and cloud infrastructure configurations
Rules for state transitions during deployments
Message formats in queues
Distributed database migrations
<NAME_YOUR_SYSTEM_THING>
Unlike common declarative infrastructure descriptions (helm charts, terraform, GitOps, and whatever else), such abstraction promises to provide guarantees of invariants and correctness of state transitions.
Of course, formally defining it and implementing is a very complex and questionable endeavor - the more dependencies in the system, the more complex the state graph becomes. So while I think it's a good example, it's quite theoretical.
And anyway...
Start with building a healthy modular monolith - you'll have time to split it later!
Looking at existing solutions like Pulumi - it feels that they're moving in this direction, opening a possibility of infrastructure expression at a higher abstraction level (we are not limited by "declarative" tool rules).
I would not be me if I did not note the connection between functional programming and building proper abstractions. FP works well with abstractions, or more precisely, FP's nature is much closer to the nature of "proper" abstractions I am talking about, as it allows reasoning strictly within the chosen semantic level, with less risk of "falling through" to implementation details.
We get this largely thanks to FP's "native" inversion of control, which brings to the table natural protection from recursive implementation diving - the less state spreads across the system, the less our attention unfocus and "abstraction" itself spreads.
Functional approaches allow expressing abstractions more correctly, with less gap between formal model and code, while with mainstream OOP we risk quickly sliding into... implementation details, hierarchical mess leading to well-known confusion.
The topic of abstractions is fascinating and deep.
I greatly enjoy investing time in learning abstract algebra, type theory, and other "fundamentals" that help me better understand this great field. And while I'm far from being an enlightened computer scientist, even touching these matters at a basic level changes (I do believe) my way of thinking dramatically.
But the main thing I've noticed is that we need to try applying this knowledge in practice, as that's the only way to truly master this powerful craft.
No matter how theoretical and non-applied this knowledge may seem (especially at first), I believe it improves both the code we write and our ability to conceive and understand more complex architectural constructs.
If you found such topics interesting or just want to see where my journey goes - consider following.
Wish you a great Journey, thank you.