One thing I've been struggling with while rewriting my documentation for DocC is how to handle wrapper types/views.
These are special types, often used when there are alternative perspectives on a piece of data. There's usually a single property on the data's "main" type, which is the primary/only way to obtain an instance of the view. String
is a good example of this pattern:
- There's the regular
String
type, which is a collection of characters, but there's also -
String.UTF8View
(accessible via the.utf8
property), -
String.UTF16View
(via the.utf16
property), and -
String.UnicodeScalarView
(via.unicodeScalars
).
Now, let's say I would like to introduce each of these views with a bit more detail; perhaps I'd like to explain a little bit about what a "unicode scalar" is and describe some unique characteristics of that view (e.g. it's a RangeReplaceableCollection
, which is uncommon; the other views are not). Where do I put that documentation?
Option 1: Add the detail to the view type itself
This seems like the logical choice, but it comes with some drawbacks. In this situation, the detailed overview lives on String.UnicodeScalarView
. However, that leaves the .unicodeScalars
property itself with only a very basic description of why you'd actually want to access that property. In order to learn what that view offers, you need to click on the property's return type and examine the type-level documentation.
This is what String
's current documentation does. The properties literally consist of one-line descriptions, like:
"A UTF-8 encoding of self
."
"A UTF-16 encoding of self
."
This is not really optimal. In other parts of the documentation, when I refer users to the unicode scalars view, I want to point them to the .unicodeScalars
property (because that's how they actually obtain an instance of the view; that's where they should go). But without much explanation of what the view offers, it's not always obvious why I'm referring them there or how they should proceed.
Indeed, this is how String introduces these views. Notice that it talks about the "unicodeScalars
property", not the "UnicodeScalarView
type". It doesn't use DocC's links, but it should, and if it did, it would point to the (not very helpful) one-liner above.
This started off seeming like a good idea, but the results are sort of disappointing. So let's try the other option and see how we get on.
Option 2: Add the detail to the property.
Basically, we take all of the type's API and add it to topics on the property.
On the one hand, the overall navigation experience ends up being a lot better. I can refer to these views very naturally from other documentation, and the user gets a great experience, showing all of the methods and properties available on that view. In particular, because <some string>.unicodeScalars
is the thing you actually write in code, Xcode's "Open in Developer Documentation" button can take you straight to the most relevant, most informative page, without extra clicks.
There are still problems though. One of the biggest is protocol conformances, which you can't organise as topics (the reference "Swift/String/UnicodeScalarView/Collection
" won't resolve), and repeating that information in prose is kinda gross. But it's still important information, such as:
- Which level of
Collection
conformance is actually offered (simpleCollection
?BidirectionalCollection
?RandomAccessCollection
?MutableCollection
?RangeReplaceableCollection
?), or - Whether the view is
Equatable
,Comparable
, orHashable
, or - Whether it is
Sendable
and hence safe to use across concurrency boundaries.
Instead, this information still lives on the type's page, which has become a husk of its former self. It no longer even documents its own methods, and any users who stumble upon it might think it doesn't offer any APIs besides those conformances. We need to add a bunch links and try to make very obvious that this is not the page you're looking for.
Basically, it's the same problem that the property-level documentation had using Option 1. This way around is... better? I guess? but in truth, it's still leaving something to be desired.
Option 3: Something else?
I'm wondering if this actually warrants a new concept in DocC, which would merge a property and type and give them a single documentation page.
This isn't the same as a documentation collection, which simply groups distinct pages in a new level of hierarchy. In this model, String.UnicodeScalarView
and String.unicodeScalars
would share the same page, including the complete UnicodeScalarView
API and all of its protocol conformances. I'm still not entirely sure how this would look, but I figured it would be worth floating the idea.
I think it makes a lot of sense, though. Unlike other properties, String.unicodeScalars
or Dictionary.keys
aren't really useful properties. They aren't like, say, Array.count
, which returns some meaningful information; these properties truly are just gateways to the wrapper type. There is no reason for them to have independent documentation.
It might also be worth establishing some sort of authoring guidelines or best practices for how to structure common Swift patterns in documentation. These kinds of views are used throughout the standard library (Dictionary.Keys
and Dictionary.Values
come to mind as non-String examples), as well as in many popular first- and third-party packages.