Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I would guess that 95% of extensible systems are never extended :-)


By the clients, sure. But by the original authors?

This design (it's the basic "convert a switch statement to polymorphism" refactoring) turns a ball of mud switch statement into several independently comprehensible classes. Operations can be understood, verified and tested apart from the whole evaluation apparatus.

No doubt many programmers today massively (perhaps even criminally) overengineer their software, but the fact remains, the example chosen by the author is a really bad one.


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 polymorphic method is far better for that than the switch statement. A programmer who chooses the latter over the former is being shortsighted.


"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.


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.


Yes, but how much time does it save the other 5% of the time?

If the other 5% of the time stuff takes off and becomes standard throughout the projects using your code, then it can more than make up for it.





Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: