Internal vs external parameter names in documentation

I'm puzzled by this warning I got from the documentation compiler in Xcode:

I think of this kind of documentation as being written primarily for clients of the code, not implementers of the method (for that, there are comments inline in the code). The caller must write forProduct and not inProduct, but the documentation insists on using the internal name inProduct. This seems counterintuitive to me.

Am I misunderstanding something? To me it seems it should never render the internal name in the documentation. It doesn't in the headline, but it does in the more detailed declaration.

I think it especially makes sense to use the internal names for APIs where the argument label is a preposition (off the top of my head there's type(of:) and unsafeBitCast(_:to:) in the standard library, for example).

I get using the internal name when there is no external name, but in type(of:), of is also the external name. But purely internal names are just that: internal, and not visible to the caller.

The external name is actually a part of the method name, and the internal name is the parameter identifier.

2 Likes

That seems like a pedantic distinction that doesn’t address the main question: For whom is the documentation, and how can an internal-only name make any kind of sense for an external audience?

1 Like

I would rename the internal identifier inProduct to simply product, and the whole declaration would sound more naturally: func updateStatus(forProduct product), as well as documentation:

Parameters
  product

That completely misses the point.

1 Like

I actually see your point.
But I cannot address the issue. Your question is rather rhetorical, as it challenges the design of the language IMHO.

BTW I have to create my documentation by hand, as DocC does not work on Windows (or does it already?) and I had the same question: should I use external "identifier" in the docs, as it is user-faced and internal identifier is not for them. And guess what? I came to conclusion that internal identifier sounds better (less quirky?), because it is not prepended with "for", "in", "from", etc. Documentation should be easy to read at a glance, easy on the eye.

1 Like

Argument labels generally express a relationship between the operation and the argument value; not only can they include prepositions, they are often only prepositions. They therefore may not make sense grammatically as a reference to the parameter in docs. I don't know if I'd go so far as to warn about using the argument label, but using the internal parameter name is perfectly fine. It's not a permanently stable name, but it clearly identifies the parameter as long as it's also rendered in the function prototype. This is, of course, commonplace in documentation for other languages that don't include argument labels.

9 Likes

Hmm, indeed: func updateStatus(for product) sounds great.

This is good to know too. I thought there is only one "right" way.

We call these "argument labels" versus "parameter names." Argument labels don't have to be unique, and plenty aren't. Parameter names do have to be unique (which is a pretty useful property for being referenced). As you note, the latter isn't purely internal, because they are exposed in documentation: it's begging the question to call parameter names "internal-only" and then wonder why they're not.

4 Likes

I'm with Rick here.

What he's essentially saying is that β€” separately from argument labels β€” there are sometimes good reasons to have an internal parameter name that's different from an external parameter name, for documentation purposes. That seems right to me.

Since we presumably don't want to add language syntax making that distinction in the function declaration, the obvious way to do it is in the documentation comments. If Rick prefers his documentation parameter name to be forProduct instead of just (say) product, and prefers to keep inProduct entirely private, that seems like his prerogative.

IOW, this seems like bureaucratic overreach on the compiler's part. I think there should be no warning for this scenario.

1 Like

Maybe it's a bureaucratic overreach on the part of DocC, not the Swift compiler.

DocC has a handful of warnings that tries to encourage consistent and up-to-date documentation for parameters and return values. For example:

  • When a parameter is documented but doesn't exist in the function signature
  • When a parameter is documented more than once
  • When a parameter exist in the function signature but is missing documentation
  • When a return value is documented but the function returns Void

These are primarily meant to help developers who modifies a function's signature to also keep the function's documentation up-to-date when for example adding or removing a parameter, adding or removing a return value, or renaming a parameter.

In order to reduce noise, DocC doesn't raise any of these warnings unless at least one parameter or at least one return value is documented for that function.

If you don't want these warnings you can pass the --disable-parameters-and-returns-validation flag to DocC.

1 Like

I'll also mention that DocC to some extent tries to encourage documentation for API that follows many of the recommendations in Swift API design guidelines.

In addition to making a distinction between parameter names and argument labels:

                 ╭───────────────┬────────── parameter names
               ──┴──            ─┴─
func move(from start: Point, to end: Point)
          ──┬─               ─┬
            ╰─────────────────┴───────────── argument labels

There's a specific recommendation about naming parameters:

Choose parameter names to serve documentation. Even though parameter names do not appear at a function or method’s point of use, they play an important explanatory role.

Choose these names to make documentation easy to read. For example, these names make documentation read naturally:

+ /// Return an `Array` containing the elements of `self`
+ /// that satisfy `predicate`.
+ func filter(_ predicate: (Element) -> Bool) -> [Generator.Element]
+
+ /// Replace the given `subRange` of elements with `newElements`.
+ mutating func replaceRange(_ subRange: Range, with newElements: [E])

These, however, make the documentation awkward and ungrammatical:

- /// Return an `Array` containing the elements of `self`
- /// that satisfy `includedInResult`.
- func filter(_ includedInResult: (Element) -> Bool) -> [Generator.Element]
-
- /// Replace the range of elements indicated by `r` with
- /// the contents of `with`.
- mutating func replaceRange(_ r: Range, with: [E])

There is also a recommendation about about omitting words that repeat type information:

Omit needless words. Every word in a name should convey salient information at the use site.

More words may be needed to clarify intent or disambiguate meaning, but those that are redundant with information the reader already possesses should be omitted. In particular, omit words that merely repeat type information.

+ public mutating func removeElement(_ member: Element) -> Element?
+
+ allViews.removeElement(cancelButton)

In this case, the word Element adds nothing salient at the call site. This API would be better:

- public mutating func remove(_ member: Element) -> Element?
-
- allViews.remove(cancelButton) // clearer

My interpretation of these two recommendations togetherβ€”when applied to this specific updateStatus exampleβ€”is that:

  • because the parameter type is Product it's redundant to mention "product" in the argument label, meaning that the argument label becomes "for"
  • to make the signature and documentation read naturally; a good name for the Product parameter would be "product" so that the signature and documentation can read as "update status for product".

To some extent, DocC's warnings about parameters is assuming that the API follows these recommendations, and that's what the warnings are trying to steer you towards.

If you and your team prefer different naming conventions and these DocC warnings are getting in your way, you can disable them by passing the --disable-parameters-and-returns-validation flag to DocC.

5 Likes