The Pyramid is a great metaphorical mental model to reflect on codebases. With the Pyramid in mind we see code arranged in blocks and layers.
Any codebase has at least one mission, whether it’s providing a product interface and its features, exposing an API or generating some data. The mission is the value users extract from the codebase. It’s the flag on top of the Pyramid.
The Pyramid itself is not exposed directly to the users. It supports the flag. It supports the mission.
The metaphor sometimes takes a few liberties with reality. What’s the difference between a software Pyramid and a real one?
Blocks in a real Pyramid are subject to gravity. They are constrained by the weight of upper layer blocks. The highest blocks are also the freest.
Blocks in a software Pyramid are subject to dependency coupling. The freest blocks are the lowest ones, having no dependency in the codebase. The most constrained blocks are the highest one: they are indirectly coupled to the full codebase.
Let’s say we’re removing Redux while seeing the affected codebase like a Pyramid.
The flag - the mission - cannot change. And because each layer depends on the one underneath, we can’t update a block at a given level until we’ve migrated the lower blocks they depend on first.
So what do we do? We update our Pyramid starting at the bottom - don’t do this with real pyramids!
We migrate the lowest-level blocks first while we keep supporting the upper-level blocks. We give them a similar-enough API to continue working without (much) refactoring needed. We progressively go up layer after layer, following the dependency chain. When we see the flag again, we’ll have migrated the full codebase.
Also : Iceberg, Layer Cake