5 ms·
> A long function is easier to understand than an exploded one. This is a pretty controversial position, and quite situational in my opinion. I absolutely agre
by ragona 8y ago
> A long function is easier to understand than an exploded one.
This is a pretty controversial position, and quite situational in my opinion. I absolutely agree that having to hop all over the source to understand something is frustrating, but that doesn't mean that very long functions are the right solution. Some combination of reasonably named helper methods and a function flow that makes the logic easy to parse should be the goal; either end of the spectrum is a problem.
- networkimprov 8y agoI took issue with this because it's a conventional wisdom, and does a fair bit of damage. Single-caller functions attract other callers over time, gain backwards-incompatible features, and result in regressions.
- Scramblejams 8y agoThis is one reason I like nested functions. They’re not available to the surrounding scope so they don’t succumb to these weaknesses, while also allowing you to organize your very long function internally by task. I use ‘em in Python all the time. It’s a bummer that more languages don’t support them, though you can get there with lambdas too, sometimes at the cost of more syntax.
- networkimprov 8y agoGo has closure functions; great feature. One of the (few) things I like about Javascript is the ability to define a closure anywhere in the containing function, so it appears in the order of operations: function f() { setTimeout(fDing, 2000); g(); function fDing() { ... } }
- johndubchak 8y agoDisclaimer: I have no Golang programming experience. I am curious with this approach though...you're nesting behavior and/or logic, doesn't this further obscure the meaning of the code and contribute more to the need to jump around the source in order to figure it out?
- SaltyBackendGuy 8y agoNow write a unit test for function fDing() { ... } Honestly with modern JS I am not sure this feature is that great. Looks more like a code smell these days imo. Edit: Formatting
- Roboprog 8y agoNow write a unit test for the inline block of code within the longer function which would have become the nested function??? You write the test (where any is needed) for the outer function. Edit: the start of the discussion was about using nested functions to decompose what otherwise would have been “unpartitioned” long functions. Such blocks of code nested within a long function would not be possible to unit test, either. Unit tests, rather than integration tests, are usually bogus, anyway, though.
- int_19h 8y agoYou write unit tests for units of code. A function with nested functions inside of it is a single unit of code; that's essentially what those functions being nested, and hence not directly invokable from the outside, indicates.
- kazagistar 8y agoMake private functions that are only visible to the current module. Then write your unit tests directly in that same module, next to the functions, so they can access them even when the rest of the world cannot. Of course, this requires sensible language support.
- Roboprog 8y agoHierarchy vs list. I don’t want a list (of subroutines). I want a tree of self contained routines. Only your containing routine uses you. Which “private“ routines use which? (I know the IDE will tell me about this routine, and that routine, but I don’t want to have to ask) Your employer doesn’t want you testing getters, anyway, but rather features. Unit test fanatics need to stop. I guess unit tests were useful for C++, when it was constantly crashing everything :-( C++ and its legacy need to ride off into the sunset, already.
- vram22 8y agoGo has anonymous functions too. The Go Programming Language book (Kernighan and Donovan) has some examples of them.
- ragona 8y agoYeah, agreed. I do this in Rust a lot too, and I picked it up while writing a lot of Python.
- Roboprog 8y agoA bit of our “heritage” in programming destroyed by the C family of programming languages Pascal, like Algol, had nested subroutines for decomposing longer operations without leaking the details. Nested functions is one of the things I like about JavaScript as well.
- Someone 8y agoC has static functions for decomposinglo ger operations without leaking the details. For better or for worse, taking advantage of that forces you to keep source files fairly short and cohesive in functionality.
- int_19h 8y agoYou are still leaking the details of the function that is the sole caller of those other functions. It's not leaking across translation unit boundary, but it's not the only one that matters.
- pjmlp 8y agoML derived languages, Julia, D and C# support them.
- Gibbon1 8y agoGNU C supports nested functions as an extension. I use them for the exact reasons you mention.
- favorited 8y agoThat extension results in executable stack memory, which is going to be a non-starter for many developers.
- Gibbon1 8y agoI believe that that only happens if you pass a nested function as a function pointer. Then gcc emits a trampoline. If you just call it from the enclosing function it's fine.
- tigershark 8y agoC# has inner named functions.
- xtian 8y agoSee: http://number-none.com/blow/john_carmack_on_inlined_code.html http://number-none.com/blow/john_carmack_on_inlined_code.htm...
- ra7 8y agoThe summary is great: > If a function is only called from a single place, consider inlining it. > If a function is called from multiple places, see if it is possible to arrange for the work to be done in a single place, perhaps with flags, and inline that. > If there are multiple versions of a function, consider making a single function with more, possibly defaulted, parameters. > If the work is close to purely functional, with few references to global state, try to make it completely functional. > Try to use const on both parameters and functions when the function really must be used in multiple places. > Minimize control flow complexity and "area under ifs", favoring consistent execution paths and times over "optimally" avoiding unnecessary work.
- kazagistar 8y agoAn excellent balance is to try to make a function only do one level of abstraction at a time. It's a bit of a flexible guideline, but basically you shouldn't call `isUserActive`, do some complex arithemtic, read extract data from a complex data structure, and call a templating engine in one function, since those a results all different levels. As long as what are doing is approximately the same type of thing, it is fine to do a lot of things without breaking readability.