
FizzBuzz in Too Much Detail - boyakasha
http://www.tomdalling.com/blog/software-design/fizzbuzz-in-too-much-detail/
======
mathieuh
It's good, but do you seriously think that's going to get past review? Here's
a much better corporate-level version of FizzBuzz:
[https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...](https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition)

~~~
benihana
It's so loosely coupled that it's completely lost its hold on reality

~~~
jnbiche
It's so loosely coupled it'd fit it at a swingers meet-up!

------
a_bonobo
Ruby has the added bonus of Flip Flops to make everything even more opaque!

    
    
        a=b=c=(1..100).each do |num|
          print num, ?\r,
            ("Fizz" unless (a = !a) .. (a = !a)),
            ("Buzz" unless (b = !b) ... !((c = !c) .. (c = !c))),
            ?\n
        end
    

Add comments as needed

Source:
[http://www.reddit.com/r/ruby/comments/2n987g/the_flip_flop_o...](http://www.reddit.com/r/ruby/comments/2n987g/the_flip_flop_operator_in_ruby/cmbiwt8)

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

~~~
phamilton
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.

~~~
alexandercrohde
>> "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](http://alexrohde.com/zennish/index.html#/challenges)

------
stevewilhelm
Articles like this one make me wonder what percent of the development
community actually uses TDD.

Shouldn't it be natural, even expected, to see the tests that drove each
iteration of abstraction?

I am particularly interested in how one defines and implements tests for
scaling and performance requirements like the 'Lazy Generation' example.

Now the standard response will be that it's an article (or programming book,
or interview question) so for the sake of brevity and clarity we omitted the
test.

Wouldn't well defined tests help shape the correct amount of generalization
and abstraction?

~~~
the_af
Aren't you assuming TDD is a reasonable way to drive the design of algorithms?
I would not expect someone to design fizzbuzz-like functions using TDD.

(I would expect to see tests, sure, but tests aren't TDD).

------
platz
I still think the "Naïve" implementation is the best one given the actual
specification of the problem, and not some made-up specification and
assumptions that solve a different problem than the one actually being asked
(which may be more interesting, but that is beside the point).

~~~
simonw
That was the conclusion of the article, if you scroll down to the bottom. "The
final implementation represents a veritable explosion of complexity".

------
ufmace
I think the point is more clearly stated in the TDWTF Soft Coding article[0]

Best quotes:

> This brings us right into the definition of Soft Coding: the practice of
> removing “things that should be in source code” from source code and placing
> them in some external resource.

> The whole point of software (hence, the “soft”) is that it can change that
> it will change. The only way to insulate your software from business rule
> changes is to build a completely generic program that’s devoid of all
> business rules yet can implement any rule. Oh, and they’ve already built
> that tool. It’s called C++. And Java. And C#. And Basic. And, dare I say,
> COBOL.

[0]
[http://thedailywtf.com/articles/Soft_Coding](http://thedailywtf.com/articles/Soft_Coding)

------
yason
I'm glad they got rid of the 'puts' calls in the end.

It was irking me to naively assume that you would always be asked to _print_
the answer sequence.

------
WatchDog
Also see FizzBuzz Enterprise Edition

[https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...](https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition)

~~~
sjg007
brillant.

------
brudgers
Hardcoding 'Fizz' and 'Buzz' inhibits internationalization.

------
wz1000
Here's a version in Haskell that has the same functionality:

    
    
        fizzbuzz i triggers = map (\x -> fromMaybe (show x) $ 
                                                   liftM mconcat (sequence triggers) x) 
                                  [i..]
    
        fizzbuzz 1 $ [\i -> ["Fizz" | i `rem` 3 == 0]
                     ,\i -> ["Buzz" | i `rem` 5 == 0]
                     ]
    

Its just me playing around and trying to be clever.The way FizzBuzz can be
expressed as a Monoid is cool. The rest is just plumbing.

    
    
        mconcat [Just "Fizz", Just "Buzz"] = Just "FizzBuzz"
        mconcat [Just "Fizz", Nothing    ] = Just "Fizz"
        mconcat [Nothing    , Nothing    ] = Nothing
    

Note that this requires {-# LANGUAGE MonadComprehensions #-} to compile. Thats
for the sugar used when constructing the triggers.

~~~
jacquesm
I'm sure that Haskell can do better than that in the readability department.

~~~
wz1000
It can, I was just trying to be clever :P

For one, I don't need to drag monads into function composition:

    
    
        fizzbuzz i triggers = map (\x -> fromMaybe (show x) $ 
                                                   mconcat $ triggers x) 
                                  [i..]
    
        fizzbuzz 1 $ \i -> [["Fizz" | i `rem` 3 == 0]
                           ,["Buzz" | i `rem` 5 == 0]
                           ]

------
Argorak
I still prefer using symbolic languages for problems of such complexity. Such
as... Ruby.

[https://github.com/sferik/active_emoji/blob/master/samples/f...](https://github.com/sferik/active_emoji/blob/master/samples/fizzbuzz.rb)

------
fizbin
The ruby quiz did a round of this back after fizzbuzz had already jumped the
shark the first time:
[http://rubyquiz.com/quiz126.html](http://rubyquiz.com/quiz126.html)

I personally thought that my two entries were pretty amusing:
[http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-
talk/...](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/254139)
and [http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-
talk/...](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/254354)

------
kelukelugames
If I get asked fizzbuzz in an interview then I'm going to drive my interviewer
insane with a switch statement.

case 0:

    
    
      print "fizzbuzz";
    

case 1:

    
    
      print 1;
    

case 2:

    
    
      print 2;
    

case 3:

    
    
      print "fizz";

~~~
yandie
Your solution failed to satisfy the requirements. You need to print the number
for 1 and 2.

~~~
kelukelugames
thanks!

------
jessaustin
_By extracting the modulo operator (%) into its own function, at least we 've
made the code more self-documenting. If someone else were to read the code and
they didn't understand how the modulo operator worked, they could work it out
based on the function name._

Someone's taking the piss. Would anyone in the "audience" for FizzBuzz code
(coders, managers... HR?) really not understand modulo? That seems like kind
of the point of FizzBuzz.

Sure the whole thing is a satire, but this aspect is sort of straw-mannish.

~~~
placeybordeaux
Did you finish the article?

~~~
jessaustin
Yes that's why I specifically noted "sure the whole thing is a satire". I just
felt that this particular aspect of the satire was unfair.

~~~
placeybordeaux
Apperently I didn't read the comment.

I think the point being that fizzbuzz is already a strawman of a programming
excersize.

------
nakovet
Now would you consider a smarter move to do the following in an interview:

\- gem install your-fizzbuzz-package

\- require 'your-fizzbuzz-package'

\- puts FizzBuzz.range(1..100)

?

My point being why reinvent the wheel.

~~~
simonw
If an interviewer asks FizzBuzz, it means they want to do a quick sanity check
that you can write code to solve a simple problem. Answer the question and the
interview can move on to something more interesting.

If you try to give a "clever" answer at this point rather than collaborating
with the interviewer, it's likely to give a bad impression. A good interview
process isn't just looking for people who are strong programmers, it's looking
for people who are good engineers - and good engineers are people who
collaborate well rather than trying to prove a point at the first available
opportunity.

~~~
collyw
I personally would find it a more experienced approach to look up a
prewritten, tested library, used by other people.

~~~
rakoo
It's not the point. At this point the interviewer isn't asking whether you can
ship something, he's asking you whether you understand code or not. You need
to fully comprehend what you're shipping, whether you imported it from a
tested library or you built it yourself.

~~~
collyw
You should have seen the shambolic mess of a Python script I inherited from a
colleague. The script was doing bash calls, to call itself with different
arguments. Functions generating functions, not because of any high level of
abstraction, but because she didn't know how to write a module. The code
inside was more complex than fizzbuzz, but the way it was shipped was beyond
terrible.

Coding something like fizbuzz is usually day one of a programming course.
Using modules maybe day 2 or 3? I would see it as a sign of a more mature
developer.

~~~
rakoo
That's exactly the point of fizzbuzz: weed out those who clearly can't code.
Only when the fizzbuzz test is passed can we start going into interesting
parts, where an interviewer can assess whether you're a (truly) mature
developer.

------
contravariant
That's not really an optimal way to check divisibility though, if you want to
be quick try:

    
    
        fizz = (uint)i*2863311531 <= (uint)i;
        buzz = (uint)i*3435973837 <= (uint)i;
    

Should work for fine for i<=1000.

Edit: changed "<" to "<=", otherwise it fails when i=0.

~~~
kazagistar
He mentions ruby uses bigintegers, while this assumes something else, right?

~~~
contravariant
The above assumes unsigned 32bit integers. It abuses integer overflow. Perhaps
I should have stated that more explicitly.

------
Tiquor
This is the best FizzBuzz articles that has come out lately.

~~~
VLM
It helps having this article next to (nearby) the HN article discussing the
80K static coding violations in Toyota throttle position sensing code, or
whatever it was exactly.

THIS article didn't get into it very much, but "obviously" you'll have four
times the bugs in a highly abstracted 40 part piece of code, than in a much
simpler, less capable 10 part piece of code.

Reality is bug count never scales at a rate as low as linear with code length
of course.

At any rate the two HN articles are both better if read at the same time.

------
Shorel
I only got to the parametrized version in C++ myself.

Nice reading.

