4 ms·
If that's all that your code does, then that's fine to use #1. But in a larger class, it's needlessly cluttering the class with operations below its abstractio
by ircmaxell 15y ago
If that's all that your code does, then that's fine to use #1. But in a larger class, it's needlessly cluttering the class with operations below its abstraction level. Why should a logger care about file locks and the such? Why should you care about file locks when editing the logger? Hint: You shouldn't normally.
As far as "the complexity is hidden", you're absolutely right. I want that complexity hidden. By hiding the complexity in this way, I can reduce duplication and at the same time make the code far easier to read. Sure, you do need to dig through more levels of abstraction if you need to debug something. But abstracting in this way enables bugs to be fixed far easier, since the methods are really small and simple, the "ripple" effect is far easier to understand and contain.
Think about how long it took you to understand what log() did. With the first one, you needed to parse a whole lot of detail (including the flag passed to fopen, the two exception checks, the arguments passed to flock, the fprintf declaration and the flock call arguments). With the second, all you needed to do is read the two steps: 1. createLogMessage() and 2. file->append($message). At a glance you know what the method is supposed to be doing.
Why is there such a hang up that people want to know what code is doing at all levels? If you name your APIs well, you should be able to look at the method's name (and perhaps its arguments in some cases) and know without a doubt what it's doing (at least to the abstraction level the API is designed for). If you really need to know details, you can go deeper, but I know when I read $file->append($message) that I'm appending a message to a file. I don't need to worry about anything else 99.9% of the time. So I'd rather get the clean win with well named APIs, than spend my time sifting through methods like the first one...
- gwillen 15y agoIf your abstractions are beautiful and clean, then you're absolutely right -- hiding the complexity is great! But you know what? 99% of the time, your abstractions are shitty and leaky. And then I need to know what's under them in order to work with them confidently. So yes, absolutely hide complexity. But hide it judiciously; hide it only when you know you have a clean, well-designed and well-constructed abstraction that won't leak to the outside. But if you hide complexity behind a leaky abstraction, which most of them are; then now, as they say, you have two problems.
- rickmb 15y agoI feel the concept of "leaky abstractions" is being abused way too much as an argument against all abstraction. Except in the well known cases, like trying to abstract away SQL to give it an OO interface, the leakiness of abstractions is rarely a big issue if those abstractions are decently designed. Not even beautiful and perfectly clean, just good enough for their purpose. Yeah, it sucks in those rare cases where the abstraction makes it hard to figure out what the hell is actually happening, but the extra effort is nothing compared to the amount of pain saved by having that abstraction throughout the rest of the development process. All plumbing will spring a leak some time (and sometimes with pretty costly consequences), but that in itself is no argument against plumbing.