I’m often having this debate, myself.
I’m not sure the segue example is as strong as you feel, however. The
doTheThing version shows two VCs that are tightly coupled, as one is directly creating the other. Otoh, the segue’s
prepare() could be doing conditional casts against protocols, with no regard for the destination VC’s actual type. Move
prepare() into an extension or shared UIVC subclass and you can handle a lot of presentations with your VCs entirely uncoupled from one another.
So imo segues offer a really nice way to keep VCs from being too inter-dependant. If you want to keep things in code, something like coordinators should be used to keep things clean.