Live data from Hacker News

Criminal Overengineering

coderoom.wordpress.com

61–67 of 67 posts

Re: Criminal Overengineering

#61

Argh. Apparently there are two very popular types of article in the software blog world: Type 1: YAGNI (like this example): Do less now. Refactor later as needed. It won't be needed, most likely. Chill out. (All driven by the question, "Dude, wtf? 100 lines of boilerplate for a 5 line case statement? Snap out of it.") Type 2: Architect astronautics: Do more now. Build for the next version. You will need more then, so…

Sometimes the world just is as simple as it seems. Type 1 is right, type 2 isn't. After 15 years of writing code I can only vouch for two metrics of code quality: clarity and length. For a long time I too thought that clarity means using "thisIsAStudentBirthDate" variable names - but it turns out there are very very few instances where the shortest code isn't also the most obvious at first glance. I think the turning…

Definitely agree this juggling rests in experienced hands. A vet knows what balls can be dropped and which ones cannot. My thoughts on this are: 1) As a rule of thumb, the longer the project the more structured it should be--which should be a no brainer. 2) Having a clean dispatch module allows you to sweep the mess under loosely coupled rugs. 3) Programmers are code excavators first, curators second, developers third.

Re: Criminal Overengineering

#63

Argh. Apparently there are two very popular types of article in the software blog world: Type 1: YAGNI (like this example): Do less now. Refactor later as needed. It won't be needed, most likely. Chill out. (All driven by the question, "Dude, wtf? 100 lines of boilerplate for a 5 line case statement? Snap out of it.") Type 2: Architect astronautics: Do more now. Build for the next version. You will need more then, so…

Type 1 design is not taught anywhere, people don't even know this is an option. The only design strategy that is taught is architecture astronautic.

I had an argument with a teacher that thought that it would be useful to abstract things from a pop/imap email fetching service, in case other protocols show up ? I'd argue that was improbable and that would complexity the design and that possible other protocols might be so different that they wouldn't fit the abstraction. He dismiss it as industry specific way of doing (but I lacked examples a little bit, so I wasn't completely convincing ).

We have to be quite vocal because we cry against the mountain.

Re: Criminal Overengineering

#64
post #38

Earlier quoted context omitted.

I'd guess that more than 5% are extended (maybe 6-8%), but that more than 95% are not extended as expected. When something is not extended as expected, either you end up with something not as good as you'd have gotten by waiting or you have to rip out some of what you put in for the future without ever using it.

The problem with this term "extended" is that it's unnecessarily limiting. Code needs to be maintained , whether or not it's "extended," and switch statements are by far less maintainable than the alternative polymorphism-based implementation. They don't as readily admit separate testing, and the implementation of specific operations are not isolated from each other, etc. 100% of code is maintained and the polymorphi…

"switch statements are by far less maintainable than the alternative polymorphism-based implementation"

You know, everyone says this, and I've never quite gotten it. Why is writing another class and implementing another virtual function so much better than adding another clause to a switch statement? At least all the cases of the switch statement are in the same place instead of scattered across a bunch of files.

Polymorphism to me just seems like a switch statement you have to think harder about. Maybe that's why I've always preferred a functional style to an object-oriented one.

Disclaimer: I program in Fortran for a living, so "SELECT-CASE Stockholm Syndrome" is definitely a possibility.

Re: Criminal Overengineering

#65
post #3

Earlier quoted context omitted.

One of my lecturers wrote the following at the top of our course notes: Contrary to popular opinion using OOP does NOT mean "thou shalt make every last thing an object"

Really, it depends on your environment. In Smalltalk, most things are objects. Not surprisingly, it turns out to be easiest to make most things objects. I find that Smalltalk is best when a program is mostly objects, there's a sprinkling of short-ish procedural methods whose workings are hidden by encapsulation, and perhaps a handful of long optimized algorithmic methods. I suspect that in Self, it's easier to make m…

In Smalltalk, everything is an object.

Re: Criminal Overengineering

#66

Earlier quoted context omitted.

The problem with this term "extended" is that it's unnecessarily limiting. Code needs to be maintained , whether or not it's "extended," and switch statements are by far less maintainable than the alternative polymorphism-based implementation. They don't as readily admit separate testing, and the implementation of specific operations are not isolated from each other, etc. 100% of code is maintained and the polymorphi…

"switch statements are by far less maintainable than the alternative polymorphism-based implementation" You know, everyone says this, and I've never quite gotten it. Why is writing another class and implementing another virtual function so much better than adding another clause to a switch statement? At least all the cases of the switch statement are in the same place instead of scattered across a bunch of files. Pol…

Polymorphism is more maintainable than a switch statement for a few reasons:

1. Polymorphic method implementations are lexically isolated from one another. Variables can be added, removed, modified, and so on without any risk of impacting unrelated code in another branch of the switch statement.

2. Polymorphic method implementations are guaranteed to return to the correct place, assuming they terminate. Switch statements in a fall through language like C/C++/Java require an error-prone "break" statement to ensure that they return to the statement after the switch rather than the next case block.

3. The existence of a polymorphic method implementation can be enforced by the compiler, which will refuse to compile the program if a polymorphic method implementation is missing. Switch statements provide no such exhaustiveness checking.

4. Polymorphic method dispatching is extensible without access to (or recompiling of) other source code. Adding another case to a switch statement requires access to the original dispatching code, not only in one place, but in every place the relevant enum is being switched on.

5. As I mentioned in my previous post, you can test polymorphic methods independent of the switching apparatus. Most functions that switch like the example the author gave will contain other code which cannot then be separately tested; virtual method calls, on the other hand, can.

6. Polymorphic method calls guarantee constant time dispatch. No sufficiently smart compiler is necessary to convert what is naturally a linear time construct (the switch statement with fall through) into a constant time construct.

Now, to answer the objections you offered. You said, "At least all the cases of the switch statement are in the same place instead of scattered across a bunch of files", to which I would reply that in the polymorphic method case, at least all the code related to a particular case is in the same place. In the switch statement case, you're spreading dispatch machinery and data-specific code all over your program, wherever you switch on an enum. In the polymorphism case, that dispatch machinery is abstracted by the compiler (and thus not present in your code at all) and all the code related to specific types of data is centralized in that type's class. The general code remains general, having no knowledge of the specific, per-type implementation.

You also said, "Polymorphism to me just seems like a switch statement you have to think harder about" to which I reply that on the contrary, polymorphism is great in that you don't have to think about it at all. A programmer attempting to demonstrate that a switch statement is correct must delve into the switch statement and show it to be correct for each case. A programmer attempting to demonstrate that a polymorphic call is correct need only ensure that the call's abstract preconditions are satisfied, and can consider the actual implementations of that call to be black boxes that he need not look into.

In response to your disclaimer, I would say that I mean no offense, but it's very possible that Sapir-Whorf is impacting your language preferences here. You find what you do most to be easiest to understand, and what you do most is switch statements, not polymorphism. I am no doubt afflicted with the same condition, but I think as I demonstrated above, there are many objective reasons why polymorphism is superior to a switch statement in most cases.

Post reply on HN