Hacker News new | ask | show | jobs
by drostie 4069 days ago
I take serious issue with the "lesson" that this article is trying to teach at the end, which is that you should not generalize your particular problem into something abstract, solve that abstract problem really well, and then solve your particular problem as an instance of that problem.

Modeling your problem as FizzBuzz is a good way to model an unrealistically simple problem. FizzBuzz itself is only meant to filter out the vast masses of applicants who are struggling to find anything in the job market and therefore apply to any job they see hoping that someone will recognize them and take pity on them. It's not a realistic starting point.

Alan Kay's words are really insightful on this matter; he says that "the right perspective is worth 80 points of IQ." If you can figure out the right way to look at the problem (the right generic problem to solve given your specific constraints) then it's like being much smarter than any ordinary programmer really is.

He gives a much more instructive example: the Windows operating system. This thing is millions of lines of code, so much that if you printed it out in textbooks it'd stretch to the top of the Empire State Building. This was produced by a bunch of people doing exactly what Tom Dalling is suggesting: work only on your specific subproblem, do not solve the generic problems of "how do I make an operating system?", etc. There's no intrinsic reason that a graphical operating system needs to be so big that nobody can read it in a lifetime.

And the bugs that exist in Windows are undebuggable. With that many different components at play in the greater ecosystem, knowing which two are interacting to cause the problems that plague you requires an unbelievable amount of insight into what the computer is doing when it performs those quirks.

I agree with the specific point that software bloat sucks; I'm working with Ext.JS right now and boy is it bloated with internal abstractions that don't make much sense. Fortunately they isolate other people from dealing with those abstractions, but if I were at Sencha developing on the product I'd constantly be wondering "why do we make an 'Operation object' for the thing that the user wants to do? What's the real point of that?" etc.

4 comments

> I take serious issue with the "lesson" that this article is trying to teach at the end, which is that you should not generalize your particular problem into something abstract...

The problem, simply stated by Emil Persson is "Premature optimizations can be troublesome to revert, but premature generalizations are often near impossible."

Or, less delicately phrased by Chris Eric -- "Premature optimization, that's like a fart. Premature abstraction is like taking a dump on another developer's desk."

The root problem is -- you think you know all the possible use cases, you don't. You think you can see the future, you can't. Solve for what is in front of you -- abstract it when you need to for reuse.

As for Alan Kay and his fight against complexity (which is fair and nobel fight, great video on it: https://vimeo.com/82301919) -- he is arguing for the RIGHT abstractions from the perspective of DSLs ... with all the good (and very, very bad) that entails. That said, it is 7 levels of bullshit when you get down to "deploy to metal". Sure, it is a few hundred lines of code for a DSL and OMeta to render geometry -- but skip to 1:40:00 for the real scoop. It was incredibly hard to get to run with any level of performance on ACTUAL hardware in the REAL world. Alan Kay even puts forth that you should always keep the option of "rolling your own hardware", which sadly speaks to a disconnect with ACTUAL software development (and hardware development for that matter). There is no doubt he is a legend of CS (and brilliant), but I simply think his perspective is too far away from reality.

"Software does not run in a magic fairy aether powered by the fevered dreams of CS PhDs." -- Mike Acton (https://youtu.be/rX0ItVEVjHc)

The point I saw (and heartily agree with) is to be deliberate. DRY is an optimization. What is the cost of DRY? What are the costs of not being DRY?

I think we frequently fall into the trap of doing DRY "because we're supposed to" rather than on a case by case basis evaluating whether or there is a net expected benefit.

That doesn't always mean taking a hard YAGNI line. There are plenty of opportunities for DRY that don't incur a big cost but enable simplicity in future development. It's fairly simple math (though it requires some degree of arbitrary numbers). <Expected cost of refactor (time and added complexity)> vs <Expected benefit (saving future time)> * <Likelihood you will need to update this code>

If you know you're most likely going to revisit the codebase in a month and it's a fairly simple refactor then go ahead and do it.

>> "Dry is an optimization. What is the cost of DRY? What are the costs of not being DRY?"

Agreed 100%.

I actually made a javascript programming game to try to find explore that balance: http://alexrohde.com/zennish/index.html#/challenges

At each step, this abstraction of FizzBuzz may have "gone wrong" - parameterizing is only one way to abstract, and it adds a lot of symbolic content that may not lead to a solution.

Sometimes you want the data to describe which code path should be run on it, and if that's the feature being added, you end up with a very different outlook on the solution space - depending on your preferred style and thinking, you could end up with an inherited class, an interface, a "FizzBuzzData" with an enumerated value describing codepath, communication with a SQL database...there are a lot of options.

Hence, one should always be more suspicious about self-harm through a bad factoring, than about "dumb code."

Corollary: if you only have 2 examples of your abstraction, there's a fair chance that you don't have the proper perspective. And, imho, building abstractions from improper perspectives is worse than not building abstractions from proper perspectives.