"Fold Method Bodies by Default" is something I deactivate immediately. After two decades of reading code, I am optimized to read syntax-highlighted code pretty hard. This just hides the stuff I am looking for - I read code because I want to know what it does.
For an overview I look at the outline. With wide screens, I think it is a much better place for a structural overview. I would be more happy to see advancements there.
In what sense is this missing? You can absolutely do this in vim so it must (by the principle of duality) also be present in emacs. Since he shows it in IntelliJ it’s obviously not missing from there so I’m assuming vscode has it also.
Automatic folding is something I almost always disable because I hate it when an editor tries to hide information from me. I strongly prefer to choose when I want things folded but by default to have things be as close as possible to the native text format just with syntax highlighting.
This is particularly true for PRs and diffs, where the details of implementation really matter and I would consider reviewing anything which was folded to be potentially extremely risky.
Sadly I believe this assumption is incorrect. VSCode supports folding, but not specifically method bodies (to my knowledge), and not by default (with or without a settings flag)
Weird. OK well you can absolutely do this in vim should you ever want to ':help foldlevel' and ':help foldexpr' will tell you how. Also 'conceallevel', although whoever came up with that I hope they suffer endless torment. I really hate that feature with a passion.
I find my self disagreeing quite strongly, I would hate that default :/
I find all kind of code folding massively throws off my spatial sense of the code. And if I'm browsing random code, then I often need to see the body too, to see if this is the place the work is done, or is it behind some abstraction down the line.
Perhaps I don't need it as much on c++ codebases, as the headers in a sense are that already. And Rust codebases I've dabbled in haven't been quite that big or overwhelming.
The outlineview/(the popup on top of buffer in many editors that lists the outline) is enough to finding my place in a file I feel lost. And if just looking how to use a lib, there is often some API documentation that helps along finding the right things (even if just barebones doxygen or rustdoc).
I'm sure this is as much of a habit thing as other editor preferences. Still I find it surprising how many people like code-folding :)
FWIW... LSE (Language Sensitive Editor) on OpenVMS (an operating system probably older than most readers) did this in the 1980s.
I think what this article is getting at but doesn't quiet explicitly say is people look at code for different reasons. If you're fixing a defect and you think you know where the problem lies, you may want everything to come up folded so you can get to the function you think you want to look at quickly. If you're trying to get a handle on what the code in the file does, you may want everything to come up unfolded. Or maybe you want to unfold all functions that take a particular data structure as a parameter.
The global settings at my installation for the LSE (Language Sensitive Editor) I mentioned earlier were set to fold all .c files. I initially found it annoying, but quickly learned the "unfold everything" key sequence. And then the "unfold this function once" which didn't unfold the contents of loops or ifs and the "unfold everything in this function." I was able to quickly get used to it and spent a year replicating the functionality in emacs.
But... I completely agree with people saying this should be a configurable setting.
And... if you implement this, please allow selective unfolding of different parts of the code.
Controlled by foldexpr in Neo/Vim IIRC, and I think VS proper has a shortcut Ctrl+M,Ctrl+O from memory. To round it out, VS Code has Ctrl+K+,Ctrl+2 where 2 is your level of folding of choice. Despite using these 3 editors every day and knowing the folding shortcut, I still don't collapse bodies as a matter of routine and I think I'd find it annoying if I had to toggle each open just to find relevant code.
There's also something to be said for the idea that code has a 2D shape to it and recognising parts visually can make navigating it a little easier if you're bouncing between a couple of areas for a particular change. I wouldn't want to obscure that, not by default anyway. But to each their own!
I am a grownup and therefore have no problem with "fold methods by default" being a toggle-able option, but this argument seemed odd to me:
> I think it is pretty obvious how awesome this actually is. Code is read more often than written, and this is one of the best multipliers for readability. Most of the code is in method bodies, but most important code is in function signatures. Folding bodies auto-magically hide the 80% of boring code, leaving the most important 20%.
I see where they're coming from, especially for codebases you already understand. But my workflow for new codebases is to at least visually inspect the method implementation before deciding whether or not to hide it. Does it actually look like boilerplate? Does it invoke any functions I haven't seen before? If it seems nontrivial, read it! Does the computation basically match my English-language description of the signature, or is there something deeper I missed? If everything was hidden by default I would either waste time un-hiding everything, or make lazy mistakes by saying "eh I'm pretty sure that's boilerplate." Coding by gluing together function signatures without reading the implementation is a recipe for making business-logic bugs.
My problem is similar to why I don't like using LLMs: taking the 80-20 thing at face value, you don't know which 20% of methods have nontrivial internal semantics which aren't conveyed by the type system, unless you already have a solid understanding of the code. (Note that Rust's type system does actually evade mutability / concurrency issues. But not incorrect business logic: it is not yet Lean or Idris.) I just don't like rolling the dice on this stuff - business logic bugs are horrible! They are difficult to suss out, especially if you weren't fully diligent in understanding the logic in the first place. Why would you roll a d5 on that?
Part of my aversion is that I am lucky enough to not be in a hurry. At my last job - 70 hrs/week of R and Python, reading papers, and writing emails - I would have been much more tempted for these "multipliers for readability," especially ChatGPT. But when you're not in a hurry, you are more sensitive to these multipliers also multiplying laziness and misconceptions.
That's probably a secondary issue. The suggestion is to change how code folding is done. Most IDEs can do some type of code folding, but in this case the author is asking for it to work in a certain way.
I don't think the example is all that good, because it's not the same code in both screenshots. The suggestion, as I read it, is that folding the "impl Body" shouldn't collapse the entire thing to impl Body { ... }, but instead collapse all the functions inside it, because that's actually more useful. So you'd get
It this was Python and you collapsed a class, then rather than getting
class User(AbstractUser): ...
you'd get:
class User(AbstractUser):
def is_manager(self): ...
def get_username(self): ...
It would perhaps even be a little neat if you could have a class collapsed and you'd be shown only public methods, if the language has the concept of public and private methods.
To build on the "hiding awful code", I think this could help show awful API/interface design. If you have a class with a few hundred lines of code and a number of methods, then you rarely get to see all your methods listed, their signature just drowns in a sea of code. The also add doc strings, then you now have a documentation view of your own code in the IDE.
The IDE isn't the root cause though, hiding code complexity is a patch.
Write cleaner code or use a higher level language that allows for more readable code. For example, some Go developers (...mainly Rob Pike, granted) eschew even syntax highlighting, as readable code shouldn't need colors to make sense of it.
I don’t see this as hiding code complexity or an alternative to writing cleaner code. It seems the argument is that when we come to a file/class/etc., that we should be initially presented with the outline rather than both the outline and details. It’s an approach to orienting oneself to a grouping of functionality, made first class by the IDE. It’s almost like opening a book and starting with the table of contents before diving into any specific chapter’s details. Allowing the reader to get a sense of what’s covered by this grouping of functionality before diving into the details. I haven’t tried this approach myself but it seems like an interesting exercise at the least.
>The IDE isn't the root cause though, hiding code complexity is a patch.
Write cleaner code
To clarify, the context of this article is using tools to understand someone else's code. (The author's setting: ">Suppose you are casually reading the source code of rust-analyzer, and are curious about handling of method bodies. There’s a Body struct in the code base, and you want to understand how it is used.")
In that particular perspective, the IDE is the root cause because it can be purposely designed to highlight/emphasize/annotate/correlate/hide ... various aspects of the unfamiliar codebase.
If the author then later chooses to refactor the code, that's when your advice of "write cleaner code" would apply.
Depending on your language you might be able to have it both ways - summary at the top, and implementation details down below. And it's just in the text itself, so it's as readable in Github as it is in an IDE.
-- Top of file:
data Indexer =
Indexer { indexDocuments :: !(CollectionName -> [Doc] -> IO (Either String Int))
, indexLocalWarcFile :: !(CollectionName -> FilePath -> IO (Either String ()))
, deleteDocument :: !(CollectionName -> String -> IO (Either String ()))
, isDocDeleted :: !(CollectionName -> String -> IO (Either String (Map Text Int)))
}
-- Further down:
indexDocumentsImpl env writer metadataApi compactor registry collectionName unsortedDocs = do
let ds = sort unsortedDocs
let nDocs = length ds
...
newLocalWarcFileIndex env warcFileReader writer metadataApi compactor registry collectionName warcFile =
batchedRead warcFileReader
warcFile
newIndexify
where
newIndexify :: Vector WarcEntry -> IO ()
newIndexify ds = do
...
etc.
I try folding from time to time but never really can get used to it (even though I work on massively big source files where folding function bodies actually should make sense). If your code requires code folding to be readable, it's really better to restructure your code to be more readable (and often it is better to not hide complexity because you can see immediately where the gnarly parts are - and by hiding those you're not doing anybody a favour).
has been around for at least a decade -- and that is basically helper code on top of functionality that's been available for longer than a fair few people reading this have been alive.
I love the JetBrains code folding, but I would hate it being on by default. Lots of arguments here about “you shouldn’t need this feature, just write better code”, which is fair, but unrealistic for massive projects you’re doing surgery on. It’s in those cases that I may use code folding to make a terrible file visually scannable again (only collapse bodies, as author mentions), then selective unfold bodies (potentially nested) as I need to see them. It’s not the most important feature TBH, but it’s nice that it’s there. I prefer it to the hierarchy tree because I don’t have to leave the editor part of the UI, and can use only keyboard shortcuts for selecting and folding code.
Hard disagree but it'd be fine to have it as an option, of course. The author mentioned an outline -- if we could have that as a separate page, easily toggled with a key combination, that'd be sweet.
Code folding by default triggers thoughts of the annoying, mostly useless TypeScript d files that VSCode dumps you in to when you ctrl/cmd click into a function. The only reason I do that is to see implementation details so I can figure out why something's not working. If third-party library d files were replaced by pre-folded source, I guess that'd be OK.
I was recently using IntelliJ to write some HTML. I suddenly noticed a wayward & character. It was blue so I assumed that was syntax highlighted... I quickly changed that to a valid entity and committed without really reviewing the code (i know I'm an idiot).
Turns out that JetBrains format the entity as the resulting character... a feature that was meant to make code readable had confused me. I had similar issues with clion which presents weird notations on the code with no indication of their purpose. This is a double edged sword.
That specific part of code folding is pure preference. I would rather my editor not just fold things on GoTo Definition. GoTo Definition already takes me to what I need to see. I use code folding to minimize large chunks of something in the way. Not to unload my visual workspace on every jump. Folding on specific commands means I’d have to unfold sometimes, extra commands.
So then not really a missing editor feature if it’s a small opt-in preference. The author assumes everyone wants this but then it will be entirely undiscoverable from the base level UI.
Also, while not automatic, if I use GoTo in sublime text, then Edit->Code Fold-> Fold All, it will fold everything I have not focused on, all the way around my code selection or indent level. Seems like you could cobble together a simple plugin or shortcut to handle the expected behavior.
I don't like folding because toggling folding state is clunky with keyboard only. I'm okay with fold/unfold all, but doing it manually fells like a chore.
I'd expect short, important method bodies that should be visible by default to vastly outnumber long and uninteresting method bodies that should be folded away by default.
This is, of course, my experience with mostly unexciting Java and Python; there should be options, maybe per language or per project, or even heuristics (e.g. fold long methods, by character count and/or line count, and recognized getters and setters but not other short methods).
It is unclear what is the condition of automatic folding of the second level and below.
If you are using "Go to..." a struct declaration or impl in Rust (or a class in other languages) it actually makes a lot of sense. If I'm going to a struct/impl/class I don't know yet which method do I won't to see. If you are just opening a file that you haven't open before though... I'm not so sure.
This is exactly how aider shares code context with LLMs using a “repo map”. It uses tree sitter to collapse relevant files into this sort of folded version, showing function signatures but eliding their bodies.
It's available in most IDE:s but I'd still argue that the best and most important way to accomplish symbol overview is in the text itself. Because it's so jarring to go between different views of the same outline. The outline doesn't (normally) show metadata/attributes, documentation, some times not even argument names etc.
So getting this right and ergonomic I think is important regardless of whether there is a symbol tree or similar (which can also be useful).
VIM already basically does this and can be configured to do it automatically with folding as the default, while providing pretty fine grained manual control on folding.
I used Mylyn's focus feature quite a lot back in the day. And I think Mylyn was revived, I just tried and it still works. However, it only hides projects/files/folders in views, I don't think it was ever hiding code within a file (or I remember incorrectly). It is pretty cool until it is not. And if it is not helping, you are constantly manually resurfacing hidden parts, which is annoying. This made me turn off the part that hides items not used recently and only turn it on when really working on some isolated parts in a huge set of projects. The other cool thing about it is that it is coupled with issue management (which you could sync with your issue tracker) and you could store the "focus" (which items are currently visible) in the context of an issue. So if you switched working on issues, it would only show the items relevant to the issue again.
BTW: In Eclipse JDT you can configure what kind of Java elements should be folded by default. The default config is that leading comments and imports are folded. Would be nice to be able to configure something like that via LSP.
"Fold Method Bodies by Default" is something I deactivate immediately. After two decades of reading code, I am optimized to read syntax-highlighted code pretty hard. This just hides the stuff I am looking for - I read code because I want to know what it does.
For an overview I look at the outline. With wide screens, I think it is a much better place for a structural overview. I would be more happy to see advancements there.
reply