Adopt the combo @returns tag javadoc syntax to avoid redundancy

Currently, we have javadoc that looks like

/**
 * Returns something.
 *
 * @param param1 blablabla
 * @param param2 blablabla
 * @return something
 */

The return looks duplicated. Of course this has two immediate issues:

  • this is more verbose than ideal
  • the description and the @return line can get duplicated
  • this promote copy pasting, which notoriously ends up causing inconsistencies at least as grating as the wrong advertised number of items in this list

JavaDoc 16 introduced the combo `@return` tags which helps get rid of the duplication. This would look like:

/**
 * {@returns something}
 *
 * @param param1 blablabla
 * @param param2 blablabla
 */

Which should be the exact equivalent to the former, up to the “Returns” at the beginning and the dot at the end of the description.

See for instance https://bugs.openjdk.org/browse/JDK-8256917 which introduces that syntax in the javadoc of the javadoc compiler itself (commit), or that test showing the result.

I propose this syntax for adoption to write the javadocs (edit: for getter-like cases like this). Vote up to 19 June next week (but we can postpone if convenient).

WDYT?

I think it’s a -1 from me for now.

Because the problem is not the repeat, it’s the fact that the javadoc is not good and should be improved.

And this proposal/vote is going to be used as an excuse to avoid writing good javadoc, which is now extremely easy with LLMs.

Maybe best is to show a real example from our code base where it would make sense to use your proposal (ie where we couldn’t find a proper javadoc to write). Maybe there are valid use cases tof it. But I fear that in most cases, it’s not valid uses.

Thanks for the idea though! I didn’t know about it :slight_smile:

Thx

hmm it’s not a VOTE atm, only a proposal

Note (in a separate post because for some reason my previous post got selected for pre-moderation (?!?)): I didn’t cherry pick the examples in the coming post. I haven’t done a comprehensive study of XWiki’s use of @return tags and descriptions, but I picked them randomly and didn’t have to dig much

See also https://dev.xwiki.org/xwiki/bin/view/Community/CodeStyle/JavaCodeStyle/#HDonotduplicatemethodcommentswithparameterscomments

The best practice already actually says to do this:

Instead of writing:

/**
 * Returns the key of the space to which this page belongs to.
 * 
 * @return - Parent space's key as String.
 */
public String getParentSpaceKey();

Write:

/**
 * @return the key of the space to which this page belongs to. For example "Main".
 */
public String getParentSpaceKey();

So you would just keep that advice add braces and remove the final dot there to adopt the feature.

So if that’s already current practice, I really don’t see the reason for the push back.

I disagree, the repeat itself is an issue and I show examples of this a bit later in this post.

But we can both remove the repeat, and also improve the javadoc in other ways.

And this proposal/vote is going to be used as an excuse to avoid writing good javadoc

I don’t see how. This doesn’t prevent us writing a good, dedicated description when that’s better. I hope bad descriptions will be usually rejected during reviews.

We have many examples in the XWiki codebase where the description mostly repeats the return and this proposal makes those cases better for people who read and write the code themselves.

One can find a lot of examples by grepping the xwiki-plaftorm code like this:

rg -F "* Get"
rg -F "* Retrieve"
rg -F "* Return"
rg -F "* Generate"

The mere existence of these 4 verbs (and probably more), in their first person or third person form (so 8 ways of doing it) to mean mostly the same thing shows that there are many inconsistencies caused by the absence of this feature.

See for instance xwiki-platform/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/web/ExportURLFactory.java at bc64d746c43ad9bb40e966d75e9de5d90aa18de4 · xwiki/xwiki-platform · GitHub :

/**
 * Generate an url targeting attachment in provided wiki page.
 *
 * @param filename the name of the attachment.
 * @param spaces a serialized space reference which can contain one or several spaces (e.g. "space1.space2"). If
 *        a space name contains a dot (".") it must be passed escaped as in "space1\.with\.dot.space2"
 * @param name the name of the page containing the attachment.
 * @param xwikidb the wiki of the page containing the attachment.
 * @param context the XWiki context.
 * @return the generated url.
 * @throws XWikiException error when retrieving document attachment.
 * @throws IOException error when retrieving document attachment.
 * @throws URISyntaxException when retrieving document attachment.
 */

Would turn into (with light editing to make it look a bit better - adopting this feature can be the occasion to perform such edits as well):

/**
 * {@return a URL targeting the given attachment in the provided wiki page}
 *
 * @param filename the name of the attachment.
 * @param spaces a serialized space reference which can contain one or several spaces (e.g. "space1.space2"). If
 *        a space name contains a dot (".") it must be passed escaped as in "space1\.with\.dot.space2"
 * @param name the name of the page containing the attachment.
 * @param xwikidb the wiki of the page containing the attachment.
 * @param context the XWiki context.
 * @throws XWikiException error when retrieving document attachment.
 * @throws IOException error when retrieving document attachment.
 * @throws URISyntaxException when retrieving document attachment.
 */

This is of course less repetition when writing and reading the javadoc source. You end up having more details in the generated javadoc at the place the return value is documented with less effort.

Another instance:

    /**
     * Perform a 3-way merge between the given objects.
     *
     * @param previousObject the previous object.
     * @param newObject the new object.
     * @param currentObject the current object.
     * @param configuration the configuration for the merge operation.
     * @param <T> the type of the object
     * @return an obtained merged object.
     */
    <T> MergeManagerResult<T, T> mergeObject(T previousObject, T newObject, T currentObject,
        MergeConfiguration configuration);

This turns into:

    /**
     * {@return a 3-way merge between the given objects}
     *
     * @param previousObject the previous object.
     * @param newObject the new object.
     * @param currentObject the current object.
     * @param configuration the configuration for the merge operation.
     * @param <T> the type of the object
     */
    <T> MergeManagerResult<T, T> mergeObject(T previousObject, T newObject, T currentObject,
        MergeConfiguration configuration);

The original writers must have felt like repeating themselves in the @return tag, so they rephrased the description with fewer details. Beside this unnecessary extra thinking to come up with an alternative phrasing because copy-pasting feels bad, that “returns the obtained merged object” phrasing reads a bit weird.

I’m quite sure the vast majority of cases are like this actually.

There are also at last several – if not many – places where we are already in the situation where the javadoc has no dedicated description but has a @return tag. It’s the case up to the example given in deprecation rules section of the development practices page:

/**
 * @param time the time in milliseconds
 * @return the time delta in milliseconds between the current date and the time passed as parameter
 * @deprecated replaced by {@link com.xpn.xwiki.api.Util#getTimeDelta(long)} since 1.3M2
 */
@Deprecated
public int XWiki.getTimeDelta(long time)
{
    return this.util.getTimeDelta(time);

or in the Javadoc Best Practices section itself:

Do not repeat the name of the method or any useless information. For example, if you have:

/**
 * @return the id
 */
public String getId()
{
    return this.id;
}

Instead, write:

/**
 * @return the attachment id (the id is the filename of the XWikiAttachment object used to construct this Attachment object)
 */
public String getId()
{
    return this.id;
}

(By the way, this is because of this section, and because I never read XWiki’s generated javadoc, that I thought it was okay to write javadocs without description and that the javadoc processor would do the right thing).

It seems to me adopting that feature would improve these occurrences as well, because suddenly the generated doc will have a description where it must appear.

Coming back to that advice:

Do not repeat the name of the method or any useless information

I know it doesn’t mean the same thing, but it seems that this feature helps with not repeating stuff, which is advised here. It would only make us more consistent with our own advice.


And this proposal/vote is going to be used as an excuse to avoid writing good javadoc, which is now extremely easy with LLMs.

It seems like you are contracting yourself: if it’s very easy with LLMs, why would one use such a mechanism as an excuse to avoid writing good javadoc?

But in reality, I don’t see how the existence of LLMs should have any bearing on the documentation practice. Whether you use them or not to write your doc, the result should ideally be the same (as in, if your LLM generates slop or subtle inaccuracies, that should be fixed before committing to match what a good documentation writer would have written by hand).

For LLM users, that’s also more concise javadocs and thus fewer token spent reading and writing those.

I personally mostly don’t use the generated javadocs unless the IDE happens to display it correctly at the right moment when I navigate the code (but never took the habit of relying on this), so those raw javadoc comments are what I see when I work with the codebase. And they are more verbose than needed. I also don’t use LLMs and don’t intend to, so I care a lot about how the javadoc looks in the code and how easy it is to write.

It seems to me we should trust the javadoc authors for having written and adopted this feature for their own codebase that it leads to better results in many cases, the opposite would be a bit weird. That’s somewhat an appeal to authority, but I’m inclined to believe that they are experts in this stuff and they know what they are doing. Why would they be wrong? I think this feature will help us writing less boilerplate and have more “time” / “cognitive energy” to focus on the rest of the javadoc and write it better.

Do you have examples of places where we risk doing the wrong thing with this new feature?

I still maintain that the content of @return should not be the same as the main content of the javadoc, and that this example is not a good way to write a good javadoc. It’s also not the purpose of the @return tag to provide detailed explanations about what the method does.

Here’s an example of what I consider a better javadoc method for this example:


 /**
  * Generates a {@code file://} URL pointing to an attachment inside the HTML export directory, copying the
  * attachment's content to that location as a side effect.
  * <p>
  * This is used during an HTML export (an offline, self-contained copy of wiki pages): the returned URL is a
  * <em>relative</em> {@code file://} URL so that the exported HTML can reference the attachment locally, without a
  * running XWiki server. The first time a given attachment is requested, its binary content is copied into the export
  * directory (under {@code attachment/<serialized attachment reference>}); later calls reuse the already-copied file.
  * <p>
  * If the attachment does not exist, no file is copied but a URL is still returned. This supports callers that build an
  * attachment URL independently of whether the attachment exists (for example the Color Theme Sheet, which uses
  * {@code $xwiki.getAttachmentURL($doc.fullName, '__tochange__')}), as well as links to missing attachments, which
  * correctly become broken links in the export.
  * <p>
  * Example: for an attachment named {@code logo.png} on page {@code Main.WebHome} of wiki {@code xwiki}, the method
  * copies the attachment to {@code <exportDir>/attachment/xwiki/Main/WebHome/logo.png} and returns a relative URL of the
  * form {@code file://attachment/xwiki/Main/WebHome/logo.png}. When the URL is generated for use inside an exported CSS
  * file, leading {@code ../} segments are prepended so the path stays relative to that CSS file.
  *
  * @param filename the name of the attachment (e.g. {@code "logo.png"})
  * @param spaces a serialized space reference which can contain one or several nested spaces (e.g.
  *     {@code "space1.space2"}); if a space name contains a dot ({@code "."}) it must be passed escaped, as in
  *     {@code "space1\.with\.dot.space2"}
  * @param name the name of the page holding the attachment
  * @param xwikidb the identifier of the wiki holding the page, or {@code null} to use the current wiki from the context
  * @param context the XWiki context
  * @return a relative {@code file://} URL pointing to the attachment's location within the export directory
  * @throws XWikiException if the document holding the attachment cannot be loaded
  * @throws IOException if the attachment's content cannot be copied into the export directory
  * @throws URISyntaxException if a valid relative URL cannot be computed from the export file path
  */

Note that this is a private method and we don’t mandate javadocs for private methods, but let’s assume it was a public method for the sake of the argument.

It does, because if we allow it, then writers will use it.

Yes, and they need to be fixed. Keeping the same bad javadoc is not a fix.

So your solution is a way to reduce exiting duplications in some cases but in no way does it improve the existing javadocs (unless you rewrite the content of the javadoc and if you do, you shouldn’t use this the @return construct in the main javadoc content.

Because it’s still less easy to use a LLM than to simply write the worst possible javadoc that matches our rules, and offering{@return} is providing a great excuse to write bad javadoc since you’re only focusing on what’s returned but that’s not the point of the main javadoc content (ie the part outside of the parameter and return explanations). That’s why there’s a @return tag btw. Otherwise it wouldn’t exist.

BTW having the main content and the return content be the same is a mistake/bug for me. The return is supposed to be short and only explain what is returned, but not what the method dooes, why it exists, the side effects, when it should ne called, provide examples, etc.

Your choice, but then you’re going to have a hard time be productive and write good javadoc (among other things, like writing tests systematically, etc).

Let’s see what the others say but ATM I’m maintaining my -1 (if it’s a vote, ATM it’s isn’t).

Thanks

(offtopic)
There’s an open question as to whether we still need javadocs with LLMs since LLMs are able to understand the code without javadoc, and they’ll be the ones writing code more and more (and even if there’s still a dev writing code, his/her LLM assistant can help). I think there’s still value for javadoc but not so much describing what the method does but why it exists (which LLMs cannot guess). But that’s another topic :wink:
(/offtopic)

I’m not sure why examples like xwiki-platform/xwiki-platform-core/xwiki-platform-export/xwiki-platform-export-pdf/xwiki-platform-export-pdf-test/xwiki-platform-export-pdf-test-pageobjects/src/main/java/org/xwiki/export/pdf/test/po/PDFExportOptionsModal.java at a734a62fb1506b59e87e768e2e33e247e886568f · xwiki/xwiki-platform · GitHub shouldn’t use this to improve the generated Javadoc. As @rjakse mentions, it is already our best practice to omit the main part in this case. I wouldn’t encourage it to be used for longer Javadoc comments, but in particular for simpler getters, it seems appropriate. So +1 to encourage using this instead of just omitting the main part which is our current best practice.

I think there’s a misunderstanding. We don’t have any best practice about this. What we have is a best practice to not duplicate the javadoc summary content and the return tag content (https://dev.xwiki.org/xwiki/bin/view/Community/CodeStyle/JavaCodeStyle/#HDonotduplicatemethodcommentswithparameterscomments).

But, and that’s important, this is not about recommending to not have a summary content. It’s the opposite actually, as we say to use How to Write Doc Comments for the Javadoc Tool (indicated at https://dev.xwiki.org/xwiki/bin/view/Community/CodeStyle/JavaCodeStyle/#HJavadocBestPractices ) which recommends to write some good first sentence and in general some good summary comments.

I think this is the main important point. This proposal was NOT about what you say here. I see nowhere in the proposal that it’s about simple getters, etc. It says: "I propose this syntax for adoption to write the javadocs. " without providing a context of where/when to use it and when not to.

After some research here’s my opinion:

  1. It’s a bit better than using just a @return ... javadoc tag with an empty summary, because, the first sentence is copied automatically by the javadoc tool into member, class/interface or package summary. See How to Write Doc Comments for the Javadoc Tool

    Quick note that the javadoc could also have been modified to do that when there’s no summary (See https://bugs.openjdk.org/browse/JDK-8075778?focusedId=13622054&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13622054), but apparently it’s not been chosen.

  2. We should still require, as a best practice, to write good summaries as much as possible and not limit the summary to be a short first sentence only about what it’s returning.

  3. Obviously this should only be used by methods returning something (not void methods nor constructors)

  4. We should allow it to be used for very simple getters. BTW this is what was the intent of the introduction of this syntax, see https://bugs.openjdk.org/browse/JDK-8075778 which says " Add javadoc tag to avoid duplication of return information in simple situations." (notice the “in simple situations”), and then below:

    or a simple, getFoo method,

    and

    The use of the {@Returns} tag would be intended for simple situation where there was a direct (near) repetition of the initial sentence and the @return tag. When such repetition was not present or desirable, the {@Returns} tag should not be used.

  5. It’s also possible to use the syntax: {@return {@inheritDoc}}, and we should document it in our doc as we also mention using {@inheritDoc} (see https://dev.xwiki.org/xwiki/bin/view/Community/CodeStyle/JavaCodeStyle/#HDonotduplicateJavadoc )

PS: It took a long time to find where it was documented. I could only find it in Documentation Comment Specification for the Standard Doclet (JDK 16) . It’s weird that I couldn’t find any reference documentation about this syntax. It’s also not mentioned on Javadoc Tool Home Page nor on http://docs.oracle.com/javase/1.5.0/docs/tooldocs/windows/javadoc.html. Anyway that seems to be oracle not updating their docs…

So, if we agree about points 1 to 5, then I’m becoming +1 for this proposal. But I’m still -1 for the proposal as it is. And the examples given inside Adopt the combo @returns tag javadoc syntax to avoid redundancy - #5 by rjakse are bad and I’m -1 to consider using the {@return} syntax as a good practice for them.

Thanks

FWIW…

An improved javadoc:

 /**
  * Generates a relative {@code file://} URL referencing an attachment within an export, ensuring the attachment's
  * content is available at that location so the exported content can be used offline.
  * <p>
  * {@link ExportURLFactory} produces {@code file://} URLs so that exported content — a self-contained copy of wiki
  * pages usable without a running XWiki server, as needed for example by the HTML export — can resolve its resources
  * locally. For a given attachment, this returns a URL relative to the export directory and makes the attachment's
  * content available there. The URL is relative so that it remains valid even when used from within an exported CSS
  * file.
  * <p>
  * If the attachment does not exist, no content is exported but a URL is still returned. This supports callers that build
  * an attachment URL regardless of whether the attachment exists (for example the Color Theme Sheet, which uses
  * {@code $xwiki.getAttachmentURL($doc.fullName, '__tochange__')}), as well as links to missing attachments, which
  * correctly become broken links in the export.
  * <p>
  * Example: for an attachment named {@code logo.png} on page {@code Main.WebHome} of wiki {@code xwiki}, this returns a
  * relative URL of the form {@code file://attachment/xwiki/Main/WebHome/logo.png}.
  *
  * @param filename the name of the attachment (e.g. {@code "logo.png"})
  * @param spaces a serialized space reference which can contain one or several nested spaces (e.g.
  *     {@code "space1.space2"}); if a space name contains a dot ({@code "."}) it must be passed escaped, as in
  *     {@code "space1\.with\.dot.space2"}
  * @param name the name of the page holding the attachment
  * @param xwikidb the identifier of the wiki holding the page, or {@code null} to use the current wiki from the context
  * @param context the XWiki context
  * @return a relative {@code file://} URL referencing the attachment within the export directory
  * @throws XWikiException if the document holding the attachment cannot be loaded
  * @throws IOException if the attachment's content cannot be written to the export directory
  * @throws URISyntaxException if a valid relative URL cannot be computed for the exported attachment
  */

2 things were improved

Note: for a private method the implementation-specific rule is less obvious but still it makes the javadoc a bit less maintainance-hungry

Sure, for me the feature shouldn’t be an excuse not to be comprehensive when documenting.

With the exception that I’m not sure it should be stricly restricted to getters: if a method builds a string and its full behavior can be described in the one or two sentences that we can fit into that @return tag, it should be allowed to be used there.

agreed, I’ve probably used to wrong word. By getter I meant a very simple method returning a value (ie to get something).

My initial intention was to do what @MichaelHamann says, not replacing comprehensive summaries by a simple @return description. I understand the push back now, replacing all javadocs by this would be terrible indeed. It didn’t even occur to me we would do this. My propposal is scoped to the simple “getter(-like)” cases like we discussed.