Language-neutral code style
One canonical way to write names, and generators that turn it into what each language community expects. A working convention, not a claim to a universally correct style.
The idea
A name is written once, as lowercase words. Whether it is a type, whether it is public, and which language it ends up in are separate metadata, not part of the spelling.
Generators then emit the market-standard spelling for each target. The canonical name does not have to look right in any language; the generated one does.
Canonical names and what generators emit
The same canonical names, as a generator would write them for common targets.
| Canonical | Kind | Java | Python | C# | Rust |
|---|---|---|---|---|---|
load_url | method | loadUrl() | load_url() | LoadUrl() | load_url() |
web_view_configuration | type | WebViewConfiguration | WebViewConfiguration | WebViewConfiguration | WebViewConfiguration |
minimal_ui | constant | MINIMAL_UI | MINIMAL_UI | MinimalUi | MINIMAL_UI |
tcp_ip_handler | type | TcpIpHandler | TcpIpHandler | TcpIpHandler | TcpIpHandler |
Illustrative. The Java, Python, C# and Rust columns follow the usual conventions of those communities; the Rust function, type and constant cases are those of the Rust API Guidelines. Which spelling a project actually ships is decided per project.
Acronyms and numbers
Proposed rule: an acronym is a word. It is written lowercase and separated like any other word, and a digit stays attached to the word it belongs to.
- Good: tcp_ip_handler, ipv6_address_parser, oauth2_http_client, xml_http_response.
- Not allowed: PHP_product and TCP_ip_handler. The word boundaries are visible, but the acronym is capitalised in a way that belongs to a target language. Putting that target-specific casing into the canonical name makes the transformation less deterministic: the generator can no longer treat every word the same way.
Targets disagree on how an acronym looks: some ecosystems write HttpClient, others HTTPClient. A generator therefore needs an explicit acronym policy per target. The canonical name does not carry that choice.
Why snake_case as the canonical form
- Word boundaries are explicit, so the name can be split into words and rebuilt in any other style without guessing. A camelCase name such as parseHTTPSUrl cannot be split back unambiguously.
- One form is easy to generate from and easy to check by tool.
What the research says
Readability is a fair argument for underscores, but the evidence does not settle it. An eye-tracking study found no difference in accuracy between camelCase and under_score, and faster recognition of identifiers in the underscore style; its participants were mainly trained in that style. A systematic literature review of formatting studies reports contradictory results on identifier style and calls for more research before guidelines are built on it.
This convention therefore does not rest on readability. It rests on the mapping argument above.
Counter-arguments
We do not claim that PascalCase or camelCase have no logical advantages. They have these:
- Ecosystem consistency. Google's Java guide requires UpperCamelCase for classes and lowerCamelCase for methods, which is also how the Java platform libraries are spelled. Rust uses UpperCamelCase for types and snake_case for functions, methods and modules. Code that follows its ecosystem is easier to join.
- Compactness. Joined words are shorter than words with separators.
- Familiar tooling. IDEs, linters and formatters expect the platform style by default.
The convention accepts these costs where a language has a strong style, and puts the difference into the generator instead of into hand-written code.
Finding definitions: a local convention
In our own C, C++, JavaScript and PHP code a definition is written with a space before the parenthesis, name (), and a call without one, name(). That makes definitions easy to find with a plain text search.
- It is a local search convention, not a universal one. Declarations, function pointers, macros and formatters all limit it.
- Language-aware navigation (language servers, tags) is more reliable than text search, and should be preferred where it exists.
Where this is applied
The planned JWebView API is drafted this way: see API style and naming for the same example in two spellings.