4 ms·
The following alternative style (vs. the 3 presented by Carmack) is one that I find very easy to read. algorithm() { do_small_thing_one(); do_small_t
by javert 12y ago
The following alternative style (vs. the 3 presented by Carmack) is one that I find very easy to read.
algorithm() {
do_small_thing_one();
do_small_thing_two();
do_small_thing_three();
...
do_small_thing_X();
}
Advantages over Carmack's Style C:
1. Substitutes comments for accurate and specific function names. Why better? Because comments can get out of sync with the code.
2. You can quickly see the sub-steps of the algorithm, rather than reading a multi-page-long giant function with a ton of comments.
When using this style, the inner functions are not visible outside of that source file (you can arrange this depending on your programming language). Then it's easy to make sure they are only called once within the source file, or only called appropriately.
That's because I agree with Carmack that functions called from lots of unrelated places are a terrible thing.
(Edited for clarity after people pointed out that it seemed like I was just advocating for Carmack's style A or B.)
- pajtai 12y agoThat is option A and B. I think the entire article is describing the down sides of that. You can't see if you a repeating the same stuff in multiple small things.
- javert 12y agoI guess this kind of got lost in my comment, but the point is that these functions are never called from anywhere else. You achieve that by not exposing them in header files.
- roghummal 12y agoIf they aren't called from anywhere else and they're only called once (in the parent), it might be better to inline them. Doing so goes against the urge to decompose as much as possible but it'd make the code easier to follow for the next guy. "What does do_small_thing_X do?" Even when the next guy is you, a year from now. Do you really remember what do_small_thing_X does?
- javert 12y agoYes, I do remember. If the function name isn't sufficient, you need a different decomposition of the problem. Another advantage of doing it my way is that you can put multiple comments inside those "small" functions if you need to. So you get two levels of decomposition. That really helps if your overall algorithm is broken into smaller parts that still need some explanation.
- otikik 12y ago> Do you really remember what do_small_thing_X does I don't need to wait a year, I forget what functions do the next day. So I try very hard to give them descriptive names. So I don't have to remember (and I just have to read).
- taeric 12y agoI'm not seeing how this is different from either of style A or B. :(
- orbifold 12y agoAll those small procedures have to be defined somewhere, his style A and B are about where they are defined. His point is that inlining them guarantees that they are not called from somewhere else and that code folding can be used to structure the code.
- ufo 12y agoI am not convinced thats all that better than inlining and then using an editor with support for code folding. You can still get a high level glance at the substeps but are 100% guaranteed that the blocks of code are never called anywhere else instead of that just being a module-enforced convention.
- sheepmullet 12y ago"1. Substitutes comments for accurate and specific function names. Why better? Because comments can get out of sync with the code." Can you explain this a bit better? In my experience function names can just as easily get out of sync with the code. I've worked on many codebases that were full of small functions with misleading names.
- javert 12y agoFunction names certainly can get out of sync, just as comments can. But my experience is that it's less of a problem. Actually, there is an additional and probably much more important reason that I prefer "functions over comments", and that is the functions can be nested. With comments, I often find myself needing a big comment that describes the next several chunks of things, and each of those chunks has some comments, too. So call those "level 1" and "level 2" comments. People tend to distinguish these cases like: /* *************************** level-one comment *************************** */ and then /* level-two comment */ But what if you have something that really "should" be a level-two comment (because it's just one small thing that doesn't have subdivisions), but it comes after a level-one comment? Now you need an end delimeter for level-one comments, like this: /* ***************** done with that ******************* */ Now at this point, your code is nasty and non-readable and it's not obvious that things have been kept in sync over time. We could just avoid all this ambiguity by using nested functions that are nonetheless only called from one place and thus _could have_ been manually inlined in theory (but, per my practice, are not).
- killertypo 12y agowhat happens when `do_small_thing_one()` gets changed enough that the name of the function is no longer representative of the code? Comments and method names can fall out of sync. Comments at least require less to update and don't require re-factoring code in multiple places.
- dllthomas 12y ago2 can be achieved with folding in your editor. I suppose one could have an editor that optionally auto-inlines for presentation; I don't know of one.