I like to model all programs as state machines with pure functions within them. These individual state machines compose into larger ones where sometimes it’s easier to visualize as a hierarchy and other times as a distributed network of actors. One system that applies this model is Erlang’s OTP, but this model is very general and comes up just about everywhere.
An issue with obsessing over generalization is the “turing tarpit” — that every computation can be modelled on a turing machine’s tape or using lambda calculus or some other simple system. The key to abstraction is to purposefully attempt to model things with the least powerful/expressive language reasonably possible. If you can solve a problem correctly with a si