4 ms·
Part of "growing up" as an OOP developer is learning what to do when. I think this is the real problem with this particular example - because the author wanted
by bermanoid 16y ago
Part of "growing up" as an OOP developer is learning what to do when.
I think this is the real problem with this particular example - because the author wanted to make this into an anti-pattern joke, he didn't actually think about what a Real Programmer actually trying to make good use of the extra keystrokes would do in this situation.
The "requirements" that he's using to build up this bloat appear to be:
1) The result might be really, really, big, so no factorial function worth a damn should be limited to a normal int.
2) We might want to swap out implementations of our factorial function, for instance, to cache intermediate results, to use a loop, to use recursion, etc.
3) We should be able to add new implementations without modifying class files already written, and we should be able to select implementations at runtime.
Fine, then. These could be 100% realistic requirements if we were talking about some more substantial or important piece of machinery than a factorial function, so we really might have to satisfy these things, in which case the three-liner would be completely and utterly unacceptable.
So let's say we're in that situation, then. A good Java developer still would never write the code the way it came out in that post, because the abstraction doesn't go far enough, and it's obvious. Almost every time he writes "FactorialAlgorithm", we could just as well replace that with "Algorithm" (or maybe better, "BigIntegerAlgorithm"), and now instead of building up a whole bunch of architecture just to support one stupid algorithm, we've spent a bit of effort to make all of our (big integer) algorithms swappable. That memoization stuff could almost immediately be refactored up and out of the individual implementations, so it would take but a single method call or flag to add that ability to an algorithm, and so on.
I'm not saying that the particular architecture that gets built up to do this stuff is necessarily pretty, that Java-style OOP is an optimal (ha!) or even passably efficient way to achieve these constraints, or that you should do these types of abstractions before you know you absolutely have to. By all means, if you don't have any other requirements on the table, write the naive factorial, FFS! But when you've got to abstract things, rule #1 is to make sure you pull everything "up" far enough, otherwise you're never going to extract enough value out of the added complexity to keep yourself sane.