Comment by zahlman
2 days ago
> Often, avoiding abstractions leads to simpler code.... But if you do it this way, we think you didn't use enough abstraction so we reject you.
I think you've unwittingly bought into your hiring team's fallacy that classes are somehow essential to "abstraction". They are not. Wikipedia:
> Abstraction is the process of generalizing rules and concepts from specific examples, literal (real or concrete) signifiers, first principles, or other methods. The result of the process, an abstraction, is a concept that acts as a common noun for all subordinate concepts and connects any related concepts as a group, field, or category.[1]
The fundamental abstraction in computer programs is the function. A class is principally a means of combination that sometimes incidentally creates a useful (but relatively complex) abstraction, by modeling some domain object. But the most natural expression of a "generalized rule" is of course the thing that takes some inputs and directly computes an output from them.
Of course, we also abstract when we assign semantics to some part of the program state, for example by using an enumeration rather than an integer. But in that case we are doing it in reverse; we have already noticed that the cases can be generalized as integers, and then explicitly... enumerate what it is that we're generalizing.
(The reason that "FFT" etc. classes are so grating is that the process of that computation hardly makes sense to model; the input and output do, but both of these are just semantic interpretations of a sequence of values. You could staple a runtime "time-domain" or "frequency-domain" type to those sequences; but the pipeline is so simple that there is never a real opportunity for confusion, nor reason for runtime introspection. I almost wonder if the hiring team comes from a Java background, where classes are required to hold the code?)
If I were writing the convolution, it would still probably involve quite a few functions, because I like to make my functions as short as feasible, hewing closely to SRP. Perhaps the ring buffer would be a class — because that would allow a good way to separate the logic of accessing the underlying array slots that make the ring buffer work, from the logic of actually using the ring buffer to do the convolution.
(I'm not sure offhand what you'd need to convolve with to get the same result as "zeroing out the second half" of the FFT. I guess a sinc pulse? But the simple convolutions I'd think of doing to implement "low-pass filter" would certainly have a different frequency characteristic.)
Well, I substituted the task for a different but related one, so the substitute task is not fully specified in detail and perfectly mathematically correct - just good enough to show the principle.
We have given extra points to a candidate for having an FFT class even though it should obviously be a function. And the comments clearly indicated that candidate simply thought everything should be a class and was skeptical of things not being classes.