I’ll take well-structured 1000-lines function over bad spaghetti of hundreds small functions any day.
I’ll take well-structured 1000-lines function over bad spaghetti of hundreds small functions any day.
I'm sure they exist - maybe some sort of exceedingly complicated data transform or something. But in almost every situation I've seen, a 1000 line function has countless side effects, probably sets a few globals, takes loads of poorly named arguments, each of which is a nested data structure which it reaches deeply into and often has the same for loop copied and pasted 10 times with one character changed.
Often a 1000 line function is actually 5 or 6 20 line functions. I'm sure there are legitimate exceptions, but I've never seen them.
Thats my personal opinion, and nothing more:
Something like complex one time financial/workflow/maintenance operation that includes calling dozens of different smaller functions, but very well structured.
It does not make sense to separate it more into different functions, because execution is generally linear and having to deal with tree of calls where some calls is depends on state of the previous is become cumbersome and makes reading and making changes more complex.
Again, thats my personal feeling, and nothing more.
This function is 1830 lines long. It's reasonably well structured I think. Although the #if 0 are maybe not so good.
If you changed a bunch of those to separate, pure (i.e. side-effect-free) functions it would if nothing else make unit testing a breeze, and then you'd be free to fix bugs in the logic without fear. As it is, if I had a bug in that huge function I'd be really worried about breaking some edge-condition or implied-state 500 lines up etc.
if (c == '\033')
term->print_state = 1;
else if (c == (unsigned char)'\233')
term->print_state = 2;
else if (c == '[' && term->print_state == 1)
term->print_state = 2;
else if (c == '4' && term->print_state == 2)
term->print_state = 3;
else if (c == 'i' && term->print_state == 3)
term->print_state = 4;
else
term->print_state = 0;
This could be turned into a pure function that takes c and print_state as input, and returns a new print_state which the outer function assigns. That's 12 lines turned into 1. term->print_state = newState(c, term->print_state);
(I am not a C developer so the sytax could be wrong).
Just because the outer function is impure doesn't mean it can't in turn call pure functions.Why some folks will absolutely insist that a series of manually-written case statements in a single thousand line function is the epitome of style, when there's a pure state machine model inside wishing you would free it from the shackles of if else if else if else....
There's a reason stacks are ubiquitous, they're much easier to fit in your head.
Depending on use and language, this may be "expensive" (e.g. you could be allocating for and then copying some huge data structure only to pass it back where is is simply copied over the top of the input), but this is where discretion comes in and decisions are made on what is appropriate (i.e. is performance critical, or is correctness and maintainability more important?)
Breaking out functions makes sense when you get either reuse or decoupling, but in this case you don't get any of these.
You would be able to see what it does at a high level at a glance and then drill down into the functions and sub-functions to focus on a particular part of it.
With this version, to get the high level overview you have to scroll through multiple pages of code and find the comments that say what each section does.
What happens if someone wants to use a different editor that doesn't have that feature or doesn't display it quite right anymore?
Lol.
edit: another one at 3826 with a preprocessor define interleaved.
Bonus: Uncle Bob teaches us not to use comments.