3 ms·
In his small example he already added unforeseen couplings that could get out of hands if it was a big codebase. If you follow the principle "switch statements
by sebstefan 4y ago
In his small example he already added unforeseen couplings that could get out of hands if it was a big codebase. If you follow the principle "switch statements over [X]", try to add a new shape down the line and see how quickly you run into problems.
In the clean code version, your compiler will remind you to implement calculateArea, calculateNumberOfVertices, calculateWhatever, and so on and so forth.
With his version you have to add a new `case` to every switch statement and hope you didn't miss one with a default case, because the compiler won't catch it.
You don't need virtual functions and polymorphism to remove his switch statements. Just compose over inheritance.
- pkolaczk 4y ago> With his version you have to add a new `case` to every switch statement and hope you didn't miss one with a default case, because the compiler won't catch it. The compiler not catching it is a limitation of the language he uses, not the limitation of the general concept of switch / pattern matching. Scala, Haskell, Rust do catch those. > If you follow the principle "switch statements over [X]", try to add a new shape down the line and see how quickly you run into problems. And who said you'd ever need to add a new shape? Maybe you will need to add a new operation? Try to add a new operation `calculateWhatever` and see how many places of the code you need to chnage instead of just adding one new function with a switch. Often you really don't know in which direction the code will evolve. Most often you can't guess the coming change, so don't make the code more complex now in order to make it simpler in the future (which may never come).
- sebstefan 4y ago>The compiler not catching it is a limitation of the language he uses, not the limitation of the general concept of switch / pattern matching. Scala, Haskell, Rust do catch those. You're thinking of defaultless switch statements. Rust and Typescript catch those issues as long as you don't add a default. I'd already thought of it when I typed it >And who said you'd ever need to add a new shape? ô_o >Maybe you will need to add a new operation? Try to add a new operation `calculateWhatever` and see how many places of the code you need to chnage instead of just adding one new function with a switch. You do realize that your "one function with a switch" does have to cover every case exactly like the clean code version, it's not magic you're just fitting it all into one switch/case, and you'll probably end up extracting those case: blocks into separate functions anyway. And on top of that you're not safe from a colleague adding a useless "default" case at the end ouf ot paranoia and making your compiler not catch a future problem when a new shape gets added.
- Tenticles 4y agoYou are not safe from a colleague adding a dozen classes to add two numbers if you are enabling the "clean" crowd either. When I was at uni I was obsessed with these clean ideas and how they would allow big teams to work. after years of working I have seen these ideas fail to actually make teams work in an harmonious manner, worst hit I have experienced against these ideologies was finally working in a place without them and seeing how a lot of the alleged "advantages" of "clean code" could be achieved by other simpler means and how much in the way these ideologies are of actually being productive. Productivity is achieved in spite of clean, not thanks to it.
- sebstefan 4y ago>You are not safe from a colleague adding a dozen classes to add two numbers The difference is, adding "default" cases to complete switch statements happens all the time, you've probably witnessed it, I know I have, whereas colleagues adding a dozen classes to add two numbers doesn't. You're also never safe from meteorites crashing your building, let's talk about real antipatterns
- pkolaczk 4y ago> You're thinking of defaultless switch statements. Rust and Typescript catch those issues as long as you don't add a default. I'd already thought of it when I typed it But the same problem exists with interfaces and virtual dispatch! If you provide a default implementation at the interface / abstract class level, then the compiler won't tell you forgot to implement that method, because it would see the default one exists.
- sebstefan 4y agoDefault implementations at the interface level, wow, apparently it's a thing in Java. I don't think it's in C++.
- hbrn 4y ago> he already added unforeseen couplings that could get out of hands if it was a big codebase And one should be able to fix things that get out of hand when they start getting out of hand. Architecture should be based on current facts, not on our fantasies about the future. For some reason we're always making this weird assumption that future engineers working on a problem are going to be less capable than us. So we decouple things in advance for them. Those future idiots won't know how to architect for scale, but we, today, with our limited domain expertise, know better. The reality is that in most cases we are those future engineers. And, unsurprisingly, "future we" tend to know more, not less.