I don’t agree. The technical device we use for creating clear boundaries, useful abstractions and managing dependencies in monolithic code is the function/method/procedure call.

The history of distributed software is littered with the corpses of attempts to make the RPC look like a function/method call (I worked for a CORBA vendor decades ago). But these two techniques are so different on a fundamental level they are not substitutable except in the most trivial cases. The compute and elapsed time RPC overhead which makes perfectly good local abstractions completely impractical across a network. And then there are the differences in terms of failure modes, concurrency and synchronicity.

So even a beautifully designed and layered piece of “monolithic” software with a code base costing of coherent and clean abstractions will not be easy to port to a microservices/distributed architecture.