Grouping Java methods using custom code folding regions with IntelliJ
Simulating the lost Smalltalk feature of method categories in Java IDEs.
Information Chunking for the win
Providing mechanisms to group things that are related is a powerful organizational feature. Java packages are great for information chunking in projects with more than seven plus or minus two classes. Imagine if Java didn’t have packages. We would have tens, hundreds, or thousands of classes in a single directory, where we would have to leverage prefixes in our class names to avoid name collisions.
I wrote about how we used information chunking to scale the package design in Eclipse Collections in the following blog.
How can we organize methods?
In Java, the first most basic thing we can do is organize methods on classes and interfaces, based on the responsibilities of the class or interface. Once the number of methods in a class exceeds the seven plus or minus two target for short term memory, we have a few options. We can sort and group the methods in the file in some manner we find suitable. We can add visual separators to make it easier to recognize groups of things. The only tool we have to find things this way is the scroll bar or text search, or tools like Structure View in IDEs like IntelliJ.
The Smalltalk programming language has the feature of method categories to group methods. It had this feature when I first learned the Smalltalk programming language thirty years ago. Java, and no other file based programming language I am aware of, has this feature. Method categories are a hidden gem for information chunking in Smalltalk. They help you better handle scale, and make source code easier to navigate. Imagine all of your getters and setters in a class hidden away in a category called “accessing” that you can ignore.
The following is a class browser in Pharo Smalltalk for the Collection
class in the Smalltalk class library. Notice the third pane. This contains an alphabetically sorted list of method categories that can filter the methods displayed in the last pane. In the image below, I am looking at the methods in the “enumerating” category of the Collection
class, with the implementation of the reduce
method in the source pane at the bottom.
The benefits of grouping methods
The Eclipse Collections library is a great example where grouping methods into method categories can help make the library easier to learn and understand. The RichIterable
parent type in Eclipse Collections has 134 unique methods (not counting overloads). This number of methods is scary sounding. If we break this large number of methods into nine categories, the distribution becomes easier to comprehend and learn. The type is suddenly a lot less scary. There are a lot of features, but there is a much smaller group of capability categories.
Here’s what the distribution of the 134 methods for RichIterable
would look like if we balance the methods across nine method categories.
How can we group the methods like this so that our IDEs and JavaDoc can help us visually group and filter based on categories?
IntelliJ to the rescue
I learned recently from Tagir Valeev on Mastodon that IntelliJ has long supported a source feature of custom code-folding regions.
IntelliJ supports two styles of custom region folding. One is compatible with NetBeans (editor-fold
), and one is compatible with VS Code (region
/ endregion
). You can only choose one alternative. I have chosen the VS Code compatible alternative.
The custom code folding feature in IntelliJ IDEA is described section 13.4 Hide Distracting Code of “Getting 2 Know IntelliJ IDEA” by Trisha Gee and Helen Scott. There are screenshots and tips for using this feature on page 112 in the edition I have on my bookshelf. I bought this book because I know that IntelliJ has so many amazing features. Even though I have used IntelliJ for 22 years, I don’t know them all. I need to spend more time going through this excellent book to find new productivity tools I am missing from my coding workflow.
Organizing RichIterable into Method Categories
I have organized the RichIterable
type in Eclipse Collections into custom regions with descriptions and submitted a PR for review with the change. The comments in code look as follows
Region comment
Endregion comment
While it is not necessary to put the description in the endregion
comment, I have found it useful when scrolling through the source editor to spot the end of a region without having to guess at which region it is.
I am happy with the results. This is how RichIterable
looks with all regions collapsed in IntelliJ.
The RichIterable
class is more than 2,500 lines of code and text (E.g. javadoc comments). With all of the regions fully collapsed it is about 20.
The real awesomeness happens in the Structure View. IntelliJ sorts the regions alphabetically, and then sorts the methods in the regions alphabetically. Browsing RichIterable
in the Structure view with IntelliJ looks as follows with the regions defined. I included the source view on the right after selecting the select
method on the left. Notice that the select method is the first method in the region in the source code, but is sorted alphabetically in the structure view for the Filtering Methods region.
IntelliJ also adds the region folding to the Ctrl-F12 shortcut which brings up a method pop up view similar to the pane on the left. This is a rudimentary but decent approximation of method categories in a Smalltalk browser.
I think this will be very beneficial for contributors and committers who work on Eclipse Collections. Users of the library can also view the source of RichIterable
in a more organized manner, so long as they are using IntelliJ or VS Code. The custom region folding will not appear in Javadoc or be able to be shown as more than text in the GitHub browser.
Et tu, Javadoc?
While using region comments to build method categories works in the source editor in IntelliJ, I want to have the same view available in Javadoc for RichIterable
. No bueno, today.
I decided to take the low tech route of defining the method categories by hand in Javadoc with all of the methods in each category that link directly to the methods. It would be ideal if there was metadata attached to each method (e.g. a Method Category annotation) that the Javadoc tool could use to automatically build the Javadoc Index of methods by category. RichIterable
as a type doesn’t evolve too much, and when it does, we only add new default methods, so I am not worried about class churn causing this index to become stale or inaccurate.
As we can see, all 134 methods can fit on a single page when organized into method categories in Javadoc. It was a bit more work to do this, but I had already done the work of organizing methods into categories for RichIterable for a book I am currently writing on Eclipse Collections. I hope the book will be published in the next couple months. Stay tuned!
Method Categories in Java
Java will benefit from adding method categories as an annotation that documentation tooling can leverage. There are many classes in Java today like Stream
, Collectors
, LocalDate
, Scanner
, String
, StringBuffer
, List
, Map
, Collections
, etc. that could all benefit from grouping methods into categories to make it easier for Java developers to navigate and learn classes in the library. I noticed that some classes in Kotlin like DataFrame have begun to use the IDE specific custom region folding approach. I wonder if there are other examples of libraries using a similar approach.
For Eclipse Collections, I plan to work with the other committers and contributors on discovering ways for us to better organize our extensive API using method categories reflected through custom region folding. Hopefully, if a Method Category feature becomes available in a later version of standard Java, we will actively convert over to using that.
Thank you for reading, and I hope you found this useful.
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.