3 ms·
I once had to work on someone else's function that was several thousand lines long, written in 'C'. Some of the code blocks went on for pages. The code had lo
by jbritton 10y ago
I once had to work on someone else's function that was several thousand lines long, written in 'C'. Some of the code blocks went on for pages. The code had lots of loops and conditionals. The code was nearly impossible to understand. My first instinct at trying to understand something like this is to break it down into pieces that I can understand. I like to pull out the body of for loops. for loops often represent either map(fun, sequence) or filter(fun, sequence) or fold(fun, sequence). More generally though, I just look for large code blocks, those delimited by {} and pull those out. If one is familiar with functional programming, one may recognize the block as some common function, maybe a partition or a grouping. Functional languages are very good at abstracting away common patterns. I like to look at a block of code and see if it matches one of these patterns. With the above large function, pulling anything out was a huge chore. This was a time before refactoring tools. This large function had tons of variables, all declared at the top. The scope of these variables was huge. Pulling out a block requires an analysis of what goes into the block and comes out of the block. What goes in, is not so hard, and you can use the compiler to help. What comes out on the other hand was near impossible. You need to determine if code below the block uses a variable set inside the block. In a smallish function, no problem, but in the one I was dealing with, near impossible. Essentially, you had to pass them all out. Only after tons of further refactoring of pulling out code blocks could one begin to see whether variables needed to be return values or were simply local temp variables. By pulling out a block from a large function, one gains a function that has defined input, defined output, a smaller state space of variables , a smaller amount of code ranging over the variables, a name, maybe a comment, and maybe some tests. This function is much more easily understood in this context than it is as code block in a large function. This large function showed me in great detail how horrible they truly are. Breaking the large function into many small ones was the only way to actually understand it. It turns out that the huge number of local variables were really a union of many smaller sets. One set may have been completely local to a code block. What became obvious to me is a kind of complexity measure. The more variables and the more code ranging over these variables the higher the complexity. I believe there to be a sort of exponential growth in complexity when adding variables and code length. When broken down sufficiently, the complexity of each function can become nearly trivial. One then needs to analyze how a bunch of trivial functions combine to make the whole. This is a much simpler task than analyzing the whole when it is one function. I can't prove it, but that is my experience. I think if one does a little study of a library in a functional programming language, like Haskell or LISP or Clojure to get a feel for what makes for a good abstraction, and ever has to deal with a hugely large function, I don't see how you could not come to the same conclusion that smaller is better. Can a function be too small? Well, I like this discussion of intent. Another piece of code that I once looked at had a fairly complicated expression and involved some bit testing. It was a one liner. Its purpose was determine if a door was outside of normal working hours. This was something that could be given a meaningful name as a function, and it is much better than seeing the ugly expression. So size alone cannot dictate if something is too small. In general, I think you will instinctively know if something is too small. If the calling function doesn't become simpler due to the presence of this other smaller function, then the small function is not helping. Usually, if I spot this situation, it is an indication that the problem has not been factored very well. It is like doing a textbook math problem and getting a weird fractional result. You know you goofed somewhere. It is time to re-examine the problem for a better solution.
- mavelikara 10y agoIs this satire?