This section contains style-related information for Fuchsia Interface Definition Language files.
See also the FIDL API Rubric.
The Naming of Cats is a difficult matter,
It isn't just one of your holiday games;
--- T.S. Eliot
Names defined in FIDL are used to generate identifiers in each target language. Some languages attach semantic or conventional meaning to names of various forms. For example, in Go, whether the initial letter in an identifier is capitalized controls the visibility of the identifier. For this reason, many of the language back ends transform the names in your library to make them more appropriate for their target language. The naming rules in this section are a balancing act between readability in the FIDL source, usability in each target language, and consistency across target languages.
Avoid commonly reserved words, such as goto
. The language back ends will transform reserved words into non-reserved identifiers, but these transforms reduce usability in those languages. Avoiding commonly reserved words reduces the frequency with which these transformations are applied.
While some FIDL keywords are also commonly reserved words in target languages, (such as struct
in C and C++), and should thus be avoided, other FIDL keywords, particularly request
and handle
, are generally descriptive and can be used as appropriate.
Names must not contain leading or trailing underscores. Leading or trailing underscores have semantic meaning in some languages (e.g., leading underscores control visibility in Dart) and conventional meaning in other languages (e.g., trailing underscores are conventionally used for member variables in C++). Additionally, the FIDL compiler uses leading and trailing underscores to munge identifiers to avoid collisions.
Use the term size
to name a number of bytes. Use the term count
to name a number of some other quantity (e.g., the number of items in a vector of structs).
Sometimes there is more than one way to decide on how to delimit words in identifiers. Our style is as follows:
non_null_http_client
).NON_NULL_HTTP_CLIENT
).NonNullHttpClient
).The following table maps the case usage to the element:
Element | Casing | Example |
---|---|---|
bits | upper camel case | InfoFeatures |
bitfield members | upper snake case | WLAN_SNOOP |
const | upper snake case | MAX_NAMES |
primitive alias | lower snake case | hw_partition |
protocol | upper camel case | AudioRenderer |
protocol method parameters | lower snake case | enable_powersave |
protocol methods | upper camel case | GetBatteryStatus |
struct | upper camel case | KeyboardEvent |
struct members | lower snake case | child_pid |
table | upper camel case | ComponentDecl |
table members | lower snake case | num_rx |
union | upper camel case | BufferFormat |
union members | lower snake case | vax_primary |
enum | upper camel case | PixelFormat |
enum members | upper snake case | RGB_888 |
Library names are period-separated lists of identifiers. Portions of the library name other than the last are also referred to as namespaces. Each component of the name is in lowercase and must match the following regular expression: [a-z][a-z0-9]*
.
We use these restrictive rules because different target languages have different restrictions on how they qualify namespaces, libraries, or packages. We have selected a conservative least common denominator in order for FIDL to work well with our current set of target languages and with potential future target languages.
Prefer functional names (e.g., fuchsia.media
) over product or code names (e.g., fuchsia.amber
or fuchsia.scenic
). Product names are appropriate when the product has some external existence beyond Fuchsia and when the protocol is specific to that product. For example, fuchsia.cobalt
is a better name for the Cobalt interface protocol than fuchsia.metrics
because other metrics implementations (e.g., Firebase) are unlikely to implement the same protocol.
Identifier names should relate to the specific role that participants play; avoid encoding access control into the name. Names based on roles are descriptive and won‘t outdate as quickly as names based on access control, which prescribe an externally-defined relationship that is subject to change as the platform evolves. For example, for an API involving FocusChain
objects, an appropriate name would be fuchsia.ui.focus
, instead of fuchsia.ui.privileged
; if we decide to make FocusChain
objects more widely accessible, then fuchsia.ui.focus
isn’t a problematic name. The following example words should be avoided:
constrained
limited
oem
private
privileged
protected
special
vendor
Identifier names should have meaning; avoid meaningless names. If fuchsia.foo.bar
and fuchsia.foo.baz
share a number of concepts that you wish to factor out into a separate library, consider defining those concepts in fuchsia.foo
rather than in fuchsia.foo.common
. The following example words should be avoided:
common
service
util
base
f<letter>l
zx<word>
Avoid repeating the names from the library name. For example, in the fuchsia.process
library, a protocol that launches process should be named Launcher
rather than ProcessLauncher
because the name process
already appears in the library name. In all target languages, top-level names are scoped by the library name in some fashion.
Primitive aliases must not repeat names from the enclosing library. In all target languages, primitive aliases are replaced by the underlying primitive type and therefore do not cause name collisions.
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/style.test.fidl" region_tag="primitive-alias" %}
Constant names must not repeat names from the enclosing library. In all target languages, constant names are scoped by their enclosing library.
Constants that describe minimum and maximum bounds should use the prefix MIN_
and MAX_
, respectively.
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/style.test.fidl" region_tag="constants" %}
Protocols are specified with the protocol
keyword.
Protocols must be noun phrases. Typically, protocols are named using nouns that suggest an action. For example, AudioRenderer
is a noun that suggests that the protocol is related to rendering audio. Similarly, Launcher
is a noun that suggests that the protocol is related to launching something. Protocols can also be passive nouns, particularly if they relate to some state held by the implementation. For example, Directory
is a noun that suggests that the protocol is used for interacting with a directory held by the implementation.
A protocol may be named using object-oriented design patterns. For example, fuchsia.fonts.Provider
uses the provider
suffix, which indicates that the protocol provides fonts (rather than represents a font itself). Similarly, fuchsia.tracing.Controller
uses the controller
suffix, which indicates that the protocol controls the tracing system (rather than represents a trace itself).
The name Manager
may be used as a name of last resort for a protocol with broad scope. For example, fuchsia.power.Manager
. However, be warned that “manager” protocols tend to attract a large amount of loosely related functionality that might be better factored into multiple protocols.
Protocols must not include the name service.
All protocols define services. The term is meaningless. For example, fuchsia.tts.TtsService
violates this rubric in two ways. First, the Tts
prefix is redundant with the library name. Second, the Service
suffix is banned.
Methods must must be verb phrases.
For example, GetBatteryStatus
and CreateSession
are verb phrases that indicate what action the method performs.
Methods on listener
or observer
protocols that are called when an event occurs should be prefixed with On
and describe the event that occurred in the past tense. For example, the ViewContainerListener
protocol has a method named OnChildAttached
.
Similarly, events (i.e., unsolicited messages from the server to the client) should be prefixed with On
and describe the event that occurred in the past tense.
For example, the AudioCapturer
protocol has an event named OnPacketCaptured
.
The method of a single method protocol should be the verb phrase of the protocol's noun phrase they are defined in, e.g. Loader.Load
, Getter.Get
, Uploader.Upload
. In the case of qualified nouns phrases such as JobCreator
or ProcessStopper
, the unqualified verb phrase should be used, i.e. JobCreator.Create
or ProcessStopper.Stop
.
Protocols that are single method but intend to evolve to multi-method overtime do not necessarily need to follow this naming convention, i.e if there is a known extension of the protocol for which the recommended naming is not appropriate, then choosing another name early on might be preferred. When in doubt, following the default advice should be preferred.
Because replacing a protocol is harder than evolving a protocol, if an API was never intended to evolve but eventually finds a need to move to a multi-method protocol, it is preferred to evolve the existing protocol by adding a method, and possibly renaming the existing method.
Structs, unions, and tables must be noun phrases. For example, Point
is a struct that defines a location in space and KeyboardEvent
is a struct that defines a keyboard-related event.
Prefer struct, union, and table member names with a single word when practical (single-word names render more consistently across target languages). However, do not be afraid to use multiple words if a single word would be ambiguous or confusing.
Member names must not repeat names from the enclosing type (or library) unless the member name is ambiguous without a name from the enclosing type. For example, a member of type KeyboardEvent
that contains the time the event was delivered should be named time
, rather than event_time
, because the name event
already appears in the name of the enclosing type. In all target languages, member names are scoped by their enclosing type.
However, a type DeviceToRoom
, that associates a smart device with the room it's located in, may need to have members device_id
and room_name
, because id
and name
are ambiguous. Either of these could refer to either the device or the room.
Enums must be noun phrases.
For example, PixelFormat
is an enum that defines how colors are encoded into bits in an image.
Enum member names must not repeat names from the enclosing type (or library). For example, members of PixelFormat
enum should be named ARGB
rather than PIXEL_FORMAT_ARGB
because the name PIXEL_FORMAT
already appears in the name of the enclosing type. In all target languages, enum member names are scoped by their enclosing type.
Bitfields must be noun phrases.
For example, InfoFeatures
is a bitfield that indicates which features are present on an Ethernet interface.
Bitfield members must not repeat names from the enclosing type (or library). For example, members of InfoFeatures
bitfield should be named WLAN
rather than INFO_FEATURES_WLAN
because the name INFO_FEATURES
already appears in the name of the enclosing type. In all target languages, bitfield member names are scoped by their enclosing type.
bits
, enum
, protocol
, struct
, table
, and union
constructs from other declarations with one blank line (two consecutive newline characters).Comments use ///
(three forward slashes). Comments in a library will also appear in the generated code to ease development when coding against the library. We say that comments “flow-through” to the target language.
Place comments above the thing being described. Except in the cases listed below, use reasonably complete sentences with proper capitalization and periods. Limit comment widths to 80 characters unless a longer comment is unavoidable (e.g., for a long URL).
Comments should be written in Markdown. We rely on the CommonMark specification for our markdown. Some tools may render output using other Markdown standards; in cases where your tool does not use CommonMark, we encourage developers to write Markdown that is compatible with both CommonMark and their tool. References to FIDL elements should always be in code font.
A documented entity is any FIDL element that has a comment attached. The first reference to any documented entity in a comment should be given with its fully qualified name, in the form [`<library>/<top level declaration>.<member>`]
(e.g., [`fuchsia.io/Node.clone`]
). This form may generate a hyperlink, if the tooling supports it. Subsequent references to that documented entity can use an abbreviated version, as long as that abbreviated version is unambiguous (e.g., clone
). The form without brackets does not generate a hyperlink.
Request parameters, response parameters, and error types should be documented as lists of the form:
+ request `param1` <description> + request `param2` <description> - response `param1` <description> - response `param2` <description> * error <description>
Requests, responses, and errors must appear in that order. A given set of parameters must also follow the order in which they were declared in the parameter list. The terms “request” and “response” may be elided if the parameter names are only found in one of the request or response parameter list.
The first part of a doc comment describing a variable, field, or type should be a noun phrase that briefly states the intended purpose of the documented entity, including information that cannot be deduced from the name and type. The description should be terminated with a period. The description should not reiterate the name of the documented entity, or its particular type of FIDL language element (e.g., struct
or protocol
).
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/style.test.fidl" region_tag="good-docs" %}
The following are examples of what you should not do:
/// BAD: Widget is a representation of violins displayed on the screen. /// BAD: struct Widget is a representation of violins displayed on the screen.
The first part of a doc comment attached to a protocol method should be a brief description of the behavior of that method, starting with a verb, including information that cannot be deduced from the name and type. The verb should be written in the present tense, agree with a third person singular pronoun, and use the indicative mood (this effectively means that you should pretend the word “it” comes before the verb, and that you are making a statement of fact). The phrase should end with a period.
A full example:
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/style.test.fidl" region_tag="good-docs-2" %}
Types or values defined by some external source of truth should be commented with references to the external thing. For example, reference the WiFi specification that describes a configuration structure. Similarly, if a structure must match an ABI defined in a C header, reference the C header.
For more information about what your comments should contain, see the API Documentation Rubric.
References to FIDL protocols or their methods in comments should follow the pattern:
/// See fuchsia.library/ProtocolName.Method for more information.
When referring to a protocol in the same library as the comment, the library name may be left off: ProtocolName.Method
.
Similarly, when referring to a method in the same protocol as the comment, the library name and protocol name may be left off: Method
.
You can provide a library overview as a documentation comment on the library
statement. The ‘library’ statement starts FIDL files. For example:
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/style.test.fidl" region_tag="library-overview" %}
Library overviews should provide general documentation to define the library. They may also provide a detailed introduction to various messages, defined protocols, and how the messages and protocols are used together.
While a library can be broken down in multiple FIDL Files, there can only be a single library overview. Consider these recommendations for library overviews:
library
statement at the top of the library file.overview.fidl
to document the library. The ‘overview.fidl’ file should not contain any declarations, type aliases, or protocol definitions.If your comments are meant for library authors, use the simpler comments //
(two forward slashes), which do not flow-through to the target language.
When deciding what should be a regular ///
comment versus a non flow-through comment, keep in mind the following.
Regular comments:
Non flow-through comments:
Both style of comments can be combined:
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/style.test.fidl" region_tag="comments-combined" %}
A library is comprised of one or more files. The files are stored in a directory hierarchy with the following conventions:
fidl/<library>/[<dir>/]*<file>.fidl
The <library>
directory is named using the dot-separated name of the FIDL library. The <dir>
subdirectories are optional and typically not used for libraries with less than a dozen files. This directory structure matches how FIDL files are included in the Fuchsia SDK.
The division of a library into files has no technical impact on consumers of the library. Declarations, including protocols, can reference each other and themselves throughout the library, regardless of the file in which they appear. Divide libraries into files to maximize readability.