I enjoyed this article a lot because this is a problem I struggle with often when coding. And not just at a particular point in the lifecycle of a project, it comes up all the time.
Decisions like this are, in my case, heavily influenced by how much I trust the rest of the codebase. Having "magic" code on top of a rock solid abstraction feels nice and safe. When I debug / troubleshoot I don't feel the need to step into the function to look at its implementation one more time.
I am much more likely to be explicit, suck it up and write the boilerplate code once again in a messy codebase where the abstractions change all the time (whether I'm the one who wrote the sucky code or not). In the end, I feel like it comes down to how well your objects / concerns are designed. When the concerns are properly separated and your objects are solid, magic code is indeed beautiful and extremely expressive.
Decisions like this are, in my case, heavily influenced by how much I trust the rest of the codebase. Having "magic" code on top of a rock solid abstraction feels nice and safe. When I debug / troubleshoot I don't feel the need to step into the function to look at its implementation one more time.
I am much more likely to be explicit, suck it up and write the boilerplate code once again in a messy codebase where the abstractions change all the time (whether I'm the one who wrote the sucky code or not). In the end, I feel like it comes down to how well your objects / concerns are designed. When the concerns are properly separated and your objects are solid, magic code is indeed beautiful and extremely expressive.