I met up with one of my peeps for lunch the other week. We’re chatting about stuff, then we started talking about coding. We have a nice rivalry – I’m very much about the “art and craft” of software engineering, and he’s all about using the latest/greatest to build stuff. I call B.S. on his shinny new, and he calls B.S. on my old and crusty.
Me: “Dependency Injection used to be your jammy jam. You told me that my code sucked because I called a constructor directly. So what’s your newest hotness?”
Peep: “I’m refactoring our code to use interfaces for property bags.”
Me: “Hmm… so you’re using some sort of library/runtime reflection to dynamically realize the interface definition?”
Peep: “No, it’s an interface.”
Me: “Well, an interface defines the contract, not the implementation details. You need a class for a concrete implementation of the interface definition.”
Peep: “Oh, that’s what you mean. Yes.”
Me: “Dude, you’ve got all these wiz-bang things that are auto-code generating, or sucking type definitions from a config file to use for injection. There’s so much magic going on, you can’t just look at the code to easily tell what’s going on. What about the dude/dudette that will come after you to work on this code?”
Peep: “(Delivered immediately and emotionlessly) That’s not my problem.”
Me: “(Laughing) Well done.”
Peep: “But yeah, I have been thinking about that…” ‘
Abstraction is good – but when you over-partition or abstract your design, that can become an anti-pattern. The more mental juggling it takes to understand what’s going on, the bigger the chance of some unintentional bug getting introduced. K.I.S.S. always wins out.