Repository: google/styleguide Branch: gh-pages Commit: c098353acb6d Files: 55 Total size: 1.8 MB Directory structure: gitextract_omg5k8n9/ ├── .github/ │ ├── CODEOWNERS │ ├── ISSUE_TEMPLATE.md │ └── PULL_REQUEST_TEMPLATE.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── Rguide.md ├── Rguide.xml ├── _includes/ │ └── head-custom.html ├── angularjs-google-style.html ├── assets/ │ └── css/ │ └── style.scss ├── cppguide.html ├── cppguide.xml ├── csharp-style.md ├── docguide/ │ ├── README.md │ ├── READMEs.md │ ├── VERSION │ ├── best_practices.md │ ├── philosophy.md │ └── style.md ├── eclipse-cpp-google-style.xml ├── eclipse-java-google-style.xml ├── go/ │ ├── best-practices.md │ ├── decisions.md │ ├── guide.md │ └── index.md ├── google-c-style.el ├── google-r-style.html ├── google_python_style.vim ├── htmlcssguide.html ├── htmlcssguide.xml ├── include/ │ ├── jsguide.js │ ├── styleguide.css │ └── styleguide.js ├── intellij-java-google-style.xml ├── javaguide.css ├── javaguide.html ├── javascriptguide.xml ├── jsguide.html ├── jsoncstyleguide.html ├── jsoncstyleguide.xml ├── lispguide.xml ├── objcguide.md ├── objcguide.xml ├── pyguide.md ├── pylintrc ├── shell.xml ├── shell.xsl ├── shellguide.md ├── styleguide.css ├── styleguide.xsl ├── tsguide.html ├── vimscriptfull.xml ├── vimscriptguide.xml └── xmlstyle.html ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/CODEOWNERS ================================================ # https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax csharp-style.md @jbcoe htmlcssguide.html @tonyruscoe shellguide.md @eatnumber1 @vapier /go/ @chressie @gaal @katrinahoffert @kliegs @matttproud ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ This repository publishes copies of Google's internal style guides to assist developers working on Google owned and originated open source projects. Development on these guides does not take place here. Substantive changes to the style rules and suggested new rules should not be submitted as issues in this repository. Material changes must be proposed, discussed, and approved on the internal forums first. If an issue points out a simple mistake — a typo, a broken link, etc. — then a correction might be made. However there is no commitment to do so. Issues are normally closed without comment. ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ These style guides are copies of Google's internal style guides to assist developers working on Google owned and originated open source projects. Changes should be made to the internal style guide first and only then copied here. Unsolicited pull requests will not be merged and are usually closed without comment. If a PR points out a simple mistake — a typo, a broken link, etc. — then the correction can be made internally and copied here through the usual process. Substantive changes to the style rules and suggested new rules should not be submitted as a PR in this repository. Material changes must be proposed, discussed, and approved on the internal forums first. ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Repo maintainers are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Repo maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0]. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. [homepage]: https://www.contributor-covenant.org [v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq ================================================ FILE: LICENSE ================================================ Creative Commons Legal Code Attribution 3.0 Unported CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE. License THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. 1. Definitions a. "Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License. b. "Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(f) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License. c. "Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership. d. "Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License. e. "Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast. f. "Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work. g. "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. h. "Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images. i. "Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium. 2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws. 3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: a. to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; b. to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified."; c. to Distribute and Publicly Perform the Work including as incorporated in Collections; and, d. to Distribute and Publicly Perform Adaptations. e. For the avoidance of doubt: i. Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; ii. Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor waives the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; and, iii. Voluntary License Schemes. The Licensor waives the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License. The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved. 4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: a. You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(b), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(b), as requested. b. If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and (iv) , consistent with Section 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4 (b) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties. c. Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise. 5. Representations, Warranties and Disclaimer UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. Termination a. This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. b. Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. 8. Miscellaneous a. Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. b. Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License. c. If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. d. No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. e. This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. f. The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law. Creative Commons Notice Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor. Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, Creative Commons does not authorize the use by either party of the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time. For the avoidance of doubt, this trademark restriction does not form part of this License. Creative Commons may be contacted at https://creativecommons.org/. ================================================ FILE: README.md ================================================ # Google Style Guides Every major open-source project has its own style guide: a set of conventions (sometimes arbitrary) about how to write code for that project. It is much easier to understand a large codebase when all the code in it is in a consistent style. “Style” covers a lot of ground, from “use camelCase for variable names” to “never use global variables” to “never use exceptions.” This project ([google/styleguide](https://github.com/google/styleguide)) links to the style guidelines we use for Google code. If you are modifying a project that originated at Google, you may be pointed to this page to see the style guides that apply to that project. * [AngularJS Style Guide][angular] * [Common Lisp Style Guide][cl] * [C++ Style Guide][cpp] * [C# Style Guide][csharp] * [Go Style Guide][go] * [HTML/CSS Style Guide][htmlcss] * [JavaScript Style Guide][js] * [Java Style Guide][java] * [JSON Style Guide][json] * [Markdown Style Guide][markdown] * [Objective-C Style Guide][objc] * [Python Style Guide][py] * [R Style Guide][r] * [Shell Style Guide][sh] * [Swift Style Guide][swift] * [TypeScript Style Guide][ts] * [Vim script Style Guide][vim] This project also contains [google-c-style.el][emacs], an Emacs settings file for Google style. We used to host the cpplint tool, but we stopped making internal updates public. An open source community has forked the project, so users are encouraged to use https://github.com/cpplint/cpplint instead. If your project requires that you create a new XML document format, the [XML Document Format Style Guide][xml] may be helpful. In addition to actual style rules, it also contains advice on designing your own vs. adapting an existing format, on XML instance document formatting, and on elements vs. attributes. The style guides in this project are licensed under the CC-By 3.0 License, which encourages you to share these documents. See [https://creativecommons.org/licenses/by/3.0/][ccl] for more details. The following Google style guide lives outside of this project: * [Effective Dart][dart] * [Kotlin Style Guide][kotlin] Since projects are largely maintained in a [VCS], writing good commit messages is important to long term project health. Please refer to [How to Write a Git Commit Message](https://cbea.ms/git-commit/) as an excellent resource. While it explicitly refers to the Git [SCM], its principles apply to any system, and many Git conventions are trivial to translate to others. ## Contributing With few exceptions, these style guides are copies of Google's internal style guides to assist developers working on Google owned and originated open source projects. Changes to the style guides are made to the internal style guides first and eventually copied into the versions found here. **External contributions are not accepted.** Pull requests are regularly closed without comment. People can file [issues using the GitHub tracker][gh-tracker]. Issues that raise questions, justify changes on technical merits, or point out obvious mistakes may get some engagement and could in theory lead to changes, but we are primarily optimizing for Google's internal needs. Creative Commons License [cpp]: https://google.github.io/styleguide/cppguide.html [csharp]: https://google.github.io/styleguide/csharp-style.html [swift]: https://google.github.io/swift/ [objc]: objcguide.md [gh-tracker]: https://github.com/google/styleguide/issues [go]: go/ [java]: https://google.github.io/styleguide/javaguide.html [json]: https://google.github.io/styleguide/jsoncstyleguide.xml [kotlin]: https://developer.android.com/kotlin/style-guide [py]: https://google.github.io/styleguide/pyguide.html [r]: https://google.github.io/styleguide/Rguide.html [sh]: https://google.github.io/styleguide/shellguide.html [htmlcss]: https://google.github.io/styleguide/htmlcssguide.html [js]: https://google.github.io/styleguide/jsguide.html [markdown]: https://google.github.io/styleguide/docguide/style.html [ts]: https://google.github.io/styleguide/tsguide.html [angular]: https://google.github.io/styleguide/angularjs-google-style.html [cl]: https://google.github.io/styleguide/lispguide.xml [vim]: https://google.github.io/styleguide/vimscriptguide.xml [emacs]: https://raw.githubusercontent.com/google/styleguide/gh-pages/google-c-style.el [xml]: https://google.github.io/styleguide/xmlstyle.html [dart]: https://www.dartlang.org/guides/language/effective-dart [ccl]: https://creativecommons.org/licenses/by/3.0/ [SCM]: https://en.wikipedia.org/wiki/Source_control_management [VCS]: https://en.wikipedia.org/wiki/Version_control_system ================================================ FILE: Rguide.md ================================================ # Google's R Style Guide R is a high-level programming language used primarily for statistical computing and graphics. The goal of the R Programming Style Guide is to make our R code easier to read, share, and verify. The Google R Style Guide is a fork of the [Tidyverse Style Guide](https://style.tidyverse.org/) by Hadley Wickham [license](https://creativecommons.org/licenses/by-sa/2.0/). Google modifications were developed in collaboration with the internal R user community. The rest of this document explains Google's primary differences with the Tidyverse guide, and why these differences exist. ## Syntax ### Naming conventions Google prefers identifying functions with `BigCamelCase` to clearly distinguish them from other objects. ``` # Good DoNothing <- function() { return(invisible(NULL)) } ``` The names of private functions should begin with a dot. This helps communicate both the origin of the function and its intended use. ``` # Good .DoNothingPrivately <- function() { return(invisible(NULL)) } ``` We previously recommended naming objects with `dot.case`. We're moving away from that, as it creates confusion with S3 methods. ### Don't use attach() The possibilities for creating errors when using `attach()` are numerous. ## Pipes ### Right-hand assignment We do not support using right-hand assignment. ``` # Bad iris %>% dplyr::summarize(max_petal = max(Petal.Width)) -> results ``` This convention differs substantially from practices in other languages and makes it harder to see in code where an object is defined. E.g. searching for `foo <-` is easier than searching for `foo <-` and `-> foo` (possibly split over lines). ### Use explicit returns Do not rely on R's implicit return feature. It is better to be clear about your intent to `return()` an object. ``` # Good AddValues <- function(x, y) { return(x + y) } # Bad AddValues <- function(x, y) { x + y } ``` ### Qualifying namespaces Users should explicitly qualify namespaces for all external functions. ``` # Good purrr::map() ``` We discourage using the `@import` Roxygen tag to bring in all functions into a NAMESPACE. Google has a very big R codebase, and importing all functions creates too much risk for name collisions. While there is a small performance penalty for using `::`, it makes it easier to understand dependencies in your code. There are some exceptions to this rule. * Infix functions (`%name%`) always need to be imported. * Certain `rlang` pronouns, notably `.data`, need to be imported. * Functions from default R packages, including `datasets`, `utils`, `grDevices`, `graphics`, `stats` and `methods`. If needed, you can `@import` the full package. When importing functions, place the `@importFrom` tag in the Roxygen header above the function where the external dependency is used. ## Documentation ### Package-level documentation All packages should have a package documentation file, in a `packagename-package.R` file. ================================================ FILE: Rguide.xml ================================================ Google's R Style Guide

Google's R Style Guide

The style guide has moved to Rguide.html

================================================ FILE: _includes/head-custom.html ================================================ ================================================ FILE: angularjs-google-style.html ================================================ Google's AngularJS Style Guide

An AngularJS Style Guide for Closure Users at Google

This is the external version of a document that was primarily written for Google engineers. It describes a recommended style for AngularJS apps that use Closure, as used internally at Google. Members of the broader AngularJS community should feel free to apply (or not apply) these recommendations, as relevant to their own use cases.

This document describes style for AngularJS apps in google3. This guide supplements and extends the Google JavaScript Style Guide.

Style Note: Examples on the AngularJS external webpage, and many external apps, are written in a style that freely uses closures, favors functional inheritance, and does not often use JavaScript types. Google follows a more rigorous Javascript style to support JSCompiler optimizations and large code bases - see the javascript-style mailing list. This is not an Angular-specific issue, and is not discussed further in this style guide. (But if you want further reading: Martin Fowler on closures, much longer description, appendix A of the closure book has a good description of inheritance patterns and why it prefers pseudoclassical, Javascript, the Good Parts as a counter.)

1 Angular Language Rules

Manage dependencies with Closure's goog.require and goog.provide

Choose a namespace for your project, and use goog.provide and goog.require.

goog.provide('hello.about.AboutCtrl');
goog.provide('hello.versions.Versions');

Why? Google BUILD rules integrate nicely with closure provide/require.

Modules

Your main application module should be in your root client directory. A module should never be altered other than the one where it is defined.

Modules may either be defined in the same file as their components (this works well for a module that contains exactly one service) or in a separate file for wiring pieces together.

Why? A module should be consistent for anyone that wants to include it as a reusable component. If a module can mean different things depending on which files are included, it is not consistent.

Modules should reference other modules using the Angular Module's "name" property

For example:

// file submodulea.js:
  goog.provide('my.submoduleA');

  my.submoduleA = angular.module('my.submoduleA', []);
  // ...

// file app.js
  goog.require('my.submoduleA');

  Yes: my.application.module = angular.module('hello', [my.submoduleA.name]);
  
      No: my.application.module = angular.module('hello', ['my.submoduleA']);
  

Why? Using a property of my.submoduleA prevents Closure presubmit failures complaining that the file is required but never used. Using the .name property avoids duplicating strings.

Use a common externs file

This maximally allows the JS compiler to enforce type safety in the presence of externally provided types from Angular, and means you don't have to worry about Angular vars being obfuscated in a confusing way.

Note to readers outside Google: the current externs file is located in an internal-to-Google directory, but an example can be found on github here.

JSCompiler Flags

Reminder: According to the JS style guide, customer facing code must be compiled.

Recommended: Use the JSCompiler (the closure compiler that works with js_binary by default) and ANGULAR_COMPILER_FLAGS_FULL from //javascript/angular/build_defs/build_defs for your base flags.

Note - if you are using @export for methods, you will need to add the compiler flag

"--generate_exports",

If you are using @export for properties, you will need to add the flags:

"--generate_exports",
"--remove_unused_prototype_props_in_externs=false",
"--export_local_property_definitions",

Controllers and Scopes

Controllers are classes. Methods should be defined on MyCtrl.prototype.

Google Angular applications should use the 'controller as' style to export the controller onto the scope. This is fully implemented in Angular 1.2 and can be mimicked in pre-Angular 1.2 builds.

Pre Angular 1.2, this looks like:

/**
 * Home controller.
 *
 * @param {!angular.Scope} $scope
 * @constructor
 * @ngInject
 * @export
 */
hello.mainpage.HomeCtrl = function($scope) {
  /** @export */
  $scope.homeCtrl = this; // This is a bridge until Angular 1.2 controller-as

  /**
   * @type {string}
   * @export
   */
  this.myColor = 'blue';
};


/**
 * @param {number} a
 * @param {number} b
 * @export
 */
hello.mainpage.HomeCtrl.prototype.add = function(a, b) {
  return a + b;
};

And the template:

<div ng-controller="hello.mainpage.HomeCtrl"/>
  <span ng-class="homeCtrl.myColor">I'm in a color!</span>
  <span>{{homeCtrl.add(5, 6)}}</span>
</div>

After Angular 1.2, this looks like:

/**
 * Home controller.
 *
 * @constructor
 * @ngInject
 * @export
 */
hello.mainpage.HomeCtrl = function() {
  /**
   * @type {string}
   * @export
   */
  this.myColor = 'blue';
};


/**
 * @param {number} a
 * @param {number} b
 * @export
 */
hello.mainpage.HomeCtrl.prototype.add = function(a, b) {
  return a + b;
};

If you are compiling with property renaming, expose properties and methods using the @export annotation. Remember to @export the constructor as well.

And in the template:

<div ng-controller="hello.mainpage.HomeCtrl as homeCtrl"/>
  <span ng-class="homeCtrl.myColor">I'm in a color!</span>
  <span>{{homeCtrl.add(5, 6)}}</span>
</div>

Why? Putting methods and properties directly onto the controller, instead of building up a scope object, fits better with the Google Closure class style. Additionally, using 'controller as' makes it obvious which controller you are accessing when multiple controllers apply to an element. Since there is always a '.' in the bindings, you don't have to worry about prototypal inheritance masking primitives.

Directives

All DOM manipulation should be done inside directives. Directives should be kept small and use composition. Files defining directives should goog.provide a static function which returns the directive definition object.

goog.provide('hello.pane.paneDirective');

/**
 * Description and usage
 * @return {angular.Directive} Directive definition object.
 */
hello.pane.paneDirective = function() {
  // ...
};

Exception: DOM manipulation may occur in services for DOM elements disconnected from the rest of the view, e.g. dialogs or keyboard shortcuts.

Services

Services registered on the module with module.service are classes. Use module.service instead of module.provider or module.factory unless you need to do initialization beyond just creating a new instance of the class.

/**
 * @param {!angular.$http} $http The Angular http service.
 * @constructor
 */
hello.request.Request = function($http) {
  /** @type {!angular.$http} */
  this.http_ = $http;
};

hello.request.Request.prototype.get = function() {/*...*/};

In the module:

module.service('request', hello.request.Request);

2 Angular Style Rules

Reserve $ for Angular properties and services

Do not use $ to prepend your own object properties and service identifiers. Consider this style of naming reserved by AngularJS and jQuery.

Yes:

  $scope.myModel = { value: 'foo' }
  myModule.service('myService', function() { /*...*/ });
  var MyCtrl = function($http) {this.http_ = $http;};

No:

  $scope.$myModel = { value: 'foo' } // BAD
  $scope.myModel = { $value: 'foo' } // BAD
  myModule.service('$myService', function() { ... }); // BAD
  var MyCtrl = function($http) {this.$http_ = $http;}; // BAD

Why? It's useful to distinguish between Angular / jQuery builtins and things you add yourself. In addition, $ is not an acceptable character for variables names in the JS style guide.

Custom elements

For custom elements (e.g. <ng-include src="template"></ng-include>), IE8 requires special support (html5shiv-like hacks) to enable css styling. Be aware of this restriction in apps targeting old versions of IE.

3 Angular Tips, Tricks, and Best Practices

These are not strict style guide rules, but are placed here as reference for folks getting started with Angular at Google.

Testing

Angular is designed for test-driven development.

The recommended unit testing setup is Jasmine + Karma (though you could use closure tests or js_test)

Angular provides easy adapters to load modules and use the injector in Jasmine tests.

Consider using the Best Practices for App Structure

This directory structure doc describes how to structure your application with controllers in nested subdirectories and all components (e.g. services and directives) in a 'components' dir.

Be aware of how scope inheritance works

See The Nuances of Scope Prototypal Inheritance

Use @ngInject for easy dependency injection compilation

This removes the need to add myCtrl['$inject'] = ... to prevent minification from messing up Angular's dependency injection.

Usage:

/**
 * My controller.
 * @param {!angular.$http} $http
 * @param {!my.app.myService} myService
 * @constructor
 * @export
 * @ngInject
 */
my.app.MyCtrl = function($http, myService) {
  //...
};

4 Best practices links and docs

Last modified Feb 07 2013
================================================ FILE: assets/css/style.scss ================================================ --- # Keep this YAML front matter block to trigger Jekyll processing. # See https://jekyllrb.com/docs/frontmatter for more information. --- @import "{{ site.theme }}"; // Hide “This site is open source. Improve this page.” .footer { display: none; } ================================================ FILE: cppguide.html ================================================ Google C++ Style Guide

Google C++ Style Guide

C++ is one of the main development languages used by many of Google's open-source projects. As every C++ programmer knows, the language has many powerful features, but this power brings with it complexity, which in turn can make code more bug-prone and harder to read and maintain.

The goal of this guide is to manage this complexity by describing in detail the dos and don'ts of writing C++ code. These rules exist to keep the codebase manageable while still allowing coders to use C++ language features productively.

Style, also known as readability, is what we call the conventions that govern our C++ code. The term Style is a bit of a misnomer, since these conventions cover far more than just source file formatting.

Most open-source projects developed by Google conform to the requirements in this guide.

Note that this guide is not a C++ tutorial: we assume that the reader is familiar with the language.

Goals of the Style Guide

Why do we have this document?

There are a few core goals that we believe this guide should serve. These are the fundamental whys that underlie all of the individual rules. By bringing these ideas to the fore, we hope to ground discussions and make it clearer to our broader community why the rules are in place and why particular decisions have been made. If you understand what goals each rule is serving, it should be clearer to everyone when a rule may be waived (some can be), and what sort of argument or alternative would be necessary to change a rule in the guide.

The goals of the style guide as we currently see them are as follows:

Style rules should pull their weight
The benefit of a style rule must be large enough to justify asking all of our engineers to remember it. The benefit is measured relative to the codebase we would get without the rule, so a rule against a very harmful practice may still have a small benefit if people are unlikely to do it anyway. This principle mostly explains the rules we don't have, rather than the rules we do: for example, goto contravenes many of the following principles, but is already vanishingly rare, so the Style Guide doesn't discuss it.
Optimize for the reader, not the writer
Our codebase (and most individual components submitted to it) is expected to continue for quite some time. As a result, more time will be spent reading most of our code than writing it. We explicitly choose to optimize for the experience of our average software engineer reading, maintaining, and debugging code in our codebase rather than ease when writing said code. "Leave a trace for the reader" is a particularly common sub-point of this principle: When something surprising or unusual is happening in a snippet of code (for example, transfer of pointer ownership), leaving textual hints for the reader at the point of use is valuable (std::unique_ptr demonstrates the ownership transfer unambiguously at the call site).
Be consistent with existing code
Using one style consistently through our codebase lets us focus on other (more important) issues. Consistency also allows for automation: tools that format your code or adjust your #includes only work properly when your code is consistent with the expectations of the tooling. In many cases, rules that are attributed to "Be Consistent" boil down to "Just pick one and stop worrying about it"; the potential value of allowing flexibility on these points is outweighed by the cost of having people argue over them. However, there are limits to consistency; it is a good tie breaker when there is no clear technical argument, nor a long-term direction. It applies more heavily locally (per file, or for a tightly-related set of interfaces). Consistency should not generally be used as a justification to do things in an old style without considering the benefits of the new style, or the tendency of the codebase to converge on newer styles over time.
Be consistent with the broader C++ community when appropriate
Consistency with the way other organizations use C++ has value for the same reasons as consistency within our codebase. If a feature in the C++ standard solves a problem, or if some idiom is widely known and accepted, that's an argument for using it. However, sometimes standard features and idioms are flawed, or were just designed without our codebase's needs in mind. In those cases (as described below) it's appropriate to constrain or ban standard features. In some cases we prefer a homegrown or third-party library over a library defined in the C++ Standard, either out of perceived superiority or insufficient value to transition the codebase to the standard interface.
Avoid surprising or dangerous constructs
C++ has features that are more surprising or dangerous than one might think at a glance. Some style guide restrictions are in place to prevent falling into these pitfalls. There is a high bar for style guide waivers on such restrictions, because waiving such rules often directly risks compromising program correctness.
Avoid constructs that our average C++ programmer would find tricky or hard to maintain
C++ has features that may not be generally appropriate because of the complexity they introduce to the code. In widely used code, it may be more acceptable to use trickier language constructs, because any benefits of more complex implementation are multiplied widely by usage, and the cost in understanding the complexity does not need to be paid again when working with new portions of the codebase. When in doubt, waivers to rules of this type can be sought by asking your project leads. This is specifically important for our codebase because code ownership and team membership changes over time: even if everyone that works with some piece of code currently understands it, such understanding is not guaranteed to hold a few years from now.
Be mindful of our scale
With a codebase of 100+ million lines and thousands of engineers, some mistakes and simplifications for one engineer can become costly for many. For instance it's particularly important to avoid polluting the global namespace: name collisions across a codebase of hundreds of millions of lines are difficult to work with and hard to avoid if everyone puts things into the global namespace.
Concede to optimization when necessary
Performance optimizations can sometimes be necessary and appropriate, even when they conflict with the other principles of this document.

The intent of this document is to provide maximal guidance with reasonable restriction. As always, common sense and good taste should prevail. By this we specifically refer to the established conventions of the entire Google C++ community, not just your personal preferences or those of your team. Be skeptical about and reluctant to use clever or unusual constructs: the absence of a prohibition is not the same as a license to proceed. Use your judgment, and if you are unsure, please don't hesitate to ask your project leads to get additional input.

C++ Version

Currently, code should target C++20, i.e., should not use C++23 features. The C++ version targeted by this guide will advance (aggressively) over time.

Do not use non-standard extensions.

Consider portability to other environments before using features from C++17 and C++20 in your project.

Header Files

In general, every .cc file should have an associated .h file. There are some common exceptions, such as unit tests and small .cc files containing just a main() function.

Correct use of header files can make a huge difference to the readability, size and performance of your code.

The following rules will guide you through the various pitfalls of using header files.

Self-contained Headers

Header files should be self-contained (compile on their own) and end in .h. Non-header files that are meant for inclusion should end in .inc and be used sparingly.

All header files should be self-contained. Users and refactoring tools should not have to adhere to special conditions to include the header. Specifically, a header should have header guards and include all other headers it needs.

When a header declares inline functions or templates that clients of the header will instantiate, the inline functions and templates must also have definitions in the header, either directly or in files it includes. Do not move these definitions to separately included header (-inl.h) files; this practice was common in the past, but is no longer allowed. When all instantiations of a template occur in one .cc file, either because they're explicit or because the definition is accessible to only the .cc file, the template definition can be kept in that file.

There are rare cases where a file designed to be included is not self-contained. These are typically intended to be included at unusual locations, such as the middle of another file. They might not use header guards, and might not include their prerequisites. Name such files with the .inc extension. Use sparingly, and prefer self-contained headers when possible.

The #define Guard

All header files should have #define guards to prevent multiple inclusion. The format of the symbol name should be <PROJECT>_<PATH>_<FILE>_H_.

To guarantee uniqueness, they should be based on the full path in a project's source tree. For example, the file foo/src/bar/baz.h in project foo should have the following guard:

#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_

...

#endif  // FOO_BAR_BAZ_H_

Include What You Use

If a source or header file refers to a symbol defined elsewhere, the file should directly include a header file which properly intends to provide a declaration or definition of that symbol. It should not include header files for any other reason.

Do not rely on transitive inclusions. This allows people to remove no-longer-needed #include statements from their headers without breaking clients. This also applies to related headers - foo.cc should include bar.h if it uses a symbol from it even if foo.h includes bar.h.

Forward Declarations

Avoid using forward declarations where possible. Instead, include the headers you need.

A "forward declaration" is a declaration of an entity without an associated definition.

// In a C++ source file:
class B;
void FuncInB();
extern int variable_in_b;
ABSL_DECLARE_FLAG(flag_in_b);

Try to avoid forward declarations of entities defined in another project.

Defining Functions in Header Files

Include the definition of a function at its point of declaration in a header file only when the definition is short. If the definition otherwise has a reason be in the header, put it in an internal part of the file. If necessary to make the definition ODR-safe, mark it with an inline specifier.

Functions defined in header files are sometimes referred to as "inline functions", which is a somewhat overloaded term that refers to several distinct but overlapping situations:

  1. A textually inline symbol's definition is exposed to the reader at the point of declaration.
  2. A function or variable defined in a header file is expandable inline since its definition is available for inline expansion by the compiler, which can lead to more efficient object code.
  3. ODR-safe entities do not violate the "One Definition Rule", which often requires the inline keyword for things defined in header files .

While functions tend to be a more common source of confusion, these definitions apply to variables as well, and so do the rules here.

Only define a function at its public declaration if it is short, say, 10 lines or fewer. Put longer function bodies in the .cc file unless they must be in the header for performance or technical reasons.

Even if a definition must be in the header, this is not a sufficient reason to put it within the public part. Instead, the definition can be in an internal part of the header, such as the private section of a class, within a namespace that includes the word internal, or below a comment like // Implementation details only below here.

Once a definition is in a header file, it must be ODR-safe by having the inline specifier or being implicitly specified inline by being a function template or defined in a class body when first declared.

template <typename T>
class Foo {
 public:
  int bar() { return bar_; }

  void MethodWithHugeBody();

 private:
  int bar_;
};

// Implementation details only below here

template <typename T>
void Foo<T>::MethodWithHugeBody() {
  ...
}

Names and Order of Includes

Include headers in the following order: Related header, C system headers, C++ standard library headers, other libraries' headers, your project's headers.

All of a project's header files should be listed as descendants of the project's source directory without use of UNIX directory aliases . (the current directory) or .. (the parent directory). For example, google-awesome-project/src/base/logging.h should be included as:

#include "base/logging.h"

Headers should only be included using an angle-bracketed path if the library requires you to do so. In particular, the following headers require angle brackets:

In dir/foo.cc or dir/foo_test.cc, whose main purpose is to implement or test the stuff in dir2/foo2.h, order your includes as follows:

  1. dir2/foo2.h.
  2. A blank line
  3. C system headers, and any other headers in angle brackets with the .h extension, e.g., <unistd.h>, <stdlib.h>, <Python.h>.
  4. A blank line
  5. C++ standard library headers (without file extension), e.g., <algorithm>, <cstddef>.
  6. A blank line
  7. Other libraries' .h files.
  8. A blank line
  9. Your project's .h files.

Separate each non-empty group with one blank line.

With the preferred ordering, if the related header dir2/foo2.h omits any necessary includes, the build of dir/foo.cc or dir/foo_test.cc will break. Thus, this rule ensures that build breaks show up first for the people working on these files, not for innocent people in other packages.

dir/foo.cc and dir2/foo2.h are usually in the same directory (e.g., base/basictypes_test.cc and base/basictypes.h), but may sometimes be in different directories too.

Note that the C headers such as stddef.h are essentially interchangeable with their C++ counterparts (cstddef). Either style is acceptable, but prefer consistency with existing code.

Within each section the includes should be ordered alphabetically. Note that older code might not conform to this rule and should be fixed when convenient.

For example, the includes in google-awesome-project/src/foo/internal/fooserver.cc might look like this:

#include "foo/server/fooserver.h"

#include <sys/types.h>
#include <unistd.h>

#include <string>
#include <vector>

#include "base/basictypes.h"
#include "foo/server/bar.h"
#include "third_party/absl/flags/flag.h"

Exception:

Sometimes, system-specific code needs conditional includes. Such code can put conditional includes after other includes. Of course, keep your system-specific code small and localized. Example:

#include "foo/public/fooserver.h"

#ifdef _WIN32
#include <windows.h>
#endif  // _WIN32

Scoping

Namespaces

With few exceptions, place code in a namespace. Namespaces should have unique names based on the project name, and possibly its path. Do not use using-directives (e.g., using namespace foo). Do not use inline namespaces. For unnamed namespaces, see Internal Linkage.

Namespaces subdivide the global scope into distinct, named scopes, and so are useful for preventing name collisions in the global scope.

Namespaces provide a method for preventing name conflicts in large programs while allowing most code to use reasonably short names.

For example, if two different projects have a class Foo in the global scope, these symbols may collide at compile time or at runtime. If each project places their code in a namespace, project1::Foo and project2::Foo are now distinct symbols that do not collide, and code within each project's namespace can continue to refer to Foo without the prefix.

Inline namespaces automatically place their names in the enclosing scope. Consider the following snippet, for example:

namespace outer {
inline namespace inner {
  void foo();
}  // namespace inner
}  // namespace outer

The expressions outer::inner::foo() and outer::foo() are interchangeable. Inline namespaces are primarily intended for ABI compatibility across versions.

Namespaces can be confusing, because they complicate the mechanics of figuring out what definition a name refers to.

Inline namespaces, in particular, can be confusing because names aren't actually restricted to the namespace where they are declared. They are only useful as part of some larger versioning policy.

In some contexts, it's necessary to repeatedly refer to symbols by their fully-qualified names. For deeply-nested namespaces, this can add a lot of clutter.

Namespaces should be used as follows:

Internal Linkage

When definitions in a .cc file do not need to be referenced outside that file, give them internal linkage by placing them in an unnamed namespace or declaring them static. Do not use either of these constructs in .h files.

All declarations can be given internal linkage by placing them in unnamed namespaces. Functions and variables can also be given internal linkage by declaring them static. This means that anything you're declaring can't be accessed from another file. If a different file declares something with the same name, then the two entities are completely independent.

Use of internal linkage in .cc files is encouraged for all code that does not need to be referenced elsewhere. Do not use internal linkage in .h files.

Format unnamed namespaces like named namespaces. In the terminating comment, leave the namespace name empty:

namespace {
...
}  // namespace

Nonmember, Static Member, and Global Functions

Prefer placing nonmember functions in a namespace; use completely global functions rarely. Do not use a class simply to group static members. Static methods of a class should generally be closely related to instances of the class or the class's static data.

Nonmember and static member functions can be useful in some situations. Putting nonmember functions in a namespace avoids polluting the global namespace.

Nonmember and static member functions may make more sense as members of a new class, especially if they access external resources or have significant dependencies.

Sometimes it is useful to define a function not bound to a class instance. Such a function can be either a static member or a nonmember function. Nonmember functions should not depend on external variables, and should nearly always exist in a namespace. Do not create classes only to group static members; this is no different than just giving the names a common prefix, and such grouping is usually unnecessary anyway.

If you define a nonmember function and it is only needed in its .cc file, use internal linkage to limit its scope.

Local Variables

Place a function's variables in the narrowest scope possible, and initialize variables in the declaration.

C++ allows you to declare variables anywhere in a function. We encourage you to declare them in a scope as local as possible, and as close to the first use as possible. This makes it easier for the reader to find the declaration and see what type the variable is and what it was initialized to. In particular, initialization should be used instead of declaration and assignment, e.g.,:

int i;
i = f();      // Bad -- initialization separate from declaration.
int i = f();  // Good -- declaration has initialization.
int jobs = NumJobs();
// More code...
f(jobs);      // Bad -- declaration separate from use.
int jobs = NumJobs();
f(jobs);      // Good -- declaration immediately (or closely) followed by use.
std::vector<int> v;
v.push_back(1);  // Prefer initializing using brace initialization.
v.push_back(2);
std::vector<int> v = {1, 2};  // Good -- v starts initialized.

Variables needed for if, while and for statements should normally be declared within those statements, so that such variables are confined to those scopes. For example:

while (const char* p = strchr(str, '/')) str = p + 1;

There is one caveat: if the variable is an object, its constructor is invoked every time it enters scope and is created, and its destructor is invoked every time it goes out of scope.

// Inefficient implementation:
for (int i = 0; i < 1000000; ++i) {
  Foo f;  // My ctor and dtor get called 1000000 times each.
  f.DoSomething(i);
}

It may be more efficient to declare such a variable used in a loop outside that loop:

Foo f;  // My ctor and dtor get called once each.
for (int i = 0; i < 1000000; ++i) {
  f.DoSomething(i);
}

Static and Global Variables

Objects with static storage duration are forbidden unless they are trivially destructible. Informally this means that the destructor does not do anything, even taking member and base destructors into account. More formally it means that the type has no user-defined or virtual destructor and that all bases and non-static members are trivially destructible. Static function-local variables may use dynamic initialization. Use of dynamic initialization for static class member variables or variables at namespace scope is discouraged, but allowed in limited circumstances; see below for details.

As a rule of thumb: a global variable satisfies these requirements if its declaration, considered in isolation, could be constexpr.

Every object has a storage duration, which correlates with its lifetime. Objects with static storage duration live from the point of their initialization until the end of the program. Such objects appear as variables at namespace scope ("global variables"), as static data members of classes, or as function-local variables that are declared with the static specifier. Function-local static variables are initialized when control first passes through their declaration; all other objects with static storage duration are initialized as part of program start-up. All objects with static storage duration are destroyed at program exit (which happens before unjoined threads are terminated).

Initialization may be dynamic, which means that something non-trivial happens during initialization. (For example, consider a constructor that allocates memory, or a variable that is initialized with the current process ID.) The other kind of initialization is static initialization. The two aren't quite opposites, though: static initialization always happens to objects with static storage duration (initializing the object either to a given constant or to a representation consisting of all bytes set to zero), whereas dynamic initialization happens after that, if required.

Global and static variables are very useful for a large number of applications: named constants, auxiliary data structures internal to some translation unit, command-line flags, logging, registration mechanisms, background infrastructure, etc.

Global and static variables that use dynamic initialization or have non-trivial destructors create complexity that can easily lead to hard-to-find bugs. Dynamic initialization is not ordered across translation units, and neither is destruction (except that destruction happens in reverse order of initialization). When one initialization refers to another variable with static storage duration, it is possible that this causes an object to be accessed before its lifetime has begun (or after its lifetime has ended). Moreover, when a program starts threads that are not joined at exit, those threads may attempt to access objects after their lifetime has ended if their destructor has already run.

Decision on destruction

When destructors are trivial, their execution is not subject to ordering at all (they are effectively not "run"); otherwise we are exposed to the risk of accessing objects after the end of their lifetime. Therefore, we only allow objects with static storage duration if they are trivially destructible. Fundamental types (like pointers and int) are trivially destructible, as are arrays of trivially destructible types. Note that variables marked with constexpr are trivially destructible.

const int kNum = 10;  // Allowed

struct X { int n; };
const X kX[] = {{1}, {2}, {3}};  // Allowed

void foo() {
  static const char* const kMessages[] = {"hello", "world"};  // Allowed
}

// Allowed: constexpr guarantees trivial destructor.
constexpr std::array<int, 3> kArray = {1, 2, 3};
// bad: non-trivial destructor
const std::string kFoo = "foo";

// Bad for the same reason, even though kBar is a reference (the
// rule also applies to lifetime-extended temporary objects).
const std::string& kBar = StrCat("a", "b", "c");

void bar() {
  // Bad: non-trivial destructor.
  static std::map<int, int> kData = {{1, 0}, {2, 0}, {3, 0}};
}

Note that references are not objects, and thus they are not subject to the constraints on destructibility. The constraint on dynamic initialization still applies, though. In particular, a function-local static reference of the form static T& t = *new T; is allowed.

Decision on initialization

Initialization is a more complex topic. This is because we must not only consider whether class constructors execute, but we must also consider the evaluation of the initializer:

int n = 5;    // Fine
int m = f();  // ? (Depends on f)
Foo x;        // ? (Depends on Foo::Foo)
Bar y = g();  // ? (Depends on g and on Bar::Bar)

All but the first statement expose us to indeterminate initialization ordering.

The concept we are looking for is called constant initialization in the formal language of the C++ standard. It means that the initializing expression is a constant expression, and if the object is initialized by a constructor call, then the constructor must be specified as constexpr, too:

struct Foo { constexpr Foo(int) {} };

int n = 5;  // Fine, 5 is a constant expression.
Foo x(2);   // Fine, 2 is a constant expression and the chosen constructor is constexpr.
Foo a[] = { Foo(1), Foo(2), Foo(3) };  // Fine

Constant initialization is always allowed. Constant initialization of static storage duration variables should be marked with constexpr or constinit. Any non-local static storage duration variable that is not so marked should be presumed to have dynamic initialization, and reviewed very carefully.

By contrast, the following initializations are problematic:

// Some declarations used below.
time_t time(time_t*);      // Not constexpr!
int f();                   // Not constexpr!
struct Bar { Bar() {} };

// Problematic initializations.
time_t m = time(nullptr);  // Initializing expression not a constant expression.
Foo y(f());                // Ditto
Bar b;                     // Chosen constructor Bar::Bar() not constexpr.

Dynamic initialization of nonlocal variables is discouraged, and in general it is forbidden. However, we do permit it if no aspect of the program depends on the sequencing of this initialization with respect to all other initializations. Under those restrictions, the ordering of the initialization does not make an observable difference. For example:

int p = getpid();  // Allowed, as long as no other static variable
                   // uses p in its own initialization.

Dynamic initialization of static local variables is allowed (and common).

Common patterns

thread_local Variables

thread_local variables that aren't declared inside a function must be initialized with a true compile-time constant, and this must be enforced by using the constinit attribute. Prefer thread_local over other ways of defining thread-local data.

Variables can be declared with the thread_local specifier:

thread_local Foo foo = ...;

Such a variable is actually a collection of objects, so that when different threads access it, they are actually accessing different objects. thread_local variables are much like static storage duration variables in many respects. For instance, they can be declared at namespace scope, inside functions, or as static class members, but not as ordinary class members.

thread_local variable instances are initialized much like static variables, except that they must be initialized separately for each thread, rather than once at program startup. This means that thread_local variables declared within a function are safe, but other thread_local variables are subject to the same initialization-order issues as static variables (and more besides).

thread_local variables have a subtle destruction-order issue: during thread shutdown, thread_local variables will be destroyed in the opposite order of their initialization (as is generally true in C++). If code triggered by the destructor of any thread_local variable refers to any already-destroyed thread_local on that thread, we will get a particularly hard to diagnose use-after-free.

thread_local variables at class or namespace scope must be initialized with a true compile-time constant (i.e., they must have no dynamic initialization). To enforce this, thread_local variables at class or namespace scope must be annotated with constinit (or constexpr, but that should be rare):

   constinit thread_local Foo foo = ...;
  

thread_local variables inside a function have no initialization concerns, but still risk use-after-free during thread exit. Note that you can use a function-scope thread_local to simulate a class- or namespace-scope thread_local by defining a function or static method that exposes it:

Foo& MyThreadLocalFoo() {
  thread_local Foo result = ComplicatedInitialization();
  return result;
}

Note that thread_local variables will be destroyed whenever a thread exits. If the destructor of any such variable refers to any other (potentially-destroyed) thread_local we will suffer from hard to diagnose use-after-free bugs. Prefer trivial types, or types that provably run no user-provided code at destruction to minimize the potential of accessing any other thread_local.

thread_local should be preferred over other mechanisms for defining thread-local data.

Classes

Classes are the fundamental unit of code in C++. Naturally, we use them extensively. This section lists the main dos and don'ts you should follow when writing a class.

Doing Work in Constructors

Avoid virtual method calls in constructors, and avoid initialization that can fail if you can't signal an error.

It is possible to perform arbitrary initialization in the body of the constructor.

Constructors should never call virtual functions. If appropriate for your code , terminating the program may be an appropriate error handling response. Otherwise, consider a factory function or Init() method as described in TotW #42 . Avoid Init() methods on objects with no other states that affect which public methods may be called (semi-constructed objects of this form are particularly hard to work with correctly).

Implicit Conversions

Do not define implicit conversions. Use the explicit keyword for conversion operators and single-argument constructors.

Implicit conversions allow an object of one type (called the source type) to be used where a different type (called the destination type) is expected, such as when passing an int argument to a function that takes a double parameter.

In addition to the implicit conversions defined by the language, users can define their own, by adding appropriate members to the class definition of the source or destination type. An implicit conversion in the source type is defined by a type conversion operator named after the destination type (e.g., operator bool()). An implicit conversion in the destination type is defined by a constructor that can take the source type as its only argument (or only argument with no default value).

The explicit keyword can be applied to a constructor or a conversion operator, to ensure that it can only be used when the destination type is explicit at the point of use, e.g., with a cast. This applies not only to implicit conversions, but to list initialization syntax:

class Foo {
  explicit Foo(int x, double y);
  ...
};

void Func(Foo f);
Func({42, 3.14});  // Error

This kind of code isn't technically an implicit conversion, but the language treats it as one as far as explicit is concerned.

Type conversion operators, and constructors that are callable with a single argument, must be marked explicit in the class definition. As an exception, copy and move constructors should not be explicit, since they do not perform type conversion.

Implicit conversions can sometimes be necessary and appropriate for types that are designed to be interchangeable, for example when objects of two types are just different representations of the same underlying value. In that case, contact your project leads to request a waiver of this rule.

Constructors that cannot be called with a single argument may omit explicit. Constructors that take a single std::initializer_list parameter should also omit explicit, in order to support copy-initialization (e.g., MyType m = {1, 2};).

Copyable and Movable Types

A class's public API must make clear whether the class is copyable, move-only, or neither copyable nor movable. Support copying and/or moving if these operations are clear and meaningful for your type.

A movable type is one that can be initialized and assigned from temporaries.

A copyable type is one that can be initialized or assigned from any other object of the same type (so is also movable by definition), with the stipulation that the value of the source does not change. std::unique_ptr<int> is an example of a movable but not copyable type (since the value of the source std::unique_ptr<int> must be modified during assignment to the destination). int and std::string are examples of movable types that are also copyable. (For int, the move and copy operations are the same; for std::string, there exists a move operation that is less expensive than a copy.)

For user-defined types, the copy behavior is defined by the copy constructor and the copy-assignment operator. Move behavior is defined by the move constructor and the move-assignment operator, if they exist, or by the copy constructor and the copy-assignment operator otherwise.

The copy/move constructors can be implicitly invoked by the compiler in some situations, e.g., when passing objects by value.

Objects of copyable and movable types can be passed and returned by value, which makes APIs simpler, safer, and more general. Unlike when passing objects by pointer or reference, there's no risk of confusion over ownership, lifetime, mutability, and similar issues, and no need to specify them in the contract. It also prevents non-local interactions between the client and the implementation, which makes them easier to understand, maintain, and optimize by the compiler. Further, such objects can be used with generic APIs that require pass-by-value, such as most containers, and they allow for additional flexibility in e.g., type composition.

Copy/move constructors and assignment operators are usually easier to define correctly than alternatives like Clone(), CopyFrom() or Swap(), because they can be generated by the compiler, either implicitly or with = default. They are concise, and ensure that all data members are copied. Copy and move constructors are also generally more efficient, because they don't require heap allocation or separate initialization and assignment steps, and they're eligible for optimizations such as copy elision.

Move operations allow the implicit and efficient transfer of resources out of rvalue objects. This allows a plainer coding style in some cases.

Some types do not need to be copyable, and providing copy operations for such types can be confusing, nonsensical, or outright incorrect. Types representing singleton objects (Registerer), objects tied to a specific scope (Cleanup), or closely coupled to object identity (Mutex) cannot be copied meaningfully. Copy operations for base class types that are to be used polymorphically are hazardous, because use of them can lead to object slicing. Defaulted or carelessly-implemented copy operations can be incorrect, and the resulting bugs can be confusing and difficult to diagnose.

Copy constructors are invoked implicitly, which makes the invocation easy to miss. This may cause confusion for programmers used to languages where pass-by-reference is conventional or mandatory. It may also encourage excessive copying, which can cause performance problems.

Every class's public interface must make clear which copy and move operations the class supports. This should usually take the form of explicitly declaring and/or deleting the appropriate operations in the public section of the declaration.

Specifically, a copyable class should explicitly declare the copy operations, a move-only class should explicitly declare the move operations, and a non-copyable/movable class should explicitly delete the copy operations. A copyable class may also declare move operations in order to support efficient moves. Explicitly declaring or deleting all four copy/move operations is permitted, but not required. If you provide a copy or move assignment operator, you must also provide the corresponding constructor.

class Copyable {
 public:
  Copyable(const Copyable& other) = default;
  Copyable& operator=(const Copyable& other) = default;

  // The implicit move operations are suppressed by the declarations above.
  // You may explicitly declare move operations to support efficient moves.
};

class MoveOnly {
 public:
  MoveOnly(MoveOnly&& other) = default;
  MoveOnly& operator=(MoveOnly&& other) = default;

  // The copy operations are implicitly deleted, but you can
  // spell that out explicitly if you want:
  MoveOnly(const MoveOnly&) = delete;
  MoveOnly& operator=(const MoveOnly&) = delete;
};

class NotCopyableOrMovable {
 public:
  // Not copyable or movable
  NotCopyableOrMovable(const NotCopyableOrMovable&) = delete;
  NotCopyableOrMovable& operator=(const NotCopyableOrMovable&)
      = delete;

  // The move operations are implicitly disabled, but you can
  // spell that out explicitly if you want:
  NotCopyableOrMovable(NotCopyableOrMovable&&) = delete;
  NotCopyableOrMovable& operator=(NotCopyableOrMovable&&)
      = delete;
};

These declarations/deletions can be omitted only if they are obvious:

A type should not be copyable/movable if the meaning of copying/moving is unclear to a casual user, or if it incurs unexpected costs. Move operations for copyable types are strictly a performance optimization and are a potential source of bugs and complexity, so avoid defining them unless they are significantly more efficient than the corresponding copy operations. If your type provides copy operations, it is recommended that you design your class so that the default implementation of those operations is correct. Remember to review the correctness of any defaulted operations as you would any other code.

To eliminate the risk of slicing, prefer to make base classes abstract, by making their constructors protected, by declaring their destructors protected, or by giving them one or more pure virtual member functions. Prefer to avoid deriving from concrete classes.

Structs vs. Classes

Use a struct only for passive objects that carry data; everything else is a class.

The struct and class keywords behave almost identically in C++. We add our own semantic meanings to each keyword, so you should use the appropriate keyword for the data-type you're defining.

structs should be used for passive objects that carry data, and may have associated constants. All fields must be public. The struct type itself must not have invariants that imply relationships between different fields, since direct user access to those fields may break those invariants, but users of a struct may have requirements and guarantees on particular uses of it. Constructors, destructors, and helper methods may be present; however, these methods must not require or enforce any invariants.

If more functionality or invariants are required, or struct has wide visibility and expected to evolve, then a class is more appropriate. If in doubt, make it a class.

For consistency with STL, you can use struct instead of class for stateless types, such as traits, template metafunctions, and some functors.

Note that member variables in structs and classes have different naming rules.

Structs vs. Pairs and Tuples

Prefer to use a struct instead of a pair or a tuple whenever the elements can have meaningful names.

While using pairs and tuples can avoid the need to define a custom type, potentially saving work when writing code, a meaningful field name will almost always be much clearer when reading code than .first, .second, or std::get<X>. While C++14's introduction of std::get<Type> to access a tuple element by type rather than index (when the type is unique) can sometimes partially mitigate this, a field name is usually substantially clearer and more informative than a type.

Pairs and tuples may be appropriate in generic code where there are not specific meanings for the elements of the pair or tuple. Their use may also be required in order to interoperate with existing code or APIs.

Inheritance

Composition is often more appropriate than inheritance. When using inheritance, make it public.

When a sub-class inherits from a base class, it includes the definitions of all the data and operations that the base class defines. "Interface inheritance" is inheritance from a pure abstract base class (one with no state or defined methods); all other inheritance is "implementation inheritance".

Implementation inheritance reduces code size by re-using the base class code as it specializes an existing type. Because inheritance is a compile-time declaration, you and the compiler can understand the operation and detect errors. Interface inheritance can be used to programmatically enforce that a class expose a particular API. Again, the compiler can detect errors, in this case, when a class does not define a necessary method of the API.

For implementation inheritance, because the code implementing a sub-class is spread between the base and the sub-class, it can be more difficult to understand an implementation. The sub-class cannot override functions that are not virtual, so the sub-class cannot change implementation.

Multiple inheritance is especially problematic, because it often imposes a higher performance overhead (in fact, the performance drop from single inheritance to multiple inheritance can often be greater than the performance drop from ordinary to virtual dispatch), and because it risks leading to "diamond" inheritance patterns, which are prone to ambiguity, confusion, and outright bugs.

All inheritance should be public. If you want to do private inheritance, you should be including an instance of the base class as a member instead. You may use final on classes when you don't intend to support using them as base classes.

Do not overuse implementation inheritance. Composition is often more appropriate. Try to restrict use of inheritance to the "is-a" case: Bar subclasses Foo if it can reasonably be said that Bar "is a kind of" Foo.

Limit the use of protected to those member functions that might need to be accessed from subclasses. Note that data members should be private.

Explicitly annotate overrides of virtual functions or virtual destructors with exactly one of an override or (less frequently) final specifier. Do not use virtual when declaring an override. Rationale: A function or destructor marked override or final that is not an override of a base class virtual function will not compile, and this helps catch common errors. The specifiers serve as documentation; if no specifier is present, the reader has to check all ancestors of the class in question to determine if the function or destructor is virtual or not.

Multiple inheritance is permitted, but multiple implementation inheritance is strongly discouraged.

Operator Overloading

Overload operators judiciously. Do not use user-defined literals.

C++ permits user code to declare overloaded versions of the built-in operators using the operator keyword, so long as one of the parameters is a user-defined type. The operator keyword also permits user code to define new kinds of literals using operator"", and to define type-conversion functions such as operator bool().

Operator overloading can make code more concise and intuitive by enabling user-defined types to behave the same as built-in types. Overloaded operators are the idiomatic names for certain operations (e.g., ==, <, =, and <<), and adhering to those conventions can make user-defined types more readable and enable them to interoperate with libraries that expect those names.

User-defined literals are a very concise notation for creating objects of user-defined types.

Define overloaded operators only if their meaning is obvious, unsurprising, and consistent with the corresponding built-in operators. For example, use | as a bitwise- or logical-or, not as a shell-style pipe.

Define operators only on your own types. More precisely, define them in the same headers, .cc files, and namespaces as the types they operate on. That way, the operators are available wherever the type is, minimizing the risk of multiple definitions. If possible, avoid defining operators as templates, because they must satisfy this rule for any possible template arguments. If you define an operator, also define any related operators that make sense, and make sure they are defined consistently.

Prefer to define non-modifying binary operators as non-member functions. If a binary operator is defined as a class member, implicit conversions will apply to the right-hand argument, but not the left-hand one. It will confuse your users if a + b compiles but b + a doesn't.

For a type T whose values can be compared for equality, define a non-member operator== and document when two values of type T are considered equal. If there is a single obvious notion of when a value t1 of type T is less than another such value t2 then you may also define operator<=>, which should be consistent with operator==. Prefer not to overload the other comparison and ordering operators.

Don't go out of your way to avoid defining operator overloads. For example, prefer to define ==, =, and <<, rather than Equals(), CopyFrom(), and PrintTo(). Conversely, don't define operator overloads just because other libraries expect them. For example, if your type doesn't have a natural ordering, but you want to store it in a std::set, use a custom comparator rather than overloading <.

Do not overload &&, ||, , (comma), or unary &. Do not overload operator"", i.e., do not introduce user-defined literals. Do not use any such literals provided by others (including the standard library).

Type conversion operators are covered in the section on implicit conversions. The = operator is covered in the section on copy constructors. Overloading << for use with streams is covered in the section on streams. See also the rules on function overloading, which apply to operator overloading as well.

Access Control

Make classes' data members private, unless they are constants. This simplifies reasoning about invariants, at the cost of some easy boilerplate in the form of accessors (usually const) if necessary.

For technical reasons, we allow data members of a test fixture class defined in a .cc file to be protected when using Google Test. If a test fixture class is defined outside of the .cc file it is used in, for example in a .h file, make data members private.

Declaration Order

Group similar declarations together, placing public parts earlier.

A class definition should usually start with a public: section, followed by protected:, then private:. Omit sections that would be empty.

Within each section, prefer grouping similar kinds of declarations together, and prefer the following order:

  1. Types and type aliases (typedef, using, enum, nested structs and classes, and friend types)
  2. (Optionally, for structs only) non-static data members
  3. Static constants
  4. Factory functions
  5. Constructors and assignment operators
  6. Destructor
  7. All other functions (static and non-static member functions, and friend functions)
  8. All other data members (static and non-static)

Do not put large method definitions inline in the class definition. Usually, only trivial or performance-critical, and very short, methods may be defined inline. See Defining Functions in Header Files for more details.

Functions

Inputs and Outputs

The output of a C++ function is naturally provided via a return value and sometimes via output parameters (or in/out parameters).

Prefer using return values over output parameters: they improve readability, and often provide the same or better performance. See TotW #176.

Prefer to return by value or, failing that, return by reference. Avoid returning a raw pointer unless it can be null.

Parameters are either inputs to the function, outputs from the function, or both. Non-optional input parameters should usually be values or const references, while non-optional output and input/output parameters should usually be references (which cannot be null). Generally, use std::optional to represent optional by-value inputs, and use a const pointer when the non-optional form would have used a reference. Use non-const pointers to represent optional outputs and optional input/output parameters.

Avoid defining functions that require a reference parameter to outlive the call. In some cases reference parameters can bind to temporaries, leading to lifetime bugs. Instead, find a way to eliminate the lifetime requirement (for example, by copying the parameter), or pass retained parameters by pointer and document the lifetime and non-null requirements. See TotW 116 for more.

When ordering function parameters, put all input-only parameters before any output parameters. In particular, do not add new parameters to the end of the function just because they are new; place new input-only parameters before the output parameters. This is not a hard-and-fast rule. Parameters that are both input and output muddy the waters, and, as always, consistency with related functions may require you to bend the rule. Variadic functions may also require unusual parameter ordering.

Write Short Functions

Prefer small and focused functions.

We recognize that long functions are sometimes appropriate, so no hard limit is placed on functions length. If a function exceeds about 40 lines, think about whether it can be broken up without harming the structure of the program.

Even if your long function works perfectly now, someone modifying it in a few months may add new behavior. This could result in bugs that are hard to find. Keeping your functions short and simple makes it easier for other people to read and modify your code. Small functions are also easier to test.

You could find long and complicated functions when working with some code. Do not be intimidated by modifying existing code: if working with such a function proves to be difficult, you find that errors are hard to debug, or you want to use a piece of it in several different contexts, consider breaking up the function into smaller and more manageable pieces.

Function Overloading

Use overloaded functions (including constructors) only if a reader looking at a call site can get a good idea of what is happening without having to first figure out exactly which overload is being called.

You may write a function that takes a const std::string& and overload it with another that takes const char*. However, in this case consider std::string_view instead.

class MyClass {
 public:
  void Analyze(const std::string& text);
  void Analyze(const char* text, size_t textlen);
};

Overloading can make code more intuitive by allowing an identically-named function to take different arguments. It may be necessary for templatized code, and it can be convenient for Visitors.

Overloading based on const or ref qualification may make utility code more usable, more efficient, or both. See TotW #148 for more.

If a function is overloaded by the argument types alone, a reader may have to understand C++'s complex matching rules in order to tell what's going on. Also many people are confused by the semantics of inheritance if a derived class overrides only some of the variants of a function.

You may overload a function when there are no semantic differences between variants. These overloads may vary in types, qualifiers, or argument count. However, a reader of such a call must not need to know which member of the overload set is chosen, only that something from the set is being called.

To reflect this unified design, prefer a single, comprehensive "umbrella" comment that documents the entire overload set and is placed before the first declaration.

Where a reader might have difficulty connecting the umbrella comment to a specific overload, it's okay to have a comment for specific overloads.

Default Arguments

Default arguments are allowed on non-virtual functions when the default is guaranteed to always have the same value. Follow the same restrictions as for function overloading, and prefer overloaded functions if the readability gained with default arguments doesn't outweigh the downsides below.

Often you have a function that uses default values, but occasionally you want to override the defaults. Default parameters allow an easy way to do this without having to define many functions for the rare exceptions. Compared to overloading the function, default arguments have a cleaner syntax, with less boilerplate and a clearer distinction between 'required' and 'optional' arguments.

Defaulted arguments are another way to achieve the semantics of overloaded functions, so all the reasons not to overload functions apply.

The defaults for arguments in a virtual function call are determined by the static type of the target object, and there's no guarantee that all overrides of a given function declare the same defaults.

Default parameters are re-evaluated at each call site, which can bloat the generated code. Readers may also expect the default's value to be fixed at the declaration instead of varying at each call.

Function pointers are confusing in the presence of default arguments, since the function signature often doesn't match the call signature. Adding function overloads avoids these problems.

Default arguments are banned on virtual functions, where they don't work properly, and in cases where the specified default might not evaluate to the same value depending on when it was evaluated. (For example, don't write void f(int n = counter++);.)

In some other cases, default arguments can improve the readability of their function declarations enough to overcome the downsides above, so they are allowed. When in doubt, use overloads.

Trailing Return Type Syntax

Use trailing return types only where using the ordinary syntax (leading return types) is impractical or much less readable.

C++ allows two different forms of function declarations. In the older form, the return type appears before the function name. For example:

int Foo(int x);

The newer form uses the auto keyword before the function name and a trailing return type after the argument list. For example, the declaration above could equivalently be written:

auto Foo(int x) -> int;

The trailing return type is in the function's scope. This doesn't make a difference for a simple case like int but it matters for more complicated cases, like types declared in class scope or types written in terms of the function parameters.

Trailing return types are the only way to explicitly specify the return type of a lambda expression. In some cases the compiler is able to deduce a lambda's return type, but not in all cases. Even when the compiler can deduce it automatically, sometimes specifying it explicitly would be clearer for readers.

Sometimes it's easier and more readable to specify a return type after the function's parameter list has already appeared. This is particularly true when the return type depends on template parameters. For example:

    template <typename T, typename U>
    auto Add(T t, U u) -> decltype(t + u);
  
versus
    template <typename T, typename U>
    decltype(declval<T&>() + declval<U&>()) Add(T t, U u);
  

Trailing return type syntax has no analogue in C++-like languages such as C and Java, so some readers may find it unfamiliar.

Existing codebases have an enormous number of function declarations that aren't going to get changed to use the new syntax, so the realistic choices are using the old syntax only or using a mixture of the two. Using a single version is better for uniformity of style.

In most cases, continue to use the older style of function declaration where the return type goes before the function name. Use the new trailing-return-type form only in cases where it's required (such as lambdas) or where, by putting the type after the function's parameter list, it allows you to write the type in a much more readable way. The latter case should be rare; it's mostly an issue in fairly complicated template code, which is discouraged in most cases.

Google-Specific Magic

There are various tricks and utilities that we use to make C++ code more robust, and various ways we use C++ that may differ from what you see elsewhere.

Ownership and Smart Pointers

Prefer to have single, fixed owners for dynamically allocated objects. Prefer to transfer ownership with smart pointers.

"Ownership" is a bookkeeping technique for managing dynamically allocated memory (and other resources). The owner of a dynamically allocated object is an object or function that is responsible for ensuring that it is deleted when no longer needed. Ownership can sometimes be shared, in which case the last owner is typically responsible for deleting it. Even when ownership is not shared, it can be transferred from one piece of code to another.

"Smart" pointers are classes that act like pointers, e.g., by overloading the * and -> operators. Some smart pointer types can be used to automate ownership bookkeeping, to ensure these responsibilities are met. std::unique_ptr is a smart pointer type which expresses exclusive ownership of a dynamically allocated object; the object is deleted when the std::unique_ptr goes out of scope. It cannot be copied, but can be moved to represent ownership transfer. std::shared_ptr is a smart pointer type that expresses shared ownership of a dynamically allocated object. std::shared_ptrs can be copied; ownership of the object is shared among all copies, and the object is deleted when the last std::shared_ptr is destroyed.

If dynamic allocation is necessary, prefer to keep ownership with the code that allocated it. If other code needs access to the object, consider passing it a copy, or passing a pointer or reference without transferring ownership. Prefer to use std::unique_ptr to make ownership transfer explicit. For example:

std::unique_ptr<Foo> FooFactory();
void FooConsumer(std::unique_ptr<Foo> ptr);

Do not design your code to use shared ownership without a very good reason. One such reason is to avoid expensive copy operations, but you should only do this if the performance benefits are significant, and the underlying object is immutable (i.e., std::shared_ptr<const Foo>). If you do use shared ownership, prefer to use std::shared_ptr.

Never use std::auto_ptr. Instead, use std::unique_ptr.

cpplint

Use cpplint.py to detect style errors.

cpplint.py is a tool that reads a source file and identifies many style errors. It is not perfect, and has both false positives and false negatives, but it is still a valuable tool.

Some projects have instructions on how to run cpplint.py from their project tools. If the project you are contributing to does not, you can download cpplint.py separately.

Other C++ Features

Rvalue References

Use rvalue references only in certain special cases listed below.

Rvalue references are a type of reference that can only bind to temporary objects. The syntax is similar to traditional reference syntax. For example, void f(std::string&& s); declares a function whose argument is an rvalue reference to a std::string.

When the token '&&' is applied to an unqualified template argument in a function parameter, special template argument deduction rules apply. Such a reference is called a forwarding reference.

Do not use rvalue references (or apply the && qualifier to methods), except as follows:

Friends

We allow use of friend classes and functions, within reason.

Friends should usually be defined in the same file so that the reader does not have to look in another file to find uses of the private members of a class. A common use of friend is to have a FooBuilder class be a friend of Foo so that it can construct the inner state of Foo correctly, without exposing this state to the world. In some cases it may be useful to make a unit test class a friend of the class it tests.

Friends extend, but do not break, the encapsulation boundary of a class. In some cases this is better than making a member public when you want to give only one other class access to it. However, most classes should interact with other classes solely through their public members.

Exceptions

We do not use C++ exceptions.

On their face, the benefits of using exceptions outweigh the costs, especially in new projects. However, for existing code, the introduction of exceptions has implications on all dependent code. If exceptions can be propagated beyond a new project, it also becomes problematic to integrate the new project into existing exception-free code. Because most existing C++ code at Google is not prepared to deal with exceptions, it is comparatively difficult to adopt new code that generates exceptions.

Given that Google's existing code is not exception-tolerant, the costs of using exceptions are somewhat greater than the costs in a new project. The conversion process would be slow and error-prone. We don't believe that the available alternatives to exceptions, such as error codes and assertions, introduce a significant burden.

Our advice against using exceptions is not predicated on philosophical or moral grounds, but practical ones. Because we'd like to use our open-source projects at Google and it's difficult to do so if those projects use exceptions, we need to advise against exceptions in Google open-source projects as well. Things would probably be different if we had to do it all over again from scratch.

This prohibition also applies to exception handling related features such as std::exception_ptr and std::nested_exception.

There is an exception to this rule (no pun intended) for Windows code.

noexcept

Specify noexcept when it is useful and correct.

The noexcept specifier is used to specify whether a function will throw exceptions or not. If an exception escapes from a function marked noexcept, the program crashes via std::terminate.

The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions.

You may use noexcept when it is useful for performance if it accurately reflects the intended semantics of your function, i.e., that if an exception is somehow thrown from within the function body then it represents a fatal error. You can assume that noexcept on move constructors has a meaningful performance benefit. If you think there is significant performance benefit from specifying noexcept on some other function, please discuss it with your project leads.

Prefer unconditional noexcept if exceptions are completely disabled (i.e., most Google C++ environments). Otherwise, use conditional noexcept specifiers with simple conditions, in ways that evaluate false only in the few cases where the function could potentially throw. The tests might include type traits check on whether the involved operation might throw (e.g., std::is_nothrow_move_constructible for move-constructing objects), or on whether allocation can throw (e.g., absl::default_allocator_is_nothrow for standard default allocation). Note in many cases the only possible cause for an exception is allocation failure (we believe move constructors should not throw except due to allocation failure), and there are many applications where it's appropriate to treat memory exhaustion as a fatal error rather than an exceptional condition that your program should attempt to recover from. Even for other potential failures you should prioritize interface simplicity over supporting all possible exception throwing scenarios: instead of writing a complicated noexcept clause that depends on whether a hash function can throw, for example, simply document that your component doesn't support hash functions throwing and make it unconditionally noexcept.

Run-Time Type Information (RTTI)

Avoid using run-time type information (RTTI).

RTTI allows a programmer to query the C++ class of an object at run-time. This is done by use of typeid or dynamic_cast.

The standard alternatives to RTTI (described below) require modification or redesign of the class hierarchy in question. Sometimes such modifications are infeasible or undesirable, particularly in widely-used or mature code.

RTTI can be useful in some unit tests. For example, it is useful in tests of factory classes where the test has to verify that a newly created object has the expected dynamic type. It is also useful in managing the relationship between objects and their mocks.

RTTI is useful when considering multiple abstract objects. Consider

bool Base::Equal(Base* other) = 0;
bool Derived::Equal(Base* other) {
  Derived* that = dynamic_cast<Derived*>(other);
  if (that == nullptr)
    return false;
  ...
}

Querying the type of an object at run-time frequently means a design problem. Needing to know the type of an object at runtime is often an indication that the design of your class hierarchy is flawed.

Undisciplined use of RTTI makes code hard to maintain. It can lead to type-based decision trees or switch statements scattered throughout the code, all of which must be examined when making further changes.

RTTI has legitimate uses but is prone to abuse, so you must be careful when using it. You may use it freely in unit tests, but avoid it when possible in other code. In particular, think twice before using RTTI in new code. If you find yourself needing to write code that behaves differently based on the class of an object, consider one of the following alternatives to querying the type:

When the logic of a program guarantees that a given instance of a base class is in fact an instance of a particular derived class, then a dynamic_cast may be used freely on the object. Usually one can use a static_cast as an alternative in such situations.

Decision trees based on type are a strong indication that your code is on the wrong track.

if (typeid(*data) == typeid(D1)) {
  ...
} else if (typeid(*data) == typeid(D2)) {
  ...
} else if (typeid(*data) == typeid(D3)) {
...

Code such as this usually breaks when additional subclasses are added to the class hierarchy. Moreover, when properties of a subclass change, it is difficult to find and modify all the affected code segments.

Do not hand-implement an RTTI-like workaround. The arguments against RTTI apply just as much to workarounds like class hierarchies with type tags. Moreover, workarounds disguise your true intent.

Casting

Use C++-style casts like static_cast<float>(double_value), or brace initialization for conversion of arithmetic types like int64_t y = int64_t{1} << 42. Do not use cast formats like (int)x unless the cast is to void. You may use cast formats like T(x) only when T is a class type.

C++ introduced a different cast system from C that distinguishes the types of cast operations.

The problem with C casts is the ambiguity of the operation; sometimes you are doing a conversion (e.g., (int)3.5) and sometimes you are doing a cast (e.g., (int)"hello"). Brace initialization and C++ casts can often help avoid this ambiguity. Additionally, C++ casts are more visible when searching for them.

The C++-style cast syntax is verbose and cumbersome.

In general, do not use C-style casts. Instead, use these C++-style casts when explicit type conversion is necessary.

See the RTTI section for guidance on the use of dynamic_cast.

Streams

Use streams where appropriate, and stick to "simple" usages. Overload << for streaming only for types representing values, and write only the user-visible value, not any implementation details.

Streams are the standard I/O abstraction in C++, as exemplified by the standard header <iostream>. They are widely used in Google code, mostly for debug logging and test diagnostics.

The << and >> stream operators provide an API for formatted I/O that is easily learned, portable, reusable, and extensible. printf, by contrast, doesn't even support std::string, to say nothing of user-defined types, and is very difficult to use portably. printf also obliges you to choose among the numerous slightly different versions of that function, and navigate the dozens of conversion specifiers.

Streams provide first-class support for console I/O via std::cin, std::cout, std::cerr, and std::clog. The C APIs do as well, but are hampered by the need to manually buffer the input.

Use streams only when they are the best tool for the job. This is typically the case when the I/O is ad-hoc, local, human-readable, and targeted at other developers rather than end-users. Be consistent with the code around you, and with the codebase as a whole; if there's an established tool for your problem, use that tool instead. In particular, logging libraries are usually a better choice than std::cerr or std::clog for diagnostic output, and the libraries in absl/strings or the equivalent are usually a better choice than std::stringstream.

Avoid using streams for I/O that faces external users or handles untrusted data. Instead, find and use the appropriate templating libraries to handle issues like internationalization, localization, and security hardening.

If you do use streams, avoid the stateful parts of the streams API (other than error state), such as imbue(), xalloc(), and register_callback(). Use explicit formatting functions (such as absl::StreamFormat()) rather than stream manipulators or formatting flags to control formatting details such as number base, precision, or padding.

Overload << as a streaming operator for your type only if your type represents a value, and << writes out a human-readable string representation of that value. Avoid exposing implementation details in the output of <<; if you need to print object internals for debugging, use named functions instead (a method named DebugString() is the most common convention).

Preincrement and Predecrement

Use the prefix form (++i) of the increment and decrement operators unless you need postfix semantics.

When a variable is incremented (++i or i++) or decremented (--i or i--) and the value of the expression is not used, one must decide whether to preincrement (decrement) or postincrement (decrement).

A postfix increment/decrement expression evaluates to the value as it was before it was modified. This can result in code that is more compact but harder to read. The prefix form is generally more readable, is never less efficient, and can be more efficient because it doesn't need to make a copy of the value as it was before the operation.

The tradition developed, in C, of using post-increment, even when the expression value is not used, especially in for loops.

Use prefix increment/decrement, unless the code explicitly needs the result of the postfix increment/decrement expression.

Use of const

In APIs, use const whenever it makes sense. constexpr is a better choice for some uses of const.

Declared variables and parameters can be preceded by the keyword const to indicate the variables are not changed (e.g., const int foo). Class functions can have the const qualifier to indicate the function does not change the state of the class member variables (e.g., class Foo { int Bar(char c) const; };).

Easier for people to understand how variables are being used. Allows the compiler to do better type checking, and, conceivably, generate better code. Helps people convince themselves of program correctness because they know the functions they call are limited in how they can modify your variables. Helps people know what functions are safe to use without locks in multi-threaded programs.

const is viral: if you pass a const variable to a function, that function must have const in its prototype (or the variable will need a const_cast). This can be a particular problem when calling library functions.

We strongly recommend using const in APIs (i.e., on function parameters, methods, and non-local variables) wherever it is meaningful and accurate. This provides consistent, mostly compiler-verified documentation of what objects an operation can mutate. Having a consistent and reliable way to distinguish reads from writes is critical to writing thread-safe code, and is useful in many other contexts as well. In particular:

Using const on local variables is neither encouraged nor discouraged.

All of a class's const operations should be safe to invoke concurrently with each other. If that's not feasible, the class must be clearly documented as "thread-unsafe".

Where to put the const

Some people favor the form int const* foo to const int* foo. They argue that this is more readable because it's more consistent: it keeps the rule that const always follows the object it's describing. However, this consistency argument doesn't apply in codebases with few deeply-nested pointer expressions since most const expressions have only one const, and it applies to the underlying value. In such cases, there's no consistency to maintain. Putting the const first is arguably more readable, since it follows English in putting the "adjective" (const) before the "noun" (int).

That said, while we encourage putting const first, we do not require it. But be consistent with the code around you!

Use of constexpr, constinit, and consteval

Use constexpr to define true constants or to ensure constant initialization. Use constinit to ensure constant initialization for non-constant variables.

Some variables can be declared constexpr to indicate the variables are true constants, i.e., fixed at compilation/link time. Some functions and constructors can be declared constexpr which enables them to be used in defining a constexpr variable. Functions can be declared consteval to restrict their use to compile time.

Use of constexpr enables definition of constants with floating-point expressions rather than just literals; definition of constants of user-defined types; and definition of constants with function calls.

Prematurely marking something as constexpr may cause migration problems if later on it has to be downgraded. Current restrictions on what is allowed in constexpr functions and constructors may invite obscure workarounds in these definitions.

constexpr definitions enable a more robust specification of the constant parts of an interface. Use constexpr to specify true constants and the functions that support their definitions. consteval may be used for code that must not be invoked at runtime. Avoid complexifying function definitions to enable their use with constexpr. Do not use constexpr or consteval to force inlining.

Integer Types

Of the built-in C++ integer types, the only one used is int. If a program needs an integer type of a different size, use an exact-width integer type from <stdint.h>, such as int16_t. If you have a value that could ever be greater than or equal to 2^31, use a 64-bit type such as int64_t. Keep in mind that even if your value won't ever be too large for an int, it may be used in intermediate calculations which may require a larger type. When in doubt, choose a larger type.

C++ does not specify exact sizes for the integer types like int. Common sizes on contemporary architectures are 16 bits for short, 32 bits for int, 32 or 64 bits for long, and 64 bits for long long, but different platforms make different choices, in particular for long.

Uniformity of declaration.

The sizes of integral types in C++ can vary based on compiler and architecture.

The standard library header <stdint.h> defines types like int16_t, uint32_t, int64_t, etc. You should always use those in preference to short, unsigned long long, and the like, when you need a guarantee on the size of an integer. Prefer to omit the std:: prefix for these types, as the extra 5 characters do not merit the added clutter. Of the built-in integer types, only int should be used. When appropriate, you are welcome to use standard type aliases like size_t and ptrdiff_t.

We use int very often, for integers we know are not going to be too big, e.g., loop counters. Use plain old int for such things. You should assume that an int is at least 32 bits, but don't assume that it has more than 32 bits. If you need a 64-bit integer type, use int64_t or uint64_t.

For integers we know can be "big", use int64_t.

You should not use the unsigned integer types such as uint32_t, unless there is a valid reason such as representing a bit pattern rather than a number, or you need defined overflow modulo 2^N. In particular, do not use unsigned types to say a number will never be negative. Instead, use assertions for this.

If your code is a container that returns a size, be sure to use a type that will accommodate any possible usage of your container. When in doubt, use a larger type rather than a smaller type.

Use care when converting integer types. Integer conversions and promotions can cause undefined behavior, leading to security bugs and other problems.

On Unsigned Integers

Unsigned integers are good for representing bitfields and modular arithmetic. Because of historical accident, the C++ standard also uses unsigned integers to represent the size of containers - many members of the standards body believe this to be a mistake, but it is effectively impossible to fix at this point. The fact that unsigned arithmetic doesn't model the behavior of a simple integer, but is instead defined by the standard to model modular arithmetic (wrapping around on overflow/underflow), means that a significant class of bugs cannot be diagnosed by the compiler. In other cases, the defined behavior impedes optimization.

That said, mixing signedness of integer types is responsible for an equally large class of problems. The best advice we can provide: try to use iterators and containers rather than pointers and sizes, try not to mix signedness, and try to avoid unsigned types (except for representing bitfields or modular arithmetic). Do not use an unsigned type merely to assert that a variable is non-negative.

Floating-Point Types

Of the built-in C++ floating-point types, the only ones used are float and double. You may assume that these types represent IEEE-754 binary32 and binary64, respectively.

Do not use long double, as it gives non-portable results.

Architecture Portability

Write architecture-portable code. Do not rely on CPU features specific to a single processor.

Preprocessor Macros

Avoid defining macros, especially in headers; prefer inline functions, enums, and const variables. Name macros with a project-specific prefix. Do not use macros to define pieces of a C++ API.

Macros mean that the code you see is not the same as the code the compiler sees. This can introduce unexpected behavior, especially since macros have global scope.

The problems introduced by macros are especially severe when they are used to define pieces of a C++ API, and still more so for public APIs. Every error message from the compiler when developers incorrectly use that interface now must explain how the macros formed the interface. Refactoring and analysis tools have a dramatically harder time updating the interface. As a consequence, we specifically disallow using macros in this way. For example, avoid patterns like:

class WOMBAT_TYPE(Foo) {
  // ...

 public:
  EXPAND_PUBLIC_WOMBAT_API(Foo)

  EXPAND_WOMBAT_COMPARISONS(Foo, ==, <)
};

Luckily, macros are not nearly as necessary in C++ as they are in C. Instead of using a macro to inline performance-critical code, use an inline function. Instead of using a macro to store a constant, use a const variable. Instead of using a macro to "abbreviate" a long variable name, use a reference. Instead of using a macro to conditionally compile code ... well, don't do that at all (except, of course, for the #define guards to prevent double inclusion of header files). It makes testing much more difficult.

Macros can do things these other techniques cannot, and you do see them in the codebase, especially in the lower-level libraries. And some of their special features (like stringifying, concatenation, and so forth) are not available through the language proper. But before using a macro, consider carefully whether there's a non-macro way to achieve the same result. If you need to use a macro to define an interface, contact your project leads to request a waiver of this rule.

The following usage pattern will avoid many problems with macros; if you use macros, follow it whenever possible:

Exporting macros from headers (i.e., defining them in a header without #undefing them before the end of the header) is extremely strongly discouraged. If you do export a macro from a header, it must have a globally unique name. To achieve this, it must be named with a prefix consisting of your project's namespace name (but upper case).

0 and nullptr/NULL

Use nullptr for pointers, and '\0' for chars (and not the 0 literal).

For pointers (address values), use nullptr, as this provides type-safety.

Use '\0' for the null character. Using the correct type makes the code more readable.

sizeof

Prefer sizeof(varname) to sizeof(type).

Use sizeof(varname) when you take the size of a particular variable. sizeof(varname) will update appropriately if someone changes the variable type either now or later. You may use sizeof(type) for code unrelated to any particular variable, such as code that manages an external or internal data format where a variable of an appropriate C++ type is not convenient.

MyStruct data;
memset(&data, 0, sizeof(data));
memset(&data, 0, sizeof(MyStruct));
if (raw_size < sizeof(int)) {
  LOG(ERROR) << "compressed record not big enough for count: " << raw_size;
  return false;
}

Type Deduction (including auto)

Use type deduction only if it makes the code clearer to readers who aren't familiar with the project, or if it makes the code safer. Do not use it merely to avoid the inconvenience of writing an explicit type.

There are several contexts in which C++ allows (or even requires) types to be deduced by the compiler, rather than spelled out explicitly in the code:

Function template argument deduction
A function template can be invoked without explicit template arguments. The compiler deduces those arguments from the types of the function arguments:
template <typename T>
void f(T t);

f(0);  // Invokes f<int>(0)
auto variable declarations
A variable declaration can use the auto keyword in place of the type. The compiler deduces the type from the variable's initializer, following the same rules as function template argument deduction with the same initializer (so long as you don't use curly braces instead of parentheses).
auto a = 42;  // a is an int
auto& b = a;  // b is an int&
auto c = b;   // c is an int
auto d{42};   // d is an int, not a std::initializer_list<int>
auto can be qualified with const, and can be used as part of a pointer or reference type, and (since C++17) as a non-type template argument. A rare variant of this syntax uses decltype(auto) instead of auto, in which case the deduced type is the result of applying decltype to the initializer.
Function return type deduction
auto (and decltype(auto)) can also be used in place of a function return type. The compiler deduces the return type from the return statements in the function body, following the same rules as for variable declarations:
auto f() { return 0; }  // The return type of f is int
Lambda expression return types can be deduced in the same way, but this is triggered by omitting the return type, rather than by an explicit auto. Confusingly, trailing return type syntax for functions also uses auto in the return-type position, but that doesn't rely on type deduction; it's just an alternative syntax for an explicit return type.
Generic lambdas
A lambda expression can use the auto keyword in place of one or more of its parameter types. This causes the lambda's call operator to be a function template instead of an ordinary function, with a separate template parameter for each auto function parameter:
// Sort `vec` in decreasing order
std::sort(vec.begin(), vec.end(), [](auto lhs, auto rhs) { return lhs > rhs; });
Lambda init captures
Lambda captures can have explicit initializers, which can be used to declare wholly new variables rather than only capturing existing ones:
[x = 42, y = "foo"] { ... }  // x is an int, and y is a const char*
This syntax doesn't allow the type to be specified; instead, it's deduced using the rules for auto variables.
Class template argument deduction
See below.
Structured bindings
When declaring a tuple, struct, or array using auto, you can specify names for the individual elements instead of a name for the whole object; these names are called "structured bindings", and the whole declaration is called a "structured binding declaration". This syntax provides no way of specifying the type of either the enclosing object or the individual names:
auto [iter, success] = my_map.insert({key, value});
if (!success) {
  iter->second = value;
}
The auto can also be qualified with const, &, and &&, but note that these qualifiers technically apply to the anonymous tuple/struct/array, rather than the individual bindings. The rules that determine the types of the bindings are quite complex; the results tend to be unsurprising, except that the binding types typically won't be references even if the declaration declares a reference (but they will usually behave like references anyway).

(These summaries omit many details and caveats; see the links for further information.)

C++ code is usually clearer when types are explicit, especially when type deduction would depend on information from distant parts of the code. In expressions like:

auto foo = x.add_foo();
auto i = y.Find(key);

it may not be obvious what the resulting types are if the type of y isn't very well known, or if y was declared many lines earlier.

Programmers have to understand when type deduction will or won't produce a reference type, or they'll get copies when they didn't mean to.

If a deduced type is used as part of an interface, then a programmer might change its type while only intending to change its value, leading to a more radical API change than intended.

The fundamental rule is: use type deduction only to make the code clearer or safer, and do not use it merely to avoid the inconvenience of writing an explicit type. When judging whether the code is clearer, keep in mind that your readers are not necessarily on your team, or familiar with your project, so types that you and your reviewer experience as unnecessary clutter will very often provide useful information to others. For example, you can assume that the return type of make_unique<Foo>() is obvious, but the return type of MyWidgetFactory() probably isn't.

These principles apply to all forms of type deduction, but the details vary, as described in the following sections.

Function template argument deduction

Function template argument deduction is almost always OK. Type deduction is the expected default way of interacting with function templates, because it allows function templates to act like infinite sets of ordinary function overloads. Consequently, function templates are almost always designed so that template argument deduction is clear and safe, or doesn't compile.

Local variable type deduction

For local variables, you can use type deduction to make the code clearer by eliminating type information that is obvious or irrelevant, so that the reader can focus on the meaningful parts of the code:

std::unique_ptr<WidgetWithBellsAndWhistles> widget =
    std::make_unique<WidgetWithBellsAndWhistles>(arg1, arg2);
absl::flat_hash_map<std::string,
                    std::unique_ptr<WidgetWithBellsAndWhistles>>::const_iterator
    it = my_map_.find(key);
std::array<int, 6> numbers = {4, 8, 15, 16, 23, 42};
auto widget = std::make_unique<WidgetWithBellsAndWhistles>(arg1, arg2);
auto it = my_map_.find(key);
std::array numbers = {4, 8, 15, 16, 23, 42};

Types sometimes contain a mixture of useful information and boilerplate, such as it in the example above: it's obvious that the type is an iterator, and in many contexts the container type and even the key type aren't relevant, but the type of the values is probably useful. In such situations, it's often possible to define local variables with explicit types that convey the relevant information:

if (auto it = my_map_.find(key); it != my_map_.end()) {
  WidgetWithBellsAndWhistles& widget = *it->second;
  // Do stuff with `widget`
}

If the type is a template instance, and the parameters are boilerplate but the template itself is informative, you can use class template argument deduction to suppress the boilerplate. However, cases where this actually provides a meaningful benefit are quite rare. Note that class template argument deduction is also subject to a separate style rule.

Do not use decltype(auto) if a simpler option will work; because it's a fairly obscure feature, it has a high cost in code clarity.

Return type deduction

Use return type deduction (for both functions and lambdas) only if the function body has a very small number of return statements, and very little other code, because otherwise the reader may not be able to tell at a glance what the return type is. Furthermore, use it only if the function or lambda has a very narrow scope, because functions with deduced return types don't define abstraction boundaries: the implementation is the interface. In particular, public functions in header files should almost never have deduced return types.

Parameter type deduction

auto parameter types for lambdas should be used with caution, because the actual type is determined by the code that calls the lambda, rather than by the definition of the lambda. Consequently, an explicit type will almost always be clearer unless the lambda is explicitly called very close to where it's defined (so that the reader can easily see both), or the lambda is passed to an interface so well-known that it's obvious what arguments it will eventually be called with (e.g., the std::sort example above).

Lambda init captures

Init captures are covered by a more specific style rule, which largely supersedes the general rules for type deduction.

Structured bindings

Unlike other forms of type deduction, structured bindings can actually give the reader additional information, by giving meaningful names to the elements of a larger object. This means that a structured binding declaration may provide a net readability improvement over an explicit type, even in cases where auto would not. Structured bindings are especially beneficial when the object is a pair or tuple (as in the insert example above), because they don't have meaningful field names to begin with, but note that you generally shouldn't use pairs or tuples unless a pre-existing API like insert forces you to.

If the object being bound is a struct, it may sometimes be helpful to provide names that are more specific to your usage, but keep in mind that this may also mean the names are less recognizable to your reader than the field names. We recommend using a comment to indicate the name of the underlying field, if it doesn't match the name of the binding, using the same syntax as for function parameter comments:

auto [/*field_name1=*/bound_name1, /*field_name2=*/bound_name2] = ...

As with function parameter comments, this can enable tools to detect if you get the order of the fields wrong.

Class Template Argument Deduction

Use class template argument deduction only with templates that have explicitly opted into supporting it.

Class template argument deduction (often abbreviated "CTAD") occurs when a variable is declared with a type that names a template, and the template argument list is not provided (not even empty angle brackets):

std::array a = {1, 2, 3};  // `a` is a std::array<int, 3>

The compiler deduces the arguments from the initializer using the template's "deduction guides", which can be explicit or implicit.

Explicit deduction guides look like function declarations with trailing return types, except that there's no leading auto, and the function name is the name of the template. For example, the above example relies on this deduction guide for std::array:

namespace std {
template <class T, class... U>
array(T, U...) -> std::array<T, 1 + sizeof...(U)>;
}

Constructors in a primary template (as opposed to a template specialization) also implicitly define deduction guides.

When you declare a variable that relies on CTAD, the compiler selects a deduction guide using the rules of constructor overload resolution, and that guide's return type becomes the type of the variable.

CTAD can sometimes allow you to omit boilerplate from your code.

The implicit deduction guides that are generated from constructors may have undesirable behavior, or be outright incorrect. This is particularly problematic for constructors written before CTAD was introduced in C++17, because the authors of those constructors had no way of knowing about (much less fixing) any problems that their constructors would cause for CTAD. Furthermore, adding explicit deduction guides to fix those problems might break any existing code that relies on the implicit deduction guides.

CTAD also suffers from many of the same drawbacks as auto, because they are both mechanisms for deducing all or part of a variable's type from its initializer. CTAD does give the reader more information than auto, but it also doesn't give the reader an obvious cue that information has been omitted.

Do not use CTAD with a given template unless the template's maintainers have opted into supporting use of CTAD by providing at least one explicit deduction guide (all templates in the std namespace are also presumed to have opted in). This should be enforced with a compiler warning if available.

Uses of CTAD must also follow the general rules on Type deduction.

Designated Initializers

Use designated initializers only in their C++20-compliant form.

Designated initializers are a syntax that allows for initializing an aggregate ("plain old struct") by naming its fields explicitly:

  struct Point {
    float x = 0.0;
    float y = 0.0;
    float z = 0.0;
  };

  Point p = {
    .x = 1.0,
    .y = 2.0,
    // z will be 0.0
  };

The explicitly listed fields will be initialized as specified, and others will be initialized in the same way they would be in a traditional aggregate initialization expression like Point{1.0, 2.0}.

Designated initializers can make for convenient and highly readable aggregate expressions, especially for structs with less straightforward ordering of fields than the Point example above.

While designated initializers have long been part of the C standard and supported by C++ compilers as an extension, they were not supported by C++ prior to C++20.

The rules in the C++ standard are stricter than in C and compiler extensions, requiring that the designated initializers appear in the same order as the fields appear in the struct definition. So in the example above, it is legal according to C++20 to initialize x and then z, but not y and then x.

Use designated initializers only in the form that is compatible with the C++20 standard: with initializers in the same order as the corresponding fields appear in the struct definition.

Lambda Expressions

Use lambda expressions where appropriate. Prefer explicit captures when the lambda will escape the current scope.

Lambda expressions are a concise way of creating anonymous function objects. They're often useful when passing functions as arguments. For example:

std::sort(v.begin(), v.end(), [](int x, int y) {
  return Weight(x) < Weight(y);
});

They further allow capturing variables from the enclosing scope either explicitly by name, or implicitly using a default capture. Explicit captures require each variable to be listed, as either a value or reference capture:

int weight = 3;
int sum = 0;
// Captures `weight` by value and `sum` by reference.
std::for_each(v.begin(), v.end(), [weight, &sum](int x) {
  sum += weight * x;
});

Default captures implicitly capture any variable referenced in the lambda body, including this if any members are used:

const std::vector<int> lookup_table = ...;
std::vector<int> indices = ...;
// Captures `lookup_table` by reference, sorts `indices` by the value
// of the associated element in `lookup_table`.
std::sort(indices.begin(), indices.end(), [&](int a, int b) {
  return lookup_table[a] < lookup_table[b];
});

A variable capture can also have an explicit initializer, which can be used for capturing move-only variables by value, or for other situations not handled by ordinary reference or value captures:

std::unique_ptr<Foo> foo = ...;
[foo = std::move(foo)] () {
  ...
}

Such captures (often called "init captures" or "generalized lambda captures") need not actually "capture" anything from the enclosing scope, or even have a name from the enclosing scope; this syntax is a fully general way to define members of a lambda object:

[foo = std::vector<int>({1, 2, 3})] () {
  ...
}

The type of a capture with an initializer is deduced using the same rules as auto.

Template Metaprogramming

Avoid complicated template programming.

Template metaprogramming refers to a family of techniques that exploit the fact that the C++ template instantiation mechanism is Turing complete and can be used to perform arbitrary compile-time computation in the type domain.

Template metaprogramming allows extremely flexible interfaces that are type safe and high performance. Facilities like GoogleTest, std::tuple, std::function, and Boost.Spirit would be impossible without it.

The techniques used in template metaprogramming are often obscure to anyone but language experts. Code that uses templates in complicated ways is often unreadable, and is hard to debug or maintain.

Template metaprogramming often leads to extremely poor compile time error messages: even if an interface is simple, the complicated implementation details become visible when the user does something wrong.

Template metaprogramming interferes with large scale refactoring by making the job of refactoring tools harder. First, the template code is expanded in multiple contexts, and it's hard to verify that the transformation makes sense in all of them. Second, some refactoring tools work with an AST that only represents the structure of the code after template expansion. It can be difficult to automatically work back to the original source construct that needs to be rewritten.

Template metaprogramming sometimes allows cleaner and easier-to-use interfaces than would be possible without it, but it's also often a temptation to be overly clever. It's best used in a small number of low level components where the extra maintenance burden is spread out over a large number of uses.

Think twice before using template metaprogramming or other complicated template techniques; think about whether the average member of your team will be able to understand your code well enough to maintain it after you switch to another project, or whether a non-C++ programmer or someone casually browsing the codebase will be able to understand the error messages or trace the flow of a function they want to call. If you're using recursive template instantiations or type lists or metafunctions or expression templates, or relying on SFINAE or on the sizeof trick for detecting function overload resolution, then there's a good chance you've gone too far.

If you use template metaprogramming, you should expect to put considerable effort into minimizing and isolating the complexity. You should hide metaprogramming as an implementation detail whenever possible, so that user-facing headers are readable, and you should make sure that tricky code is especially well commented. You should carefully document how the code is used, and you should say something about what the "generated" code looks like. Pay extra attention to the error messages that the compiler emits when users make mistakes. The error messages are part of your user interface, and your code should be tweaked as necessary so that the error messages are understandable and actionable from a user point of view.

Concepts and Constraints

Use concepts sparingly. In general, concepts and constraints should only be used in cases where templates would have been used prior to C++20. Avoid introducing new concepts in headers, unless the headers are marked as internal to the library. Do not define concepts that are not enforced by the compiler. Prefer constraints over template metaprogramming, and avoid the template<Concept T> syntax; instead, use the requires(Concept<T>) syntax.

The concept keyword is a new mechanism for defining requirements (such as type traits or interface specifications) for a template parameter. The requires keyword provides mechanisms for placing anonymous constraints on templates and verifying that constraints are satisfied at compile time. Concepts and constraints are often used together, but can be also used independently.

Predefined concepts in the standard library should be preferred to type traits, when equivalent ones exist. (e.g., if std::is_integral_v would have been used before C++20, then std::integral should be used in C++20 code.) Similarly, prefer modern constraint syntax (via requires(Condition)). Avoid legacy template metaprogramming constructs (such as std::enable_if<Condition>) as well as the template<Concept T> syntax.

Do not manually re-implement any existing concepts or traits. For example, use requires(std::default_initializable<T>) instead of requires(requires { T v; }) or the like.

New concept declarations should be rare, and only defined internally within a library, such that they are not exposed at API boundaries. More generally, do not use concepts or constraints in cases where you wouldn't use their legacy template equivalents in C++17.

Do not define concepts that duplicate the function body, or impose requirements that would be insignificant or obvious from reading the body of the code or the resulting error messages. For example, avoid the following:

template <typename T>     // Bad - redundant with negligible benefit
concept Addable = std::copyable<T> && requires(T a, T b) { a + b; };
template <Addable T>
T Add(T x, T y, T z) { return x + y + z; }
Instead, prefer to leave code as an ordinary template unless you can demonstrate that concepts result in significant improvement for that particular case, such as in the resulting error messages for a deeply nested or non-obvious requirement.

Concepts should be statically verifiable by the compiler. Do not use any concept whose primary benefits would come from a semantic (or otherwise unenforced) constraint. Requirements that are unenforced at compile time should instead be imposed via other mechanisms such as comments, assertions, or tests.

C++20 modules

Do not use C++20 Modules.

C++20 introduces "modules", a new language feature designed as an alternative to textual inclusion of header files. It introduces three new keywords to support this: module, export, and import.

Modules are a big shift in how C++ is written and compiled, and we are still assessing how they may fit into Google's C++ ecosystem in the future. Furthermore, they are not currently well-supported by our build systems, compilers, and other tooling, and need further exploration as to the best practices when writing and using them.

Coroutines

Only use C++20 coroutines via libraries that have been approved by your project leads.

C++20 introduced coroutines: functions that can suspend and resume executing later. They are especially convenient for asynchronous programming, where they can provide substantial improvements over traditional callback-based frameworks.

Unlike most other programming languages (Kotlin, Rust, TypeScript, etc.), C++ does not provide a concrete implementation of coroutines. Instead, it requires users to implement their own awaitable type (using a promise type) which determines coroutine parameter types, how coroutines are executed, and allows running user-defined code during different stages of their execution.

In summary, designing a high-quality and interoperable coroutine library requires a large amount of difficult work, careful thought, and extensive documentation.

Use only coroutine libraries that have been approved for project-wide use by your project leads. Do not roll your own promise or awaitable types.

Boost

Use only approved libraries from the Boost library collection.

The Boost library collection is a popular collection of peer-reviewed, free, open-source C++ libraries.

Boost code is generally very high-quality, is widely portable, and fills many important gaps in the C++ standard library, such as type traits and better binders.

Some Boost libraries encourage coding practices which can hamper readability, such as metaprogramming and other advanced template techniques, and an excessively "functional" style of programming.

In order to maintain a high level of readability for all contributors who might read and maintain code, we only allow an approved subset of Boost features. Currently, the following libraries are permitted:

We are actively considering adding other Boost features to the list, so this list may be expanded in the future.

Disallowed standard library features

As with Boost, some modern C++ library functionality encourages coding practices that hamper readability — for example by removing checked redundancy (such as type names) that may be helpful to readers, or by encouraging template metaprogramming. Other extensions duplicate functionality available through existing mechanisms, which may lead to confusion and conversion costs.

The following C++ standard library features may not be used:

Nonstandard Extensions

Nonstandard extensions to C++ may not be used unless otherwise specified.

Compilers support various extensions that are not part of standard C++. Such extensions include GCC's __attribute__, intrinsic functions such as __builtin_prefetch or SIMD, #pragma, inline assembly, __COUNTER__, __PRETTY_FUNCTION__, compound statement expressions (e.g., foo = ({ int x; Bar(&x); x }), variable-length arrays and alloca(), and the "Elvis Operator" a?:b.

Do not use nonstandard extensions. You may use portability wrappers that are implemented using nonstandard extensions, so long as those wrappers are provided by a designated project-wide portability header.

Aliases

Public aliases are for the benefit of an API's user, and should be clearly documented.

There are several ways to create names that are aliases of other entities:

using Bar = Foo;
typedef Foo Bar;  // But prefer `using` in C++ code.
using ::other_namespace::Foo;
using enum MyEnumType;  // Creates aliases for all enumerators in MyEnumType.

In new code, using is preferable to typedef, because it provides a more consistent syntax with the rest of C++ and works with templates.

Like other declarations, aliases declared in a header file are part of that header's public API unless they're in a function definition, in the private portion of a class, or in an explicitly-marked internal namespace. Aliases in such areas or in .cc files are implementation details (because client code can't refer to them), and are not restricted by this rule.

Don't put an alias in your public API just to save typing in the implementation; do so only if you intend it to be used by your clients.

When defining a public alias, document the intent of the new name, including whether it is guaranteed to always be the same as the type it's currently aliased to, or whether a more limited compatibility is intended. This lets the user know whether they can treat the types as substitutable or whether more specific rules must be followed, and can help the implementation retain some degree of freedom to change the alias.

Don't put namespace aliases in your public API. (See also Namespaces.)

For example, these aliases document how they are intended to be used in client code:

namespace mynamespace {
// Used to store field measurements. DataPoint may change from Bar* to some internal type.
// Client code should treat it as an opaque pointer.
using DataPoint = ::foo::Bar*;

// A set of measurements. Just an alias for user convenience.
using TimeSeries = std::unordered_set<DataPoint, std::hash<DataPoint>, DataPointComparator>;
}  // namespace mynamespace

These aliases don't document intended use, and half of them aren't meant for client use:

namespace mynamespace {
// Bad: none of these say how they should be used.
using DataPoint = ::foo::Bar*;
using ::std::unordered_set;  // Bad: just for local convenience
using ::std::hash;           // Bad: just for local convenience
typedef unordered_set<DataPoint, hash<DataPoint>, DataPointComparator> TimeSeries;
}  // namespace mynamespace

However, local convenience aliases are fine in function definitions, private sections of classes, explicitly-marked internal namespaces, and in .cc files:

// In a .cc file
using ::foo::Bar;

Switch Statements

If not conditional on an enumerated value, switch statements should always have a default case (in the case of an enumerated value, the compiler will warn you if any values are not handled). If the default case should never execute, treat this as an error. For example:

switch (var) {
  case 0: {
    ...
    break;
  }
  case 1: {
    ...
    break;
  }
  default: {
    LOG(FATAL) << "Invalid value in switch statement: " << var;
  }
}

Fall-through from one case label to another must be annotated using the [[fallthrough]]; attribute. [[fallthrough]]; should be placed at a point of execution where a fall-through to the next case label occurs. A common exception is consecutive case labels without intervening code, in which case no annotation is needed.

switch (x) {
  case 41:  // No annotation needed here.
  case 43:
    if (dont_be_picky) {
      // Use this instead of or along with annotations in comments.
      [[fallthrough]];
    } else {
      CloseButNoCigar();
      break;
    }
  case 42:
    DoSomethingSpecial();
    [[fallthrough]];
  default:
    DoSomethingGeneric();
    break;
}

Inclusive Language

In all code, including naming and comments, use inclusive language and avoid terms that other programmers might find disrespectful or offensive (such as "master" and "slave", "blacklist" and "whitelist", or "redline"), even if the terms also have an ostensibly neutral meaning. Similarly, use gender-neutral language unless you're referring to a specific person (and using their pronouns). For example, use "they"/"them"/"their" for people of unspecified gender (even when singular), and "it"/"its" for software, computers, and other things that aren't people.

Naming

The most important consistency rules are those that govern naming. The style of a name immediately informs us what sort of thing the named entity is: a type, a variable, a function, a constant, a macro, etc., without requiring us to search for the declaration of that entity. The pattern-matching engine in our brains relies a great deal on these naming rules.

Style rules about naming are pretty arbitrary, but we feel that consistency is more important than individual preferences in this area, so regardless of whether you find them sensible or not, the rules are the rules.

For the purposes of the naming rules below, a "word" is anything that you would write in English without internal spaces. Either words are all lowercase, with underscores between words ("snake_case"), or words are mixed case with the first letter of each word capitalized ("camelCase" or "PascalCase").

Choosing Names

Give things names that make their purpose or intent understandable to a new reader, even someone on a different team than the owners. Do not worry about saving horizontal space as it is far more important to make your code immediately understandable by a new reader.

Consider the context in which the name will be used. A name should be descriptive even if it is used far from the code that makes it available for use. However, a name should not distract the reader by repeating information that's present in the immediate context. Generally, this means that descriptiveness should be proportional to the name's scope of visibility. A free function declared in a header should probably mention the header's library, while a local variable probably shouldn't explain what function it's within.

Minimize the use of abbreviations that would likely be unknown to someone outside your project (especially acronyms and initialisms). Do not abbreviate by deleting letters within a word. When an abbreviation is used, prefer to capitalize it as a single "word", e.g., StartRpc() rather than StartRPC(). As a rule of thumb, an abbreviation is probably OK if it's listed in Wikipedia. Note that certain universally-known abbreviations are OK, such as i for a loop index and T for a template parameter.

The names you see most frequently are not like most names; a small number of "vocabulary" names are reused so widely that they are always in context. These names tend to be short or even abbreviated and their full meaning comes from explicit long-form documentation rather than from just comments on their definition and the words within the names. For example, absl::Status has a dedicated page in a devguide, documenting its proper use. You probably won't define new vocabulary names very often, but if you do, get additional design review to make sure the chosen names work well when used widely.

class MyClass {
 public:
  int CountFooErrors(const std::vector<Foo>& foos) {
    int n = 0;  // Clear meaning given limited scope and context
    for (const auto& foo : foos) {
      ...
      ++n;
    }
    return n;
  }
  // Function comment doesn't need to explain that this returns non-OK on
  // failure as that is implied by the `absl::Status` return type, but it
  // might document behavior for some specific codes.
  absl::Status DoSomethingImportant() {
    std::string fqdn = ...;  // Well-known abbreviation for Fully Qualified Domain Name
    return absl::OkStatus();
  }
 private:
  const int kMaxAllowedConnections = ...;  // Clear meaning within context
};
class MyClass {
 public:
  int CountFooErrors(const std::vector<Foo>& foos) {
    int total_number_of_foo_errors = 0;  // Overly verbose given limited scope and context
    for (int foo_index = 0; foo_index < foos.size(); ++foo_index) {  // Use idiomatic `i`
      ...
      ++total_number_of_foo_errors;
    }
    return total_number_of_foo_errors;
  }
  // A return type with a generic name is unclear without widespread education.
  Result DoSomethingImportant() {
    int cstmr_id = ...;  // Deletes internal letters
  }
 private:
  const int kNum = ...;  // Unclear meaning within broad scope
};

File Names

Filenames should be all lowercase and can include underscores (_) or dashes (-). Follow the convention that your project uses. If there is no consistent local pattern to follow, prefer "_".

Examples of acceptable file names:

C++ files should have a .cc filename extension, and header files should have a .h extension. Files that rely on being textually included at specific points should end in .inc (see also the section on self-contained headers).

Do not use filenames that already exist in /usr/include, such as db.h.

In general, make your filenames very specific. For example, use http_server_logs.h rather than logs.h. A very common case is to have a pair of files called, e.g., foo_bar.h and foo_bar.cc, defining a class called FooBar.

Type Names

Type names start with a capital letter and have a capital letter for each new word, with no underscores: MyExcitingClass, MyExcitingEnum.

The names of all types — classes, structs, type aliases, enums, and type template parameters — have the same naming convention. Type names should start with a capital letter and have a capital letter for each new word. No underscores. For example:

// classes and structs
class UrlTable { ...
class UrlTableTester { ...
struct UrlTableProperties { ...

// typedefs
typedef hash_map<UrlTableProperties*, std::string> PropertiesMap;

// using aliases
using PropertiesMap = hash_map<UrlTableProperties*, std::string>;

// enums
enum class UrlTableError { ...

Concept Names

Concept names follow the same rules as type names.

Variable Names

The names of variables (including function parameters) and data members are snake_case (all lowercase, with underscores between words). Data members of classes (but not structs) additionally have trailing underscores. For instance: a_local_variable, a_struct_data_member, a_class_data_member_.

Common Variable names

For example:

std::string table_name;  // OK - snake_case.
std::string tableName;   // Bad - mixed case.

Class Data Members

Data members of classes, both static and non-static, are named like ordinary nonmember variables, but with a trailing underscore. The exception to this is static constant class members, which should follow the rules for naming constants.

class TableInfo {
 public:
  ...
  static const int kTableVersion = 3;  // OK - constant naming.
  ...

 private:
  std::string table_name_;             // OK - underscore at end.
  static Pool<TableInfo>* pool_;       // OK.
};

Struct Data Members

Data members of structs, both static and non-static, are named like ordinary nonmember variables. They do not have the trailing underscores that data members in classes have.

struct UrlTableProperties {
  std::string name;
  int num_entries;
  static Pool<UrlTableProperties>* pool;
};

See Structs vs. Classes for a discussion of when to use a struct versus a class.

Constant Names

Variables declared constexpr or const, and whose value is fixed for the duration of the program, are named with a leading "k" followed by mixed case. Underscores can be used as separators in the rare cases where capitalization cannot be used for separation. For example:

const int kDaysInAWeek = 7;
const int kAndroid8_0_0 = 24;  // Android 8.0.0

All such variables with static storage duration (i.e., statics and globals, see Storage Duration for details) should be named this way, including those that are static constant class data members and those in templates where different instantiations of the template may have different values. This convention is optional for variables of other storage classes, e.g., automatic variables; otherwise the usual variable naming rules apply. For example:

void ComputeFoo(absl::string_view suffix) {
  // Either of these is acceptable.
  const absl::string_view kPrefix = "prefix";
  const absl::string_view prefix = "prefix";
  ...
}
void ComputeFoo(absl::string_view suffix) {
  // Bad - different invocations of ComputeFoo give kCombined different values.
  const std::string kCombined = absl::StrCat(kPrefix, suffix);
  ...
}

Function Names

Ordinarily, functions follow PascalCase: start with a capital letter and have a capital letter for each new word.

AddTableEntry()
DeleteUrl()
OpenFileOrDie()

The same naming rule applies to class- and namespace-scope constants that are exposed as part of an API and that are intended to look like functions, because the fact that they're objects rather than functions is an unimportant implementation detail.

Accessors and mutators (get and set functions) may be named like variables, in snake_case. These often correspond to actual member variables, but this is not required. For example, int count() and void set_count(int count).

Namespace Names

Namespace names are snake_case (all lowercase, with underscores between words).

When choosing names for namespaces, note that names must be fully qualified when used in a header outside the namespace, because unqualified Aliases are generally banned.

Top-level namespaces must be globally unique and recognizable, so each one should be owned by a single project or team, with a name based on the name of that project or team. Usually, all code in the namespace should be under one or more directories with the same name as the namespace.

Nested namespaces should avoid the names of well-known top-level namespaces, especially std and absl, because in C++, nested namespaces do not protect from collisions with names in other namespaces (see TotW #130).

Enumerator Names

Enumerators (for both scoped and unscoped enums) should be named like constants, not like macros. That is, use kEnumName not ENUM_NAME.

enum class UrlTableError {
  kOk = 0,
  kOutOfMemory,
  kMalformedInput,
};
enum class AlternateUrlTableError {
  OK = 0,
  OUT_OF_MEMORY = 1,
  MALFORMED_INPUT = 2,
};

Until January 2009, the style was to name enum values like macros. This caused problems with name collisions between enum values and macros. Hence, the change to prefer constant-style naming was put in place. New code should use constant-style naming.

Template Parameter Names

Template parameters should follow the naming style for their category: type template parameters should follow the rules for naming types, and non-type template parameters should follow the rules for naming variables or constants.

Macro Names

You're not really going to define a macro, are you? If you do, they're like this: MY_MACRO_THAT_SCARES_SMALL_CHILDREN_AND_ADULTS_ALIKE.

Please see the description of macros; in general macros should not be used. However, if they are absolutely needed, then they should be named with all capitals and underscores, and with a project-specific prefix.

#define MYPROJECT_ROUND(x) ...

Aliases

The name for an alias follows the same principles as any other new name, applied in the context where the alias is defined rather than where the original name appears.

Exceptions to Naming Rules

If you are naming something that is analogous to an existing C or C++ entity (or a Rust entity via interop), then you can follow the existing naming convention scheme.

bigopen()
function name, follows form of open()
uint
typedef
bigpos
struct or class, follows form of pos
sparse_hash_map
STL-like entity; follows STL naming conventions
LONGLONG_MAX
a constant, as in INT_MAX

Comments

Comments are absolutely vital to keeping our code readable. The following rules describe what you should comment and where. But remember: while comments are very important, the best code is self-documenting. Giving sensible names to types and variables is much better than using obscure names that you must then explain through comments.

When writing your comments, write for your audience: the next contributor who will need to understand your code. Be generous — the next one may be you!

Comment Style

Use either the // or /* */ syntax, as long as you are consistent.

While either syntax is acceptable, // is much more common. Be consistent with how you comment and what style you use where.

File Comments

Start each file with license boilerplate.

If a source file (such as a .h file) declares multiple user-facing abstractions (common functions, related classes, etc.), include a comment describing the collection of those abstractions. Include enough detail for future authors to know what does not fit there. However, the detailed documentation about individual abstractions belongs with those abstractions, not at the file level.

For instance, if you write a file comment for frobber.h, you do not need to include a file comment in frobber.cc or frobber_test.cc. On the other hand, if you write a collection of classes in registered_objects.cc that has no associated header file, you must include a file comment in registered_objects.cc.

Legal Notice and Author Line

Every file should contain license boilerplate. Choose the appropriate boilerplate for the license used by the project (for example, Apache 2.0, BSD, LGPL, GPL).

If you make significant changes to a file with an author line, consider deleting the author line. New files should usually not contain copyright notice or author line.

Struct and Class Comments

Every non-obvious class or struct declaration should have an accompanying comment that describes what it is for and how it should be used.

// Iterates over the contents of a GargantuanTable.
// Example:
//    std::unique_ptr<GargantuanTableIterator> iter = table->NewIterator();
//    for (iter->Seek("foo"); !iter->done(); iter->Next()) {
//      process(iter->key(), iter->value());
//    }
class GargantuanTableIterator {
  ...
};

Class Comments

The class comment should provide the reader with enough information to know how and when to use the class, as well as any additional considerations necessary to correctly use the class. Document the synchronization assumptions the class makes, if any. If an instance of the class can be accessed by multiple threads, take extra care to document the rules and invariants surrounding multithreaded use.

The class comment is often a good place for a small example code snippet demonstrating a simple and focused usage of the class.

When sufficiently separated (e.g., .h and .cc files), comments describing the use of the class should go together with its interface definition; comments about the class operation and implementation should accompany the implementation of the class's methods.

Function Comments

Declaration comments describe use of the function (when it is non-obvious); comments at the definition of a function describe operation.

Function Declarations

Almost every function declaration should have comments immediately preceding it that describe what the function does and how to use it. These comments may be omitted only if the function is simple and obvious (e.g., simple accessors for obvious properties of the class). Private methods and functions declared in .cc files are not exempt. Function comments should be written with an implied subject of This function and should start with the verb phrase; for example, "Opens the file", rather than "Open the file". In general, these comments do not describe how the function performs its task. Instead, that should be left to comments in the function definition.

Types of things to mention in comments at the function declaration:

Here is an example:

// Returns an iterator for this table, positioned at the first entry
// lexically greater than or equal to `start_word`. If there is no
// such entry, returns a null pointer. The client must not use the
// iterator after the underlying GargantuanTable has been destroyed.
//
// This method is equivalent to:
//    std::unique_ptr<Iterator> iter = table->NewIterator();
//    iter->Seek(start_word);
//    return iter;
std::unique_ptr<Iterator> GetIterator(absl::string_view start_word) const;

However, do not be unnecessarily verbose or state the completely obvious.

When documenting function overrides, focus on the specifics of the override itself, rather than repeating the comment from the overridden function. In many of these cases, the override needs no additional documentation and thus no comment is required.

When commenting constructors and destructors, remember that the person reading your code knows what constructors and destructors are for, so comments that just say something like "destroys this object" are not useful. Document what constructors do with their arguments (for example, if they take ownership of pointers), and what cleanup the destructor does. If this is trivial, just skip the comment. It is quite common for destructors not to have a header comment.

Function Definitions

If there is anything tricky about how a function does its job, the function definition should have an explanatory comment. For example, in the definition comment you might describe any coding tricks you use, give an overview of the steps you go through, or explain why you chose to implement the function in the way you did rather than using a viable alternative. For instance, you might mention why it must acquire a lock for the first half of the function but why it is not needed for the second half.

Note you should not just repeat the comments given with the function declaration, in the .h file or wherever. It's okay to recapitulate briefly what the function does, but the focus of the comments should be on how it does it.

Variable Comments

In general the actual name of the variable should be descriptive enough to give a good idea of what the variable is used for. In certain cases, more comments are required.

Class Data Members

The purpose of each class data member (also called an instance variable or member variable) must be clear. If there are any invariants (special values, relationships between members, lifetime requirements) not clearly expressed by the type and name, they must be commented. However, if the type and name suffice (int num_events_;), no comment is needed.

In particular, add comments to describe the existence and meaning of sentinel values, such as nullptr or -1, when they are not obvious. For example:

private:
 // Used to bounds-check table accesses. -1 means
 // that we don't yet know how many entries the table has.
 int num_total_entries_;

Global Variables

All global variables should have a comment describing what they are, what they are used for, and (if unclear) why they need to be global. For example:

// The total number of test cases that we run through in this regression test.
const int kNumTestCases = 6;

Implementation Comments

In your implementation you should have comments in tricky, non-obvious, interesting, or important parts of your code.

Explanatory Comments

Tricky or complicated code blocks should have comments before them.

Function Argument Comments

When the meaning of a function argument is nonobvious, consider one of the following remedies:

Consider the following example:
// What are these arguments?
const DecimalNumber product = CalculateProduct(values, 7, false, nullptr);

versus:

ProductOptions options;
options.set_precision_decimals(7);
options.set_use_cache(ProductOptions::kDontUseCache);
const DecimalNumber product =
    CalculateProduct(values, options, /*completion_callback=*/nullptr);

Don'ts

Do not state the obvious. In particular, don't literally describe what code does, unless the behavior is nonobvious to a reader who understands C++ well. Instead, provide higher-level comments that describe why the code does what it does, or make the code self-describing.

Compare this:
// Find the element in the vector.  <-- Bad: obvious!
if (std::find(v.begin(), v.end(), element) != v.end()) {
  Process(element);
}
To this:
// Process "element" unless it was already processed.
if (std::find(v.begin(), v.end(), element) != v.end()) {
  Process(element);
}

Self-describing code doesn't need a comment. The comment from the example above would be obvious:

if (!IsAlreadyProcessed(element)) {
  Process(element);
}

Punctuation, Spelling, and Grammar

Pay attention to punctuation, spelling, and grammar; it is easier to read well-written comments than badly written ones.

Comments should be as readable as narrative text, with proper capitalization and punctuation. In many cases, complete sentences are more readable than sentence fragments. Shorter comments, such as comments at the end of a line of code, can sometimes be less formal, but you should be consistent with your style.

Although it can be frustrating to have a code reviewer point out that you are using a comma when you should be using a semicolon, it is very important that source code maintain a high level of clarity and readability. Proper punctuation, spelling, and grammar help with that goal.

TODO Comments

Use TODO comments for code that is temporary, a short-term solution, or good-enough but not perfect.

TODOs should include the string TODO in all caps, followed by the bug ID, name, e-mail address, or other identifier of the person or issue with the best context about the problem referenced by the TODO.

Recommended styles are (in order of preference):

// TODO: bug 12345678 - Remove this after the 2047q4 compatibility window expires.
// TODO: example.com/my-design-doc - Manually fix up this code the next time it's touched.
// TODO(bug 12345678): Update this list after the Foo service is turned down.
// TODO(John): Use a "\*" here for concatenation operator.

If your TODO is of the form "At a future date do something" make sure that you either include a very specific date ("Fix by November 2005") or a very specific event ("Remove this code when all clients can handle XML responses.").

Formatting

Coding style and formatting are pretty arbitrary, but a project is much easier to follow if everyone uses the same style. Individuals may not agree with every aspect of the formatting rules, and some of the rules may take some getting used to, but it is important that all project contributors follow the style rules so that they can all read and understand everyone's code easily.

To help you format code correctly, we've created a settings file for emacs.

Line Length

Each line of text in your code should be at most 80 characters long.

We recognize that this rule is controversial, but so much existing code already adheres to it, and we feel that consistency is important.

Those who favor this rule argue that it is rude to force them to resize their windows and there is no need for anything longer. Some folks are used to having several code windows side-by-side, and thus don't have room to widen their windows in any case. People set up their work environment assuming a particular maximum window width, and 80 columns has been the traditional standard. Why change it?

Proponents of change argue that a wider line can make code more readable. The 80-column limit is an hidebound throwback to 1960s mainframes; modern equipment has wide screens that can easily show longer lines.

80 characters is the maximum.

A line may exceed 80 characters if it is

Non-ASCII Characters

Non-ASCII characters should be rare, and must use UTF-8 formatting.

You shouldn't hard-code user-facing text in source, even English, so use of non-ASCII characters should be rare. However, in certain cases it is appropriate to include such words in your code. For example, if your code parses data files from foreign sources, it may be appropriate to hard-code the non-ASCII string(s) used in those data files as delimiters. More commonly, unit test code (which does not need to be localized) might contain non-ASCII strings. In such cases, you should use UTF-8, since that is an encoding understood by most tools able to handle more than just ASCII.

Hex encoding is also OK, and encouraged where it enhances readability — for example, "\xEF\xBB\xBF", or, even more simply, "\uFEFF", is the Unicode zero-width no-break space character, which would be invisible if included in the source as straight UTF-8.

When possible, avoid the u8 prefix. It has significantly different semantics starting in C++20 than in C++17, producing arrays of char8_t rather than char, and will change again in C++23.

You shouldn't use char16_t and char32_t character types, since they're for non-UTF-8 text. For similar reasons you also shouldn't use wchar_t (unless you're writing code that interacts with the Windows API, which uses wchar_t extensively).

Spaces vs. Tabs

Use only spaces, and indent 2 spaces at a time.

We use spaces for indentation. Do not use tabs in your code. You should set your editor to emit spaces when you hit the tab key.

Function Declarations and Definitions

Return type on the same line as function name, parameters on the same line if they fit. Wrap parameter lists which do not fit on a single line as you would wrap arguments in a function call.

Functions look like this:

ReturnType ClassName::FunctionName(Type par_name1, Type par_name2) {
  DoSomething();
  ...
}

If you have too much text to fit on one line:

ReturnType ClassName::ReallyLongFunctionName(Type par_name1, Type par_name2,
                                             Type par_name3) {
  DoSomething();
  ...
}

or if you cannot fit even the first parameter:

ReturnType LongClassName::ReallyReallyReallyLongFunctionName(
    Type par_name1,  // 4 space indent
    Type par_name2,
    Type par_name3) {
  DoSomething();  // 2 space indent
  ...
}

Some points to note:

Unused parameters that are obvious from context may omit the name:

class Foo {
 public:
  Foo(const Foo&) = delete;
  Foo& operator=(const Foo&) = delete;
};

Unused parameters that might not be obvious should comment out the variable name in the function definition:

class Shape {
 public:
  virtual void Rotate(double radians) = 0;
};

class Circle : public Shape {
 public:
  void Rotate(double radians) override;
};

void Circle::Rotate(double /*radians*/) {}
// Bad - if someone wants to implement later, it's not clear what the
// variable means.
void Circle::Rotate(double) {}

Attributes, and macros that expand to attributes, appear at the very beginning of the function declaration or definition, before the return type:

  ABSL_ATTRIBUTE_NOINLINE void ExpensiveFunction();
  [[nodiscard]] bool IsOk();

Lambda Expressions

Format parameters and bodies as for any other function, and capture lists like other comma-separated lists.

For by-reference captures, do not leave a space between the ampersand (&) and the variable name.

int x = 0;
auto x_plus_n = [&x](int n) -> int { return x + n; }

Short lambdas may be written inline as function arguments.

absl::flat_hash_set<int> to_remove = {7, 8, 9};
std::vector<int> digits = {3, 9, 1, 8, 4, 7, 1};
digits.erase(std::remove_if(digits.begin(), digits.end(), [&to_remove](int i) {
               return to_remove.contains(i);
             }),
             digits.end());

Floating-point Literals

Floating-point literals should always have a radix point, with digits on both sides, even if they use exponential notation. Readability is improved if all floating-point literals take this familiar form, as this helps ensure that they are not mistaken for integer literals, and that the E/e of the exponential notation is not mistaken for a hexadecimal digit. It is fine to initialize a floating-point variable with an integer literal (assuming the variable type can exactly represent that integer), but note that a number in exponential notation is never an integer literal.

float f = 1.f;
long double ld = -.5L;
double d = 1248e6;
float f = 1.0f;
float f2 = 1.0;  // Also OK
float f3 = 1;    // Also OK
long double ld = -0.5L;
double d = 1248.0e6;

Function Calls

Either write the call all on a single line, wrap the arguments at the parenthesis, or start the arguments on a new line indented by four spaces and continue at that 4 space indent. In the absence of other considerations, use the minimum number of lines, including placing multiple arguments on each line where appropriate.

Function calls have the following format:

bool result = DoSomething(argument1, argument2, argument3);

If the arguments do not all fit on one line, they should be broken up onto multiple lines, with each subsequent line aligned with the first argument. Do not add spaces after the open paren or before the close paren:

bool result = DoSomething(averyveryveryverylongargument1,
                          argument2, argument3);

Arguments may optionally all be placed on subsequent lines with a four space indent:

if (...) {
  ...
  ...
  if (...) {
    bool result = DoSomething(
        argument1, argument2,  // 4 space indent
        argument3, argument4);
    ...
  }

Put multiple arguments on a single line to reduce the number of lines necessary for calling a function unless there is a specific readability problem. Some find that formatting with strictly one argument on each line is more readable and simplifies editing of the arguments. However, we prioritize for the reader over the ease of editing arguments, and most readability problems are better addressed with the following techniques.

If having multiple arguments in a single line decreases readability due to the complexity or confusing nature of the expressions that make up some arguments, try creating variables that capture those arguments in a descriptive name:

int my_heuristic = scores[x] * y + bases[x];
bool result = DoSomething(my_heuristic, x, y, z);

Or put the confusing argument on its own line with an explanatory comment:

bool result = DoSomething(scores[x] * y + bases[x],  // Score heuristic.
                          x, y, z);

If there is still a case where one argument is significantly more readable on its own line, then put it on its own line. The decision should be specific to the argument which is made more readable rather than a general policy.

Sometimes arguments form a structure that is important for readability. In those cases, feel free to format the arguments according to that structure:

// Transform the widget by a 3x3 matrix.
my_widget.Transform(x1, x2, x3,
                    y1, y2, y3,
                    z1, z2, z3);

Braced Initializer List Format

Format a braced initializer list exactly like you would format a function call in its place.

If the braced list follows a name (e.g., a type or variable name), format as if the {} were the parentheses of a function call with that name. If there is no name, assume a zero-length name.

// Examples of braced init list on a single line.
return {foo, bar};
functioncall({foo, bar});
std::pair<int, int> p{foo, bar};

// When you have to wrap.
SomeFunction(
    {"assume a zero-length name before {"},
    some_other_function_parameter);
SomeType variable{
    some, other, values,
    {"assume a zero-length name before {"},
    SomeOtherType{
        "Very long string requiring the surrounding breaks.",
        some, other, values},
    SomeOtherType{"Slightly shorter string",
                  some, other, values}};
SomeType variable{
    "This is too long to fit all in one line"};
MyType m = {  // Here, you could also break before {.
    superlongvariablename1,
    superlongvariablename2,
    {short, interior, list},
    {interiorwrappinglist,
     interiorwrappinglist2}};

Looping and branching statements

At a high level, looping or branching statements consist of the following components:

For these statements:
if (condition) {                   // Good - no spaces inside parentheses, space before brace.
  DoOneThing();                    // Good - two-space indent.
  DoAnotherThing();
} else if (int a = f(); a != 3) {  // Good - closing brace on new line, else on same line.
  DoAThirdThing(a);
} else {
  DoNothing();
}

// Good - the same rules apply to loops.
while (condition) {
  RepeatAThing();
}

// Good - the same rules apply to loops.
do {
  RepeatAThing();
} while (condition);

// Good - the same rules apply to loops.
for (int i = 0; i < 10; ++i) {
  RepeatAThing();
}
if(condition) {}                   // Bad - space missing after `if`.
else if ( condition ) {}           // Bad - space between the parentheses and the condition.
else if (condition){}              // Bad - space missing before `{`.
else if(condition){}               // Bad - multiple spaces missing.

for (int a = f();a == 10) {}       // Bad - space missing after the semicolon.

// Bad - `if ... else` statement does not have braces everywhere.
if (condition)
  foo;
else {
  bar;
}

// Bad - `if` statement too long to omit braces.
if (condition)
  // Comment
  DoSomething();

// Bad - `if` statement too long to omit braces.
if (condition1 &&
    condition2)
  DoSomething();

For historical reasons, we allow one exception to the above rules: the curly braces for the controlled statement or the line breaks inside the curly braces may be omitted if as a result the entire statement appears on either a single line (in which case there is a space between the closing parenthesis and the controlled statement) or on two lines (in which case there is a line break after the closing parenthesis and there are no braces).

// OK - fits on one line.
if (x == kFoo) { return new Foo(); }

// OK - braces are optional in this case.
if (x == kFoo) return new Foo();

// OK - condition fits on one line, body fits on another.
if (x == kBar)
  Bar(arg1, arg2, arg3);

This exception does not apply to multi-keyword statements like if ... else or do ... while.

// Bad - `if ... else` statement is missing braces.
if (x) DoThis();
else DoThat();

// Bad - `do ... while` statement is missing braces.
do DoThis();
while (x);

Use this style only when the statement is brief, and consider that loops and branching statements with complex conditions or controlled statements may be more readable with curly braces. Some projects require curly braces always.

case blocks in switch statements can have curly braces or not, depending on your preference. If you do include curly braces, they should be placed as shown below.

switch (var) {
  case 0: {  // 2 space indent
    Foo();   // 4 space indent
    break;
  }
  default: {
    Bar();
  }
}

Empty loop bodies should use either an empty pair of braces or continue with no braces, rather than a single semicolon.

while (condition) {}  // Good - `{}` indicates no logic.
while (condition) {
  // Comments are okay, too
}
while (condition) continue;  // Good - `continue` indicates no logic.
while (condition);  // Bad - looks like part of `do-while` loop.

Pointer and Reference Expressions and Types

No spaces around period or arrow. Pointer operators do not have trailing spaces.

The following are examples of correctly-formatted pointer and reference expressions:

x = *p;
p = &x;
x = r.y;
x = r->y;

Note that:

When referring to a pointer or reference (variable declarations or definitions, arguments, return types, template parameters, etc.), you must not place a space before the asterisk/ampersand. Use a space to separate the type from the declared name (if present).

// These are fine.
char* c;
const std::string& str;
int* GetPointer();
std::vector<char*>  // Note no space between '*' and '>'

It is allowed (if unusual) to declare multiple variables in the same declaration, but it is disallowed if any of those have pointer or reference decorations. Such declarations are easily misread.

// Fine if helpful for readability.
int x, y;
int x, *y;  // Disallowed - no & or * in multiple declaration
int *x, *y;  // Disallowed - no & or * in multiple declaration
int *x;  // Disallowed - & or * must be left of the space
char * c;  // Bad - spaces on both sides of *
const std::string & str;  // Bad - spaces on both sides of &

Boolean Expressions

When you have a boolean expression that is longer than the standard line length, be consistent in how you break up the lines.

In this example, the logical AND operator is always at the end of the lines:

if (this_one_thing > this_other_thing &&
    a_third_thing == a_fourth_thing &&
    yet_another && last_one) {
  ...
}

Note that when the code wraps in this example, both of the && logical AND operators are at the end of the line. This is more common in Google code, though wrapping all operators at the beginning of the line is also allowed. Feel free to insert extra parentheses judiciously because they can be very helpful in increasing readability when used appropriately, but be careful about overuse. Also note that you should always use the punctuation operators, such as && and ~, rather than the word operators, such as and and compl.

Return Values

Do not needlessly surround the return expression with parentheses.

Use parentheses in return expr; only where you would use them in x = expr;.

return result;                  // No parentheses in the simple case.
// Parentheses OK to make a complex expression more readable.
return (some_long_condition &&
        another_condition);
return (value);                // You wouldn't write var = (value);
return(result);                // return is not a function!

Variable and Array Initialization

You may choose between =, (), and {}; the following are all correct:

int x = 3;
int x(3);
int x{3};
std::string name = "Some Name";
std::string name("Some Name");
std::string name{"Some Name"};

Be careful when using a braced initialization list {...} on a type with an std::initializer_list constructor. A nonempty braced-init-list prefers the std::initializer_list constructor whenever possible. Note that empty braces {} are special, and will call a default constructor if available. To force the non-std::initializer_list constructor, use parentheses instead of braces.

std::vector<int> v(100, 1);  // A vector containing 100 items: All 1s.
std::vector<int> v{100, 1};  // A vector containing 2 items: 100 and 1.

Also, the brace form prevents narrowing of integral types. This can prevent some types of programming errors.

int pi(3.14);  // OK -- pi == 3.
int pi{3.14};  // Compile error: narrowing conversion.

Preprocessor Directives

The hash mark that starts a preprocessor directive should always be at the beginning of the line.

Even when preprocessor directives are within the body of indented code, the directives should start at the beginning of the line.

// Good - directives at beginning of line
  if (lopsided_score) {
#if DISASTER_PENDING      // Correct -- Starts at beginning of line
    DropEverything();
# if NOTIFY               // OK but not required -- Spaces after #
    NotifyClient();
# endif
#endif
    BackToNormal();
  }
// Bad - indented directives
  if (lopsided_score) {
    #if DISASTER_PENDING  // Wrong!  The "#if" should be at beginning of line
    DropEverything();
    #endif                // Wrong!  Do not indent "#endif"
    BackToNormal();
  }

Class Format

Sections in public, protected, and private order, each indented one space.

The basic format for a class definition (lacking the comments, see Class Comments for a discussion of what comments are needed) is:

class MyClass : public OtherClass {
 public:      // Note the 1 space indent!
  MyClass();  // Regular 2 space indent.
  explicit MyClass(int var);
  ~MyClass() {}

  void SomeFunction();
  void SomeFunctionThatDoesNothing() {
  }

  void set_some_var(int var) { some_var_ = var; }
  int some_var() const { return some_var_; }

 private:
  bool SomeInternalFunction();

  int some_var_;
  int some_other_var_;
};

Things to note:

Constructor Initializer Lists

Constructor initializer lists can be all on one line or with subsequent lines indented four spaces.

The acceptable formats for initializer lists are:

// When everything fits on one line:
MyClass::MyClass(int var) : some_var_(var) {
  DoSomething();
}

// If the signature and initializer list are not all on one line,
// you must wrap before the colon and indent 4 spaces:
MyClass::MyClass(int var)
    : some_var_(var), some_other_var_(var + 1) {
  DoSomething();
}

// When the list spans multiple lines, put each member on its own line
// and align them:
MyClass::MyClass(int var)
    : some_var_(var),             // 4 space indent
      some_other_var_(var + 1) {  // lined up
  DoSomething();
}

// As with any other code block, the close curly can be on the same
// line as the open curly, if it fits.
MyClass::MyClass(int var)
    : some_var_(var) {}

Namespace Formatting

The contents of namespaces are not indented.

Namespaces do not add an extra level of indentation. For example, use:

namespace {

void foo() {  // Correct.  No extra indentation within namespace.
  ...
}

}  // namespace

Do not indent within a namespace:

namespace {

  // Wrong!  Indented when it should not be.
  void foo() {
    ...
  }

}  // namespace

Horizontal Whitespace

Use of horizontal whitespace depends on location. Never put trailing whitespace at the end of a line.

General

int i = 0;  // Two spaces before end-of-line comments.

void f(bool b) {  // Open braces should always have a space before them.
  ...
int i = 0;  // Semicolons usually have no space before them.
// Spaces inside braces for braced-init-list are optional.  If you use them,
// put them on both sides!
int x[] = { 0 };
int x[] = {0};

// Spaces around the colon in inheritance and initializer lists.
class Foo : public Bar {
 public:
  // For inline function implementations, put spaces between the braces
  // and the implementation itself.
  Foo(int b) : Bar(), baz_(b) {}  // No spaces inside empty braces.
  void Reset() { baz_ = 0; }  // Spaces separating braces from implementation.
  ...

Adding trailing whitespace can cause extra work for others editing the same file when they merge, as can removing existing trailing whitespace. So, don't introduce trailing whitespace. Remove it if you're already changing that line, or do it in a separate clean-up operation (preferably when no one else is working on the file).

Loops and Conditionals

if (b) {          // Space after the keyword in conditions and loops.
} else {          // Spaces around else.
}
while (test) {}   // There is usually no space inside parentheses.
switch (i) {
for (int i = 0; i < 5; ++i) {
// Loops and conditions may have spaces inside parentheses, but this
// is rare.  Be consistent.
switch ( i ) {
if ( test ) {
for ( int i = 0; i < 5; ++i ) {
// For loops always have a space after the semicolon.  They may have a space
// before the semicolon, but this is rare.
for ( ; i < 5 ; ++i) {
  ...

// Range-based for loops always have a space before and after the colon.
for (auto x : counts) {
  ...
}
switch (i) {
  case 1:         // No space before colon in a switch case.
    ...
  case 2: break;  // Use a space after a colon if there's code after it.

Operators

// Assignment operators always have spaces around them.
x = 0;

// Other binary operators usually have spaces around them, but it's
// OK to remove spaces around factors.  Parentheses should have no
// internal padding.
v = w * x + y / z;
v = w*x + y/z;
v = w * (x + z);

// No spaces separating unary operators and their arguments.
x = -5;
++x;
if (x && !y)
  ...

Templates and Casts

// No spaces inside the angle brackets (< and >), before
// <, or between >( in a cast
std::vector<std::string> x;
y = static_cast<char*>(x);

// No spaces between type and pointer.
std::vector<char*> x;

Vertical Whitespace

Use vertical whitespace sparingly; unnecessary blank lines make it harder to see overall code structure. Use blank lines only where they aid the reader in understanding the structure.

Do not add blank lines where indentation already provides clear delineation, such as at the start or end of a code block. Do use blank lines to separate code into closely related chunks, analogous to paragraph breaks in prose. Within a statement or declaration, usually only insert line breaks to stay within the line length limit, or to attach a comment to only part of the contents.

Exceptions to the Rules

The coding conventions described above are mandatory. However, like all good rules, these sometimes have exceptions, which we discuss here.

Existing Non-conformant Code

You may diverge from the rules when dealing with code that does not conform to this style guide.

If you find yourself modifying code that was written to specifications other than those presented by this guide, you may have to diverge from these rules in order to stay consistent with the local conventions in that code. If you are in doubt about how to do this, ask the original author or the person currently responsible for the code. Remember that consistency includes local consistency, too.

Windows Code

Windows programmers have developed their own set of coding conventions, mainly derived from the conventions in Windows headers and other Microsoft code. We want to make it easy for anyone to understand your code, so we have a single set of guidelines for everyone writing C++ on any platform.

It is worth reiterating a few of the guidelines that you might forget if you are used to the prevalent Windows style:

However, there are just a few rules that we occasionally need to break on Windows:

================================================ FILE: cppguide.xml ================================================ Redirecting Redirecting you to cppguide.html. ================================================ FILE: csharp-style.md ================================================ # C# at Google Style Guide This style guide is for C# code developed internally at Google, and is the default style for C# code at Google. It makes stylistic choices that conform to other languages at Google, such as Google C++ style and Google Java style. ## Formatting guidelines ### Naming rules Naming rules follow [Microsoft's C# naming guidelines](https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines). Where Microsoft's naming guidelines are unspecified (e.g. private and local variables), rules are taken from the [CoreFX C# coding guidelines](https://github.com/dotnet/runtime/blob/HEAD/docs/coding-guidelines/coding-style.md) Rule summary: #### Code * Names of classes, methods, enumerations, public fields, public properties, namespaces: `PascalCase`. * Names of local variables, parameters: `camelCase`. * Names of private, protected, internal and protected internal fields and properties: `_camelCase`. * Naming convention is unaffected by modifiers such as const, static, readonly, etc. * For casing, a "word" is anything written without internal spaces, including acronyms. For example, `MyRpc` instead of ~~`MyRPC`~~. * Names of interfaces start with `I`, e.g. `IInterface`. #### Files * Filenames and directory names are `PascalCase`, e.g. `MyFile.cs`. * Where possible the file name should be the same as the name of the main class in the file, e.g. `MyClass.cs`. * In general, prefer one core class per file. ### Organization * Modifiers occur in the following order: `public protected internal private new abstract virtual override sealed static readonly extern unsafe volatile async`. * Namespace `using` declarations go at the top, before any namespaces. `using` import order is alphabetical, apart from `System` imports which always go first. * Class member ordering: * Group class members in the following order: * Nested classes, enums, delegates and events. * Static, const and readonly fields. * Fields and properties. * Constructors and finalizers. * Methods. * Within each group, elements should be in the following order: * Public. * Internal. * Protected internal. * Protected. * Private. * Where possible, group interface implementations together. ### Whitespace rules Developed from Google Java style. * A maximum of one statement per line. * A maximum of one assignment per statement. * Indentation of 2 spaces, no tabs. * Column limit: 100. * No line break before opening brace. * No line break between closing brace and `else`. * Braces used even when optional. * Space after `if`/`for`/`while` etc., and after commas. * No space after an opening parenthesis or before a closing parenthesis. * No space between a unary operator and its operand. One space between the operator and each operand of all other operators. * Line wrapping developed from Google C++ style guidelines, with minor modifications for compatibility with Microsoft's C# formatting tools: * In general, line continuations are indented 4 spaces. * Line breaks with braces (e.g. list initializers, lambdas, object initializers, etc) do not count as continuations. * For function definitions and calls, if the arguments do not all fit on one line they should be broken up onto multiple lines, with each subsequent line aligned with the first argument. If there is not enough room for this, arguments may instead be placed on subsequent lines with a four space indent. The code example below illustrates this. ### Example ```c# using System; // `using` goes at the top, outside the // namespace. namespace MyNamespace { // Namespaces are PascalCase. // Indent after namespace. public interface IMyInterface { // Interfaces start with 'I' public int Calculate(float value, float exp); // Methods are PascalCase // ...and space after comma. } public enum MyEnum { // Enumerations are PascalCase. Yes, // Enumerators are PascalCase. No, } public class MyClass { // Classes are PascalCase. public int Foo = 0; // Public member variables are // PascalCase. public bool NoCounting = false; // Field initializers are encouraged. private class Results { public int NumNegativeResults = 0; public int NumPositiveResults = 0; } private Results _results; // Private member variables are // _camelCase. public static int NumTimesCalled = 0; private const int _bar = 100; // const does not affect naming // convention. private int[] _someTable = { // Container initializers use a 2 2, 3, 4, // space indent. } public MyClass() { _results = new Results { NumNegativeResults = 1, // Object initializers use a 2 space NumPositiveResults = 1, // indent. }; } public int CalculateValue(int mulNumber) { // No line break before opening brace. var resultValue = Foo * mulNumber; // Local variables are camelCase. NumTimesCalled++; Foo += _bar; if (!NoCounting) { // No space after unary operator and // space after 'if'. if (resultValue < 0) { // Braces used even when optional and // spaces around comparison operator. _results.NumNegativeResults++; } else if (resultValue > 0) { // No newline between brace and else. _results.NumPositiveResults++; } } return resultValue; } public void ExpressionBodies() { // For simple lambdas, fit on one line if possible, no brackets or braces required. Func increment = x => x + 1; // Closing brace aligns with first character on line that includes the opening brace. Func difference1 = (x, y) => { long diff = (long)x - y; return diff >= 0 ? diff : -diff; }; // If defining after a continuation line break, indent the whole body. Func difference2 = (x, y) => { long diff = (long)x - y; return diff >= 0 ? diff : -diff; }; // Inline lambda arguments also follow these rules. Prefer a leading newline before // groups of arguments if they include lambdas. CallWithDelegate( (x, y) => { long diff = (long)x - y; return diff >= 0 ? diff : -diff; }); } void DoNothing() {} // Empty blocks may be concise. // If possible, wrap arguments by aligning newlines with the first argument. void AVeryLongFunctionNameThatCausesLineWrappingProblems(int longArgumentName, int p1, int p2) {} // If aligning argument lines with the first argument doesn't fit, or is difficult to // read, wrap all arguments on new lines with a 4 space indent. void AnotherLongFunctionNameThatCausesLineWrappingProblems( int longArgumentName, int longArgumentName2, int longArgumentName3) {} void CallingLongFunctionName() { int veryLongArgumentName = 1234; int shortArg = 1; // If possible, wrap arguments by aligning newlines with the first argument. AnotherLongFunctionNameThatCausesLineWrappingProblems(shortArg, shortArg, veryLongArgumentName); // If aligning argument lines with the first argument doesn't fit, or is difficult to // read, wrap all arguments on new lines with a 4 space indent. AnotherLongFunctionNameThatCausesLineWrappingProblems( veryLongArgumentName, veryLongArgumentName, veryLongArgumentName); } } } ``` ## C# coding guidelines ### Constants * Variables and fields that can be made `const` should always be made `const`. * If `const` isn’t possible, `readonly` can be a suitable alternative. * Prefer named constants to magic numbers. ### IEnumerable vs IList vs IReadOnlyList * For inputs use the most restrictive collection type possible, for example `IReadOnlyCollection` / `IReadOnlyList` / `IEnumerable` as inputs to methods when the inputs should be immutable. * For outputs, if passing ownership of the returned container to the owner, prefer `IList` over `IEnumerable`. If not transferring ownership, prefer the most restrictive option. ### Generators vs containers * Use your best judgement, bearing in mind: * Generator code is often less readable than filling in a container. * Generator code can be more performant if the results are going to be processed lazily, e.g. when not all the results are needed. * Generator code that is directly turned into a container via `ToList()` will be less performant than filling in a container directly. * Generator code that is called multiple times will be considerably slower than iterating over a container multiple times. ### Property styles * For single line read-only properties, prefer expression body properties (`=>`) when possible. * For everything else, use the older `{ get; set; }` syntax. ### Expression body syntax For example: ```c# int SomeProperty => _someProperty ``` * Judiciously use expression body syntax in lambdas and properties. * Don’t use on method definitions. This will be reviewed when C# 7 is live, which uses this syntax heavily. * As with methods and other scoped blocks of code, align the closing with the first character of the line that includes the opening brace. See sample code for examples. ### Structs and classes: * Structs are very different from classes: * Structs are always passed and returned by value. * Assigning a value to a member of a returned struct doesn’t modify the original - e.g. `transform.position.x = 10` doesn’t set the transform’s position.x to 10; `position` here is a property that returns a `Vector3` by value, so this just sets the x parameter of a copy of the original. * Almost always use a class. * Consider struct when the type can be treated like other value types - for example, if instances of the type are small and commonly short-lived or are commonly embedded in other objects. Good examples include Vector3, Quaternion and Bounds. * Note that this guidance may vary from team to team where, for example, performance issues might force the use of structs. ### Lambdas vs named methods * If a lambda is non-trivial (e.g. more than a couple of statements, excluding declarations), or is reused in multiple places, it should probably be a named method. ### Field initializers * Field initializers are generally encouraged. ### Extension methods * Only use an extension method when the source of the original class is not available, or else when changing the source is not feasible. * Only use an extension method if the functionality being added is a ‘core’ general feature that would be appropriate to add to the source of the original class. * Note - if we have the source to the class being extended, and the maintainer of the original class does not want to add the function, prefer not using an extension method. * Only put extension methods into core libraries that are available everywhere - extensions that are only available in some code will become a readability issue. * Be aware that using extension methods always obfuscates the code, so err on the side of not adding them. ### ref and out * Use `out` for returns that are not also inputs. * Place `out` parameters after all other parameters in the method definition. * `ref` should be used rarely, when mutating an input is necessary. * Do not use `ref` as an optimisation for passing structs. * Do not use `ref` to pass a modifiable container into a method. `ref` is only required when the supplied container needs be replaced with an entirely different container instance. ### LINQ * In general, prefer single line LINQ calls and imperative code, rather than long chains of LINQ. Mixing imperative code and heavily chained LINQ is often hard to read. * Prefer member extension methods over SQL-style LINQ keywords - e.g. prefer `myList.Where(x)` to `myList where x`. * Avoid `Container.ForEach(...)` for anything longer than a single statement. ### Array vs List * In general, prefer `List<>` over arrays for public variables, properties, and return types (keeping in mind the guidance on `IList` / `IEnumerable` / `IReadOnlyList` above). * Prefer `List<>` when the size of the container can change. * Prefer arrays when the size of the container is fixed and known at construction time. * Prefer array for multidimensional arrays. * Note: * array and `List<>` both represent linear, contiguous containers. * Similar to C++ arrays vs `std::vector`, arrays are of fixed capacity, whereas `List<>` can be added to. * In some cases arrays are more performant, but in general `List<>` is more flexible. ### Folders and file locations * Be consistent with the project. * Prefer a flat structure where possible. ### Use of tuple as a return type * In general, prefer a named class type over `Tuple<>`, particularly when returning complex types. ### String interpolation vs `String.Format()` vs `String.Concat` vs `operator+` * In general, use whatever is easiest to read, particularly for logging and assert messages. * Be aware that chained `operator+` concatenations will be slower and cause significant memory churn. * If performance is a concern, `StringBuilder` will be faster for multiple string concatenations. ### `using` * Generally, don’t alias long typenames with `using`. Often this is a sign that a `Tuple<>` needs to be turned into a class. * e.g. `using RecordList = List>` should probably be a named class instead. * Be aware that `using` statements are only file scoped and so of limited use. Type aliases will not be available for external users. ### Object Initializer syntax For example: ```c# var x = new SomeClass { Property1 = value1, Property2 = value2, }; ``` * Object Initializer Syntax is fine for ‘plain old data’ types. * Avoid using this syntax for classes or structs with constructors. * If splitting across multiple lines, indent one block level. ### Namespace naming * In general, namespaces should be no more than 2 levels deep. * Don't force file/folder layout to match namespaces. * For shared library/module code, use namespaces. For leaf 'application' code, such as `unity_app`, namespaces are not necessary. * New top-level namespace names must be globally unique and recognizable. ### Default values/null returns for structs * Prefer returning a ‘success’ boolean value and a struct `out` value. * Where performance isn't a concern and the resulting code significantly more readable (e.g. chained null conditional operators vs deeply nested if statements) nullable structs are acceptable. * Notes: * Nullable structs are convenient, but reinforce the general ‘null is failure’ pattern Google prefers to avoid. We will investigate a `StatusOr` equivalent in the future, if there is enough demand. ### Removing from containers while iterating C# (like many other languages) does not provide an obvious mechanism for removing items from containers while iterating. There are a couple of options: * If all that is required is to remove items that satisfy some condition, `someList.RemoveAll(somePredicate)` is recommended. * If other work needs to be done in the iteration, `RemoveAll` may not be sufficient. A common alternative pattern is to create a new container outside of the loop, insert items to keep in the new container, and swap the original container with the new one at the end of iteration. ### Calling delegates * When calling a delegate, use `Invoke()` and use the null conditional operator - e.g. `SomeDelegate?.Invoke()`. This clearly marks the call at the callsite as ‘a delegate that is being called’. The null check is concise and robust against threading race conditions. ### The `var` keyword * Use of `var` is encouraged if it aids readability by avoiding type names that are noisy, obvious, or unimportant. * Encouraged: * When the type is obvious - e.g. `var apple = new Apple();`, or `var request = Factory.Create();` * For transient variables that are only passed directly to other methods - e.g. `var item = GetItem(); ProcessItem(item);` * Discouraged: * When working with basic types - e.g. `var success = true;` * When working with compiler-resolved built-in numeric types - e.g. `var number = 12 * ReturnsFloat();` * When users would clearly benefit from knowing the type - e.g. `var listOfItems = GetList();` ### Attributes * Attributes should appear on the line above the field, property, or method they are associated with, separated from the member by a newline. * Multiple attributes should be separated by newlines. This allows for easier adding and removing of attributes, and ensures each attribute is easy to search for. ### Argument Naming Derived from the Google C++ style guide. When the meaning of a function argument is nonobvious, consider one of the following remedies: * If the argument is a literal constant, and the same constant is used in multiple function calls in a way that tacitly assumes they're the same, use a named constant to make that constraint explicit, and to guarantee that it holds. * Consider changing the function signature to replace a `bool` argument with an `enum` argument. This will make the argument values self-describing. * Replace large or complex nested expressions with named variables. * Consider using [Named Arguments](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments) to clarify argument meanings at the call site. * For functions that have several configuration options, consider defining a single class or struct to hold all the options and pass an instance of that. This approach has several advantages. Options are referenced by name at the call site, which clarifies their meaning. It also reduces function argument count, which makes function calls easier to read and write. As an added benefit, call sites don't need to be changed when another option is added. Consider the following example: ```c# // Bad - what are these arguments? DecimalNumber product = CalculateProduct(values, 7, false, null); ``` versus: ```c# // Good ProductOptions options = new ProductOptions(); options.PrecisionDecimals = 7; options.UseCache = CacheUsage.DontUseCache; DecimalNumber product = CalculateProduct(values, options, completionDelegate: null); ``` ================================================ FILE: docguide/README.md ================================================ # Google documentation guide * [Markdown styleguide](style.md) * [Best practices](best_practices.md) * [README files](READMEs.md) * [Philosophy](philosophy.md) ## See also * [How to update this guide](https://goto.google.com/doc-guide), for Googlers. ================================================ FILE: docguide/READMEs.md ================================================ # READMEs About README.md files. 1. [Overview](#overview) 1. [Readable README files](#readable-readme-files) 1. [Where to put your README](#where-to-put-your-readme) 1. [What to put in your README](#what-to-put-in-your-readme) ## Overview A README is a short summary of the contents of a directory. The contents of the file are displayed in GitHub and Gitiles when you view the contents of the containing directory. README files provide critical information for people browsing your code, especially first-time users. This document covers how to create README files that are readable with GitHub and Gitiles. ## Readable README files **README files must be named `README.md`.** The file name *must* end with the `.md` extension and is case sensitive. For example, the file /README.md is rendered when you view the contents of the containing directory: https://github.com/google/styleguide/tree/gh-pages Also `README.md` at `HEAD` ref is rendered by Gitiles when displaying repository index: https://gerrit.googlesource.com/gitiles/ ## Where to put your README Unlike all other Markdown files, `README.md` files should not be located inside your product or library's documentation directory. `README.md` files should be located in the top-level directory for your product or library's actual codebase. All top-level directories for a code package should have an up-to-date `README.md` file. This is especially important for package directories that provide interfaces for other teams. ## What to put in your README At a minimum, your `README.md` file should contain a link to your user- and/or team-facing documentation. Every package-level `README.md` should include or point to the following information: 1. What is in this package or library and what's it used for. 1. Points of contact. 1. Status of whether this package or library is deprecated, or not for general release, etc. 1. How to use the package or library. Examples include sample code, copyable `bazel run` or `bazel test` commands, etc. 1. Links to relevant documentation. ================================================ FILE: docguide/VERSION ================================================ 2.0 ================================================ FILE: docguide/best_practices.md ================================================ # Documentation Best Practices "Say what you mean, simply and directly." - [Brian Kernighan](https://en.wikipedia.org/wiki/The_Elements_of_Programming_Style) Contents: 1. [Minimum Viable Documentation](#minimum-viable-documentation) 1. [Update Docs with Code](#update-docs-with-code) 1. [Delete Dead Documentation](#delete-dead-documentation) 1. [Prefer the Good Over the Perfect](#prefer-the-good-over-the-perfect) 1. [Documentation is the Story of Your Code](#documentation-is-the-story-of-your-code) 1. [Duplication is Evil](#duplication-is-evil) ## Minimum Viable Documentation A small set of fresh and accurate docs is better than a large assembly of "documentation" in various states of disrepair. Write short and useful documents. Cut out everything unnecessary, including out-of-date, incorrect, or redundant information. Also make a habit of continually massaging and improving every doc to suit your changing needs. **Docs work best when they are alive but frequently trimmed, like a bonsai tree**. See also [these Agile Documentation best practices](https://www.agilemodeling.com/essays/agileDocumentationBestPractices.htm). ## Update Docs with Code **Change your documentation in the same CL as the code change**. This keeps your docs fresh, and is also a good place to explain to your reviewer what you're doing. A good reviewer can at least insist that docstrings, header files, README.md files, and any other docs get updated alongside the CL. ## Delete Dead Documentation Dead docs are bad. They misinform, they slow down, they incite despair in engineers and laziness in team leads. They set a precedent for leaving behind messes in a code base. If your home is clean, most guests will be clean without being asked. Just like any big cleaning project, **it's easy to be overwhelmed**. If your docs are in bad shape: * Take it slow, doc health is a gradual accumulation. * First delete what you're certain is wrong, ignore what's unclear. * Get your whole team involved. Devote time to quickly scan every doc and make a simple decision: Keep or delete? * Default to delete or leave behind if migrating. Stragglers can always be recovered. * Iterate. ## Prefer the Good Over the Perfect Documentation is an art. There is no perfect document, there are only proven methods and prudent guidelines. See [Better is better than best](./style.md). ## Documentation is the Story of Your Code Writing excellent code doesn't end when your code compiles or even if your test coverage reaches 100%. It's easy to write something a computer understands, it's much harder to write something both a human and a computer understand. Your mission as a Code Health-conscious engineer is to **write for humans first, computers second.** Documentation is an important part of this skill. There's a spectrum of engineering documentation that ranges from terse comments to detailed prose: 1. **Meaningful names**: Good naming allows the code to convey information that would otherwise be relegated to comments or documentation. This includes nameable entities at all levels, from local variables to classes, files, and directories. 2. **Inline comments**: The primary purpose of inline comments is to provide information that the code itself cannot contain, such as why the code is there. 3. **Method and class comments**: * **Method API documentation**: The header / Javadoc / docstring comments that say what methods do and how to use them. This documentation is **the contract of how your code must behave**. The intended audience is future programmers who will use and modify your code. It is often reasonable to say that any behavior documented here should have a test verifying it. This documentation details what arguments the method takes, what it returns, any "gotchas" or restrictions, and what exceptions it can throw or errors it can return. It does not usually explain why code behaves a particular way unless that's relevant to a developer's understanding of how to use the method. "Why" explanations are for inline comments. Think in practical terms when writing method documentation: "This is a hammer. You use it to pound nails." * **Class / Module API documentation**: The header / Javadoc / docstring comments for a class or a whole file. This documentation gives a brief overview of what the class / file does and often gives a few short examples of how you might use the class / file. Examples are particularly relevant when there's several distinct ways to use the class (some advanced, some simple). Always list the simplest use case first. 4. **README.md**: A good README.md orients the new user to the directory and points to more detailed explanation and user guides: * What is this directory intended to hold? * Which files should the developer look at first? Are some files an API? * Who maintains this directory and where I can learn more? See the [README.md guidelines](READMEs.md). 5. **docs**: The contents of a good docs directory explain how to: * Get started using the relevant API, library, or tool. * Run its tests. * Debug its output. * Release the binary. 6. **Design docs, PRDs**: A good design doc or PRD discusses the proposed implementation at length for the purpose of collecting feedback on that design. However, once the code is implemented, design docs should serve as archives of these decisions, not as half-correct docs (they are often misused). 7. **Other external docs**: Some teams maintain documentation in other locations, separate from the code, such as Google Sites, Drive, or wiki. If you do maintain documentation in other locations, you should clearly point to those locations from your project directory (for example, by adding an obvious link to the location from your project's `README.md`). ## Duplication is Evil Do not write your own guide to a common Google technology or process. Link to it instead. If the guide doesn't exist or it's badly out of date, submit your updates to the appropriate directory or create a package-level README.md. **Take ownership and don't be shy**: Other teams will usually welcome your contributions. ================================================ FILE: docguide/philosophy.md ================================================ # Philosophy 埏埴以為器,當其無,有器之用. *Clay becomes pottery through craft, but it's the emptiness that makes a pot useful.* \- [Laozi](https://ctext.org/dictionary.pl?if=en&id=11602) Contents: 1. [Radical simplicity](#radical-simplicity) 1. [Readable source text](#readable-source-text) 1. [Minimum viable documentation](#minimum-viable-documentation) 1. [Better is better than best](#better-is-better-than-best) ## Radical simplicity * **Scalability and interoperability** are more important than a menagerie of unessential features. Scale comes from simplicity, speed, and ease. Interoperability comes from unadorned, digestible content. * **Fewer distractions** make for better writing and more productive reading. * **New features should never interfere with the simplest use case** and should remain invisible to users who don't need them. * **Markdown is designed for the average engineer** -- the busy, just-want-to-go-back-to-coding engineer. Large and complex documentation is possible but not the primary focus. * **Minimizing context switching makes people happier.** Engineers should be able to interact with documentation using the same tools they use to read and write code. ## Readable source text * **Plain text not only suffices, it is superior**. Markdown itself is not essential to this formula, but it is the best and most widely supported solution right now. HTML is generally not encouraged. * **Content and presentation should not mingle**. It should always be possible to ditch the renderer and read the essential information at source. Users should never have to touch the presentation layer if they don't want to. * **Portability and future-proofing leave room for the unimagined integrations to come**, and are best achieved by keeping the source as human-readable as possible. * **Static content is better than dynamic**, because content should not depend on the features of any one server. However, **fresh is better than stale**. We strive to balance these needs. ## Minimum viable documentation * **Docs thrive when they're treated like tests**: a necessary chore one learns to savor because it rewards over time. See [Best Practices](best_practices.md). * **Brief and utilitarian is better than long and exhaustive**. The vast majority of users need only a small fraction of the author's total knowledge, but they need it quickly and often. ## Better is better than best * **Incremental improvement is better than prolonged debate**. Patience and tolerance of imperfection allow projects to evolve organically. * **Don't [lick the cookie](https://community.redhat.com/blog/2018/09/dont-lick-the-cookie/), pass the plate**. Ideas are cheap. We're drowning in potentially impactful projects. Choose only those you can really handle and release those you can't. ================================================ FILE: docguide/style.md ================================================ # Markdown style guide Much of what makes Markdown refreshing is the ability to write plain text and get great formatted output as a result. To keep the slate clean for the next author, your Markdown should be simple and consistent with the whole corpus wherever possible. We seek to balance three goals: 1. *Source text is readable and portable.* 2. *The Markdown corpus is maintainable over time and across teams.* 3. *The syntax is simple and easy to remember.* Contents: 1. [Minimum viable documentation](#minimum-viable-documentation) 1. [Better is better than best](#better-is-better-than-best) 1. [Capitalization](#capitalization) 1. [Document layout](#document-layout) 1. [Table of contents](#table-of-contents) 1. [Character line limit](#character-line-limit) 1. [Trailing whitespace](#trailing-whitespace) 1. [Headings](#headings) 1. [ATX-style headings](#atx-style-headings) 1. [Use unique, complete names for headings](#use-unique-complete-names-for-headings) 1. [Add spacing to headings](#add-spacing-to-headings) 1. [Use a single H1 heading](#use-a-single-h1-heading) 1. [Capitalization of titles and headers](#capitalization-of-titles-and-headers) 1. [Lists](#lists) 1. [Use lazy numbering for long lists](#use-lazy-numbering-for-long-lists) 1. [Nested list spacing](#nested-list-spacing) 1. [Code](#code) 1. [Inline](#inline) 1. [Use code span for escaping](#use-code-span-for-escaping) 1. [Codeblocks](#codeblocks) 1. [Declare the language](#declare-the-language) 1. [Escape newlines](#escape-newlines) 1. [Use fenced code blocks instead of indented code blocks](#use-fenced-code-blocks-instead-of-indented-code-blocks) 1. [Nest codeblocks within lists](#nest-codeblocks-within-lists) 1. [Links](#links) 1. [Use explicit paths for links within Markdown](#use-explicit-paths-for-links-within-markdown) 1. [Avoid relative paths unless within the same directory](#avoid-relative-paths-unless-within-the-same-directory) 1. [Use informative Markdown link titles](#use-informative-markdown-link-titles) 1. [Reference links](#reference-links) 1. [Use reference links for long links](#use-reference-links-for-long-links) 1. [Use reference links to reduce duplication](#use-reference-links-to-reduce-duplication) 1. [Define reference links after their first use](#define-reference-links-after-their-first-use) 1. [Images](#images) 1. [Tables](#tables) 1. [Strongly prefer Markdown to HTML](#strongly-prefer-markdown-to-html) ## Minimum viable documentation A small set of fresh and accurate docs is better than a sprawling, loose assembly of "documentation" in various states of disrepair. The **Markdown way** encourages engineers to take ownership of their docs and keep them up to date with the same zeal we keep our tests in good order. Strive for this. * Identify what you really need: release docs, API docs, testing guidelines. * Delete cruft frequently and in small batches. ## Better is better than best The standards for an internal documentation review are different from the standards for code reviews. Reviewers should ask for improvements, but in general, the author should always be able to invoke the "Better/Best Rule." Fast iteration is your friend. To get long-term improvement, **authors must stay productive** when making short-term improvements. Set lower standards for each CL, so that **more such CLs** can happen. As a reviewer of a documentation CL: 1. When reasonable, LGTM immediately and trust that comments will be fixed appropriately. 2. Prefer to suggest an alternative rather than leaving a vague comment. 3. For substantial changes, start your own follow-up CL instead. Especially try to avoid comments of the form "You should *also*...". 4. On rare occasions, hold up submission if the CL actually makes the docs worse. It's okay to ask the author to revert. As an author: 1. Avoid wasting cycles with trivial argument. Capitulate early and move on. 2. Cite the Better/Best Rule as often as needed. ## Capitalization Use the original names of products, tools and binaries, preserving the capitalization. E.g.: ```markdown # Markdown style guide `Markdown` is a dead-simple platform for internal engineering documentation. ``` and not ```markdown # markdown bad style guide example `markdown` is a dead-simple platform for internal engineering documentation. ``` ## Document layout In general, documents benefit from some variation of the following layout: ```markdown # Document Title Short introduction. [TOC] ## Topic Content. ## See also * https://link-to-more-info ``` 1. `# Document title`: The first heading should be a level-one heading, ideally the same or nearly the same as the filename. The first level-one heading is used as the page ``. 1. `author`: *Optional*. If you'd like to claim ownership of the document or if you are very proud of it, add yourself under the title. However, revision history generally suffices. 1. `Short introduction.` 1–3 sentences providing a high-level overview of the topic. Imagine yourself as a complete newbie who landed on your "Extending Foo" doc and doesn't know the most basic information you take for granted. "What is Foo? Why would I extend it?" 1. `[TOC]`: if you use hosting that supports table of contents, such as Gitiles, put `[TOC]` after the short introduction. See [`[TOC]` documentation][TOC-docs]. 1. `## Topic`: The rest of your headings should start from level 2. 1. `## See also`: Put miscellaneous links at the bottom for the user who wants to know more or didn't find what they needed. [TOC-docs]: https://gerrit.googlesource.com/gitiles/+/HEAD/Documentation/markdown.md#Table-of-contents ## Table of contents ### Use a `[TOC]` directive Use a [`[TOC]` directive][TOC-docs] unless all of your content is above the fold[^above] on a laptop. [^above]: Content is "above the fold" if it is visible when the page is first displayed. Content is "below the fold" if it is hidden until the user scrolls down the page on a computer or literally unfolds a document such as a newspaper. ### Place the `[TOC]` directive after the introduction Place the `[TOC]` directive after your page's introduction and before the first H2 heading. For example: ```markdown # My Page This is my introduction **before** the TOC. [TOC] ## My first H2 ``` ```markdown # My Page [TOC] This is my introduction **after** the TOC where it should not be. ## My first H2 ``` For users who read your documentation visually, it doesn't matter where your `[TOC]` directive is placed, as Markdown always displays the TOC toward the top and to the right of the page. However, `[TOC]` placement matters a lot when screen readers or keyboard controls are involved. That's because `[TOC]` inserts the HTML for the table of contents into the DOM wherever you've included the directive in your Markdown file. If, for example, you place the directive at the very bottom of your file, screen readers won't read it until they get to the end of the document. ## Character line limit Markdown content follows the residual convention of an 80-character line limit. Why? Because it's what most of us do for code. * **Tooling integration**: All our tooling is designed around code, so the more our documents are formatted according to similar rules, the better these tools will work. For example, Code Search doesn't soft wrap. * **Quality**. The more engineers use their well-worn coding habits when creating and editing Markdown content, the better the quality. Markdown takes advantage of the excellent review culture we already have. ### Exceptions Exceptions to the 80-character rule include: * Links * Tables * Headings * Code blocks This means that lines with links are allowed to extend past column 80, along with any relevant punctuation: ```markdown * See the [foo docs](https://gerrit.googlesource.com/gitiles/+/HEAD/Documentation/markdown.md). and find the logfile. ``` However, note that text before and after the link gets wrapped. Tables may also run long. However, there are [best practices for creating short, readable tables](#tables). ```markdown Foo | Bar | Baz ----------------------------------------------------------------------------- | --- | --- Somehow-unavoidable-long-cell-filled-with-content-that-simply-refuses-to-wrap | Foo | Bar ``` ## Trailing whitespace Don't use trailing whitespace. Use a trailing backslash to break lines. The [CommonMark spec](http://spec.commonmark.org/0.20/#hard-line-breaks) decrees that two spaces at the end of a line should insert a `<br />` tag. However, many directories have a presubmit check for trailing whitespace, and many IDEs will clean it up anyway. Use a trailing backslash, sparingly: ```markdown For some reason I just really want a break here,\ though it's probably not necessary. ``` Best practice is to avoid the need for a `<br />` altogether. A pair of newlines will create a paragraph tag; get used to that. ## Headings ### ATX-style headings ```markdown # Heading 1 ## Heading 2 ``` Headings with `=` or `-` underlines can be annoying to maintain and don't fit with the rest of the heading syntax. An editor has to ask: Does `---` mean H1 or H2? ```markdown Heading - do you remember what level? DO NOT DO THIS. --------- ``` ### Use unique, complete names for headings Use unique and fully descriptive names for each heading, even for sub-sections. Since link anchors are constructed from headings, this helps ensure that the automatically-constructed anchor links are intuitive and clear. For example, instead of: ```markdown ## Foo ### Summary ### Example ## Bar ### Summary ### Example ``` prefer: ```markdown ## Foo ### Foo summary ### Foo example ## Bar ### Bar summary ### Bar example ``` ### Add spacing to headings Prefer spacing after `#` and newlines before and after: ```markdown ...text before. ## Heading 2 Text after... ``` Lack of spacing makes it a little harder to read in source: ```markdown ...text before. ##Heading 2 Text after... DO NOT DO THIS. ``` ### Use a single H1 heading Use one H1 heading as the title of your document. Subsequent headings should be H2 or deeper. See [Document layout](#document-layout) for more information. ### Capitalization of titles and headers Follow the guidance for [capitalization](https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings) in the [Google Developer Documentation Style Guide](https://developers.google.com/style/). ## Lists ### Use lazy numbering for long lists Markdown is smart enough to let the resulting HTML render your numbered lists correctly. For longer lists that may change, especially long nested lists, use "lazy" numbering: ```markdown 1. Foo. 1. Bar. 1. Foofoo. 1. Barbar. 1. Baz. ``` However, if the list is small and you don't anticipate changing it, prefer fully numbered lists, because it's nicer to read in source: ```markdown 1. Foo. 2. Bar. 3. Baz. ``` ### Nested list spacing When nesting lists, use a 4-space indent for both numbered and bulleted lists: ```markdown 1. Use 2 spaces after the item number, so the text itself is indented 4 spaces. Use a 4-space indent for wrapped text. 2. Use 2 spaces again for the next item. * Use 3 spaces after a bullet, so the text itself is indented 4 spaces. Use a 4-space indent for wrapped text. 1. Use 2 spaces with numbered lists, as before. Wrapped text in a nested list needs an 8-space indent. 2. Looks nice, doesn't it? * Back to the bulleted list, indented 3 spaces. ``` The following works, but it's very messy: ```markdown * One space, with no indent for wrapped text. 1. Irregular nesting... DO NOT DO THIS. ``` Even when there's no nesting, using the 4 space indent makes layout consistent for wrapped text: ```markdown * Foo, wrapped with a 4-space indent. 1. Two spaces for the list item and 4 spaces before wrapped text. 2. Back to 2 spaces. ``` However, when lists are small, not nested, and a single line, one space can suffice for both kinds of lists: ```markdown * Foo * Bar * Baz. 1. Foo. 2. Bar. ``` ## Code ### Inline `Backticks` designate `inline code` that will be rendered literally. Use them for short code quotations, field names, and more: ```markdown You'll want to run `really_cool_script.sh arg`. Pay attention to the `foo_bar_whammy` field in that table. ``` Use inline code when referring to file types in a generic sense, rather than a specific existing file: ```markdown Be sure to update your `README.md`! ``` ### Use code span for escaping When you don't want text to be processed as normal Markdown, like a fake path or example URL that would lead to a bad autolink, wrap it in backticks: ```markdown An example Markdown shortlink would be: `Markdown/foo/Markdown/bar.md` An example query might be: `https://www.google.com/search?q=$TERM` ``` ### Codeblocks For code quotations longer than a single line, use a fenced code block: <pre> ```python def Foo(self, bar): self.bar = bar ``` </pre> #### Declare the language It is best practice to explicitly declare the language, so that neither the syntax highlighter nor the next editor must guess. #### Use fenced code blocks instead of indented code blocks Four-space indenting is also interpreted as a code block. However, we strongly recommend fencing for all code blocks. Indented code blocks can sometimes look cleaner in the source, but they have several drawbacks: * You cannot specify the language. Some Markdown features are tied to language specifiers. * The beginning and end of the code block are ambiguous. * Indented code blocks are harder to search for in Code Search. ```markdown You'll need to run: bazel run :thing -- --foo And then: bazel run :another_thing -- --bar And again: bazel run :yet_again -- --baz ``` #### Escape newlines Because most command-line snippets are intended to be copied and pasted directly into a terminal, it's best practice to escape any newlines. Use a single backslash at the end of the line: <pre> ```shell $ bazel run :target -- --flag --foo=longlonglonglonglongvalue \ --bar=anotherlonglonglonglonglonglonglonglonglonglongvalue ``` </pre> #### Nest codeblocks within lists If you need a code block within a list, make sure to indent it so as to not break the list: ```markdown * Bullet. ```c++ int foo; ``` * Next bullet. ``` You can also create a nested code block with 4 spaces. Simply indent 4 additional spaces from the list indentation: ```markdown * Bullet. int foo; * Next bullet. ``` ## Links Long links make source Markdown difficult to read and break the 80 character wrapping. **Wherever possible, shorten your links**. ### Use explicit paths for links within Markdown Use the explicit path for Markdown links. For example: ```markdown [...](/path/to/other/markdown/page.md) ``` You don't need to use the entire qualified URL: ```markdown [...](https://bad-full-url.example.com/path/to/other/markdown/page.md) ``` ### Avoid relative paths unless within the same directory Relative paths are fairly safe within the same directory. For example: ```markdown [...](other-page-in-same-dir.md) [...](/path/to/another/dir/other-page.md) ``` Avoid relative links if you need to specify other directories with `../`: ```markdown [...](../../bad/path/to/another/dir/other-page.md) ``` ### Use informative Markdown link titles Markdown link syntax allows you to set a link title. Use it wisely. Users often do not read documents; they scan them. Links catch the eye. But titling your links "here," "link," or simply duplicating the target URL tells the hasty reader precisely nothing and is a waste of space: ```markdown DO NOT DO THIS. See the Markdown guide for more info: [link](markdown.md), or check out the style guide [here](style.md). Check out a typical test result: [https://example.com/foo/bar](https://example.com/foo/bar). ``` Instead, write the sentence naturally, then go back and wrap the most appropriate phrase with the link: ```markdown See the [Markdown guide](markdown.md) for more info, or check out the [style guide](style.md). Check out a [typical test result](https://example.com/foo/bar). ``` ### Reference For long links or image URLs, you may want to split the link use from the link definition, like this: <!-- Known bug: We use a zero-width non-breaking space (U+FEFF) here to prevent --> <!-- reference links from rendering within code blocks. --> ```markdown See the [Markdown style guide][style], which has suggestions for making docs more readable. [style]: http://Markdown/corp/Markdown/docs/reference/style.md ``` #### Use reference links for long links Use reference links where the length of the link would detract from the readability of the surrounding text if it were inlined. Reference links make it harder to see the destination of a link in source text, and add additional syntax. In this example, reference link usage is not appropriate, because the link is not long enough to disrupt the flow of the text: ```markdown DO NOT DO THIS. The [style guide][style_guide] says not to use reference links unless you have to. [style_guide]: https://google.com/Markdown-style ``` Just inline it instead: ```markdown https://google.com/Markdown-style says not to use reference links unless you have to. ``` In this example, the link destination is long enough that it makes sense to use a reference link: ```markdown The [style guide] says not to use reference links unless you have to. [style guide]: https://docs.google.com/document/d/13HQBxfhCwx8lVRuN2Wf6poqvAfVeEXmFVcawP5I6B3c/edit ``` Use reference links more often in tables. It is particularly important to keep table content short, since Markdown does not provide a facility to break text in cell tables across multiple lines, and smaller tables are more readable. For example, this table's readability is worsened by inline links: ```markdown DO NOT DO THIS. Site | Description ---------------------------------------------------------------- | ----------------------- [site 1](http://google.com/excessively/long/path/example_site_1) | This is example site 1. [site 2](http://google.com/excessively/long/path/example_site_2) | This is example site 2. ``` Instead, use reference links to keep the line length manageable: ```markdown Site | Description -------- | ----------------------- [site 1] | This is example site 1. [site 2] | This is example site 2. [site 1]: http://google.com/excessively/long/path/example_site_1 [site 2]: http://google.com/excessively/long/path/example_site_2 ``` #### Use reference links to reduce duplication Consider using reference links when referencing the same link destination multiple times in a document, to reduce duplication. #### Define reference links after their first use We recommend putting reference link definitions just before the next heading, at the end of the section in which they're first used. If your editor has its own opinion about where they should go, don't fight it; the tools always win. We define a "section" as all text between two headings. Think of reference links like footnotes, and the current section like the current page. This arrangement makes it easy to find the link destination in source view, while keeping the flow of text free from clutter. In long documents with lots of reference links, it also prevents "footnote overload" at the bottom of the file, which makes it difficult to pick out the relevant link destination. There is one exception to this rule: reference link definitions that are used in multiple sections should go at the end of the document. This avoids dangling links when a section is updated or moved. In the following example, the reference definition is far from its initial use, which makes the document harder to read: ```markdown # Header FOR A BAD DOCUMENT Some text with a [link][link_def]. Some more text with the same [link][link_def]. ## Header 2 ... lots of text ... ## Header 3 Some more text using a [different_link][different_link_def]. [link_def]: http://reallyreallyreallylonglink.com [different_link_def]: http://differentreallyreallylonglink.com ``` Instead, put it just before the header following its first use: ```markdown # Header Some text with a [link][link_def]. Some more text with the same [link][link_def]. [link_def]: http://reallyreallyreallylonglink.com ## Header 2 ... lots of text ... ## Header 3 Some more text using a [different_link][different_link_def]. [different_link_def]: http://differentreallyreallylonglink.com ``` ## Images See [image syntax](https://gerrit.googlesource.com/gitiles/+/HEAD/Documentation/markdown.md#Images). Use images sparingly, and prefer simple screenshots. This guide is designed around the idea that plain text gets users down to the business of communication faster with less reader distraction and author procrastination. However, it's sometimes very helpful to show what you mean. * Use images when it's easier to *show* a reader something than to *describe it*. For example, explaining how to navigate a UI is often easier with an image than text. * Make sure to provide appropriate text to describe your image. Readers who are not sighted cannot see your image and still need to understand the content! See the alt text best practices below. ## Tables Use tables when they make sense: for the presentation of tabular data that needs to be scanned quickly. Avoid using tables when your data could easily be presented in a list. Lists are much easier to write and read in Markdown. For example: ```markdown DO NOT DO THIS Fruit | Metrics | Grows on | Acute curvature | Attributes | Notes ------ | ------------ | -------- | ------------------ | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- Apple | Very popular | Trees | | [Juicy](http://cs/SomeReallyReallyReallyReallyReallyReallyReallyReallyLongQuery), Firm, Sweet | Apples keep doctors away. Banana | Very popular | Trees | 16 degrees average | [Convenient](http://cs/SomeDifferentReallyReallyReallyReallyReallyReallyReallyReallyLongQuery), Soft, Sweet | Contrary to popular belief, most apes prefer mangoes. Don't you? See the [design doc][banana_v2] for the newest hotness in bananiels. ``` This table illustrates a few typical problems: * **Poor distribution**: Several columns don't differ across rows, and some cells are empty. This is usually a sign that your data may not benefit from tabular display. * **Unbalanced dimensions**: There are a small number of rows relative to columns. When this ratio is unbalanced in either direction, a table becomes little more than an inflexible format for text. * **Rambling prose** in some cells. Tables should tell a succinct story at a glance. [Lists](#lists) and subheadings sometimes suffice to present the same information. Let's see this data in list form: ```markdown ## Fruits Both types are highly popular, sweet, and grow on trees. ### Apple * [Juicy](http://SomeReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLongURL) * Firm Apples keep doctors away. ### Banana * [Convenient](http://cs/SomeDifferentReallyReallyReallyReallyReallyReallyReallyReallyLongQuery) * Soft * 16 degrees average acute curvature. Contrary to popular belief, most apes prefer mangoes. Don't you? See the [design doc][banana_v2] for the newest hotness in bananiels. ``` The list form is more spacious, and arguably therefore much easier for the reader to find what interests her in this case. However, there are times a table is the best choice. When you have: * Relatively uniform data distribution across two dimensions. * Many parallel items with distinct attributes. In those cases, a table format is just the thing. In fact, a compact table can improve readability: ```markdown Transport | Favored by | Advantages ---------------- | -------------- | ----------------------------------------------- Swallow | Coconuts | [Fast when unladen][airspeed] Bicycle | Miss Gulch | [Weatherproof][tornado_proofing] X-34 landspeeder | Whiny farmboys | [Cheap][tosche_station] since the XP-38 came out [airspeed]: http://google3/airspeed.h [tornado_proofing]: http://google3/kansas/ [tosche_station]: http://google3/power_converter.h ``` Note that [reference links](#reference-links) are used to keep the table cells manageable. ## Strongly prefer Markdown to HTML Please prefer standard Markdown syntax wherever possible and avoid HTML hacks. If you can't seem to accomplish what you want, reconsider whether you really need it. Except for [big tables](#tables), Markdown meets almost all needs already. Every bit of HTML hacking reduces the readability and portability of our Markdown corpus. This in turn limits the usefulness of integrations with other tools, which may either present the source as plain text or render it. See [Philosophy](philosophy.md). Gitiles does not render HTML. ================================================ FILE: eclipse-cpp-google-style.xml ================================================ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <profiles version="1"> <profile kind="CodeFormatterProfile" name="Google C++" version="1"> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.lineSplit" value="80"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_member_access" value="16"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line" value="false"/> <setting id="org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_constructor_initializer_list" value="83"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier" value="true"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.comment.min_distance_between_code_and_line_comment" value="2"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.tabulation.size" value="2"/> <setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_enumerator_list" value="51"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_declarator_list" value="16"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.indent_empty_lines" value="false"/> <setting id="org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/> <setting id="org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line" value="true"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_semicolon" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases" value="true"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.join_wrapped_lines" value="true"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation" value="18"/> <setting id="org.eclipse.cdt.core.formatter.comment.never_indent_line_comments_on_first_column" value="true"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration" value="18"/> <setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.brace_position_for_block" value="end_of_line"/> <setting id="org.eclipse.cdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="true"/> <setting id="org.eclipse.cdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.continuation_indentation" value="2"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_expression_list" value="0"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_binary_operator" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_conditional_expression" value="34"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line" value="false"/> <setting id="org.eclipse.cdt.core.formatter.indent_access_specifier_extra_spaces" value="1"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header" value="false"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header" value="false"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_compact_if" value="0"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_assignment" value="16"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain" value="18"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_binary_operator" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration" value="16"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header" value="false"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.indent_statements_compare_to_body" value="true"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_binary_expression" value="16"/> <setting id="org.eclipse.cdt.core.formatter.indent_statements_compare_to_block" value="true"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.tabulation.char" value="space"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_colon_in_constructor_initializer_list" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/> <setting id="org.eclipse.cdt.core.formatter.compact_else_if" value="true"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line" value="false"/> <setting id="org.eclipse.cdt.core.formatter.brace_position_for_switch" value="end_of_line"/> <setting id="org.eclipse.cdt.core.formatter.alignment_for_overloaded_left_shift_chain" value="18"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line" value="false"/> <setting id="org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.indentation.size" value="2"/> <setting id="org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration" value="end_of_line"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters" value="insert"/> <setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments" value="do not insert"/> </profile> </profiles> ================================================ FILE: eclipse-java-google-style.xml ================================================ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <profiles version="13"> <profile kind="CodeFormatterProfile" name="GoogleStyle" version="13"> <setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_cascading_method_invocation_with_arguments.count_dependent" value="16|-1|16"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/> <setting id="org.eclipse.jdt.core.formatter.wrap_prefer_two_fragments" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.wrap_comment_inline_tags" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_local_variable_declaration" value="16"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="1040"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type.count_dependent" value="1585|-1|1585"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields.count_dependent" value="16|-1|16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression.count_dependent" value="16|4|80"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration.count_dependent" value="16|4|48"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration.count_dependent" value="16|4|49"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_cascading_method_invocation_with_arguments" value="16"/> <setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration.count_dependent" value="16|4|48"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/> <setting id="org.eclipse.jdt.core.formatter.wrap_non_simple_local_variable_annotation" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/> <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="0"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants.count_dependent" value="16|5|48"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.lineSplit" value="100"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation.count_dependent" value="16|4|48"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="1585"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="16"/> <setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/> <setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/> <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/> <setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/> <setting id="org.eclipse.jdt.core.formatter.wrap_non_simple_type_annotation" value="true"/> <setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_field_declaration" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/> <setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_generic_type_arguments" value="16"/> <setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/> <setting id="org.eclipse.jdt.core.formatter.comment_new_line_at_start_of_html_paragraph" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comment_prefix" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/> <setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/> <setting id="org.eclipse.jdt.core.formatter.wrap_non_simple_parameter_annotation" value="false"/> <setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="1585"/> <setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/> <setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation.count_dependent" value="16|5|80"/> <setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter.count_dependent" value="1040|-1|1040"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package.count_dependent" value="1585|-1|1585"/> <setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.force_if_else_statement_brace" value="true"/> <setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/> <setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="3"/> <setting id="org.eclipse.jdt.core.formatter.wrap_non_simple_package_annotation" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation.count_dependent" value="16|-1|16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="1585"/> <setting id="org.eclipse.jdt.core.compiler.compliance" value="1.7"/> <setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_new_anonymous_class" value="20"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable.count_dependent" value="1585|-1|1585"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field.count_dependent" value="1585|-1|1585"/> <setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration.count_dependent" value="16|5|80"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/> <setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/> <setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant.count_dependent" value="16|-1|16"/> <setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="100"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="0"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/> <setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/> <setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="2"/> <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/> <setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/> <setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="0"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="1585"/> <setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer.count_dependent" value="16|5|80"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/> <setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/> <setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/> <setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="true"/> <setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration.count_dependent" value="16|4|48"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method.count_dependent" value="1585|-1|1585"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression.count_dependent" value="16|-1|16"/> <setting id="org.eclipse.jdt.core.formatter.wrap_non_simple_member_annotation" value="true"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="1585"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call.count_dependent" value="16|5|80"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_generic_type_arguments.count_dependent" value="16|-1|16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression.count_dependent" value="16|5|80"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration.count_dependent" value="16|5|80"/> <setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/> <setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignment_for_for_statement" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/> <setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/> </profile> </profiles> ================================================ FILE: go/best-practices.md ================================================ <!--* toc_depth: 3 *--> # Go Style Best Practices https://google.github.io/styleguide/go/best-practices [Overview](index) | [Guide](guide) | [Decisions](decisions) | [Best practices](best-practices) <!-- --> {% raw %} **Note:** This is part of a series of documents that outline [Go Style](index) at Google. This document is **neither [normative](index#normative) nor [canonical](index#canonical)**, and is an auxiliary document to the [core style guide](guide). See [the overview](index#about) for more information. <a id="about"></a> ## About This file documents **guidance about how to best apply the Go Style Guide**. This guidance is intended for common situations that arise frequently, but may not apply in every circumstance. Where possible, multiple alternative approaches are discussed along with the considerations that go into the decision about when and when not to apply them. See [the overview](index#about) for the full set of Style Guide documents. <a id="naming"></a> ## Naming <a id="function-names"></a> ### Function and method names <a id="function-name-repetition"></a> #### Avoid repetition When choosing the name for a function or method, consider the context in which the name will be read. Consider the following recommendations to avoid excess [repetition](decisions#repetition) at the call site: * The following can generally be omitted from function and method names: * The types of the inputs and outputs (when there is no collision) * The type of a method's receiver * Whether an input or output is a pointer * For functions, do not [repeat the name of the package](decisions#repetitive-with-package). ```go // Bad: package yamlconfig func ParseYAMLConfig(input string) (*Config, error) ``` ```go // Good: package yamlconfig func Parse(input string) (*Config, error) ``` * For methods, do not repeat the name of the method receiver. ```go // Bad: func (c *Config) WriteConfigTo(w io.Writer) (int64, error) ``` ```go // Good: func (c *Config) WriteTo(w io.Writer) (int64, error) ``` * Do not repeat the names of variables passed as parameters. ```go // Bad: func OverrideFirstWithSecond(dest, source *Config) error ``` ```go // Good: func Override(dest, source *Config) error ``` * Do not repeat the names and types of the return values. ```go // Bad: func TransformToJSON(input *Config) *jsonconfig.Config ``` ```go // Good: func Transform(input *Config) *jsonconfig.Config ``` When it is necessary to disambiguate functions of a similar name, it is acceptable to include extra information. ```go // Good: func (c *Config) WriteTextTo(w io.Writer) (int64, error) func (c *Config) WriteBinaryTo(w io.Writer) (int64, error) ``` <a id="function-name-conventions"></a> #### Naming conventions There are some other common conventions when choosing names for functions and methods: * Functions that return something are given noun-like names. ```go // Good: func (c *Config) JobName(key string) (value string, ok bool) ``` A corollary of this is that function and method names should [avoid the prefix `Get`](decisions#getters). ```go // Bad: func (c *Config) GetJobName(key string) (value string, ok bool) ``` * Functions that do something are given verb-like names. ```go // Good: func (c *Config) WriteDetail(w io.Writer) (int64, error) ``` * Identical functions that differ only by the types involved include the name of the type at the end of the name. ```go // Good: func ParseInt(input string) (int, error) func ParseInt64(input string) (int64, error) func AppendInt(buf []byte, value int) []byte func AppendInt64(buf []byte, value int64) []byte ``` If there is a clear "primary" version, the type can be omitted from the name for that version: ```go // Good: func (c *Config) Marshal() ([]byte, error) func (c *Config) MarshalText() (string, error) ``` <a id="naming-doubles"></a> ### Test double and helper packages There are several disciplines you can apply to [naming] packages and types that provide test helpers and especially [test doubles]. A test double could be a stub, fake, mock, or spy. These examples mostly use stubs. Update your names accordingly if your code uses fakes or another kind of test double. [naming]: guide#naming [test doubles]: https://abseil.io/resources/swe-book/html/ch13.html#basic_concepts Suppose you have a well-focused package providing production code similar to this: ```go package creditcard import ( "errors" "path/to/money" ) // ErrDeclined indicates that the issuer declines the charge. var ErrDeclined = errors.New("creditcard: declined") // Card contains information about a credit card, such as its issuer, // expiration, and limit. type Card struct { // omitted } // Service allows you to perform operations with credit cards against external // payment processor vendors like charge, authorize, reimburse, and subscribe. type Service struct { // omitted } func (s *Service) Charge(c *Card, amount money.Money) error { /* omitted */ } ``` <a id="naming-doubles-helper-package"></a> #### Creating test helper packages Suppose you want to create a package that contains test doubles for another. We'll use `package creditcard` (from above) for this example: One approach is to introduce a new Go package based on the production one for testing. A safe choice is to append the word `test` to the original package name ("creditcard" + "test"): ```go // Good: package creditcardtest ``` Unless stated explicitly otherwise, all examples in the sections below are in `package creditcardtest`. <a id="naming-doubles-simple"></a> #### Simple case You want to add a set of test doubles for `Service`. Because `Card` is effectively a dumb data type, similar to a Protocol Buffer message, it needs no special treatment in tests, so no double is required. If you anticipate only test doubles for one type (like `Service`), you can take a concise approach to naming the doubles: ```go // Good: import ( "path/to/creditcard" "path/to/money" ) // Stub stubs creditcard.Service and provides no behavior of its own. type Stub struct{} func (Stub) Charge(*creditcard.Card, money.Money) error { return nil } ``` This is strictly preferable to a naming choice like `StubService` or the very poor `StubCreditCardService`, because the base package name and its domain types imply what `creditcardtest.Stub` is. Finally, if the package is built with Bazel, make sure the new `go_library` rule for the package is marked as `testonly`: ```build # Good: go_library( name = "creditcardtest", srcs = ["creditcardtest.go"], deps = [ ":creditcard", ":money", ], testonly = True, ) ``` The approach above is conventional and will be reasonably well understood by other engineers. See also: * [Go Tip #42: Authoring a Stub for Testing](https://google.github.io/styleguide/go/index.html#gotip) <a id="naming-doubles-multiple-behaviors"></a> #### Multiple test double behaviors When one kind of stub is not enough (for example, you also need one that always fails), we recommend naming the stubs according to the behavior they emulate. Here we rename `Stub` to `AlwaysCharges` and introduce a new stub called `AlwaysDeclines`: ```go // Good: // AlwaysCharges stubs creditcard.Service and simulates success. type AlwaysCharges struct{} func (AlwaysCharges) Charge(*creditcard.Card, money.Money) error { return nil } // AlwaysDeclines stubs creditcard.Service and simulates declined charges. type AlwaysDeclines struct{} func (AlwaysDeclines) Charge(*creditcard.Card, money.Money) error { return creditcard.ErrDeclined } ``` <a id="naming-doubles-multiple-types"></a> #### Multiple doubles for multiple types But now suppose that `package creditcard` contains multiple types worth creating doubles for, as seen below with `Service` and `StoredValue`: ```go package creditcard type Service struct { // omitted } type Card struct { // omitted } // StoredValue manages customer credit balances. This applies when returned // merchandise is credited to a customer's local account instead of processed // by the credit issuer. For this reason, it is implemented as a separate // service. type StoredValue struct { // omitted } func (s *StoredValue) Credit(c *Card, amount money.Money) error { /* omitted */ } ``` In this case, more explicit test double naming is sensible: ```go // Good: type StubService struct{} func (StubService) Charge(*creditcard.Card, money.Money) error { return nil } type StubStoredValue struct{} func (StubStoredValue) Credit(*creditcard.Card, money.Money) error { return nil } ``` <a id="naming-doubles-local-variables"></a> #### Local variables in tests When variables in your tests refer to doubles, choose a name that most clearly differentiates the double from other production types based on context. Consider some production code you want to test: ```go package payment import ( "path/to/creditcard" "path/to/money" ) type CreditCard interface { Charge(*creditcard.Card, money.Money) error } type Processor struct { CC CreditCard } var ErrBadInstrument = errors.New("payment: instrument is invalid or expired") func (p *Processor) Process(c *creditcard.Card, amount money.Money) error { if c.Expired() { return ErrBadInstrument } return p.CC.Charge(c, amount) } ``` In the tests, a test double called a "spy" for `CreditCard` is juxtaposed against production types, so prefixing the name may improve clarity. ```go // Good: package payment import "path/to/creditcardtest" func TestProcessor(t *testing.T) { var spyCC creditcardtest.Spy proc := &Processor{CC: spyCC} // declarations omitted: card and amount if err := proc.Process(card, amount); err != nil { t.Errorf("proc.Process(card, amount) = %v, want nil", err) } charges := []creditcardtest.Charge{ {Card: card, Amount: amount}, } if got, want := spyCC.Charges, charges; !cmp.Equal(got, want) { t.Errorf("spyCC.Charges = %v, want %v", got, want) } } ``` This is clearer than when the name is not prefixed. ```go // Bad: package payment import "path/to/creditcardtest" func TestProcessor(t *testing.T) { var cc creditcardtest.Spy proc := &Processor{CC: cc} // declarations omitted: card and amount if err := proc.Process(card, amount); err != nil { t.Errorf("proc.Process(card, amount) = %v, want nil", err) } charges := []creditcardtest.Charge{ {Card: card, Amount: amount}, } if got, want := cc.Charges, charges; !cmp.Equal(got, want) { t.Errorf("cc.Charges = %v, want %v", got, want) } } ``` <a id="shadowing"></a> ### Shadowing **Note:** This explanation uses two informal terms, *stomping* and *shadowing*. They are not official concepts in the Go language spec. Like many programming languages, Go has mutable variables: assigning to a variable changes its value. ```go // Good: func abs(i int) int { if i < 0 { i *= -1 } return i } ``` When using [short variable declarations] with the `:=` operator, in some cases a new variable is not created. We can call this *stomping*. It's OK to do this when the original value is no longer needed. ```go // Good: // innerHandler is a helper for some request handler, which itself issues // requests to other backends. func (s *Server) innerHandler(ctx context.Context, req *pb.MyRequest) *pb.MyResponse { // Unconditionally cap the deadline for this part of request handling. ctx, cancel := context.WithTimeout(ctx, 3*time.Second) defer cancel() ctxlog.Info(ctx, "Capped deadline in inner request") // Code here no longer has access to the original context. // This is good style if when first writing this, you anticipate // that even as the code grows, no operation legitimately should // use the (possibly unbounded) original context that the caller provided. // ... } ``` Be careful using short variable declarations in a new scope, though: that introduces a new variable. We can call this *shadowing* the original variable. Code after the end of the block refers to the original. Here is a buggy attempt to shorten the deadline conditionally: ```go // Bad: func (s *Server) innerHandler(ctx context.Context, req *pb.MyRequest) *pb.MyResponse { // Attempt to conditionally cap the deadline. if *shortenDeadlines { ctx, cancel := context.WithTimeout(ctx, 3*time.Second) defer cancel() ctxlog.Info(ctx, "Capped deadline in inner request") } // BUG: "ctx" here again means the context that the caller provided. // The above buggy code compiled because both ctx and cancel // were used inside the if statement. // ... } ``` A correct version of the code might be: ```go // Good: func (s *Server) innerHandler(ctx context.Context, req *pb.MyRequest) *pb.MyResponse { if *shortenDeadlines { var cancel func() // Note the use of simple assignment, = and not :=. ctx, cancel = context.WithTimeout(ctx, 3*time.Second) defer cancel() ctxlog.Info(ctx, "Capped deadline in inner request") } // ... } ``` In the case we called stomping, because there's no new variable, the type being assigned must match that of the original variable. With shadowing, an entirely new entity is introduced so it can have a different type. Intentional shadowing can be a useful practice, but you can always use a new name if it improves [clarity](guide#clarity). It is not a good idea to use variables with the same name as standard packages other than very small scopes, because that renders free functions and values from that package inaccessible. Conversely, when picking a name for your package, avoid names that are likely to require [import renaming](decisions#import-renaming) or cause shadowing of otherwise good variable names at the client side. ```go // Bad: func LongFunction() { url := "https://example.com/" // Oops, now we can't use net/url in code below. } ``` [short variable declarations]: https://go.dev/ref/spec#Short_variable_declarations <a id="util-packages"></a> ### Util packages Go packages have a name specified on the `package` declaration, separate from the import path. The package name matters more for readability than the path. Go package names should be [related to what the package provides](decisions#package-names). Naming a package just `util`, `helper`, `common` or similar is usually a poor choice (it can be used as *part* of the name though). Uninformative names make the code harder to read, and if used too broadly they are liable to cause needless [import conflicts](decisions#import-renaming). Instead, consider what the callsite will look like. ```go // Good: db := spannertest.NewDatabaseFromFile(...) _, err := f.Seek(0, io.SeekStart) b := elliptic.Marshal(curve, x, y) ``` You can tell roughly what each of these do even without knowing the imports list (`cloud.google.com/go/spanner/spannertest`, `io`, and `crypto/elliptic`). With less focused names, these might read: ```go // Bad: db := test.NewDatabaseFromFile(...) _, err := f.Seek(0, common.SeekStart) b := helper.Marshal(curve, x, y) ``` <a id="package-size"></a> ## Package size If you're asking yourself how big your Go packages should be and whether to place related types in the same package or split them into different ones, a good place to start is the [Go blog post about package names][blog-pkg-names]. Despite the post title, it's not solely about naming. It contains some helpful hints and cites several useful articles and talks. Here are some other considerations and notes. Users see [godoc] for the package in one page, and any methods exported by types supplied by the package are grouped by their type. Godoc also group constructors along with the types they return. If *client code* is likely to need two values of different type to interact with each other, it may be convenient for the user to have them in the same package. Code within a package can access unexported identifiers in the package. If you have a few related types whose *implementation* is tightly coupled, placing them in the same package lets you achieve this coupling without polluting the public API with these details. A good test for this coupling is to imagine a hypothetical user of two packages, where the packages cover closely related topics: if the user must import both packages in order to use either in any meaningful way, combining them together is usually the right thing to do. The standard library generally demonstrates this kind of scoping and layering well. All of that being said, putting your entire project in a single package would likely make that package too large. When something is conceptually distinct, giving it its own small package can make it easier to use. The short name of the package as known to clients together with the exported type name work together to make a meaningful identifier: e.g. `bytes.Buffer`, `ring.New`. The [Package Names blog post][blog-pkg-names] has more examples. Go style is flexible about file size, because maintainers can move code within a package from one file to another without affecting callers. But as a general guideline: it is usually not a good idea to have a single file with many thousands of lines in it, or having many tiny files. There is no "one type, one file" convention as in some other languages. As a rule of thumb, files should be focused enough that a maintainer can tell which file contains something, and the files should be small enough that it will be easy to find once there. The standard library often splits large packages to several source files, grouping related code by file. The source for [package `bytes`] is a good example. Packages with long package documentation may choose to dedicate one file called `doc.go` that has the [package documentation](decisions#package-comments), a package declaration, and nothing else, but this is not required. Within the Google codebase and in projects using Bazel, directory layout for Go code is different than it is in open source Go projects: you can have multiple `go_library` targets in a single directory. A good reason to give each package its own directory is if you expect to open source your project in the future. A few non-canonical reference examples to help demonstrate these ideas in action: * small packages that contain one cohesive idea that warrant nothing more being added nor nothing being removed: * [package `csv`][package `csv`]: CSV data encoding and decoding with responsibility split respectively between [reader.go] and [writer.go]. * [package `expvar`][package `expvar`]: whitebox program telemetry all contained in [expvar.go]. * moderately sized packages that contain one large domain and its multiple responsibilities together: * [package `flag`][package `flag`]: command line flag management all contained in [flag.go]. * large packages that divide several closely related domains across several files: * [package `http`][package `http`]: the core of HTTP: [client.go][http-client], support for HTTP clients; [server.go][http-client], support for HTTP servers; [cookie.go], cookie management. * [package `os`][package `os`]: cross-platform operating system abstractions: [exec.go], subprocess management; [file.go], file management; [tempfile.go], temporary files. See also: * [Test double packages](#naming-doubles) * [Organizing Go Code (Blog Post)] * [Organizing Go Code (Presentation)] [blog-pkg-names]: https://go.dev/blog/package-names [package `bytes`]: https://go.dev/src/bytes/ [Organizing Go Code (Blog Post)]: https://go.dev/blog/organizing-go-code [Organizing Go Code (Presentation)]: https://go.dev/talks/2014/organizeio.slide [package `csv`]: https://pkg.go.dev/encoding/csv [reader.go]: https://go.googlesource.com/go/+/refs/heads/master/src/encoding/csv/reader.go [writer.go]: https://go.googlesource.com/go/+/refs/heads/master/src/encoding/csv/writer.go [package `expvar`]: https://pkg.go.dev/expvar [expvar.go]: https://go.googlesource.com/go/+/refs/heads/master/src/expvar/expvar.go [package `flag`]: https://pkg.go.dev/flag [flag.go]: https://go.googlesource.com/go/+/refs/heads/master/src/flag/flag.go [godoc]: https://pkg.go.dev/ [package `http`]: https://pkg.go.dev/net/http [http-client]: https://go.googlesource.com/go/+/refs/heads/master/src/net/http/client.go [http-server]: https://go.googlesource.com/go/+/refs/heads/master/src/net/http/server.go [cookie.go]: https://go.googlesource.com/go/+/refs/heads/master/src/net/http/cookie.go [package `os`]: https://pkg.go.dev/os [exec.go]: https://go.googlesource.com/go/+/refs/heads/master/src/os/exec.go [file.go]: https://go.googlesource.com/go/+/refs/heads/master/src/os/file.go [tempfile.go]: https://go.googlesource.com/go/+/refs/heads/master/src/os/tempfile.go <a id="imports"></a> ## Imports <a id="import-protos"></a> ### Protocol Buffer Messages and Stubs Proto library imports are treated differently than standard Go imports due to their cross-language nature. The convention for renamed proto imports are based on the rule that generated the package: * The `pb` suffix is generally used for `go_proto_library` rules. * The `grpc` suffix is generally used for `go_grpc_library` rules. Often a single word describing the package is used: ```go // Good: import ( foopb "path/to/package/foo_service_go_proto" foogrpc "path/to/package/foo_service_go_grpc" ) ``` Follow the style guidance for [package names](https://google.github.io/styleguide/go/decisions#package-names). Prefer whole words. Short names are good, but avoid ambiguity. When in doubt, use the proto package name up to _go with a pb suffix: ```go // Good: import ( pushqueueservicepb "path/to/package/push_queue_service_go_proto" ) ``` **Note:** Previous guidance encouraged very short names such as "xpb" or even just "pb". New code should prefer more descriptive names. Existing code which uses short names should not be used as an example, but does not need to be changed. <a id="import-order"></a> ### Import ordering See the [Go Style Decisions: Import grouping](decisions.md#import-grouping). <a id="error-handling"></a> ## Error handling In Go, [errors are values]; they are created by code and consumed by code. Errors can be: * Converted into diagnostic information for display to humans * Used by the maintainer * Interpreted by an end user Error messages also show up across a variety of different surfaces including log messages, error dumps, and rendered UIs. Code that processes (produces or consumes) errors should do so deliberately. It can be tempting to ignore or blindly propagate an error return value. However, it is always worth considering whether the current function in the call frame is positioned to handle the error most effectively. This is a large topic and it is hard to give categorical advice. Use your judgment, but keep the following considerations in mind: * When creating an error value, decide whether to give it any [structure](#error-structure). * When handling an error, consider [adding information](#error-extra-info) that you have but that the caller and/or callee might not. * See also guidance on [error logging](#error-logging). While it is usually not appropriate to ignore an error, a reasonable exception to this is when orchestrating related operations, where often only the first error is useful. Package [`errgroup`] provides a convenient abstraction for a group of operations that can all fail or be canceled as a group. [errors are values]: https://go.dev/blog/errors-are-values [`errgroup`]: https://pkg.go.dev/golang.org/x/sync/errgroup See also: * [Effective Go on errors](https://go.dev/doc/effective_go#errors) * [A post by the Go Blog on errors](https://go.dev/blog/go1.13-errors) * [Package `errors`](https://pkg.go.dev/errors) * [Package `upspin.io/errors`](https://commandcenter.blogspot.com/2017/12/error-handling-in-upspin.html) * [GoTip #89: When to Use Canonical Status Codes as Errors](https://google.github.io/styleguide/go/index.html#gotip) * [GoTip #48: Error Sentinel Values](https://google.github.io/styleguide/go/index.html#gotip) * [GoTip #13: Designing Errors for Checking](https://google.github.io/styleguide/go/index.html#gotip) <a id="error-structure"></a> ### Error structure If callers need to interrogate the error (e.g., distinguish different error conditions), give the error value structure so that this can be done programmatically rather than having the caller perform string matching. This advice applies to production code as well as to tests that care about different error conditions. The simplest structured errors are unparameterized global values. ```go type Animal string var ( // ErrDuplicate occurs if this animal has already been seen. ErrDuplicate = errors.New("duplicate") // ErrMarsupial occurs because we're allergic to marsupials outside Australia. // Sorry. ErrMarsupial = errors.New("marsupials are not supported") ) func process(animal Animal) error { switch { case seen[animal]: return ErrDuplicate case marsupial(animal): return ErrMarsupial } seen[animal] = true // ... return nil } ``` The caller can simply compare the returned error value of the function with one of the known error values: ```go // Good: func handlePet(...) { switch err := process(an); err { case ErrDuplicate: return fmt.Errorf("feed %q: %v", an, err) case ErrMarsupial: // Try to recover with a friend instead. alternate = an.BackupAnimal() return handlePet(..., alternate, ...) } } ``` The above uses sentinel values, where the error must be equal (in the sense of `==`) to the expected value. That is perfectly adequate in many cases. If `process` returns wrapped errors (discussed below), you can use [`errors.Is`]. ```go // Good: func handlePet(...) { switch err := process(an); { case errors.Is(err, ErrDuplicate): return fmt.Errorf("feed %q: %v", an, err) case errors.Is(err, ErrMarsupial): // ... } } ``` Do not attempt to distinguish errors based on their string form. (See [Go Tip #13: Designing Errors for Checking](https://google.github.io/styleguide/go/index.html#gotip) for more.) ```go // Bad: func handlePet(...) { err := process(an) if regexp.MatchString(`duplicate`, err.Error()) {...} if regexp.MatchString(`marsupial`, err.Error()) {...} } ``` If there is extra information in the error that the caller needs programmatically, it should ideally be presented structurally. For example, the [`os.PathError`] type is documented to place the pathname of the failing operation in a struct field which the caller can easily access. Other error structures can be used as appropriate, for example a project struct containing an error code and detail string. [Package `status`][status] is a common encapsulation; if you choose this approach (which you are not obligated to do), use [canonical codes]. See [Go Tip #89: When to Use Canonical Status Codes as Errors](https://google.github.io/styleguide/go/index.html#gotip) to know if using status codes is the right choice. [`os.PathError`]: https://pkg.go.dev/os#PathError [`errors.Is`]: https://pkg.go.dev/errors#Is [`errors.As`]: https://pkg.go.dev/errors#As [`package cmp`]: https://pkg.go.dev/github.com/google/go-cmp/cmp [status]: https://pkg.go.dev/google.golang.org/grpc/status [canonical codes]: https://pkg.go.dev/google.golang.org/grpc/codes <a id="error-extra-info"></a> ### Adding information to errors When adding information to errors, avoid redundant information that the underlying error already provides. The `os` package, for instance, already includes path information in its errors. ```go // Good: if err := os.Open("settings.txt"); err != nil { return fmt.Errorf("launch codes unavailable: %v", err) } // Output: // // launch codes unavailable: open settings.txt: no such file or directory ``` Here, "launch codes unavailable" adds specific meaning to the `os.Open` error that's relevant to the current function's context, without duplicating the underlying file path information. ```go // Bad: if err := os.Open("settings.txt"); err != nil { return fmt.Errorf("could not open settings.txt: %v", err) } // Output: // // could not open settings.txt: open settings.txt: no such file or directory ``` Don't add an annotation if its sole purpose is to indicate a failure without adding new information. The presence of an error sufficiently conveys the failure to the caller. ```go // Bad: return fmt.Errorf("failed: %v", err) // just return err instead ``` The [choice between `%v` and `%w` when wrapping errors](https://go.dev/blog/go1.13-errors#whether-to-wrap) with `fmt.Errorf` is a nuanced decision that significantly impacts how errors are propagated handled, inspected, and documented within your application. The core principle is to make error values useful to their observers, whether those observers are humans or code. 1. **`%v` for simple annotation or new error** The `%v` verb is your general-purpose tool for string formatting of any Go value, including errors. When used with `fmt.Errorf`, it embeds the string representation of an error (what its `Error()` method returns) into a new error value, dropping any structured information from the original error. Examples to use `%v`: * Adding interesting, non-redundant context: as in the example above. * Logging or displaying errors: When the primary goal is to present a human-readable error message in logs or to a user, and you don't intend for the caller to programmatically `errors.Is` or `errors.As` the error (Note: `errors.Unwrap` is generally not recommended here as it doesn't handle multi-errors). * Creating fresh, independent errors: Sometimes it is necessary to transform an error into a new error message, thereby hiding the specifics of the original error. This practice is particularly beneficial at system boundaries, including but not limited to RPC, IPC, and storage, where we translate domain-specific errors into a canonical error space. ```go // Good: func (*FortuneTeller) SuggestFortune(context.Context, *pb.SuggestionRequest) (*pb.SuggestionResponse, error) { // ... if err != nil { return nil, fmt.Errorf("couldn't find fortune database: %v", err) } } ``` We could also explicitly annotate RPC code `Internal` to the example above. ```go // Good: import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) func (*FortuneTeller) SuggestFortune(context.Context, *pb.SuggestionRequest) (*pb.SuggestionResponse, error) { // ... if err != nil { // Or use fmt.Errorf with the %w verb if deliberately wrapping an // error which the caller is meant to unwrap. return nil, status.Errorf(codes.Internal, "couldn't find fortune database", status.ErrInternal) } } ``` 1. **`%w` (wrap) for programmatic inspection and error chaining** The `%w` verb is specifically designed for error wrapping. It creates a new error that provides an `Unwrap()` method, allowing callers to programmatically inspect the error chain using `errors.Is` and `errors.As`. Examples to use `%w`: * Adding context while preserving the original error for programmatic inspection: This is the primary use case within helpers of your application. You want to enrich an error with additional context (e.g., what operation was being performed when it failed) but still allow the caller to check if the underlying error is a specific sentinel error or type. ```go // Good: func (s *Server) internalFunction(ctx context.Context) error { // ... if err != nil { return fmt.Errorf("couldn't find remote file: %w", err) } } ``` This allows a higher-level function to do `errors.Is(err, fs.ErrNotExist)` if the underlying error was `fs.ErrNotExist`, even though it's wrapped. At points where your system interacts with external systems like RPC, IPC, or storage, it's often better to translate domain-specific errors into a standardized error space (e.g., gRPC status codes) rather than simply wrapping the raw underlying error with `%w`. The client typically doesn't care about the exact internal file system error; they care about the canonical result (e.g., `Internal`, `NotFound`, `PermissionDenied`). * When you explicitly document and test the underlying errors you expose: If your package's API guarantees that certain underlying errors can be unwrapped and checked by callers (e.g., "this function might return `ErrInvalidConfig` wrapped within a more general error"), then `%w` is appropriate. This forms part of your package's contract. See also: * [Error Documentation Conventions](#documentation-conventions-errors) * [Blog post on error wrapping](https://blog.golang.org/go1.13-errors) <a id="error-percent-w"></a> ### Placement of %w in errors Prefer to place `%w` at the end of an error string *if* you are to use [error wrapping](https://go.dev/blog/go1.13-errors) with the `%w` formatting verb. Errors can be wrapped with the `%w` verb, or by placing them in a [structured error](https://google.github.io/styleguide/go/index.html#gotip) that implements `Unwrap() error` (ex: [`fs.PathError`](https://pkg.go.dev/io/fs#PathError)). Wrapped errors form error chains: each new layer of wrapping adds a new entry to the front of the error chain. The error chain can be traversed with the `Unwrap() error` method. For example: ```go err1 := fmt.Errorf("err1") err2 := fmt.Errorf("err2: %w", err1) err3 := fmt.Errorf("err3: %w", err2) ``` This forms an error chain of the form, ```mermaid flowchart LR err3 == err3 wraps err2 ==> err2; err2 == err2 wraps err1 ==> err1; ``` Regardless of where the `%w` verb is placed, the error returned always represents the front of the error chain, and the `%w` is the next child. Similarly, `Unwrap() error` always traverses the error chain from newest to oldest error. Placement of the `%w` verb does, however, affect whether the error chain is printed newest to oldest, oldest to newest, or neither: ```go // Good: err1 := fmt.Errorf("err1") err2 := fmt.Errorf("err2: %w", err1) err3 := fmt.Errorf("err3: %w", err2) fmt.Println(err3) // err3: err2: err1 // err3 is a newest-to-oldest error chain, that prints newest-to-oldest. ``` ```go // Bad: err1 := fmt.Errorf("err1") err2 := fmt.Errorf("%w: err2", err1) err3 := fmt.Errorf("%w: err3", err2) fmt.Println(err3) // err1: err2: err3 // err3 is a newest-to-oldest error chain, that prints oldest-to-newest. ``` ```go // Bad: err1 := fmt.Errorf("err1") err2 := fmt.Errorf("err2-1 %w err2-2", err1) err3 := fmt.Errorf("err3-1 %w err3-2", err2) fmt.Println(err3) // err3-1 err2-1 err1 err2-2 err3-2 // err3 is a newest-to-oldest error chain, that neither prints newest-to-oldest // nor oldest-to-newest. ``` Therefore, in order for error text to mirror error chain structure, prefer placing the `%w` verb at the end with the form `[...]: %w`. <a id="error-percent-w-sentinel-placement"></a> #### Sentinel error placement An exception to this rule is when wrapping sentinel errors. A sentinel error is an error that serves as a primary categorization of a failure. This helps observers quickly understand the nature of a failure (such as "not found" or "invalid argument") without having to parse the entire error message. Identifying that error type as early as possible in the error string is beneficial. Examples of sentinel errors include os errors (e.g., [`os.ErrInvalid`]) and package-level errors. In these cases, placing the `%w` verb at the beginning of the error string can improve readability by immediately identifying the category of the error. ```go // Good: package parser var ErrParse = fmt.Errorf("parse error") // This is another package error that could be returned. var ErrParseInvalidHeader = fmt.Errorf("%w: invalid header", ErrParse) func parseHeader() error { err := checkHeader() return fmt.Errorf("%w: invalid character in header: %v", ErrParseInvalidHeader, err) } err := fmt.Errorf("%w: couldn't find fortune database: %v", ErrInternal, err) ``` Placing the status at the beginning ensures that the most relevant categorical information is most prominent. ```go // Bad: package parser var ErrParse = fmt.Errorf("parse error") // This is another package error that could be returned. var ErrParseInvalidHeader = fmt.Errorf("%w: invalid header", ErrParse) func parseHeader() error { err := checkHeader() return fmt.Errorf("invalid character in header: %v: %w", err, ErrParseInvalidHeader) } var ErrInternal = status.Error(codes.Internal, "internal") err2 := fmt.Errorf("couldn't find fortune database: %v: %w", err, ErrInternal) ``` When you place it at the end, it makes it harder to identify the error category when reading the error text, as it's buried in the specific error details. [`os.ErrInvalid`]: https://pkg.go.dev/os#ErrInvalid See also: * [Go Tip #48: Error Sentinel Values] * [Go Tip #106: Error Naming Conventions] [commentary]: decisions#commentary [Go Tip #48: Error Sentinel Values]: https://google.github.io/styleguide/go/index.html#gotip [Go Tip #106: Error Naming Conventions]: https://google.github.io/styleguide/go/index.html#gotip <a id="error-logging"></a> ### Logging errors Functions sometimes need to tell an external system about an error without propagating it to their callers. Logging is an obvious choice here; but be conscious of what and how you log errors. * Like [good test failure messages], log messages should clearly express what went wrong and help the maintainer by including relevant information to diagnose the problem. * Avoid duplication. If you return an error, it's usually better not to log it yourself but rather let the caller handle it. The caller can choose to log the error, or perhaps rate-limit logging using [`rate.Sometimes`]. Other options include attempting recovery or even [stopping the program]. In any case, giving the caller control helps avoid logspam. The downside to this approach, however, is that any logging is written using the caller's line coordinates. * Be careful with [PII]. Many log sinks are not appropriate destinations for sensitive end-user information. * Use `log.Error` sparingly. ERROR level logging causes a flush and is more expensive than lower logging levels. This can have serious performance impact on your code. When deciding between error and warning levels, consider the best practice that messages at the error level should be actionable rather than "more serious" than a warning. * Inside Google, we have monitoring systems that can be set up for more effective alerting than writing to a log file and hoping someone notices it. This is similar but not identical to the standard library [package `expvar`]. [good test failure messages]: https://google.github.io/styleguide/go/decisions#useful-test-failures [stopping the program]: #checks-and-panics [`rate.Sometimes`]: https://pkg.go.dev/golang.org/x/time/rate#Sometimes [PII]: https://en.wikipedia.org/wiki/Personal_data [package `expvar`]: https://pkg.go.dev/expvar <a id="vlog"></a> #### Custom verbosity levels Use verbose logging ([`log.V`]) to your advantage. Verbose logging can be useful for development and tracing. Establishing a convention around verbosity levels can be helpful. For example: * Write a small amount of extra information at `V(1)` * Trace more information in `V(2)` * Dump large internal states in `V(3)` To minimize the cost of verbose logging, you should ensure not to accidentally call expensive functions even when `log.V` is turned off. `log.V` offers two APIs. The more convenient one carries the risk of this accidental expense. When in doubt, use the slightly more verbose style. ```go // Good: for _, sql := range queries { log.V(1).Infof("Handling %v", sql) if log.V(2) { log.Infof("Handling %v", sql.Explain()) } sql.Run(...) } ``` ```go // Bad: // sql.Explain called even when this log is not printed. log.V(2).Infof("Handling %v", sql.Explain()) ``` [`log.V`]: https://pkg.go.dev/github.com/golang/glog#V <a id="program-init"></a> ### Program initialization Program initialization errors (such as bad flags and configuration) should be propagated upward to `main`, which should call `log.Exit` with an error that explains how to fix the error. In these cases, `log.Fatal` should not generally be used, because a stack trace that points at the check is not likely to be as useful as a human-generated, actionable message. <a id="checks-and-panics"></a> ### Program checks and panics As stated in the [decision against panics], standard error handling should be structured around error return values. Libraries should prefer returning an error to the caller rather than aborting the program, especially for transient errors. It is occasionally necessary to perform consistency checks on an invariant and terminate the program if it is violated. In general, this is only done when a failure of the invariant check means that the internal state has become unrecoverable. The most reliable way to do this in the Google codebase is to call `log.Fatal`. Using `panic` in these cases is not reliable, because it is possible for deferred functions to deadlock or further corrupt internal or external state. Similarly, resist the temptation to recover panics to avoid crashes, as doing so can result in propagating a corrupted state. The further you are from the panic, the less you know about the state of the program, which could be holding locks or other resources. The program can then develop other unexpected failure modes that can make the problem even more difficult to diagnose. Instead of trying to handle unexpected panics in code, use monitoring tools to surface unexpected failures and fix related bugs with a high priority. **Note:** The standard [`net/http` server] violates this advice and recovers panics from request handlers. Consensus among experienced Go engineers is that this was a historical mistake. If you sample server logs from application servers in other languages, it is common to find large stacktraces that are left unhandled. Avoid this pitfall in your servers. [decision against panics]: https://google.github.io/styleguide/go/decisions#dont-panic [`net/http` server]: https://pkg.go.dev/net/http#Server <a id="when-to-panic"></a> ### When to panic The standard library panics on API misuse. For example, [`reflect`] issues a panic in many cases where a value is accessed in a way that suggests it was misinterpreted. This is analogous to the panics on core language bugs such as accessing an element of a slice that is out of bounds. Code review and tests should discover such bugs, which are not expected to appear in production code. These panics act as invariant checks that do not depend on a library, as the standard library does not have access to the [levelled `log`] package that the Google codebase uses. [`reflect`]: https://pkg.go.dev/reflect [levelled `log`]: decisions#logging Another case in which panics can be useful, though uncommon, is as an internal implementation detail of a package which always has a matching recover in the callchain. Parsers and similar deeply nested, tightly coupled internal function groups can benefit from this design, where plumbing error returns adds complexity without value. The key attribute of this design is that these **panics are never allowed to escape across package boundaries** and do not form part of the package's API. This is typically accomplished with a top-level deferred function that uses `recover` to translate a propagated panic into a returned error at the public API boundary. It requires the code that panics and recovers to distinguish between panics that the code raises itself and those that it doesn't: ```go // Good: type syntaxError struct { msg string } func parseInt(in string) int { n, err := strconv.Atoi(in) if err != nil { panic(&syntaxError{"not a valid integer"}) } } func Parse(in string) (_ *Node, err error) { defer func() { if p := recover(); p != nil { sErr, ok := p.(*syntaxError) if !ok { panic(p) // Propagate the panic since it is outside our code's domain. } err = fmt.Errorf("syntax error: %v", sErr.msg) } }() ... // Parse input calling parseInt internally to parse integers } ``` > **Warning:** Code employing this pattern must take care to manage any > resources associated with the code run in such defer-managed sections (e.g., > close, free, or unlock). > > See: [Go Tip #81: Avoiding Resource Leaks in API Design] Panic is also used when the compiler cannot identify unreachable code, for example when using a function like `log.Fatal` that will not return: ```go // Good: func answer(i int) string { switch i { case 42: return "yup" case 54: return "base 13, huh" default: log.Fatalf("Sorry, %d is not the answer.", i) panic("unreachable") } } ``` [Do not call `log` functions before flags have been parsed.](https://pkg.go.dev/github.com/golang/glog#pkg-overview) If you must die in a package initialization function (an `init` or a ["must" function](decisions#must-functions)), a panic is acceptable in place of the fatal logging call. See also: * [Handling panics](https://go.dev/ref/spec#Handling_panics) and [Run-time Panics](https://go.dev/ref/spec#Run_time_panics) in the language specification * [Defer, Panic, and Recover](https://go.dev/blog/defer-panic-and-recover) * [On the uses and misuses of panics in Go](https://eli.thegreenplace.net/2018/on-the-uses-and-misuses-of-panics-in-go/) [Go Tip #81: Avoiding Resource Leaks in API Design]: https://google.github.io/styleguide/go/index.html#gotip <a id="documentation"></a> ## Documentation <a id="documentation-conventions"></a> ### Conventions This section augments the decisions document's [commentary] section. Go code that is documented in familiar style is easier to read and less likely to be misused than something misdocumented or not documented at all. Runnable [examples] show up in Godoc and Code Search and are an excellent way of explaining how to use your code. [examples]: decisions#examples <a id="documentation-conventions-params"></a> #### Parameters and configuration Not every parameter must be enumerated in the documentation. This applies to: * function and method parameters * struct fields * APIs for options Document the error-prone or non-obvious fields and parameters by saying why they are interesting. In the following snippet, the highlighted commentary adds little useful information to the reader: ```go // Bad: // Sprintf formats according to a format specifier and returns the resulting // string. // // format is the format, and data is the interpolation data. func Sprintf(format string, data ...any) string ``` However, this snippet demonstrates a code scenario similar to the previous where the commentary instead states something non-obvious or materially helpful to the reader: ```go // Good: // Sprintf formats according to a format specifier and returns the resulting // string. // // The provided data is used to interpolate the format string. If the data does // not match the expected format verbs or the amount of data does not satisfy // the format specification, the function will inline warnings about formatting // errors into the output string as described by the Format errors section // above. func Sprintf(format string, data ...any) string ``` Consider your likely audience in choosing what to document and at what depth. Maintainers, newcomers to the team, external users, and even yourself six months in the future may appreciate slightly different information from what is on your mind when you first come to write your docs. See also: * [GoTip #41: Identify Function Call Parameters] * [GoTip #51: Patterns for Configuration] [commentary]: decisions#commentary [GoTip #41: Identify Function Call Parameters]: https://google.github.io/styleguide/go/index.html#gotip [GoTip #51: Patterns for Configuration]: https://google.github.io/styleguide/go/index.html#gotip <a id="documentation-conventions-contexts"></a> #### Contexts It is implied that the cancellation of a context argument interrupts the function it is provided to. If the function can return an error, conventionally it is `ctx.Err()`. This fact does not need to be restated: ```go // Bad: // Run executes the worker's run loop. // // The method will process work until the context is cancelled and accordingly // returns an error. func (Worker) Run(ctx context.Context) error ``` Because that is implied, the following is better: ```go // Good: // Run executes the worker's run loop. func (Worker) Run(ctx context.Context) error ``` Where context behavior is different or non-obvious, it should be expressly documented if any of the following are true. * The function returns an error other than `ctx.Err()` when the context is cancelled: ```go // Good: // Run executes the worker's run loop. // // If the context is cancelled, Run returns a nil error. func (Worker) Run(ctx context.Context) error ``` * The function has other mechanisms that may interrupt it or affect lifetime: ```go // Good: // Run executes the worker's run loop. // // Run processes work until the context is cancelled or Stop is called. // Context cancellation is handled asynchronously internally: run may return // before all work has stopped. The Stop method is synchronous and waits // until all operations from the run loop finish. Use Stop for graceful // shutdown. func (Worker) Run(ctx context.Context) error func (Worker) Stop() ``` * The function has special expectations about context lifetime, lineage, or attached values: ```go // Good: // NewReceiver starts receiving messages sent to the specified queue. // The context should not have a deadline. func NewReceiver(ctx context.Context) *Receiver // Principal returns a human-readable name of the party who made the call. // The context must have a value attached to it from security.NewContext. func Principal(ctx context.Context) (name string, ok bool) ``` **Warning:** Avoid designing APIs that make such demands (like contexts not having deadlines) from their callers. The above is only an example of how to document this if it cannot be avoided, not an endorsement of the pattern. <a id="documentation-conventions-concurrency"></a> #### Concurrency Go users assume that conceptually read-only operations are safe for concurrent use and do not require extra synchronization. The extra remark about concurrency can safely be removed in this Godoc: ```go // Len returns the number of bytes of the unread portion of the buffer; // b.Len() == len(b.Bytes()). // // It is safe to be called concurrently by multiple goroutines. func (*Buffer) Len() int ``` Mutating operations, however, are not assumed to be safe for concurrent use and require the user to consider synchronization. Similarly, the extra remark about concurrency can safely be removed here: ```go // Grow grows the buffer's capacity. // // It is not safe to be called concurrently by multiple goroutines. func (*Buffer) Grow(n int) ``` Documentation is strongly encouraged if any of the following are true. * It is unclear whether the operation is read-only or mutating: ```go // Good: package lrucache // Lookup returns the data associated with the key from the cache. // // This operation is not safe for concurrent use. func (*Cache) Lookup(key string) (data []byte, ok bool) ``` Why? A cache hit when looking up the key mutate a LRU cache internally. How this is implemented may not be obvious to all readers. * Synchronization is provided by the API: ```go // Good: package fortune_go_proto // NewFortuneTellerClient returns an *rpc.Client for the FortuneTeller service. // It is safe for simultaneous use by multiple goroutines. func NewFortuneTellerClient(cc *rpc.ClientConn) *FortuneTellerClient ``` Why? Stubby provides synchronization. **Note:** If the API is a type and the API provides synchronization in entirety, conventionally only the type definition documents the semantics. * The API consumes user-implemented types of interfaces, and the interface's consumer has particular concurrency requirements: ```go // Good: package health // A Watcher reports the health of some entity (usually a backend service). // // Watcher methods are safe for simultaneous use by multiple goroutines. type Watcher interface { // Watch sends true on the passed-in channel when the Watcher's // status has changed. Watch(changed chan<- bool) (unwatch func()) // Health returns nil if the entity being watched is healthy, or a // non-nil error explaining why the entity is not healthy. Health() error } ``` Why? Whether an API is safe for use by multiple goroutines is part of its contract. <a id="documentation-conventions-cleanup"></a> #### Cleanup Document any explicit cleanup requirements that the API has. Otherwise, callers won't use the API correctly, leading to resource leaks and other possible bugs. Call out cleanups that are up to the caller: ```go // Good: // NewTicker returns a new Ticker containing a channel that will send the // current time on the channel after each tick. // // Call Stop to release the Ticker's associated resources when done. func NewTicker(d Duration) *Ticker func (*Ticker) Stop() ``` If it is potentially unclear how to clean up the resources, explain how: ```go // Good: // Get issues a GET to the specified URL. // // When err is nil, resp always contains a non-nil resp.Body. // Caller should close resp.Body when done reading from it. // // resp, err := http.Get("http://example.com/") // if err != nil { // // handle error // } // defer resp.Body.Close() // body, err := io.ReadAll(resp.Body) func (c *Client) Get(url string) (resp *Response, err error) ``` See also: * [GoTip #110: Don’t Mix Exit With Defer] [GoTip #110: Don’t Mix Exit With Defer]: https://google.github.io/styleguide/go/index.html#gotip <a id="documentation-conventions-errors"></a> #### Errors Document significant error sentinel values or error types that your functions return to callers so that callers can anticipate what types of conditions they can handle in their code. ```go // Good: package os // Read reads up to len(b) bytes from the File and stores them in b. It returns // the number of bytes read and any error encountered. // // At end of file, Read returns 0, io.EOF. func (*File) Read(b []byte) (n int, err error) { ``` When a function returns a specific error type, correctly note whether the error is a pointer receiver or not: ```go // Good: package os type PathError struct { Op string Path string Err error } // Chdir changes the current working directory to the named directory. // // If there is an error, it will be of type *PathError. func Chdir(dir string) error { ``` Documenting whether the values returned are pointer receivers enables callers to correctly compare the errors using [`errors.Is`], [`errors.As`], and [`package cmp`]. This is because a non-pointer value is not equivalent to a pointer value. **Note:** In the `Chdir` example, the return type is written as `error` rather than `*PathError` due to [how nil interface values work](https://go.dev/doc/faq#nil_error). Document overall error conventions in the [package's documentation](decisions#package-comments) when the behavior is applicable to most errors found in the package: ```go // Good: // Package os provides a platform-independent interface to operating system // functionality. // // Often, more information is available within the error. For example, if a // call that takes a file name fails, such as Open or Stat, the error will // include the failing file name when printed and will be of type *PathError, // which may be unpacked for more information. package os ``` Thoughtful application of these approaches can add [extra information to errors](#error-extra-info) without much effort and help callers avoid adding redundant annotations. See also: * [Go Tip #106: Error Naming Conventions](https://google.github.io/styleguide/go/index.html#gotip) * [Go Tip #89: When to Use Canonical Status Codes as Errors](https://google.github.io/styleguide/go/index.html#gotip) <a id="documentation-preview"></a> ### Preview Go features a [documentation server](https://pkg.go.dev/golang.org/x/pkgsite/cmd/pkgsite). It is recommended to preview the documentation your code produces both before and during the code review process. This helps to validate that the [godoc formatting] is rendered correctly. [godoc formatting]: #godoc-formatting <a id="godoc-formatting"></a> ### Godoc formatting [Godoc] provides some specific syntax to [format documentation]. * A blank line is required to separate paragraphs: ```go // Good: // LoadConfig reads a configuration out of the named file. // // See some/shortlink for config file format details. ``` * Test files can contain [runnable examples] that appear attached to the corresponding documentation in godoc: ```go // Good: func ExampleConfig_WriteTo() { cfg := &Config{ Name: "example", } if err := cfg.WriteTo(os.Stdout); err != nil { log.Exitf("Failed to write config: %s", err) } // Output: // { // "name": "example" // } } ``` * Indenting lines by an additional two spaces formats them verbatim: ```go // Good: // Update runs the function in an atomic transaction. // // This is typically used with an anonymous TransactionFunc: // // if err := db.Update(func(state *State) { state.Foo = bar }); err != nil { // //... // } ``` Note, however, that it can often be more appropriate to put code in a runnable example instead of including it in a comment. This verbatim formatting can be leveraged for formatting that is not native to godoc, such as lists and tables: ```go // Good: // LoadConfig reads a configuration out of the named file. // // LoadConfig treats the following keys in special ways: // "import" will make this configuration inherit from the named file. // "env" if present will be populated with the system environment. ``` * A single line that begins with a capital letter, contains no punctuation except parentheses and commas, and is followed by another paragraph, is formatted as a header: ```go // Good: // The following line is formatted as a heading. // // Using headings // // Headings come with autogenerated anchor tags for easy linking. ``` [Godoc]: https://pkg.go.dev/ [format documentation]: https://go.dev/doc/comment [runnable examples]: decisions#examples <a id="signal-boost"></a> ### Signal boosting Sometimes a line of code looks like something common, but actually isn't. One of the best examples of this is an `err == nil` check (since `err != nil` is much more common). The following two conditional checks are hard to distinguish: ```go // Good: if err := doSomething(); err != nil { // ... } ``` ```go // Bad: if err := doSomething(); err == nil { // ... } ``` You can instead "boost" the signal of the conditional by adding a comment: ```go // Good: if err := doSomething(); err == nil { // if NO error // ... } ``` The comment draws attention to the difference in the conditional. <a id="vardecls"></a> ## Variable declarations <a id="vardeclinitialization"></a> ### Initialization For consistency, prefer `:=` over `var` when initializing a new variable with a non-zero value. ```go // Good: i := 42 ``` ```go // Bad: var i = 42 ``` <a id="vardeclzero"></a> ### Declaring variables with zero values The following declarations use the [zero value]: ```go // Good: var ( coords Point magic [4]byte primes []int ) ``` [zero value]: https://golang.org/ref/spec#The_zero_value You should declare values using the zero value when you want to convey an empty value that **is ready for later use**. Using composite literals with explicit initialization can be clunky: ```go // Bad: var ( coords = Point{X: 0, Y: 0} magic = [4]byte{0, 0, 0, 0} primes = []int(nil) ) ``` A common application of zero value declaration is when using a variable as the output when unmarshalling: ```go // Good: var coords Point if err := json.Unmarshal(data, &coords); err != nil { ``` It is also okay to use the zero value in the following form when you need a variable of a pointer type: ```go // Good: msg := new(pb.Bar) // or "&pb.Bar{}" if err := proto.Unmarshal(data, msg); err != nil { ``` If you need a lock or other field that [must not be copied](decisions#copying) in your struct, you can make it a value type to take advantage of zero value initialization. It does mean that the containing type must now be passed via a pointer and not a value. Methods on the type must take pointer receivers. ```go // Good: type Counter struct { // This field does not have to be "*sync.Mutex". However, // users must now pass *Counter objects between themselves, not Counter. mu sync.Mutex data map[string]int64 } // Note this must be a pointer receiver to prevent copying. func (c *Counter) IncrementBy(name string, n int64) ``` It's acceptable to use value types for local variables of composites (such as structs and arrays) even if they contain such uncopyable fields. However, if the composite is returned by the function, or if all accesses to it end up needing to take an address anyway, prefer declaring the variable as a pointer type at the outset. Similarly, protobuf messages should be declared as pointer types. ```go // Good: func NewCounter(name string) *Counter { c := new(Counter) // "&Counter{}" is also fine. registerCounter(name, c) return c } var msg = new(pb.Bar) // or "&pb.Bar{}". ``` This is because `*pb.Something` satisfies [`proto.Message`] while `pb.Something` does not. ```go // Bad: func NewCounter(name string) *Counter { var c Counter registerCounter(name, &c) return &c } var msg = pb.Bar{} ``` [`proto.Message`]: https://pkg.go.dev/google.golang.org/protobuf/proto#Message > **Important:** Map types must be explicitly initialized before they can be > modified. However, reading from zero-value maps is perfectly fine. > > For map and slice types, if the code is particularly performance sensitive and > if you know the sizes in advance, see the [size hints](#vardeclsize) section. <a id="vardeclcomposite"></a> ### Composite literals The following are [composite literal] declarations: ```go // Good: var ( coords = Point{X: x, Y: y} magic = [4]byte{'I', 'W', 'A', 'D'} primes = []int{2, 3, 5, 7, 11} captains = map[string]string{"Kirk": "James Tiberius", "Picard": "Jean-Luc"} ) ``` You should declare a value using a composite literal when you know initial elements or members. In contrast, using composite literals to declare empty or memberless values can be visually noisy compared to [zero-value initialization](#vardeclzero). When you need a pointer to a zero value, you have two options: empty composite literals and `new`. Both are fine, but the `new` keyword can serve to remind the reader that if a non-zero value were needed, a composite literal wouldn't work: ```go // Good: var ( buf = new(bytes.Buffer) // non-empty Buffers are initialized with constructors. msg = new(pb.Message) // non-empty proto messages are initialized with builders or by setting fields one by one. ) ``` [composite literal]: https://golang.org/ref/spec#Composite_literals <a id="vardeclsize"></a> ### Size hints The following are declarations that take advantage of size hints in order to preallocate capacity: ```go // Good: var ( // Preferred buffer size for target filesystem: st_blksize. buf = make([]byte, 131072) // Typically process up to 8-10 elements per run (16 is a safe assumption). q = make([]Node, 0, 16) // Each shard processes shardSize (typically 32000+) elements. seen = make(map[string]bool, shardSize) ) ``` Size hints and preallocation are important steps **when combined with empirical analysis of the code and its integrations**, to create performance-sensitive and resource-efficient code. Most code does not need a size hint or preallocation, and can allow the runtime to grow the slice or map as necessary. It is acceptable to preallocate when the final size is known (e.g. when converting between a map and a slice) but this is not a readability requirement, and may not be worth the clutter in small cases. **Warning:** Preallocating more memory than you need can waste memory in the fleet or even harm performance. When in doubt, see [GoTip #3: Benchmarking Go Code] and default to a [zero initialization](#vardeclzero) or a [composite literal declaration](#vardeclcomposite). [GoTip #3: Benchmarking Go Code]: https://google.github.io/styleguide/go/index.html#gotip <a id="decl-chan"></a> ### Channel direction Specify [channel direction] where possible. ```go // Good: // sum computes the sum of all of the values. It reads from the channel until // the channel is closed. func sum(values <-chan int) int { // ... } ``` This prevents casual programming errors that are possible without specification: ```go // Bad: func sum(values chan int) (out int) { for v := range values { out += v } // values must already be closed for this code to be reachable, which means // a second close triggers a panic. close(values) } ``` When the direction is specified, the compiler catches simple errors like this. It also helps to convey a measure of ownership to the type. See also Bryan Mills' talk "Rethinking Classical Concurrency Patterns": [slides][rethinking-concurrency-slides] [video][rethinking-concurrency-video]. [rethinking-concurrency-slides]: https://drive.google.com/file/d/1nPdvhB0PutEJzdCq5ms6UI58dp50fcAN/view?usp=sharing [rethinking-concurrency-video]: https://www.youtube.com/watch?v=5zXAHh5tJqQ [channel direction]: https://go.dev/ref/spec#Channel_types <a id="funcargs"></a> ## Function argument lists Don't let the signature of a function get too long. As more parameters are added to a function, the role of individual parameters becomes less clear, and adjacent parameters of the same type become easier to confuse. Functions with large numbers of arguments are less memorable and more difficult to read at the call-site. When designing an API, consider splitting a highly configurable function whose signature is growing complex into several simpler ones. These can share an (unexported) implementation if necessary. Where a function requires many inputs, consider introducing an [option struct] for some of the arguments or employing the more advanced [variadic options] technique. The primary consideration for which strategy to choose should be how the function call looks across all expected use cases. The recommendations below primarily apply to exported APIs, which are held to a higher standard than unexported ones. These techniques may be unnecessary for your use case. Use your judgment, and balance the principles of [clarity] and [least mechanism]. See also: [Go Tip #24: Use Case-Specific Constructions](https://google.github.io/styleguide/go/index.html#gotip) [option struct]: #option-structure [variadic options]: #variadic-options [clarity]: guide#clarity [least mechanism]: guide#least-mechanism <a id="option-structure"></a> ### Option structure An option structure is a struct type that collects some or all of the arguments of a function or method, that is then passed as the last argument to the function or method. (The struct should be exported only if it is used in an exported function.) Using an option structure has a number of benefits: * The struct literal includes both fields and values for each argument, which makes them self-documenting and harder to swap. * Irrelevant or "default" fields can be omitted. * Callers can share the option struct and write helpers to operate on it. * Structs provide cleaner per-field documentation than function arguments. * Option structs can grow over time without impacting call-sites. Here is an example of a function that could be improved: ```go // Bad: func EnableReplication(ctx context.Context, config *replicator.Config, primaryRegions, readonlyRegions []string, replicateExisting, overwritePolicies bool, replicationInterval time.Duration, copyWorkers int, healthWatcher health.Watcher) { // ... } ``` The function above could be rewritten with an option structure as follows: ```go // Good: type ReplicationOptions struct { Config *replicator.Config PrimaryRegions []string ReadonlyRegions []string ReplicateExisting bool OverwritePolicies bool ReplicationInterval time.Duration CopyWorkers int HealthWatcher health.Watcher } func EnableReplication(ctx context.Context, opts ReplicationOptions) { // ... } ``` The function can then be called in a different package: ```go // Good: func foo(ctx context.Context) { // Complex call: storage.EnableReplication(ctx, storage.ReplicationOptions{ Config: config, PrimaryRegions: []string{"us-east1", "us-central2", "us-west3"}, ReadonlyRegions: []string{"us-east5", "us-central6"}, OverwritePolicies: true, ReplicationInterval: 1 * time.Hour, CopyWorkers: 100, HealthWatcher: watcher, }) // Simple call: storage.EnableReplication(ctx, storage.ReplicationOptions{ Config: config, PrimaryRegions: []string{"us-east1", "us-central2", "us-west3"}, }) } ``` **Note:** [Contexts are never included in option structs](decisions#contexts). This option is often preferred when some of the following apply: * All callers need to specify one or more of the options. * A large number of callers need to provide many options. * The options are shared between multiple functions that the user will call. <a id="variadic-options"></a> ### Variadic options Using variadic options, exported functions are created which return closures that can be passed to the [variadic (`...`) parameter] of a function. The function takes as its parameters the values of the option (if any), and the returned closure accepts a mutable reference (usually a pointer to a struct type) that will be updated based on the inputs. [variadic (`...`) parameter]: https://golang.org/ref/spec#Passing_arguments_to_..._parameters Using variadic options can provide a number of benefits: * Options take no space at a call-site when no configuration is needed. * Options are still values, so callers can share them, write helpers, and accumulate them. * Options can accept multiple parameters (e.g. `cartesian.Translate(dx, dy int) TransformOption`). * The option functions can return a named type to group options together in godoc. * Packages can allow (or prevent) third-party packages to define (or from defining) their own options. **Note:** Using variadic options requires a substantial amount of additional code (see the following example), so it should only be used when the advantages outweigh the overhead. Here is an example of a function that could be improved: ```go // Bad: func EnableReplication(ctx context.Context, config *placer.Config, primaryCells, readonlyCells []string, replicateExisting, overwritePolicies bool, replicationInterval time.Duration, copyWorkers int, healthWatcher health.Watcher) { ... } ``` The example above could be rewritten with variadic options as follows: ```go // Good: type replicationOptions struct { readonlyCells []string replicateExisting bool overwritePolicies bool replicationInterval time.Duration copyWorkers int healthWatcher health.Watcher } // A ReplicationOption configures EnableReplication. type ReplicationOption func(*replicationOptions) // ReadonlyCells adds additional cells that should additionally // contain read-only replicas of the data. // // Passing this option multiple times will add additional // read-only cells. // // Default: none func ReadonlyCells(cells ...string) ReplicationOption { return func(opts *replicationOptions) { opts.readonlyCells = append(opts.readonlyCells, cells...) } } // ReplicateExisting controls whether files that already exist in the // primary cells will be replicated. Otherwise, only newly-added // files will be candidates for replication. // // Passing this option again will overwrite earlier values. // // Default: false func ReplicateExisting(enabled bool) ReplicationOption { return func(opts *replicationOptions) { opts.replicateExisting = enabled } } // ... other options ... // DefaultReplicationOptions control the default values before // applying options passed to EnableReplication. var DefaultReplicationOptions = []ReplicationOption{ OverwritePolicies(true), ReplicationInterval(12 * time.Hour), CopyWorkers(10), } func EnableReplication(ctx context.Context, config *placer.Config, primaryCells []string, opts ...ReplicationOption) { var options replicationOptions for _, opt := range DefaultReplicationOptions { opt(&options) } for _, opt := range opts { opt(&options) } } ``` The function can then be called in a different package: ```go // Good: func foo(ctx context.Context) { // Complex call: storage.EnableReplication(ctx, config, []string{"po", "is", "ea"}, storage.ReadonlyCells("ix", "gg"), storage.OverwritePolicies(true), storage.ReplicationInterval(1*time.Hour), storage.CopyWorkers(100), storage.HealthWatcher(watcher), ) // Simple call: storage.EnableReplication(ctx, config, []string{"po", "is", "ea"}) } ``` Prefer this option when many of the following apply: * Most callers will not need to specify any options. * Most options are used infrequently. * There are a large number of options. * Options require arguments. * Options could fail or be set incorrectly (in which case the option function returns an `error`). * Options require a lot of documentation that can be hard to fit in a struct. * Users or other packages can provide custom options. Options in this style should accept parameters rather than using presence to signal their value; the latter can make dynamic composition of arguments much more difficult. For example, binary settings should accept a boolean (e.g. `rpc.FailFast(enable bool)` is preferable to `rpc.EnableFailFast()`). An enumerated option should accept an enumerated constant (e.g. `log.Format(log.Capacitor)` is preferable to `log.CapacitorFormat()`). The alternative makes it much more difficult for users who must programmatically choose which options to pass; such users are forced to change the actual composition of the parameters rather than simply changing the arguments to the options. Don't assume that all users will know the full set of options statically. In general, options should be processed in order. If there is a conflict or if a non-cumulative option is passed multiple times, the last argument should win. The parameter to the option function is generally unexported in this pattern, to restrict the options to being defined only within the package itself. This is a good default, though there may be times when it is appropriate to allow other packages to define options. See [Rob Pike's original blog post] and [Dave Cheney's talk] for a more in-depth look at how these options can be used. [Rob Pike's original blog post]: http://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html [Dave Cheney's talk]: https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis <a id="complex-clis"></a> ## Complex command-line interfaces Some programs wish to present users with a rich command-line interface that includes sub-commands. For example, `kubectl create`, `kubectl run`, and many other sub-commands are all provided by the program `kubectl`. There are at least the following libraries in common use for achieving this. If you don't have a preference or other considerations are equal, [subcommands] is recommended, since it is the simplest and is easy to use correctly. However, if you need different features that it doesn't provide, pick one of the other options. * **[cobra]** * Flag convention: getopt * Common outside the Google codebase. * Many extra features. * Pitfalls in usage (see below). * **[subcommands]** * Flag convention: Go * Simple and easy to use correctly. * Recommended if you don't need extra features. **Warning**: cobra command functions should use `cmd.Context()` to obtain a context rather than creating their own root context with `context.Background`. Code that uses the subcommands package already receives the correct context as a function parameter. You are not required to place each subcommand in a separate package, and it is often not necessary to do so. Apply the same considerations about package boundaries as in any Go codebase. If your code can be used both as a library and as a binary, it is usually beneficial to separate the CLI code and the library, making the CLI just one more of its clients. (This is not specific to CLIs that have subcommands, but is mentioned here because it is a common place where it comes up.) [subcommands]: https://pkg.go.dev/github.com/google/subcommands [cobra]: https://pkg.go.dev/github.com/spf13/cobra <a id="tests"></a> ## Tests <a id="test-functions"></a> ### Leave testing to the `Test` function <!-- Note to maintainers: This section overlaps with decisions#assert and decisions#mark-test-helpers. The point is not to repeat information, but to have one place that summarizes the distinction that newcomers to the language often wonder about. --> Go distinguishes between "test helpers" and "assertion helpers": * **Test helpers** are functions that do setup or cleanup tasks. All failures that occur in test helpers are expected to be failures of the environment (not from the code under test) — for example when a test database cannot be started because there are no more free ports on this machine. For functions like these, calling `t.Helper` is often appropriate to [mark them as a test helper]. See [error handling in test helpers] for more details. * **Assertion helpers** are functions that check the correctness of a system and fail the test if an expectation is not met. Assertion helpers are [not considered idiomatic] in Go. The purpose of a test is to report pass/fail conditions of the code under test. The ideal place to fail a test is within the `Test` function itself, as that ensures that [failure messages] and the test logic are clear. [mark them as a test helper]: decisions#mark-test-helpers [error handling in test helpers]: #test-helper-error-handling [not considered idiomatic]: decisions#assert [failure messages]: decisions#useful-test-failures As your testing code grows, it may become necessary to factor out some functionality to separate functions. Standard software engineering considerations still apply, as *test code is still code*. If the functionality does not interact with the testing framework, then all of the usual rules apply. When the common code interacts with the framework, however, some care must be taken to avoid common pitfalls that can lead to uninformative failure messages and unmaintainable tests. If many separate test cases require the same validation logic, arrange the test in one of the following ways instead of using assertion helpers or complex validation functions: * Inline the logic (both the validation and the failure) in the `Test` function, even if it is repetitive. This works best in simple cases. * If inputs are similar, consider unifying them into a [table-driven test] while keeping the logic inlined in the loop. This helps to avoid repetition while keeping the validation and failure in the `Test`. * If there are multiple callers who need the same validation function but table tests are not suitable (typically because the inputs are not simple enough or the validation is required as part of a sequence of operations), arrange the validation function so that it returns a value (typically an `error`) rather than taking a `testing.T` parameter and using it to fail the test. Use logic within the `Test` to decide whether to fail, and to provide [useful test failures]. You can also create test helpers to factor out common boilerplate setup code. The design outlined in the last point maintains orthogonality. For example, [package `cmp`] is not designed to fail tests, but rather to compare (and to diff) values. It therefore does not need to know about the context in which the comparison was made, since the caller can supply that. If your common testing code provides a `cmp.Transformer` for your data type, that can often be the simplest design. For other validations, consider returning an `error` value. ```go // Good: // polygonCmp returns a cmp.Option that equates s2 geometry objects up to // some small floating-point error. func polygonCmp() cmp.Option { return cmp.Options{ cmp.Transformer("polygon", func(p *s2.Polygon) []*s2.Loop { return p.Loops() }), cmp.Transformer("loop", func(l *s2.Loop) []s2.Point { return l.Vertices() }), cmpopts.EquateApprox(0.00000001, 0), cmpopts.EquateEmpty(), } } func TestFenceposts(t *testing.T) { // This is a test for a fictional function, Fenceposts, which draws a fence // around some Place object. The details are not important, except that // the result is some object that has s2 geometry (github.com/golang/geo/s2) got := Fencepost(tomsDiner, 1*meter) if diff := cmp.Diff(want, got, polygonCmp()); diff != "" { t.Errorf("Fencepost(tomsDiner, 1m) returned unexpected diff (-want+got):\n%v", diff) } } func FuzzFencepost(f *testing.F) { // Fuzz test (https://go.dev/doc/fuzz) for the same. f.Add(tomsDiner, 1*meter) f.Add(school, 3*meter) f.Fuzz(func(t *testing.T, geo Place, padding Length) { got := Fencepost(geo, padding) // Simple reference implementation: not used in prod, but easy to // reason about and therefore useful to check against in random tests. reference := slowFencepost(geo, padding) // In the fuzz test, inputs and outputs can be large so don't // bother with printing a diff. cmp.Equal is enough. if !cmp.Equal(got, reference, polygonCmp()) { t.Errorf("Fencepost returned wrong placement") } }) } ``` The `polygonCmp` function is agnostic about how it's called; it doesn't take a concrete input type nor does it police what to do in case two objects don't match. Therefore, more callers can make use of it. **Note:** There is an analogy between test helpers and plain library code. Code in libraries should usually [not panic] except in rare circumstances; code called from a test should not stop the test unless there is [no point in proceeding]. [table-driven test]: decisions#table-driven-tests [useful test failures]: decisions#useful-test-failures [package `cmp`]: https://pkg.go.dev/github.com/google/go-cmp/cmp [not panic]: decisions#dont-panic [no point in proceeding]: #t-fatal <a id="test-validation-apis"></a> ### Designing extensible validation APIs Most of the advice about testing in the style guide is about testing your own code. This section is about how to provide facilities for other people to test the code they write to ensure that it conforms to your library's requirements. <a id="test-validation-apis-what"></a> #### Acceptance testing Such testing is referred to as [acceptance testing]. The premise of this kind of testing is that the person using the test does not know every last detail of what goes on in the test; they just hand the inputs over to the testing facility to do the work. This can be thought of as a form of [inversion of control]. In a typical Go test, the test function controls the program flow, and the [no assert](decisions#assert) and [test functions](#test-functions) guidance encourages you to keep it that way. This section explains how to author support for these tests in a way that is consistent with Go style. Before diving into how, consider an example from [`io/fs`], excerpted below: ```go type FS interface { Open(name string) (File, error) } ``` While there exist well-known implementations of `fs.FS`, a Go developer may be expected to author one. To help validate the user-implemented `fs.FS` is correct, a generic library has been provided in [`testing/fstest`] called [`fstest.TestFS`]. This API treats the implementation as a blackbox to make sure it upholds the most basic parts of the `io/fs` contract. [acceptance testing]: https://en.wikipedia.org/wiki/Acceptance_testing [inversion of control]: https://en.wikipedia.org/wiki/Inversion_of_control [`io/fs`]: https://pkg.go.dev/io/fs [`testing/fstest`]: https://pkg.go.dev/testing/fstest [`fstest.TestFS`]: https://pkg.go.dev/testing/fstest#TestFS <a id="test-validation-apis-writing"></a> #### Writing an acceptance test Now that we know what an acceptance test is and why you might use one, let's explore building an acceptance test for `package chess`, a package used to simulate chess games. Users of `chess` are expected to implement the `chess.Player` interface. These implementations are the primary thing we will validate. Our acceptance test concerns itself with whether the player implementation makes legal moves, not whether the moves are smart. 1. Create a new package for the validation behavior, [customarily named](#naming-doubles-helper-package) by appending the word `test` to the package name (for example, `chesstest`). 1. Create the function that performs the validation by accepting the implementation under test as an argument and exercises it: ```go // ExercisePlayer tests a Player implementation in a single turn on a board. // The board itself is spot checked for sensibility and correctness. // // It returns a nil error if the player makes a correct move in the context // of the provided board. Otherwise ExercisePlayer returns one of this // package's errors to indicate how and why the player failed the // validation. func ExercisePlayer(b *chess.Board, p chess.Player) error ``` The test should note which invariants are broken and how. Your design can choose between two disciplines for failure reporting: * **Fail fast**: return an error as soon as the implementation violates an invariant. This is the simplest approach, and it works well if the acceptance test is expected to execute quickly. Simple error [sentinels] and [custom types] can be used easily here, which conversely makes testing the acceptance test easy. ```go for color, army := range b.Armies { // The king should never leave the board, because the game ends at // checkmate. if army.King == nil { return &MissingPieceError{Color: color, Piece: chess.King} } } ``` * **Aggregate all failures**: collect all failures, and report them all. This approach resembles the [keep going](decisions#keep-going) guidance in feel and may be preferable if the acceptance test is expected to execute slowly. How you aggregate the failures should be dictated by whether you want to give users the ability or yourself the ability to interrogate individual failures (for example, for you to test your acceptance test). Below demonstrates using a [custom error type][custom types] that [aggregates errors]: ```go var badMoves []error move := p.Move() if putsOwnKingIntoCheck(b, move) { badMoves = append(badMoves, PutsSelfIntoCheckError{Move: move}) } if len(badMoves) > 0 { return SimulationError{BadMoves: badMoves} } return nil ``` The acceptance test should honor the [keep going](decisions#keep-going) guidance by not calling `t.Fatal` unless the test detects a broken invariant in the system being exercised. For example, `t.Fatal` should be reserved for exceptional cases such as [setup failure](#test-helper-error-handling) as usual: ```go func ExerciseGame(t *testing.T, cfg *Config, p chess.Player) error { t.Helper() if cfg.Simulation == Modem { conn, err := modempool.Allocate() if err != nil { t.Fatalf("No modem for the opponent could be provisioned: %v", err) } t.Cleanup(func() { modempool.Return(conn) }) } // Run acceptance test (a whole game). } ``` This technique can help you create concise, canonical validations. But do not attempt to use it to bypass the [guidance on assertions](decisions#assert). The final product should be in a form similar to this for end users: ```go // Good: package deepblue_test import ( "chesstest" "deepblue" ) func TestAcceptance(t *testing.T) { player := deepblue.New() err := chesstest.ExerciseGame(t, chesstest.SimpleGame, player) if err != nil { t.Errorf("Deep Blue player failed acceptance test: %v", err) } } ``` [sentinels]: https://google.github.io/styleguide/go/index.html#gotip [custom types]: https://google.github.io/styleguide/go/index.html#gotip [aggregates errors]: https://google.github.io/styleguide/go/index.html#gotip <a id="use-real-transports"></a> ### Use real transports When testing component integrations, especially where HTTP or RPC are used as the underlying transport between the components, prefer using the real underlying transport to connect to the test version of the backend. For example, suppose the code you want to test (sometimes referred to as "system under test" or SUT) interacts with a backend that implements the [long running operations] API. To test your SUT, use a real [OperationsClient] that is connected to a [test double](https://abseil.io/resources/swe-book/html/ch13.html#basic_concepts) (e.g., a mock, stub, or fake) of the [OperationsServer]. [test double]: https://abseil.io/resources/swe-book/html/ch13.html#basic_concepts [long running operations]: https://pkg.go.dev/google.golang.org/genproto/googleapis/longrunning [OperationsClient]: https://pkg.go.dev/google.golang.org/genproto/googleapis/longrunning#OperationsClient [OperationsServer]: https://pkg.go.dev/google.golang.org/genproto/googleapis/longrunning#OperationsServer This is recommended over hand-implementing the client, due to the complexity of imitating client behavior correctly. By using the production client with a test-specific server, you ensure your test is using as much of the real code as possible. **Tip:** Where possible, use a testing library provided by the authors of the service under test. <a id="t-fatal"></a> ### `t.Error` vs. `t.Fatal` As discussed in [decisions](decisions#keep-going), tests should generally not abort at the first encountered problem. However, some situations require that the test not proceed. Calling `t.Fatal` is appropriate when some piece of test setup fails, especially in [test setup helpers], without which you cannot run the rest of the test. In a table-driven test, `t.Fatal` is appropriate for failures that set up the whole test function before the test loop. Failures that affect a single entry in the test table, which make it impossible to continue with that entry, should be reported as follows: * If you're not using `t.Run` subtests, use `t.Error` followed by a `continue` statement to move on to the next table entry. * If you're using subtests (and you're inside a call to `t.Run`), use `t.Fatal`, which ends the current subtest and allows your test case to progress to the next subtest. **Warning:** It is not always safe to call `t.Fatal` and similar functions. [More details here](#t-fatal-goroutine). [test setup helpers]: #test-helper-error-handling <a id="test-helper-error-handling"></a> ### Error handling in test helpers **Note:** This section discusses [test helpers] in the sense Go uses the term: functions that perform test setup and cleanup, not common assertion facilities. See the [test functions](#test-functions) section for more discussion. [test helpers]: decisions#mark-test-helpers Operations performed by a test helper sometimes fail. For example, setting up a directory with files involves I/O, which can fail. When test helpers fail, their failure often signifies that the test cannot continue, since a setup precondition failed. When this happens, prefer calling one of the `Fatal` functions in the helper: ```go // Good: func mustAddGameAssets(t *testing.T, dir string) { t.Helper() if err := os.WriteFile(path.Join(dir, "pak0.pak"), pak0, 0644); err != nil { t.Fatalf("Setup failed: could not write pak0 asset: %v", err) } if err := os.WriteFile(path.Join(dir, "pak1.pak"), pak1, 0644); err != nil { t.Fatalf("Setup failed: could not write pak1 asset: %v", err) } } ``` This keeps the calling side cleaner than if the helper were to return the error to the test itself: ```go // Bad: func addGameAssets(t *testing.T, dir string) error { t.Helper() if err := os.WriteFile(path.Join(d, "pak0.pak"), pak0, 0644); err != nil { return err } if err := os.WriteFile(path.Join(d, "pak1.pak"), pak1, 0644); err != nil { return err } return nil } ``` **Warning:** It is not always safe to call `t.Fatal` and similar functions. [More details](#t-fatal-goroutine) here. The failure message should include a description of what happened. This is important, as you may be providing a testing API to many users, especially as the number of error-producing steps in the helper increases. When the test fails, the user should know where, and why. **Tip:** Go 1.14 introduced a [`t.Cleanup`] function that can be used to register cleanup functions that run when your test completes. The function also works with test helpers. See [GoTip #4: Cleaning Up Your Tests](https://google.github.io/styleguide/go/index.html#gotip) for guidance on simplifying test helpers. The snippet below in a fictional file called `paint_test.go` demonstrates how `(*testing.T).Helper` influences failure reporting in a Go test: ```go package paint_test import ( "fmt" "testing" ) func paint(color string) error { return fmt.Errorf("no %q paint today", color) } func badSetup(t *testing.T) { // This should call t.Helper, but doesn't. if err := paint("taupe"); err != nil { t.Fatalf("Could not paint the house under test: %v", err) // line 15 } } func goodSetup(t *testing.T) { t.Helper() if err := paint("lilac"); err != nil { t.Fatalf("Could not paint the house under test: %v", err) } } func TestBad(t *testing.T) { badSetup(t) // ... } func TestGood(t *testing.T) { goodSetup(t) // line 32 // ... } ``` Here is an example of this output when run. Note the highlighted text and how it differs: ```text === RUN TestBad paint_test.go:15: Could not paint the house under test: no "taupe" paint today --- FAIL: TestBad (0.00s) === RUN TestGood paint_test.go:32: Could not paint the house under test: no "lilac" paint today --- FAIL: TestGood (0.00s) FAIL ``` The error with `paint_test.go:15` refers to the line of the setup function that failed in `badSetup`: `t.Fatalf("Could not paint the house under test: %v", err)` Whereas `paint_test.go:32` refers to the line of the test that failed in `TestGood`: `goodSetup(t)` Correctly using `(*testing.T).Helper` attributes the location of the failure much better when: * the helper functions grow * the helper functions call other helpers * the amount of helper usage in the test functions grow **Tip:** If a helper calls `(*testing.T).Error` or `(*testing.T).Fatal`, provide some context in the format string to help determine what went wrong and why. **Tip:** If nothing a helper does can cause a test to fail, it doesn't need to call `t.Helper`. Simplify its signature by removing `t` from the function parameter list. [`t.Cleanup`]: https://pkg.go.dev/testing#T.Cleanup <a id="t-fatal-goroutine"></a> ### Don't call `t.Fatal` from separate goroutines As [documented in package testing](https://pkg.go.dev/testing#T), it is incorrect to call `t.FailNow`, `t.Fatal`, etc. from any goroutine but the one running the Test function (or the subtest). If your test starts new goroutines, they must not call these functions from inside these goroutines. [Test helpers](#test-functions) usually don't signal failure from new goroutines, and therefore it is all right for them to use `t.Fatal`. If in doubt, call `t.Error` and return instead. ```go // Good: func TestRevEngine(t *testing.T) { engine, err := Start() if err != nil { t.Fatalf("Engine failed to start: %v", err) } num := 11 var wg sync.WaitGroup wg.Add(num) for i := 0; i < num; i++ { go func() { defer wg.Done() if err := engine.Vroom(); err != nil { // This cannot be t.Fatalf. t.Errorf("No vroom left on engine: %v", err) return } if rpm := engine.Tachometer(); rpm > 1e6 { t.Errorf("Inconceivable engine rate: %d", rpm) } }() } wg.Wait() if seen := engine.NumVrooms(); seen != num { t.Errorf("engine.NumVrooms() = %d, want %d", seen, num) } } ``` Adding `t.Parallel` to a test or subtest does not make it unsafe to call `t.Fatal`. When all calls to the `testing` API are in the [test function](#test-functions), it is usually easy to spot incorrect usage because the `go` keyword is plain to see. Passing `testing.T` arguments around makes tracking such usage harder. Typically, the reason for passing these arguments is to introduce a test helper, and those should not depend on the system under test. Therefore, if a test helper [registers a fatal test failure](#test-helper-error-handling), it can and should do so from the test's goroutine. <a id="t-field-names"></a> ### Use field names in struct literals <a id="t-field-labels"></a> In table-driven tests, prefer to specify field names when initializing test case struct literals. This is helpful when the test cases cover a large amount of vertical space (e.g. more than 20-30 lines), when there are adjacent fields with the same type, and also when you wish to omit fields which have the zero value. For example: ```go // Good: func TestStrJoin(t *testing.T) { tests := []struct { slice []string separator string skipEmpty bool want string }{ { slice: []string{"a", "b", ""}, separator: ",", want: "a,b,", }, { slice: []string{"a", "b", ""}, separator: ",", skipEmpty: true, want: "a,b", }, // ... } // ... } ``` <a id="t-common-setup-scope"></a> ### Keep setup code scoped to specific tests Where possible, setup of resources and dependencies should be as closely scoped to specific test cases as possible. For example, given a setup function: ```go // mustLoadDataSet loads a data set for the tests. // // This example is very simple and easy to read. Often realistic setup is more // complex, error-prone, and potentially slow. func mustLoadDataset(t *testing.T) []byte { t.Helper() data, err := os.ReadFile("path/to/your/project/testdata/dataset") if err != nil { t.Fatalf("Could not load dataset: %v", err) } return data } ``` Call `mustLoadDataset` explicitly in test functions that need it: ```go // Good: func TestParseData(t *testing.T) { data := mustLoadDataset(t) parsed, err := ParseData(data) if err != nil { t.Fatalf("Unexpected error parsing data: %v", err) } want := &DataTable{ /* ... */ } if got := parsed; !cmp.Equal(got, want) { t.Errorf("ParseData(data) = %v, want %v", got, want) } } func TestListContents(t *testing.T) { data := mustLoadDataset(t) contents, err := ListContents(data) if err != nil { t.Fatalf("Unexpected error listing contents: %v", err) } want := []string{ /* ... */ } if got := contents; !cmp.Equal(got, want) { t.Errorf("ListContents(data) = %v, want %v", got, want) } } func TestRegression682831(t *testing.T) { if got, want := guessOS("zpc79.example.com"), "grhat"; got != want { t.Errorf(`guessOS("zpc79.example.com") = %q, want %q`, got, want) } } ``` The test function `TestRegression682831` does not use the data set and therefore does not call `mustLoadDataset`, which could be slow and failure-prone: ```go // Bad: var dataset []byte func TestParseData(t *testing.T) { // As documented above without calling mustLoadDataset directly. } func TestListContents(t *testing.T) { // As documented above without calling mustLoadDataset directly. } func TestRegression682831(t *testing.T) { if got, want := guessOS("zpc79.example.com"), "grhat"; got != want { t.Errorf(`guessOS("zpc79.example.com") = %q, want %q`, got, want) } } func init() { dataset = mustLoadDataset() } ``` A user may wish to run a function in isolation of the others and should not be penalized by these factors: ```shell # No reason for this to perform the expensive initialization. $ go test -run TestRegression682831 ``` <a id="t-custom-main"></a> #### When to use a custom `TestMain` entrypoint If **all tests in the package** require common setup and the **setup requires teardown**, you can use a [custom testmain entrypoint]. This can happen if the resource the test cases require is especially expensive to setup, and the cost should be amortized. Typically you have extracted any unrelated tests from the test suite at that point. It is typically only used for [functional tests]. Using a custom `TestMain` **should not be your first choice** due the amount of care that should be taken for correct use. Consider first whether the solution in the [*amortizing common test setup*] section or an ordinary [test helper] is sufficient for your needs. [custom testmain entrypoint]: https://golang.org/pkg/testing/#hdr-Main [functional tests]: https://en.wikipedia.org/wiki/Functional_testing [*amortizing common test setup*]: #t-setup-amortization [test helper]: #t-common-setup-scope ```go // Good: var db *sql.DB func TestInsert(t *testing.T) { /* omitted */ } func TestSelect(t *testing.T) { /* omitted */ } func TestUpdate(t *testing.T) { /* omitted */ } func TestDelete(t *testing.T) { /* omitted */ } // runMain sets up the test dependencies and eventually executes the tests. // It is defined as a separate function to enable the setup stages to clearly // defer their teardown steps. func runMain(ctx context.Context, m *testing.M) (code int, err error) { ctx, cancel := context.WithCancel(ctx) defer cancel() d, err := setupDatabase(ctx) if err != nil { return 0, err } defer d.Close() // Expressly clean up database. db = d // db is defined as a package-level variable. // m.Run() executes the regular, user-defined test functions. // Any defer statements that have been made will be run after m.Run() // completes. return m.Run(), nil } func TestMain(m *testing.M) { code, err := runMain(context.Background(), m) if err != nil { // Failure messages should be written to STDERR, which log.Fatal uses. log.Fatal(err) } // NOTE: defer statements do not run past here due to os.Exit // terminating the process. os.Exit(code) } ``` Ideally a test case is hermetic between invocations of itself and between other test cases. At the very least, ensure that individual test cases reset any global state they have modified if they have done so (for instance, if the tests are working with an external database). <a id="t-setup-amortization"></a> #### Amortizing common test setup Using a `sync.Once` may be appropriate, though not required, if all of the following are true about the common setup: * It is expensive. * It only applies to some tests. * It does not require teardown. ```go // Good: var dataset struct { once sync.Once data []byte err error } func mustLoadDataset(t *testing.T) []byte { t.Helper() dataset.once.Do(func() { data, err := os.ReadFile("path/to/your/project/testdata/dataset") // dataset is defined as a package-level variable. dataset.data = data dataset.err = err }) if err := dataset.err; err != nil { t.Fatalf("Could not load dataset: %v", err) } return dataset.data } ``` When `mustLoadDataset` is used in multiple test functions, its cost is amortized: ```go // Good: func TestParseData(t *testing.T) { data := mustLoadDataset(t) // As documented above. } func TestListContents(t *testing.T) { data := mustLoadDataset(t) // As documented above. } func TestRegression682831(t *testing.T) { if got, want := guessOS("zpc79.example.com"), "grhat"; got != want { t.Errorf(`guessOS("zpc79.example.com") = %q, want %q`, got, want) } } ``` The reason that common teardown is tricky is there is no uniform place to register cleanup routines. If the setup function (in this case `mustLoadDataset`) relies on a context, `sync.Once` may be problematic. This is because the second of two racing calls to the setup function would need to wait for the first call to finish before returning. This period of waiting cannot be easily made to respect the context's cancellation. <a id="string-concat"></a> ## String concatenation There are several ways to concatenate strings in Go. Some examples include: * The "+" operator * `fmt.Sprintf` * `strings.Builder` * `text/template` * `safehtml/template` Though there is no one-size-fits-all rule for which to choose, the following guidance outlines when each method is preferred. <a id="string-concat-simple"></a> ### Prefer "+" for simple cases Prefer using "+" when concatenating few strings. This method is syntactically the simplest and requires no import. ```go // Good: key := "projectid: " + p ``` <a id="string-concat-fmt"></a> ### Prefer `fmt.Sprintf` when formatting Prefer using `fmt.Sprintf` when building a complex string with formatting. Using many "+" operators may obscure the end result. ```go // Good: str := fmt.Sprintf("%s [%s:%d]-> %s", src, qos, mtu, dst) ``` ```go // Bad: bad := src.String() + " [" + qos.String() + ":" + strconv.Itoa(mtu) + "]-> " + dst.String() ``` **Best Practice:** When the output of the string-building operation is an `io.Writer`, don't construct a temporary string with `fmt.Sprintf` just to send it to the Writer. Instead, use `fmt.Fprintf` to emit to the Writer directly. When the formatting is even more complex, prefer [`text/template`] or [`safehtml/template`] as appropriate. [`text/template`]: https://pkg.go.dev/text/template [`safehtml/template`]: https://pkg.go.dev/github.com/google/safehtml/template <a id="string-concat-piecemeal"></a> ### Prefer `strings.Builder` for constructing a string piecemeal Prefer using `strings.Builder` when building a string bit-by-bit. `strings.Builder` takes amortized linear time, whereas "+" and `fmt.Sprintf` take quadratic time when called sequentially to form a larger string. ```go // Good: b := new(strings.Builder) for i, d := range digitsOfPi { fmt.Fprintf(b, "the %d digit of pi is: %d\n", i, d) } str := b.String() ``` **Note:** For more discussion, see [GoTip #29: Building Strings Efficiently](https://google.github.io/styleguide/go/index.html#gotip). <a id="string-constants"></a> ### Constant strings Prefer to use backticks (\`) when constructing constant, multi-line string literals. ```go // Good: usage := `Usage: custom_tool [args]` ``` ```go // Bad: usage := "" + "Usage:\n" + "\n" + "custom_tool [args]" ``` <!-- --> {% endraw %} <a id="globals"></a> ## Global state Libraries should not force their clients to use APIs that rely on [global state](https://en.wikipedia.org/wiki/Global_variable). They are advised not to expose APIs or export [package level](https://go.dev/ref/spec#TopLevelDecl) variables that control behavior for all clients as parts of their API. The rest of the section uses "global" and "package level state" synonymously. Instead, if your functionality maintains state, allow your clients to create and use instance values. **Important:** While this guidance is applicable to all developers, it is most critical for infrastructure providers who offer libraries, integrations, and services to other teams. ```go // Good: // Package sidecar manages subprocesses that provide features for applications. package sidecar type Registry struct { plugins map[string]*Plugin } func New() *Registry { return &Registry{plugins: make(map[string]*Plugin)} } func (r *Registry) Register(name string, p *Plugin) error { ... } ``` Your users will instantiate the data they need (a `*sidecar.Registry`) and then pass it as an explicit dependency: ```go // Good: package main func main() { sidecars := sidecar.New() if err := sidecars.Register("Cloud Logger", cloudlogger.New()); err != nil { log.Exitf("Could not setup cloud logger: %v", err) } cfg := &myapp.Config{Sidecars: sidecars} myapp.Run(context.Background(), cfg) } ``` There are different approaches to migrating existing code to support dependency passing. The main one you will use is passing dependencies as parameters to constructors, functions, methods, or struct fields on the call chain. See also: * [Go Tip #5: Slimming Your Client Libraries](https://google.github.io/styleguide/go/index.html#gotip) * [Go Tip #24: Use Case-Specific Constructions](https://google.github.io/styleguide/go/index.html#gotip) * [Go Tip #40: Improving Time Testability with Function Parameters](https://google.github.io/styleguide/go/index.html#gotip) * [Go Tip #41: Identify Function Call Parameters](https://google.github.io/styleguide/go/index.html#gotip) * [Go Tip #44: Improving Time Testability with Struct Fields](https://google.github.io/styleguide/go/index.html#gotip) * [Go Tip #80: Dependency Injection Principles](https://google.github.io/styleguide/go/index.html#gotip) APIs that do not support explicit dependency passing become fragile as the number of clients increases: ```go // Bad: package sidecar var registry = make(map[string]*Plugin) func Register(name string, p *Plugin) error { /* registers plugin in registry */ } ``` Consider what happens in the case of tests exercising code that transitively relies on a sidecar for cloud logging. ```go // Bad: package app import ( "cloudlogger" "sidecar" "testing" ) func TestEndToEnd(t *testing.T) { // The system under test (SUT) relies on a sidecar for a production cloud // logger already being registered. ... // Exercise SUT and check invariants. } func TestRegression_NetworkUnavailability(t *testing.T) { // We had an outage because of a network partition that rendered the cloud // logger inoperative, so we added a regression test to exercise the SUT with // a test double that simulates network unavailability with the logger. sidecar.Register("cloudlogger", cloudloggertest.UnavailableLogger) ... // Exercise SUT and check invariants. } func TestRegression_InvalidUser(t *testing.T) { // The system under test (SUT) relies on a sidecar for a production cloud // logger already being registered. // // Oops. cloudloggertest.UnavailableLogger is still registered from the // previous test. ... // Exercise SUT and check invariants. } ``` Go tests are executed sequentially by default, so the tests above run as: 1. `TestEndToEnd` 2. `TestRegression_NetworkUnavailability`, which overrides the default value of cloudlogger 3. `TestRegression_InvalidUser`, which requires the default value of cloudlogger registered in `package sidecar` This creates an order-dependent test case, which breaks running with test filters, and prevents tests from running in parallel or being sharded. Using global state poses problems that lack easy answers for you and the API's clients: * What happens if a client needs to use different and separately operating sets of `Plugin`s (for example, to support multiple servers) in the same process space? * What happens if a client wants to replace a registered `Plugin` with an alternative implementation in a test, like a [test double]? What happens if a client's tests require hermeticity between instances of a `Plugin`, or between all of the plugins registered? * What happens if multiple clients `Register` a `Plugin` under the same name? Which one wins, if any? How should errors be [handled](decisions#handle-errors)? If the code panics or calls `log.Fatal`, will that always be [appropriate for all places in which API would be called](decisions#dont-panic)? Can a client verify it doesn't do something bad before doing so? * Are there certain stages in a program's startup phases or lifetime during which `Register` can be called and when it can't? What happens if `Register` is called at the wrong time? A client could call `Register` in [`func init`](https://go.dev/ref/spec#Package_initialization), before flags are parsed, or after `main`. The stage at which a function is called affects error handling. If the author of an API assumes the API is *only* called during program initialization without the requirement that it is, the assumption may nudge the author to design error handling to [abort the program](best-practices#program-init) by modeling the API as a `Must`-like function. Aborting is not appropriate for general-purpose library functions that can be used at any stage. * What if the client's and the designer's concurrency needs are mismatched? See also: * [Go Tip #36: Enclosing Package-Level State](https://google.github.io/styleguide/go/index.html#gotip) * [Go Tip #71: Reducing Parallel Test Flakiness](https://google.github.io/styleguide/go/index.html#gotip) * [Go Tip #80: Dependency Injection Principles](https://google.github.io/styleguide/go/index.html#gotip) * Error Handling: [Look Before You Leap](https://docs.python.org/3/glossary.html#term-LBYL) versus [Easier to Ask for Forgiveness than Permission](https://docs.python.org/3/glossary.html#term-EAFP) * [Unit Testing Practices on Public APIs] Global state has cascading effects on the [health of the Google codebase](guide.md#maintainability). Global state should be approached with **extreme scrutiny**. [Global state comes in several forms](#globals-forms), and you can use a few [litmus tests to identify when it is safe](#globals-litmus-tests). [Unit Testing Practices on Public APIs]: index.md#unit-testing-practices <a id="globals-forms"></a> ### Major forms of package state APIs Several of the most common problematic API forms are enumerated below: * Top-level variables irrespective of whether they are exported. ```go // Bad: package logger // Sinks manages the default output sources for this package's logging API. This // variable should be set at package initialization time and never thereafter. var Sinks []Sink ``` See the [litmus tests](#globals-litmus-tests) to know when these are safe. * The [service locator pattern](https://en.wikipedia.org/wiki/Service_locator_pattern). See the [first example](#globals). The service locator pattern itself is not problematic, rather the locator being defined as global. * Registries for [callbacks](https://en.wikipedia.org/wiki/Callback_\(computer_programming\)) and similar behaviors. ```go // Bad: package health var unhealthyFuncs []func func OnUnhealthy(f func()) { unhealthyFuncs = append(unhealthyFuncs, f) } ``` * Thick-Client singletons for things like backends, storage, data access layers, and other system resources. These often pose additional problems with service reliability. ```go // Bad: package useradmin var client pb.UserAdminServiceClientInterface func Client() *pb.UserAdminServiceClient { if client == nil { client = ... // Set up client. } return client } ``` > **Note:** Many legacy APIs in the Google codebase do not follow this guidance; > in fact, some Go standard libraries allow for configuration via global values. > Nevertheless, the legacy API's contravention of this guidance > **[should not be used as precedent](guide#local-consistency)** for continuing > the pattern. > > It is better to invest in proper API design today than pay for redesigning > later. <a id="globals-litmus-tests"></a> ### Litmus tests [APIs using the patterns above](#globals-forms) are unsafe when: * Multiple functions interact via global state when executed in the same program, despite being otherwise independent (for example, authored by different authors in vastly different directories). * Independent test cases interact with each other through global state. * Users of the API are tempted to swap or replace global state for testing purposes, particularly to replace any part of the state with a [test double], like a stub, fake, spy, or mock. * Users have to consider special ordering requirements when interacting with global state: `func init`, whether flags are parsed yet, etc. Provided the conditions above are avoided, there are a **few limited circumstances under which these APIs are safe**, namely when any of the following is true: * The global state is logically constant ([example](https://github.com/klauspost/compress/blob/290f4cfacb3eff892555a491e3eeb569a48665e7/zstd/snappy.go#L413)). * The package's observable behavior is stateless. For example, a public function may use a private global variable as a cache, but so long as the caller can't distinguish cache hits from misses, the function is stateless. * The global state does not bleed into things that are external to the program, like sidecar processes or files on a shared filesystem. * There is no expectation of predictable behavior ([example](https://pkg.go.dev/math/rand)). > **Note:** > [Sidecar processes](https://www.oreilly.com/library/view/designing-distributed-systems/9781491983638/ch02.html) > may **not** strictly be process-local. They can and often are shared with more > than one application process. Moreover, these sidecars often interact with > external distributed systems. > > Further, the same stateless, idempotent, and local rules in addition to the > base considerations above would apply to the code of the sidecar process > itself! An example of one of these safe situations is [`package image`](https://pkg.go.dev/image) with its [`image.RegisterFormat`](https://pkg.go.dev/image#RegisterFormat) function. Consider the litmus tests from above applied to a typical decoder, like the one for handling the [PNG](https://pkg.go.dev/image/png) format: * Multiple calls to `package image`'s APIs that use the registered decoders (for example, `image.Decode`) cannot interfere with one another, similarly for tests. The only exception is `image.RegisterFormat`, but that is mitigated by the points below. * It is extremely unlikely that a user would want to replace a decoder with a [test double], as the PNG decoder exemplifies a case in which our codebase's preference for real objects applies. However, a user would be more likely to replace a decoder with a test double if the decoder statefully interacted with operating system resources (for example, the network). * Collisions in registration are conceivable, though they are probably rare in practice. * The decoders are stateless, idempotent, and pure. <a id="globals-default-instance"></a> ### Providing a default instance While not recommended, it is acceptable to provide a simplified API that uses package level state if you need to maximize convenience for the user. Follow the [litmus tests](#globals-litmus-tests) with these guidelines in such cases: 1. The package must offer clients the ability to create isolated instances of package types as [described above](#globals-forms). 2. The public APIs that use global state must be a thin proxy to the previous API. A good example of this is [`http.Handle`](https://pkg.go.dev/net/http#Handle) internally calling [`(*http.ServeMux).Handle`](https://pkg.go.dev/net/http#ServeMux.Handle) on the package variable [`http.DefaultServeMux`](https://pkg.go.dev/net/http#DefaultServeMux). 3. This package-level API must only be used by [binary build targets], not [libraries], unless the libraries are undertaking a refactoring to support dependency passing. Infrastructure libraries that can be imported by other packages must not rely on package-level state of the packages they import. For example, an infrastructure provider implementing a sidecar that is to be shared with other teams using the API from the top should offer an API to accommodate this: ```go // Good: package cloudlogger func New() *Logger { ... } func Register(r *sidecar.Registry, l *Logger) { r.Register("Cloud Logging", l) } ``` 4. This package-level API must [document](#documentation-conventions) and enforce its invariants (for example, at which stage in the program's life it can be called, whether it can be used concurrently). Further, it must provide an API to reset global state to a known-good default (for example, to facilitate testing). [binary build targets]: https://github.com/bazelbuild/rules_go/blob/master/docs/go/core/rules.md#go_binary [libraries]: https://github.com/bazelbuild/rules_go/blob/master/docs/go/core/rules.md#go_library See also: * [Go Tip #36: Enclosing Package-Level State](https://google.github.io/styleguide/go/index.html#gotip) * [Go Tip #80: Dependency Injection Principles](https://google.github.io/styleguide/go/index.html#gotip) <a id="interfaces"></a> ## Interfaces Interfaces in Go are powerful but can be overused or misunderstood. Because Go interfaces are satisfied implicitly, they are a structural tool rather than a declarative one. The following guidance provides the best practices for how to design and return interfaces in Go without over-engineering your codebase. Refer to [Decisions' section on interfaces](decisions#interfaces) for a summary. <a id="avoid-unnecessary-interfaces"></a> ### Avoid unnecessary interfaces The most common mistake is creating an interface before a [real need](guide#simplicity) exists. 1. **Don’t confuse the concept with the keyword:** Just because you are designing a "service" or a "repository" or similar pattern doesn't mean you need a named interface type (e.g., `type Service interface`). Focus on the behavior and its concrete implementation first. 2. **Reuse existing interfaces:** If an interface already exists, especially in generated code, like a RPC client or server, use it ([testing RPC]). Do not wrap a generated RPC code in a new, manual interface just for the sake of abstraction or testing. [Use real transports](#use-real-transports) instead. 3. **Don't define back doors only for tests:** Do not export a [test double] implementation of an interface from an API that consumes it. Instead, prefer to design the API so that it can be tested using the [public API] of the real implementation. Every exported type increases the cognitive load for the reader. When you export a test double alongside the real implementation, you force the reader to understand three entities (the interface, the real implementation, and the test double) instead of one. Export an interface for a test double when you have a [material need](guide#least-mechanism) to support substitution. When it does make sense to create an interface: 1. **Multiple implementations:** When there are two or more concrete types that must be handled by the same logic (e.g., something that operates with both [json.Encoder](https://pkg.go.dev/encoding/json#Encoder) and [gob.GobEncoder](https://pkg.go.dev/encoding/gob#GobEncoder)), the API consumer could define an interface. 2. **Decoupling packages:** To break circular dependencies between two packages (see an [example](#avoiding-circular-dependencies)), an API producer could define an interface. **Caution:** Carefully observe guidance on [Package Size](#package-size). Introducing interfaces to break dependency cycles is often a signal of improperly structured packages. 3. **Hiding complexity:** When a concrete type has a massive API surface, but a specific function only needs one or two methods, an API consumer may define an interface. <a id="interface-ownership-and-visibility"></a> ### Interface ownership and visibility 1. **Do not export interface types unnecessarily:** If an interface is only used internally within a package to satisfy a specific logic flow, keep the interface unexported. Exporting an interface commits you to maintaining that API for external callers. 2. **The consumer defines the interface:** In Go, interfaces generally belong in the package that uses them, not the package that implements them. The consumer should define only the methods they actually use [GoTip #78: Minimal Viable Interfaces], adhering to the idea that [the bigger the interface, the weaker the abstraction](https://go-proverbs.github.io/). There are common scenarios where it often makes sense for the producer (the package providing the logic) to export the interface: * **The interface is the product:** When a package’s primary purpose is to provide a common protocol that many different implementations must follow, the producer defines the interface. For example, [io.Writer](https://pkg.go.dev/io#Writer), [hash.Hash](https://pkg.go.dev/hash#Hash). The concept of "protocol" includes aspects like [documentation](#documentation) about critical behaviors (e.g., expected use case, edge cases, concurrency) that need to be centrally and canonically explicated. Another prominent example of this is generated interfaces from protobuf. It doesn't abstract a specific behavior, it defines a boundary. Its purpose is to ensure that your server implementation exactly matches the schema defined in the `.proto` file. Here, the interface serves as a rigid legal contract between the service and its clients. For large systems, if the interface lives inside a huge implementation package, every client is forced to import the entire world just to reference the interface. You may define the interface in a standalone, implementation-free package, avoiding unnecessary symbols and potential circular dependencies. This is also the same philosophy used by generated code from protobuf. * **Prevent interface bloat:** In large codebases, maintenance becomes difficult if numerous packages utilize the same `AuthService` while each defining an identical `type Authorizer interface`. While Go often favors [a little copying over a little dependency](https://go-proverbs.github.io/), keep in mind that maintaining perfectly mirrored interfaces (see point above) across many packages can create an unnecessary burden. * **Resolve circular dependency:** see [an example](#avoiding-circular-dependencies) below. <a id="designing-effective-interfaces"></a> ### Designing effective interfaces 1. **Keep interfaces small:** The larger the interface, [the harder it is to implement and to write code that takes advantage of it](https://go-proverbs.github.io/). Small interfaces are easier to compose into larger ones if needed. 2. **Documentation:** Treat every interface as the "user manual" for your abstraction. The depth of your documentation should be proportional to the interface's cognitive load, not just the count of its methods. Whether an interface has ten methods or a single `Write` of [io.Writer](https://pkg.go.dev/io#Writer), if a programmer is expected to interact with that type, the API must be documented thoroughly. * **Single-method interfaces:** documentation on the type itself is usually sufficient (e.g., io.Writer). Explain its contract, edge cases, and expected errors. * **Multi-method interfaces:** each individual method requires its own documentation. * **Unexported interfaces:** consider documenting them anyway. They are often the glue that holds complex internal logic together, and because they are invisible to external users, they can easily become mystery code for future maintainers (including your future self). 3. **Accept interfaces, return concrete types:** Returning a concrete type allows the caller to use the full functionality of the value without being locked into a specific interface abstraction [GoTip #49: Accept Interfaces, Return Concrete Types]. There are several common scenarios where returning an interface is the idiomatic choice: 1. **Encapsulation:** While interfaces cannot strictly hide exported methods (as they remain accessible via type assertions), returning an interface is a powerful tool for limiting the default API surface and guiding the caller's behavior.. The most common example is the `error` interface; you [almost never return a concrete error type](decisions#errors) like `*MyCustomError`. Consider a `ThrottledReader` that implements `io.Reader` but also has a `Refill` method for internal bucket management. Returning the concrete `*ThrottledReader` invites the caller to manage the bucket manually, which could lead to race conditions or broken rate-limiting logic. By returning an interface, you tell the caller that your only job is to consume this reader. If you try to cast this back to a `ThrottledReader` to `Refill` the internal bucket, you are breaking the contract. ```go // Good: type ThrottledReader struct { source io.Reader limit int // bytes per second balance int // current allowance of bytes lastRefill time.Time } // Read implements the io.Reader interface with rate-limiting logic. func (t *ThrottledReader) Read(p []byte) (int, error) { ... } // Refill manually adds tokens to the bucket. // INTERNAL USE ONLY: Calling this from outside breaks the rate limit logic. func (t *ThrottledReader) Refill(amount int) { t.balance = min(t.balance + amount, t.limit) } // New returns the io.Reader with rate-limiting. func New(r io.Reader, bytesPerSec int) io.Reader { return &ThrottledReader{ source: r, limit: bytesPerSec, balance: bytesPerSec, // start with a full bucket lastRefill: time.Now(), } } ``` This raises a natural question: if `Refill` is dangerous, why export it at all? In complex systems, you often need internal orchestration. For example, an `AggregateReader` manages multiple `ThrottledReader` values to ensure total bandwidth across all streams stays under a global limit. This coordinator needs to call Refill to distribute tokens, but the non-power user processing the data should never see that capability. **Caution:** Before returning an interface to hide implementation, ask: "Would a user calling these extra methods actually break the system's integrity or meaningfully limit maintainability?" If the extra details allow the user to bypass safety checks, or if exposing the concrete type makes it impossible to change the underlying provider later without a breaking change, you may return an interface. Do not rotely encapsulate without reason. 2. **Certain patterns:** If a function is designed to return one of several different concrete types based on decisions made at runtime, it must return an interface. This is commonly true with command, chaining, factory, and [strategy](https://en.wikipedia.org/wiki/Strategy_pattern) patterns. Consider this code that selects which encoder to use based the requested format: ```go // Good: func NewWriter(format string) io.Writer { switch format { case "json": return &jsonWriter{} case "xml": return &xmlWriter{} default: return &textWriter{} } } ``` The following example of a chaining API demonstrates how returning an interface enables polymorphic behavior. By allowing callers to use either `client.Do(req)` or `client.WithAuth("token").Do(req)`, you can swap implementations without breaking the calling code. ```go // Good: type Client interface { WithAuth(token string) Client Do(req *Request) error } ``` These patterns are guidelines, not rules. Avoid forcing an interface if a single, robust concrete type can handle the abstraction internally. For example, the standard [database/sql](https://pkg.go.dev/database/sql#DB) library exports a single concrete `DB` type instead of forcing an interface to handle types like `MySQLDB` and `OracleDB`. 3. <span id="avoiding-circular-dependencies">**Avoiding circular dependencies:**</span> If returning a concrete type would require importing a package that already imports your current package, you must return an interface to break the circular dependency. For example: ```go // Bad: package app import "myproject/plugin" type Config struct { APIKey string } func Start() { p := plugin.New() } ``` ```go // Bad: package plugin import "myproject/app" // ERROR: Import cycle! func New() *app.Config { return &app.Config{APIKey: "secret"} } ``` In this case, `plugin`'s `New` cannot return `*app.Config` because it would create a circular import. To break this, we use the fact that interfaces are satisfied implicitly. We move the "contract" to a neutral place or have the producer return an interface that the consumer already understands. If `plugin`'s `New` returns an interface instead of the concrete `*app.Config` struct, it no longer needs to import package `app`. ```go package plugin type Configurer interface { APIKey() string } type localConfig struct { key string } func (c localConfig) APIKey() string { return c.key } // New returns the interface Configurer instead of the concrete app.Config func New() Configurer { return &localConfig{key: "secret"} } ``` ```go package app import "myproject/plugin" func Start() { conf := plugin.New() // 'conf' is now a Configurer interface fmt.Println(conf.APIKey()) } ``` **Caution:** Carefully observe guidance on [Package Size](#package-size). Introducing interfaces to break dependency cycles is often a signal of improperly structured packages. Consolidated packages are often preferred over too many too small packages that fail to stand on their own. [GoTip #78: Minimal Viable Interfaces]: https://google.github.io/styleguide/go/index.html#gotip [GoTip #49: Accept Interfaces, Return Concrete Types]: https://google.github.io/styleguide/go/index.html#gotip [testing RPC]: https://codelabs.developers.google.com/grpc/getting-started-grpc-go#3 [test double]: https://abseil.io/resources/swe-book/html/ch13.html [public API]: https://abseil.io/resources/swe-book/html/ch12.html#test_via_public_apis ================================================ FILE: go/decisions.md ================================================ <!--* toc_depth: 3 *--> # Go Style Decisions https://google.github.io/styleguide/go/decisions [Overview](index) | [Guide](guide) | [Decisions](decisions) | [Best practices](best-practices) <!-- --> {% raw %} **Note:** This is part of a series of documents that outline [Go Style](index) at Google. This document is **[normative](index#normative) but not [canonical](index#canonical)**, and is subordinate to the [core style guide](guide). See [the overview](index#about) for more information. <a id="about"></a> ## About This document contains style decisions intended to unify and provide standard guidance, explanations, and examples for the advice given by the Go readability mentors. This document is **not exhaustive** and will grow over time. In cases where [the core style guide](guide) contradicts the advice given here, **the style guide takes precedence**, and this document should be updated accordingly. See [the Overview](https://google.github.io/styleguide/go#about) for the full set of Go Style documents. The following sections have moved from style decisions to another part of the guide: * **MixedCaps**: see [guide#mixed-caps](guide#mixed-caps) <a id="mixed-caps"></a> * **Formatting**: see [guide#formatting](guide#formatting) <a id="formatting"></a> * **Line Length**: see [guide#line-length](guide#line-length) <a id="line-length"></a> <a id="naming"></a> ## Naming See the naming section within [the core style guide](guide#naming) for overarching guidance on naming. The following sections provide further clarification on specific areas within naming. <a id="underscores"></a> ### Underscores Names in Go should in general not contain underscores. There are three exceptions to this principle: 1. Package names that are only imported by generated code may contain underscores. See [package names](#package-names) for more detail around how to choose multi-word package names. 1. Test, Benchmark and Example function names within `*_test.go` files may include underscores. 1. Low-level libraries that interoperate with the operating system or cgo may reuse identifiers, as is done in [`syscall`]. This is expected to be very rare in most codebases. **Note:** Filenames of source code are not Go identifiers and do not have to follow these conventions. They may contain underscores. [`syscall`]: https://pkg.go.dev/syscall#pkg-constants <a id="package-names"></a> ### Package names <a id="TOC-PackageNames"></a> In Go, package names must be concise and use only lowercase letters and numbers (e.g., [`k8s`], [`oauth2`]). Multi-word package names should remain unbroken and in all lowercase (e.g., [`tabwriter`] instead of `tabWriter`, `TabWriter`, or `tab_writer`). Avoid selecting package names that are likely to be [shadowed] by commonly used local variable names. For example, `usercount` is a better package name than `count`, since `count` is a commonly used variable name. Go package names should not have underscores. If you need to import a package that does have one in its name (usually from generated or third party code), it must be renamed at import time to a name that is suitable for use in Go code. An exception to this is that package names that are only imported by generated code may contain underscores. Specific examples include: * Using the `_test` suffix for unit tests that only exercise the exported API of a package (package `testing` calls these ["black box tests"](https://pkg.go.dev/testing)). For example, a package `linkedlist` must define its black box unit tests in a package named `linkedlist_test` (not `linked_list_test`) * Using underscores and the `_test` suffix for packages that specify functional or integration tests. For example, a linked list service integration test could be named `linked_list_service_test` * Using the `_test` suffix for [package-level documentation examples](https://go.dev/blog/examples) [`tabwriter`]: https://pkg.go.dev/text/tabwriter [`k8s`]: https://pkg.go.dev/k8s.io/client-go/kubernetes [`oauth2`]: https://pkg.go.dev/golang.org/x/oauth2 [shadowed]: best-practices#shadowing Avoid uninformative package names like `util`, `utility`, `common`, `helper`, `model`, `testhelper`, and so on that would tempt users of the package to [rename it when importing](#import-renaming). See: * [Guidance on so-called "utility packages"](best-practices#util-packages) * [Go Tip #97: What's in a Name](https://google.github.io/styleguide/go/index.html#gotip) * [Go Tip #108: The Power of a Good Package Name](https://google.github.io/styleguide/go/index.html#gotip) When an imported package is renamed (e.g. `import foopb "path/to/foo_go_proto"`), the local name for the package must comply with the rules above, as the local name dictates how the symbols in the package are referenced in the file. If a given import is renamed in multiple files, particularly in the same or nearby packages, the same local name should be used wherever possible for consistency. <!--#include file="/go/g3doc/style/includes/special-name-exception.md"--> See also: [Go blog post about package names](https://go.dev/blog/package-names). <a id="receiver-names"></a> ### Receiver names <a id="TOC-ReceiverNames"></a> [Receiver] variable names must be: * Short (usually one or two letters in length) * Abbreviations for the type itself * Applied consistently to every receiver for that type * Not an underscore; omit the name if it is unused Long Name | Better Name --------------------------- | ------------------------- `func (tray Tray)` | `func (t Tray)` `func (info *ResearchInfo)` | `func (ri *ResearchInfo)` `func (this *ReportWriter)` | `func (w *ReportWriter)` `func (self *Scanner)` | `func (s *Scanner)` [Receiver]: https://golang.org/ref/spec#Method_declarations <a id="constant-names"></a> ### Constant names Constant names must use [MixedCaps] like all other names in Go. ([Exported] constants start with uppercase, while unexported constants start with lowercase.) This applies even when it breaks conventions in other languages. Constant names should not be a derivative of their values and should instead explain what the value denotes. ```go // Good: const MaxPacketSize = 512 const ( ExecuteBit = 1 << iota WriteBit ReadBit ) ``` [MixedCaps]: guide#mixed-caps [Exported]: https://tour.golang.org/basics/3 Do not use non-MixedCaps constant names or constants with a `K` prefix. ```go // Bad: const MAX_PACKET_SIZE = 512 const kMaxBufferSize = 1024 const KMaxUsersPergroup = 500 ``` Name constants based on their role, not their values. If a constant does not have a role apart from its value, then it is unnecessary to define it as a constant. ```go // Bad: const Twelve = 12 const ( UserNameColumn = "username" GroupColumn = "group" ) ``` <!--#include file="/go/g3doc/style/includes/special-name-exception.md"--> <a id="initialisms"></a> ### Initialisms <a id="TOC-Initialisms"></a> Words in names that are initialisms or acronyms (e.g., `URL` and `NATO`) should have the same case. `URL` should appear as `URL` or `url` (as in `urlPony`, or `URLPony`), never as `Url`. As a general rule, identifiers (e.g., `ID` and `DB`) should also be capitalized similar to their usage in English prose. * In names with multiple initialisms (e.g. `XMLAPI` because it contains `XML` and `API`), each letter within a given initialism should have the same case, but each initialism in the name does not need to have the same case. * In names with an initialism containing a lowercase letter (e.g. `DDoS`, `iOS`, `gRPC`), the initialism should appear as it would in standard prose, unless you need to change the first letter for the sake of [exportedness]. In these cases, the entire initialism should be the same case (e.g. `ddos`, `IOS`, `GRPC`). [exportedness]: https://golang.org/ref/spec#Exported_identifiers <!-- Keep this table narrow. If it must grow wider, replace with a list. --> English Usage | Scope | Correct | Incorrect ------------- | ---------- | -------- | -------------------------------------- XML API | Exported | `XMLAPI` | `XmlApi`, `XMLApi`, `XmlAPI`, `XMLapi` XML API | Unexported | `xmlAPI` | `xmlapi`, `xmlApi` iOS | Exported | `IOS` | `Ios`, `IoS` iOS | Unexported | `iOS` | `ios` gRPC | Exported | `GRPC` | `Grpc` gRPC | Unexported | `gRPC` | `grpc` DDoS | Exported | `DDoS` | `DDOS`, `Ddos` DDoS | Unexported | `ddos` | `dDoS`, `dDOS` ID | Exported | `ID` | `Id` ID | Unexported | `id` | `iD` DB | Exported | `DB` | `Db` DB | Unexported | `db` | `dB` Txn | Exported | `Txn` | `TXN` <!--#include file="/go/g3doc/style/includes/special-name-exception.md"--> <a id="getters"></a> ### Getters <a id="TOC-Getters"></a> Function and method names should not use a `Get` or `get` prefix, unless the underlying concept uses the word "get" (e.g. an HTTP GET). Prefer starting the name with the noun directly, for example use `Counts` over `GetCounts`. If the function involves performing a complex computation or executing a remote call, a different word like `Compute` or `Fetch` can be used in place of `Get`, to make it clear to a reader that the function call may take time and could block or fail. <!--#include file="/go/g3doc/style/includes/special-name-exception.md"--> <a id="variable-names"></a> ### Variable names <a id="TOC-VariableNames"></a> The general rule of thumb is that the length of a name should be proportional to the size of its scope and inversely proportional to the number of times that it is used within that scope. A variable created at file scope may require multiple words, whereas a variable scoped to a single inner block may be a single word or even just a character or two, to keep the code clear and avoid extraneous information. Here is a rough baseline. These numeric guidelines are not strict rules. Apply judgement based on context, [clarity], and [concision]. * A small scope is one in which one or two small operations are performed, say 1-7 lines. * A medium scope is a few small or one large operation, say 8-15 lines. * A large scope is one or a few large operations, say 15-25 lines. * A very large scope is anything that spans more than a page (say, more than 25 lines). [clarity]: guide#clarity [concision]: guide#concision A name that might be perfectly clear (e.g., `c` for a counter) within a small scope could be insufficient in a larger scope and would require clarification to remind the reader of its purpose further along in the code. A scope in which there are many variables, or variables that represent similar values or concepts, may necessitate longer variable names than the scope suggests. The specificity of the concept can also help to keep a variable's name concise. For example, assuming there is only a single database in use, a short variable name like `db` that might normally be reserved for very small scopes may remain perfectly clear even if the scope is very large. In this case, a single word `database` is likely acceptable based on the size of the scope, but is not required as `db` is a very common shortening for the word with few alternate interpretations. The name of a local variable should reflect what it contains and how it is being used in the current context, rather than where the value originated. For example, it is often the case that the best local variable name is not the same as the struct or protocol buffer field name. In general: * Single-word names like `count` or `options` are a good starting point. * Additional words can be added to disambiguate similar names, for example `userCount` and `projectCount`. * Do not simply drop letters to save typing. For example `Sandbox` is preferred over `Sbx`, particularly for exported names. * Omit [types and type-like words] from most variable names. * For a number, `userCount` is a better name than `numUsers` or `usersInt`. * For a slice, `users` is a better name than `userSlice`. * It is acceptable to include a type-like qualifier if there are two versions of a value in scope, for example you might have an input stored in `ageString` and use `age` for the parsed value. * Omit words that are clear from the [surrounding context]. For example, in the implementation of a `UserCount` method, a local variable called `userCount` is probably redundant; `count`, `users`, or even `c` are just as readable. [types and type-like words]: #repetitive-with-type [surrounding context]: #repetitive-in-context <a id="v"></a> #### Single-letter variable names Single-letter variable names can be a useful tool to minimize [repetition](#repetition), but can also make code needlessly opaque. Limit their use to instances where the full word is obvious and where it would be repetitive for it to appear in place of the single-letter variable. In general: * For a [method receiver variable], a one-letter or two-letter name is preferred. * Using familiar variable names for common types is often helpful: * `r` for an `io.Reader` or `*http.Request` * `w` for an `io.Writer` or `http.ResponseWriter` * Single-letter identifiers are acceptable as integer loop variables, particularly for indices (e.g., `i`) and coordinates (e.g., `x` and `y`). * Abbreviations can be acceptable loop identifiers when the scope is short, for example `for _, n := range nodes { ... }`. [method receiver variable]: #receiver-names <a id="repetition"></a> ### Repetition <!-- Note to future editors: Do not use the term "stutter" to refer to cases when a name is repetitive. --> A piece of Go source code should avoid unnecessary repetition. One common source of this is repetitive names, which often include unnecessary words or repeat their context or type. Code itself can also be unnecessarily repetitive if the same or a similar code segment appears multiple times in close proximity. Repetitive naming can come in many forms, including: <a id="repetitive-with-package"></a> #### Package vs. exported symbol name When naming exported symbols, the name of the package is always visible outside your package, so redundant information between the two should be reduced or eliminated. If a package exports only one type and it is named after the package itself, the canonical name for the constructor is `New` if one is required. > **Examples:** Repetitive Name -> Better Name > > * `widget.NewWidget` -> `widget.New` > * `widget.NewWidgetWithName` -> `widget.NewWithName` > * `db.LoadFromDatabase` -> `db.Load` > * `goatteleportutil.CountGoatsTeleported` -> `gtutil.CountGoatsTeleported` > or `goatteleport.Count` > * `myteampb.MyTeamMethodRequest` -> `mtpb.MyTeamMethodRequest` or > `myteampb.MethodRequest` <a id="repetitive-with-type"></a> #### Variable name vs. type The compiler always knows the type of a variable, and in most cases it is also clear to the reader what type a variable is by how it is used. It is only necessary to clarify the type of a variable if its value appears twice in the same scope. Repetitive Name | Better Name ----------------------------- | ---------------------- `var numUsers int` | `var users int` `var nameString string` | `var name string` `var primaryProject *Project` | `var primary *Project` If the value appears in multiple forms, this can be clarified either with an extra word like `raw` and `parsed` or with the underlying representation: ```go // Good: limitRaw := r.FormValue("limit") limit, err := strconv.Atoi(limitRaw) ``` ```go // Good: limitStr := r.FormValue("limit") limit, err := strconv.Atoi(limitStr) ``` <a id="repetitive-in-context"></a> #### External context vs. local names Names that include information from their surrounding context often create extra noise without benefit. The package name, method name, type name, function name, import path, and even filename can all provide context that automatically qualifies all names within. ```go // Bad: // In package "ads/targeting/revenue/reporting" type AdsTargetingRevenueReport struct{} func (p *Project) ProjectName() string ``` ```go // Good: // In package "ads/targeting/revenue/reporting" type Report struct{} func (p *Project) Name() string ``` ```go // Bad: // In package "sqldb" type DBConnection struct{} ``` ```go // Good: // In package "sqldb" type Connection struct{} ``` ```go // Bad: // In package "ads/targeting" func Process(in *pb.FooProto) *Report { adsTargetingID := in.GetAdsTargetingID() } ``` ```go // Good: // In package "ads/targeting" func Process(in *pb.FooProto) *Report { id := in.GetAdsTargetingID() } ``` Repetition should generally be evaluated in the context of the user of the symbol, rather than in isolation. For example, the following code has lots of names that may be fine in some circumstances, but redundant in context: ```go // Bad: func (db *DB) UserCount() (userCount int, err error) { var userCountInt64 int64 if dbLoadError := db.LoadFromDatabase("count(distinct users)", &userCountInt64); dbLoadError != nil { return 0, fmt.Errorf("failed to load user count: %s", dbLoadError) } userCount = int(userCountInt64) return userCount, nil } ``` Instead, information about names that are clear from context or usage can often be omitted: ```go // Good: func (db *DB) UserCount() (int, error) { var count int64 if err := db.Load("count(distinct users)", &count); err != nil { return 0, fmt.Errorf("failed to load user count: %s", err) } return int(count), nil } ``` <a id="commentary"></a> ## Commentary The conventions around commentary (which include what to comment, what style to use, how to provide runnable examples, etc.) are intended to support the experience of reading the documentation of a public API. See [Effective Go](http://golang.org/doc/effective_go.html#commentary) for more information. The best practices document's section on [documentation conventions] discusses this further. **Best Practice:** Use [doc preview] during development and code review to see whether the documentation and runnable examples are useful and are presented the way you expect them to be. **Tip:** Godoc uses very little special formatting; lists and code snippets should usually be indented to avoid linewrapping. Apart from indentation, decoration should generally be avoided. [doc preview]: best-practices#documentation-preview [documentation conventions]: best-practices#documentation-conventions <a id="comment-line-length"></a> ### Comment line length There is no fixed [line length] for comments in Go. [line length]: guide#line-length Long comment lines should be wrapped to ensure that source is readable in tools which do not perform automatic wrapping of comment lines. If you are uncertain where to wrap, 80 or 100 columns are common choices. However, this is not a hard cut-off; there are situations where breaking a long literal text is harmful. There is no requirement for the specific column width at which wrapping occurs. Aim to be [consistent](guide#consistency) within a file. See this [post from The Go Blog on documentation] for more on commentary. [post from The Go Blog on documentation]: https://blog.golang.org/godoc-documenting-go-code ```text # Good: // This is a comment paragraph. // The length of individual lines doesn't matter in Godoc; // but the choice of wrapping makes it easy to read on narrow screens. // // Don't worry too much about the long URL: // https://supercalifragilisticexpialidocious.example.com:8080/Animalia/Chordata/Mammalia/Rodentia/Geomyoidea/Geomyidae/ // // Similarly, if you have other information that is made awkward // by too many line breaks, use your judgment and include a long line // if it helps rather than hinders. ``` Avoid comments that fit large amounts of text onto a single line, which is a poor reader experience. ```text # Bad: // This is a comment paragraph. While some code editors and viewers will wrap the paragraph for the reader, others will display a very long line that will overflow most windows and require users to scroll horizontally. In addition, even on a screen capable of displaying the entire line, it is easier to read a narrower paragraph than very wide one. // // Don't worry too much about the long URL: // https://supercalifragilisticexpialidocious.example.com:8080/Animalia/Chordata/Mammalia/Rodentia/Geomyoidea/Geomyidae/ ``` <a id="doc-comments"></a> ### Doc comments <a id="TOC-DocComments"></a> All top-level exported names must have doc comments, as should unexported type or function declarations with unobvious behavior or meaning. These comments should be [full sentences] that begin with the name of the object being described. An article ("a", "an", "the") can precede the name to make it read more naturally. ```go // Good: // A Request represents a request to run a command. type Request struct { ... // Encode writes the JSON encoding of req to w. func Encode(w io.Writer, req *Request) { ... ``` Doc comments appear in [Godoc](https://pkg.go.dev/) and are surfaced by IDEs, and therefore should be written for anyone using the package. [full sentences]: #comment-sentences A documentation comment applies to the following symbol, or the group of fields if it appears in a struct. ```go // Good: // Options configure the group management service. type Options struct { // General setup: Name string Group *FooGroup // Dependencies: DB *sql.DB // Customization: LargeGroupThreshold int // optional; default: 10 MinimumMembers int // optional; default: 2 } ``` **Best Practice:** If you have doc comments for unexported code, follow the same custom as if it were exported (namely, starting the comment with the unexported name). This makes it easy to export it later by simply replacing the unexported name with the newly-exported one across both comments and code. <a id="comment-sentences"></a> ### Comment sentences <a id="TOC-CommentSentences"></a> Comments that are complete sentences should be capitalized and punctuated like standard English sentences. (As an exception, it is okay to begin a sentence with an uncapitalized identifier name if it is otherwise clear. Such cases are probably best done only at the beginning of a paragraph.) Comments that are sentence fragments have no such requirements for punctuation or capitalization. [Documentation comments] should always be complete sentences, and as such should always be capitalized and punctuated. Simple end-of-line comments (especially for struct fields) can be simple phrases that assume the field name is the subject. ```go // Good: // A Server handles serving quotes from the collected works of Shakespeare. type Server struct { // BaseDir points to the base directory under which Shakespeare's works are stored. // // The directory structure is expected to be the following: // {BaseDir}/manifest.json // {BaseDir}/{name}/{name}-part{number}.txt BaseDir string WelcomeMessage string // displayed when user logs in ProtocolVersion string // checked against incoming requests PageLength int // lines per page when printing (optional; default: 20) } ``` [Documentation comments]: #doc-comments <a id="examples"></a> ### Examples <a id="TOC-Examples"></a> Packages should clearly document their intended usage. Try to provide a [runnable example]; examples show up in Godoc. Runnable examples belong in the test file, not the production source file. See this example ([Godoc], [source]). [runnable example]: http://blog.golang.org/examples [Godoc]: https://pkg.go.dev/time#example-Duration [source]: https://cs.opensource.google/go/go/+/HEAD:src/time/example_test.go If it isn't feasible to provide a runnable example, example code can be provided within code comments. As with other code and command-line snippets in comments, it should follow standard formatting conventions. <a id="named-result-parameters"></a> ### Named result parameters <a id="TOC-NamedResultParameters"></a> When naming parameters, consider how function signatures appear in Godoc. The name of the function itself and the type of the result parameters are often sufficiently clear. ```go // Good: func (n *Node) Parent1() *Node func (n *Node) Parent2() (*Node, error) ``` If a function returns two or more parameters of the same type, adding names can be useful. ```go // Good: func (n *Node) Children() (left, right *Node, err error) ``` If the caller must take action on particular result parameters, naming them can help suggest what the action is: ```go // Good: // WithTimeout returns a context that will be canceled no later than d duration // from now. // // The caller must arrange for the returned cancel function to be called when // the context is no longer needed to prevent a resource leak. func WithTimeout(parent Context, d time.Duration) (ctx Context, cancel func()) ``` In the code above, cancellation is a particular action a caller must take. However, were the result parameters written as `(Context, func())` alone, it would be unclear what is meant by "cancel function". Don't use named result parameters when the names produce [unnecessary repetition](#repetitive-with-type). ```go // Bad: func (n *Node) Parent1() (node *Node) func (n *Node) Parent2() (node *Node, err error) ``` Don't name result parameters in order to avoid declaring a variable inside the function. This practice results in unnecessary API verbosity at the cost of minor implementation brevity. [Naked returns] are acceptable only in a small function. Once it's a medium-sized function, be explicit with your returned values. Similarly, do not name result parameters just because it enables you to use naked returns. [Clarity](guide#clarity) is always more important than saving a few lines in your function. It is always acceptable to name a result parameter if its value must be changed in a deferred closure. > **Tip:** Types can often be clearer than names in function signatures. > [GoTip #38: Functions as Named Types] demonstrates this. > > In, [`WithTimeout`] above, the real code uses a [`CancelFunc`] instead of a > raw `func()` in the result parameter list and requires little effort to > document. [Naked returns]: https://tour.golang.org/basics/7 [GoTip #38: Functions as Named Types]: https://google.github.io/styleguide/go/index.html#gotip [`WithTimeout`]: https://pkg.go.dev/context#WithTimeout [`CancelFunc`]: https://pkg.go.dev/context#CancelFunc <a id="package-comments"></a> ### Package comments <a id="TOC-PackageComments"></a> Package comments must appear immediately above the package clause with no blank line between the comment and the package name. Example: ```go // Good: // Package math provides basic constants and mathematical functions. // // This package does not guarantee bit-identical results across architectures. package math ``` There must be a single package comment per package. If a package is composed of multiple files, exactly one of the files should have a package comment. Comments for `main` packages have a slightly different form, where the name of the `go_binary` rule in the BUILD file takes the place of the package name. ```go // Good: // The seed_generator command is a utility that generates a Finch seed file // from a set of JSON study configs. package main ``` Other styles of comment are fine as long as the name of the binary is exactly as written in the BUILD file. When the binary name is the first word, capitalizing it is required even though it does not strictly match the spelling of the command-line invocation. ```go // Good: // Binary seed_generator ... // Command seed_generator ... // Program seed_generator ... // The seed_generator command ... // The seed_generator program ... // Seed_generator ... ``` Tips: * Example command-line invocations and API usage can be useful documentation. For Godoc formatting, indent the comment lines containing code. * If there is no obvious primary file or if the package comment is extraordinarily long, it is acceptable to put the doc comment in a file named `doc.go` with only the comment and the package clause. * Multiline comments can be used instead of multiple single-line comments. This is primarily useful if the documentation contains sections which may be useful to copy and paste from the source file, as with sample command-lines (for binaries) and template examples. ```go // Good: /* The seed_generator command is a utility that generates a Finch seed file from a set of JSON study configs. seed_generator *.json | base64 > finch-seed.base64 */ package template ``` * Comments intended for maintainers and that apply to the whole file are typically placed after import declarations. These are not surfaced in Godoc and are not subject to the rules above on package comments. <a id="imports"></a> ## Imports <a id="TOC-Imports"></a> <a id="import-renaming"></a> ### Import renaming Package imports shouldn't normally be renamed, but there are cases where they must be renamed or where a rename improves readability. Local names for imported packages must follow [the guidance around package naming](#package-names), including the prohibition on the use of underscores and capital letters. Try to be [consistent](guide#consistency) by always using the same local name for the same imported package. An imported package *must* be renamed to avoid a name collision with other imports. (A corollary of this is that [good package names](#package-names) should not require renaming.) In the event of a name collision, prefer to rename the most local or project-specific import. Generated protocol buffer packages *must* be renamed to remove underscores from their names, and their local names must have a `pb` suffix. See [proto and stub best practices](best-practices#import-protos) for more information. ```go // Good: import ( foosvcpb "path/to/package/foo_service_go_proto" ) ``` Lastly, an imported, non-autogenerated package *can* be renamed if it has an uninformative name (e.g. `util` or `v1`) Do this sparingly: do not rename the package if the code surrounding the use of the package conveys enough context. When possible, prefer refactoring the package itself with a more suitable name. ```go // Good: import ( core "github.com/kubernetes/api/core/v1" meta "github.com/kubernetes/apimachinery/pkg/apis/meta/v1beta1" ) ``` If you need to import a package whose name collides with a common local variable name that you want to use (e.g. `url`, `ssh`) and you wish to rename the package, the preferred way to do so is with the `pkg` suffix (e.g. `urlpkg`). Note that it is possible to shadow a package with a local variable; this rename is only necessary if the package still needs to be used when such a variable is in scope. <a id="import-grouping"></a> ### Import grouping Imports should be organized into the following groups, in order: 1. Standard library packages 1. Other (project and vendored) packages 1. Protocol Buffer imports (e.g., `fpb "path/to/foo_go_proto"`) 1. Import for [side-effects](https://go.dev/doc/effective_go#blank_import) (e.g., `_ "path/to/package"`) ```go // Good: package main import ( "fmt" "hash/adler32" "os" "github.com/dsnet/compress/flate" "golang.org/x/text/encoding" "google.golang.org/protobuf/proto" foopb "myproj/foo/proto/proto" _ "myproj/rpc/protocols/dial" _ "myproj/security/auth/authhooks" ) ``` <a id="import-blank"></a> ### Import "blank" (`import _`) <a id="TOC-ImportBlank"></a> Packages that are imported only for their side effects (using the syntax `import _ "package"`) may only be imported in a main package, or in tests that require them. Some examples of such packages include: * [time/tzdata](https://pkg.go.dev/time/tzdata) * [image/jpeg](https://pkg.go.dev/image/jpeg) in image processing code Avoid blank imports in library packages, even if the library indirectly depends on them. Constraining side-effect imports to the main package helps control dependencies, and makes it possible to write tests that rely on a different import without conflict or wasted build costs. The following are the only exceptions to this rule: * You may use a blank import to bypass the check for disallowed imports in the [nogo static checker]. * You may use a blank import of the [embed](https://pkg.go.dev/embed) package in a source file which uses the `//go:embed` compiler directive. **Tip:** If you create a library package that indirectly depends on a side-effect import in production, document the intended usage. [nogo static checker]: https://github.com/bazelbuild/rules_go/blob/master/go/nogo.rst <a id="import-dot"></a> ### Import "dot" (`import .`) <a id="TOC-ImportDot"></a> The `import .` form is a language feature that allows bringing identifiers exported from another package to the current package without qualification. See the [language spec](https://go.dev/ref/spec#Import_declarations) for more. Do **not** use this feature in the Google codebase; it makes it harder to tell where the functionality is coming from. ```go // Bad: package foo_test import ( "bar/testutil" // also imports "foo" . "foo" ) var myThing = Bar() // Bar defined in package foo; no qualification needed. ``` ```go // Good: package foo_test import ( "bar/testutil" // also imports "foo" "foo" ) var myThing = foo.Bar() ``` <a id="errors"></a> ## Errors <a id="returning-errors"></a> ### Returning errors <a id="TOC-ReturningErrors"></a> Use `error` to signal that a function can fail. By convention, `error` is the last result parameter. ```go // Good: func Good() error { /* ... */ } ``` Returning a `nil` error is the idiomatic way to signal a successful operation that could otherwise fail. If a function returns an error, callers must treat all non-error return values as unspecified unless explicitly documented otherwise. Commonly, the non-error return values are their zero values, but this cannot be assumed. ```go // Good: func GoodLookup() (*Result, error) { // ... if err != nil { return nil, err } return res, nil } ``` Exported functions that return errors should return them using the `error` type. Concrete error types are susceptible to subtle bugs: a concrete `nil` pointer can get wrapped into an interface and thus become a non-nil value (see the [Go FAQ entry on the topic][nil error]). ```go // Bad: func Bad() *os.PathError { /*...*/ } ``` **Tip:** A function that takes a [`context.Context`] argument should usually return an `error` so that the caller can determine if the context was cancelled while the function was running. [nil error]: https://golang.org/doc/faq#nil_error <a id="error-strings"></a> ### Error strings <a id="TOC-ErrorStrings"></a> Error strings should not be capitalized (unless beginning with an exported name, a proper noun or an acronym) and should not end with punctuation. This is because error strings usually appear within other context before being printed to the user. ```go // Bad: err := fmt.Errorf("Something bad happened.") ``` ```go // Good: err := fmt.Errorf("something bad happened") ``` On the other hand, the style for the full displayed message (logging, test failure, API response, or other UI) depends, but should typically be capitalized. ```go // Good: log.Infof("Operation aborted: %v", err) log.Errorf("Operation aborted: %v", err) t.Errorf("Op(%q) failed unexpectedly; err=%v", args, err) ``` <a id="handle-errors"></a> ### Handle errors <a id="TOC-HandleErrors"></a> Code that encounters an error should make a deliberate choice about how to handle it. It is not usually appropriate to discard errors using `_` variables. If a function returns an error, do one of the following: * Handle and address the error immediately. * Return the error to the caller. * In exceptional situations, call [`log.Fatal`] or (if absolutely necessary) `panic`. **Note:** `log.Fatalf` is not the standard library log. See [#logging]. In the rare circumstance where it is appropriate to ignore or discard an error (for example a call to [`(*bytes.Buffer).Write`] that is documented to never fail), an accompanying comment should explain why this is safe. ```go // Good: var b *bytes.Buffer n, _ := b.Write(p) // never returns a non-nil error ``` For more discussion and examples of error handling, see [Effective Go](http://golang.org/doc/effective_go.html#errors) and [best practices](best-practices.md#error-handling). [`(*bytes.Buffer).Write`]: https://pkg.go.dev/bytes#Buffer.Write <a id="in-band-errors"></a> ### In-band errors <a id="TOC-In-Band-Errors"></a> In C and similar languages, it is common for functions to return values like -1, null, or the empty string to signal errors or missing results. This is known as in-band error handling. ```go // Bad: // Lookup returns the value for key or -1 if there is no mapping for key. func Lookup(key string) int ``` Failing to check for an in-band error value can lead to bugs and can attribute errors to the wrong function. ```go // Bad: // The following line returns an error that Parse failed for the input value, // whereas the failure was that there is no mapping for missingKey. return Parse(Lookup(missingKey)) ``` Go's support for multiple return values provides a better solution (see the [Effective Go section on multiple returns]). Instead of requiring clients to check for an in-band error value, a function should return an additional value to indicate whether its other return values are valid. This return value may be an error or a boolean when no explanation is needed, and should be the final return value. ```go // Good: // Lookup returns the value for key or ok=false if there is no mapping for key. func Lookup(key string) (value string, ok bool) ``` This API prevents the caller from incorrectly writing `Parse(Lookup(key))` which causes a compile-time error, since `Lookup(key)` has 2 outputs. Returning errors in this way encourages more robust and explicit error handling: ```go // Good: value, ok := Lookup(key) if !ok { return fmt.Errorf("no value for %q", key) } return Parse(value) ``` Some standard library functions, like those in package `strings`, return in-band error values. This greatly simplifies string-manipulation code at the cost of requiring more diligence from the programmer. In general, Go code in the Google codebase should return additional values for errors. [Effective Go section on multiple returns]: http://golang.org/doc/effective_go.html#multiple-returns <a id="indent-error-flow"></a> ### Indent error flow <a id="TOC-IndentErrorFlow"></a> Handle errors before proceeding with the rest of your code. This improves the readability of the code by enabling the reader to find the normal path quickly. This same logic applies to any block which tests a condition then ends in a terminal condition (e.g., `return`, `panic`, `log.Fatal`). Code that runs if the terminal condition is not met should appear after the `if` block, and should not be indented in an `else` clause. ```go // Good: if err != nil { // error handling return // or continue, etc. } // normal code ``` ```go // Bad: if err != nil { // error handling } else { // normal code that looks abnormal due to indentation } ``` > **Tip:** If you are using a variable for more than a few lines of code, it is > generally not worth using the `if`-with-initializer style. In these cases, it > is usually better to move the declaration out and use a standard `if` > statement: > > ```go > // Good: > x, err := f() > if err != nil { > // error handling > return > } > // lots of code that uses x > // across multiple lines > ``` > > ```go > // Bad: > if x, err := f(); err != nil { > // error handling > return > } else { > // lots of code that uses x > // across multiple lines > } > ``` See [Go Tip #1: Line of Sight] and [TotT: Reduce Code Complexity by Reducing Nesting](https://testing.googleblog.com/2017/06/code-health-reduce-nesting-reduce.html) for more details. [Go Tip #1: Line of Sight]: https://google.github.io/styleguide/go/index.html#gotip <a id="language"></a> ## Language <a id="literal-formatting"></a> ### Literal formatting Go has an exceptionally powerful [composite literal syntax], with which it is possible to express deeply-nested, complicated values in a single expression. Where possible, this literal syntax should be used instead of building values field-by-field. The `gofmt` formatting for literals is generally quite good, but there are some additional rules for keeping these literals readable and maintainable. [composite literal syntax]: https://golang.org/ref/spec#Composite_literals <a id="literal-field-names"></a> #### Field names Struct literals must specify **field names** for types defined outside the current package. * Include field names for types from other packages. ```go // Good: // https://pkg.go.dev/encoding/csv#Reader r := csv.Reader{ Comma: ',', Comment: '#', FieldsPerRecord: 4, } ``` The position of fields in a struct and the full set of fields (both of which are necessary to get right when field names are omitted) are not usually considered to be part of a struct's public API; specifying the field name is needed to avoid unnecessary coupling. ```go // Bad: r := csv.Reader{',', '#', 4, false, false, false, false} ``` * For package-local types, field names are optional. ```go // Good: okay := Type{42} also := internalType{4, 2} ``` Field names should still be used if it makes the code clearer, and it is very common to do so. For example, a struct with a large number of fields should almost always be initialized with field names. <!-- TODO: Maybe a better example here that doesn't have many fields. --> ```go // Good: okay := StructWithLotsOfFields{ field1: 1, field2: "two", field3: 3.14, field4: true, } ``` <a id="literal-matching-braces"></a> #### Matching braces The closing half of a brace pair should always appear on a line with the same amount of indentation as the opening brace. One-line literals necessarily have this property. When the literal spans multiple lines, maintaining this property keeps the brace matching for literals the same as brace matching for common Go syntactic constructs like functions and `if` statements. The most common mistake in this area is putting the closing brace on the same line as a value in a multi-line struct literal. In these cases, the line should end with a comma and the closing brace should appear on the next line. ```go // Good: good := []*Type{{Key: "value"}} ``` ```go // Good: good := []*Type{ {Key: "multi"}, {Key: "line"}, } ``` ```go // Bad: bad := []*Type{ {Key: "multi"}, {Key: "line"}} ``` ```go // Bad: bad := []*Type{ { Key: "value"}, } ``` <a id="literal-cuddled-braces"></a> #### Cuddled braces Dropping whitespace between braces (aka "cuddling" them) for slice and array literals is only permitted when both of the following are true. * The [indentation matches](#literal-matching-braces) * The inner values are also literals or proto builders (i.e. not a variable or other expression) ```go // Good: good := []*Type{ { // Not cuddled Field: "value", }, { Field: "value", }, } ``` ```go // Good: good := []*Type{{ // Cuddled correctly Field: "value", }, { Field: "value", }} ``` ```go // Good: good := []*Type{ first, // Can't be cuddled {Field: "second"}, } ``` ```go // Good: okay := []*pb.Type{pb.Type_builder{ Field: "first", // Proto Builders may be cuddled to save vertical space }.Build(), pb.Type_builder{ Field: "second", }.Build()} ``` ```go // Bad: bad := []*Type{ first, { Field: "second", }} ``` <a id="literal-repeated-type-names"></a> #### Repeated type names Repeated type names may be omitted from slice and map literals. This can be helpful in reducing clutter. A reasonable occasion for repeating the type names explicitly is when dealing with a complex type that is not common in your project, when the repetitive type names are on lines that are far apart and can remind the reader of the context. ```go // Good: good := []*Type{ {A: 42}, {A: 43}, } ``` ```go // Bad: repetitive := []*Type{ &Type{A: 42}, &Type{A: 43}, } ``` ```go // Good: good := map[Type1]*Type2{ {A: 1}: {B: 2}, {A: 3}: {B: 4}, } ``` ```go // Bad: repetitive := map[Type1]*Type2{ Type1{A: 1}: &Type2{B: 2}, Type1{A: 3}: &Type2{B: 4}, } ``` **Tip:** If you want to remove repetitive type names in struct literals, you can run `gofmt -s`. <a id="literal-zero-value-fields"></a> #### Zero-value fields [Zero-value] fields may be omitted from struct literals when clarity is not lost as a result. Well-designed APIs often employ zero-value construction for enhanced readability. For example, omitting the three zero-value fields from the following struct draws attention to the only option that is being specified. [Zero-value]: https://golang.org/ref/spec#The_zero_value ```go // Bad: import ( "github.com/golang/leveldb" "github.com/golang/leveldb/db" ) ldb := leveldb.Open("/my/table", &db.Options{ BlockSize: 1<<16, ErrorIfDBExists: true, // These fields all have their zero values. BlockRestartInterval: 0, Comparer: nil, Compression: nil, FileSystem: nil, FilterPolicy: nil, MaxOpenFiles: 0, WriteBufferSize: 0, VerifyChecksums: false, }) ``` ```go // Good: import ( "github.com/golang/leveldb" "github.com/golang/leveldb/db" ) ldb := leveldb.Open("/my/table", &db.Options{ BlockSize: 1<<16, ErrorIfDBExists: true, }) ``` Structs within table-driven tests often benefit from [explicit field names], especially when the test struct is not trivial. This allows the author to omit the zero-valued fields entirely when the fields in question are not related to the test case. For example, successful test cases should omit any error-related or failure-related fields. In cases where the zero value is necessary to understand the test case, such as testing for zero or `nil` inputs, the field names should be specified. [explicit field names]: #literal-field-names **Concise** ```go tests := []struct { input string wantPieces []string wantErr error }{ { input: "1.2.3.4", wantPieces: []string{"1", "2", "3", "4"}, }, { input: "hostname", wantErr: ErrBadHostname, }, } ``` **Explicit** ```go tests := []struct { input string wantIPv4 bool wantIPv6 bool wantErr bool }{ { input: "1.2.3.4", wantIPv4: true, wantIPv6: false, }, { input: "1:2::3:4", wantIPv4: false, wantIPv6: true, }, { input: "hostname", wantIPv4: false, wantIPv6: false, wantErr: true, }, } ``` <a id="nil-slices"></a> ### Nil slices For most purposes, there is no functional difference between `nil` and the empty slice. Built-in functions like `len` and `cap` behave as expected on `nil` slices. ```go // Good: import "fmt" var s []int // nil fmt.Println(s) // [] fmt.Println(len(s)) // 0 fmt.Println(cap(s)) // 0 for range s {...} // no-op s = append(s, 42) fmt.Println(s) // [42] ``` If you declare an empty slice as a local variable (especially if it can be the source of a return value), prefer the nil initialization to reduce the risk of bugs by callers. ```go // Good: var t []string ``` ```go // Bad: t := []string{} ``` Do not create APIs that force their clients to make distinctions between nil and the empty slice. ```go // Good: // Ping pings its targets. // Returns hosts that successfully responded. func Ping(hosts []string) ([]string, error) { ... } ``` ```go // Bad: // Ping pings its targets and returns a list of hosts // that successfully responded. Can be empty if the input was empty. // nil signifies that a system error occurred. func Ping(hosts []string) []string { ... } ``` When designing interfaces, avoid making a distinction between a `nil` slice and a non-`nil`, zero-length slice, as this can lead to subtle programming errors. This is typically accomplished by using `len` to check for emptiness, rather than `== nil`. This implementation accepts both `nil` and zero-length slices as "empty": ```go // Good: // describeInts describes s with the given prefix, unless s is empty. func describeInts(prefix string, s []int) { if len(s) == 0 { return } fmt.Println(prefix, s) } ``` Instead of relying on the distinction as a part of the API: ```go // Bad: func maybeInts() []int { /* ... */ } // describeInts describes s with the given prefix; pass nil to skip completely. func describeInts(prefix string, s []int) { // The behavior of this function unintentionally changes depending on what // maybeInts() returns in 'empty' cases (nil or []int{}). if s == nil { return } fmt.Println(prefix, s) } describeInts("Here are some ints:", maybeInts()) ``` See [in-band errors] for further discussion. [in-band errors]: #in-band-errors <a id="indentation-confusion"></a> ### Indentation confusion Avoid introducing a line break if it would align the rest of the line with an indented code block. If this is unavoidable, leave a space to separate the code in the block from the wrapped line. ```go // Bad: if longCondition1 && longCondition2 && // Conditions 3 and 4 have the same indentation as the code within the if. longCondition3 && longCondition4 { log.Info("all conditions met") } ``` See the following sections for specific guidelines and examples: * [Function formatting](#func-formatting) * [Conditionals and loops](#conditional-formatting) * [Literal formatting](#literal-formatting) <a id="func-formatting"></a> ### Function formatting The signature of a function or method declaration should remain on a single line to avoid [indentation confusion](#indentation-confusion). Function argument lists can make some of the longest lines in a Go source file. However, they precede a change in indentation, and therefore it is difficult to break the line in a way that does not make subsequent lines look like part of the function body in a confusing way: ```go // Bad: func (r *SomeType) SomeLongFunctionName(foo1, foo2, foo3 string, foo4, foo5, foo6 int) { foo7 := bar(foo1) // ... } ``` See [best practices](best-practices#funcargs) for a few options for shortening the call sites of functions that would otherwise have many arguments. Lines can often be shortened by factoring out local variables. ```go // Good: local := helper(some, parameters, here) good := foo.Call(list, of, parameters, local) ``` Similarly, function and method calls should not be separated based solely on line length. ```go // Good: good := foo.Call(long, list, of, parameters, all, on, one, line) ``` ```go // Bad: bad := foo.Call(long, list, of, parameters, with, arbitrary, line, breaks) ``` Avoid adding inline comments to specific function arguments where possible. Instead, use an [option struct](best-practices#option-structure) or add more detail to the function documentation. ```go // Good: good := server.New(ctx, server.Options{Port: 42}) ``` ```go // Bad: bad := server.New( ctx, 42, // Port ) ``` If the API cannot be changed or if the local call is unusual (whether or not the call is too long), it is always permissible to add line breaks if it aids in understanding the call. ```go // Good: canvas.RenderHeptagon(fillColor, x0, y0, vertexColor0, x1, y1, vertexColor1, x2, y2, vertexColor2, x3, y3, vertexColor3, x4, y4, vertexColor4, x5, y5, vertexColor5, x6, y6, vertexColor6, ) ``` Note that the lines in the above example are not wrapped at a specific column boundary but are grouped based on vertex coordinates and color. Long string literals within functions should not be broken for the sake of line length. For functions that include such strings, a line break can be added after the string format, and the arguments can be provided on the next or subsequent lines. The decision about where the line breaks should go is best made based on semantic groupings of inputs, rather than based purely on line length. ```go // Good: log.Warningf("Database key (%q, %d, %q) incompatible in transaction started by (%q, %d, %q)", currentCustomer, currentOffset, currentKey, txCustomer, txOffset, txKey) ``` ```go // Bad: log.Warningf("Database key (%q, %d, %q) incompatible in"+ " transaction started by (%q, %d, %q)", currentCustomer, currentOffset, currentKey, txCustomer, txOffset, txKey) ``` <a id="conditional-formatting"></a> ### Conditionals and loops An `if` statement should not be line broken; multi-line `if` clauses can lead to [indentation confusion](#indentation-confusion). ```go // Bad: // The second if statement is aligned with the code within the if block, causing // indentation confusion. if db.CurrentStatusIs(db.InTransaction) && db.ValuesEqual(db.TransactionKey(), row.Key()) { return db.Errorf(db.TransactionError, "query failed: row (%v): key does not match transaction key", row) } ``` If the short-circuit behavior is not required, the boolean operands can be extracted directly: ```go // Good: inTransaction := db.CurrentStatusIs(db.InTransaction) keysMatch := db.ValuesEqual(db.TransactionKey(), row.Key()) if inTransaction && keysMatch { return db.Error(db.TransactionError, "query failed: row (%v): key does not match transaction key", row) } ``` There may also be other locals that can be extracted, especially if the conditional is already repetitive: ```go // Good: uid := user.GetUniqueUserID() if db.UserIsAdmin(uid) || db.UserHasPermission(uid, perms.ViewServerConfig) || db.UserHasPermission(uid, perms.CreateGroup) { // ... } ``` ```go // Bad: if db.UserIsAdmin(user.GetUniqueUserID()) || db.UserHasPermission(user.GetUniqueUserID(), perms.ViewServerConfig) || db.UserHasPermission(user.GetUniqueUserID(), perms.CreateGroup) { // ... } ``` `if` statements that contain closures or multi-line struct literals should ensure that the [braces match](#literal-matching-braces) to avoid [indentation confusion](#indentation-confusion). ```go // Good: if err := db.RunInTransaction(func(tx *db.TX) error { return tx.Execute(userUpdate, x, y, z) }); err != nil { return fmt.Errorf("user update failed: %s", err) } ``` ```go // Good: if _, err := client.Update(ctx, &upb.UserUpdateRequest{ ID: userID, User: user, }); err != nil { return fmt.Errorf("user update failed: %s", err) } ``` Similarly, don't try inserting artificial linebreaks into `for` statements. You can always let the line simply be long if there is no elegant way to refactor it: ```go // Good: for i, max := 0, collection.Size(); i < max && !collection.HasPendingWriters(); i++ { // ... } ``` Often, though, there is: ```go // Good: for i, max := 0, collection.Size(); i < max; i++ { if collection.HasPendingWriters() { break } // ... } ``` `switch` and `case` statements should also remain on a single line. ```go // Good: switch good := db.TransactionStatus(); good { case db.TransactionStarting, db.TransactionActive, db.TransactionWaiting: // ... case db.TransactionCommitted, db.NoTransaction: // ... default: // ... } ``` ```go // Bad: switch bad := db.TransactionStatus(); bad { case db.TransactionStarting, db.TransactionActive, db.TransactionWaiting: // ... case db.TransactionCommitted, db.NoTransaction: // ... default: // ... } ``` If the line is excessively long, indent all cases and separate them with a blank line to avoid [indentation confusion](#indentation-confusion): ```go // Good: switch db.TransactionStatus() { case db.TransactionStarting, db.TransactionActive, db.TransactionWaiting, db.TransactionCommitted: // ... case db.NoTransaction: // ... default: // ... } ``` In conditionals comparing a variable to a constant, place the variable value on the left hand side of the equality operator: ```go // Good: if result == "foo" { // ... } ``` Instead of the less clear phrasing where the constant comes first (["Yoda style conditionals"](https://en.wikipedia.org/wiki/Yoda_conditions)): ```go // Bad: if "foo" == result { // ... } ``` <a id="copying"></a> ### Copying <a id="TOC-Copying"></a> To avoid unexpected aliasing and similar bugs, be careful when copying a struct from another package. For example, synchronization objects such as `sync.Mutex` must not be copied. The `bytes.Buffer` type contains a `[]byte` slice and, as an optimization for small strings, a small byte array to which the slice may refer. If you copy a `Buffer`, the slice in the copy may alias the array in the original, causing subsequent method calls to have surprising effects. In general, do not copy a value of type `T` if its methods are associated with the pointer type, `*T`. ```go // Bad: b1 := bytes.Buffer{} b2 := b1 ``` Invoking a method that takes a value receiver can hide the copy. When you author an API, you should generally take and return pointer types if your structs contain fields that should not be copied. These are acceptable: ```go // Good: type Record struct { buf bytes.Buffer // other fields omitted } func New() *Record {...} func (r *Record) Process(...) {...} func Consumer(r *Record) {...} ``` But these are usually wrong: ```go // Bad: type Record struct { buf bytes.Buffer // other fields omitted } func (r Record) Process(...) {...} // Makes a copy of r.buf func Consumer(r Record) {...} // Makes a copy of r.buf ``` This guidance also applies to copying `sync.Mutex`. <a id="dont-panic"></a> ### Don't panic <a id="TOC-Don-t-Panic"></a> Do not use `panic` for normal error handling. Instead, use `error` and multiple return values. See the [Effective Go section on errors]. Within `package main` and initialization code, consider [`log.Exit`] for errors that should terminate the program (e.g., invalid configuration), as in many of these cases a stack trace will not help the reader. Please note that [`log.Exit`] calls [`os.Exit`] and any deferred functions will not be run. For errors that indicate "impossible" conditions, namely bugs that should always be caught during code review and/or testing, a function may reasonably return an error or call [`log.Fatal`]. Also see [when panic is acceptable](best-practices.md#when-to-panic). **Note:** `log.Fatalf` is not the standard library log. See [#logging]. [Effective Go section on errors]: http://golang.org/doc/effective_go.html#errors [`os.Exit`]: https://pkg.go.dev/os#Exit <a id="must-functions"></a> ### Must functions Setup helper functions that stop the program on failure follow the naming convention `MustXYZ` (or `mustXYZ`). In general, they should only be called early on program startup, not on things like user input where normal Go error handling is preferred. This often comes up for functions called to initialize package-level variables exclusively at [package initialization time](https://golang.org/ref/spec#Package_initialization) (e.g. [template.Must](https://golang.org/pkg/text/template/#Must) and [regexp.MustCompile](https://golang.org/pkg/regexp/#MustCompile)). ```go // Good: func MustParse(version string) *Version { v, err := Parse(version) if err != nil { panic(fmt.Sprintf("MustParse(%q) = _, %v", version, err)) } return v } // Package level "constant". If we wanted to use `Parse`, we would have had to // set the value in `init`. var DefaultVersion = MustParse("1.2.3") ``` The same convention may be used in test helpers that only stop the current test (using `t.Fatal`). Such helpers are often convenient in creating test values, for example in struct fields of [table driven tests](#table-driven-tests), as functions that return errors cannot be directly assigned to a struct field. ```go // Good: func mustMarshalAny(t *testing.T, m proto.Message) *anypb.Any { t.Helper() any, err := anypb.New(m) if err != nil { t.Fatalf("mustMarshalAny(t, m) = %v; want %v", err, nil) } return any } func TestCreateObject(t *testing.T) { tests := []struct{ desc string data *anypb.Any }{ { desc: "my test case", // Creating values directly within table driven test cases. data: mustMarshalAny(t, mypb.Object{}), }, // ... } // ... } ``` In both of these cases, the value of this pattern is that the helpers can be called in a "value" context. These helpers should not be called in places where it's difficult to ensure an error would be caught or in a context where an error should be [checked](#handle-errors) (e.g., in many request handlers). For constant inputs, this allows tests to easily ensure that the `Must` arguments are well-formed, and for non-constant inputs it permits tests to validate that errors are [properly handled or propagated](best-practices#error-handling). Where `Must` functions are used in a test, they should generally be [marked as a test helper](#mark-test-helpers) and call `t.Fatal` on error (see [error handling in test helpers](best-practices#test-helper-error-handling) for more considerations of using that). They should not be used when [ordinary error handling](best-practices#error-handling) is possible (including with some refactoring): ```go // Bad: func Version(o *servicepb.Object) (*version.Version, error) { // Return error instead of using Must functions. v := version.MustParse(o.GetVersionString()) return dealiasVersion(v) } ``` <a id="goroutine-lifetimes"></a> ### Goroutine lifetimes <a id="TOC-GoroutineLifetimes"></a> When you spawn goroutines, make it clear when or whether they exit. Goroutines can leak by blocking on channel sends or receives. The garbage collector will not terminate a goroutine blocked on a channel even if no other goroutine has a reference to the channel. Even when goroutines do not leak, leaving them in-flight when they are no longer needed can cause other subtle and hard-to-diagnose problems. Sending on a channel that has been closed causes a panic. ```go // Bad: ch := make(chan int) ch <- 42 close(ch) ch <- 13 // panic ``` Modifying still-in-use inputs "after the result isn't needed" can lead to data races. Leaving goroutines in-flight for arbitrarily long can lead to unpredictable memory usage. Concurrent code should be written such that the goroutine lifetimes are obvious. Typically this will mean keeping synchronization-related code constrained within the scope of a function and factoring out the logic into [synchronous functions]. If the concurrency is still not obvious, it is important to document when and why the goroutines exit. Code that follows best practices around context usage often helps make this clear. It is conventionally managed with a [`context.Context`]: ```go // Good: func (w *Worker) Run(ctx context.Context) error { var wg sync.WaitGroup // ... for item := range w.q { // process returns at latest when the context is cancelled. wg.Add(1) go func() { defer wg.Done() process(ctx, item) }() } // ... wg.Wait() // Prevent spawned goroutines from outliving this function. } ``` There are other variants of the above that use raw signal channels like `chan struct{}`, synchronized variables, [condition variables][rethinking-slides], and more. The important part is that the goroutine's end is evident for subsequent maintainers. In contrast, the following code is careless about when its spawned goroutines finish: ```go // Bad: func (w *Worker) Run() { // ... for item := range w.q { // process returns when it finishes, if ever, possibly not cleanly // handling a state transition or termination of the Go program itself. go process(item) } // ... } ``` This code may look OK, but there are several underlying problems: * The code probably has undefined behavior in production, and the program may not terminate cleanly, even if the operating system releases the resources. * The code is difficult to test meaningfully due to the code's indeterminate lifecycle. * The code may leak resources as described above. See also: * [Never start a goroutine without knowing how it will stop][cheney-stop] * Rethinking Classical Concurrency Patterns: [slides][rethinking-slides], [video][rethinking-video] * [When Go programs end] * [Documentation Conventions: Contexts] [synchronous functions]: #synchronous-functions [cheney-stop]: https://dave.cheney.net/2016/12/22/never-start-a-goroutine-without-knowing-how-it-will-stop [rethinking-slides]: https://drive.google.com/file/d/1nPdvhB0PutEJzdCq5ms6UI58dp50fcAN/view [rethinking-video]: https://www.youtube.com/watch?v=5zXAHh5tJqQ [When Go programs end]: https://changelog.com/gotime/165 [Documentation Conventions: Contexts]: best-practices.md#documentation-conventions-contexts <a id="interfaces"></a> ### Interfaces <a id="TOC-Interfaces"></a> Avoid creating interfaces until a [real need](guide#simplicity) exists. Focus on the required behavior rather than just abstract named patterns like "service" or "repository" and the like. * Do not wrap RPC clients in new manual interfaces just for the sake of abstraction or testing. [Use real transports](best-practices#use-real-transports) instead ([testing RPC]). * Do not define back doors or export [test double] implementations of an interface solely for testing. Prefer testing via the [public API] of the real implementation instead. Design interfaces to be small for easier implementation and composition ([GoTip #78: Minimal Viable Interfaces]). Document interfaces appropriately including their contract, edge cases, and expected errors. Keep interface types unexported if they are only used internally within a package. The consumer of the interface should define it (not the package implementing the interface), ensuring it includes only the methods they actually use. The producer package may export the interface if the interface is the product (a common protocol) to prevent interface redefinition bloat. There is an adage: Functions should take interfaces as arguments but return concrete types ([GoTip #49: Accept Interfaces, Return Concrete Types]). Returning concrete types allows the caller to have access to every public method and field of that specific implementation, not just the subset of methods defined in a pre-chosen interface. The caller can still pass that concrete result into any other function that expects an interface. Sometimes returning an interface is acceptable for encapsulation (e.g., `error` interface), and certain constructs like command, chaining, factory, and [strategy](https://en.wikipedia.org/wiki/Strategy_pattern) patterns. Deeper discussion on interfaces exists in the [Best Practices' section on interfaces](best-practices#interfaces). [GoTip #78: Minimal Viable Interfaces]: https://google.github.io/styleguide/go/index.html#gotip [GoTip #49: Accept Interfaces, Return Concrete Types]: https://google.github.io/styleguide/go/index.html#gotip [testing RPC]: https://codelabs.developers.google.com/grpc/getting-started-grpc-go#3 [test double]: https://abseil.io/resources/swe-book/html/ch13.html [public API]: https://abseil.io/resources/swe-book/html/ch12.html#test_via_public_apis <a id="generics"></a> ### Generics Generics (formally called "[Type Parameters]") are allowed where they fulfill your business requirements. In many applications, a conventional approach using existing language features (slices, maps, interfaces, and so on) works just as well without the added complexity, so be wary of premature use. See the discussion on [least mechanism](guide#least-mechanism). When introducing an exported API that uses generics, make sure it is suitably documented. It's highly encouraged to include motivating runnable [examples]. Do not use generics just because you are implementing an algorithm or data structure that does not care about the type of its member elements. If there is only one type being instantiated in practice, start by making your code work on that type without using generics at all. Adding polymorphism later will be straightforward compared to removing abstraction that is found to be unnecessary. Do not use generics to invent domain-specific languages (DSLs). In particular, refrain from introducing error-handling frameworks that might put a significant burden on readers. Instead prefer established [error handling](#errors) practices. For testing, be especially wary of introducing [assertion libraries](#assert) or frameworks that result in less useful [test failures](#useful-test-failures). In general: * [Write code, don't design types]. From a GopherCon talk by Robert Griesemer and Ian Lance Taylor. * If you have several types that share a useful unifying interface, consider modeling the solution using that interface. Generics may not be needed. * Otherwise, instead of relying on the `any` type and excessive [type switching](https://tour.golang.org/methods/16), consider generics. See also: * [Using Generics in Go], talk by Ian Lance Taylor * [Generics tutorial] on Go's webpage [Generics tutorial]: https://go.dev/doc/tutorial/generics [Type Parameters]: https://go.dev/design/43651-type-parameters [Using Generics in Go]: https://www.youtube.com/watch?v=nr8EpUO9jhw [Write code, don't design types]: https://www.youtube.com/watch?v=Pa_e9EeCdy8&t=1250s <a id="pass-values"></a> ### Pass values <a id="TOC-PassValues"></a> Do not pass pointers as function arguments just to save a few bytes. If a function reads its argument `x` only as `*x` throughout, then the argument shouldn't be a pointer. Common instances of this include passing a pointer to a string (`*string`) or a pointer to an interface value (`*io.Reader`). In both cases, the value itself is a fixed size and can be passed directly. This advice does not apply to large structs, or even small structs that may increase in size. In particular, protocol buffer messages should generally be handled by pointer rather than by value. The pointer type satisfies the `proto.Message` interface (accepted by `proto.Marshal`, `protocmp.Transform`, etc.), and protocol buffer messages can be quite large and often grow larger over time. <a id="receiver-type"></a> ### Receiver type <a id="TOC-ReceiverType"></a> A [method receiver] can be passed either as a value or a pointer, just as if it were a regular function parameter. The choice between the two is based on which [method set(s)] the method should be a part of. [method receiver]: https://golang.org/ref/spec#Method_declarations [method set(s)]: https://golang.org/ref/spec#Method_sets **Correctness wins over speed or simplicity.** There are cases where you must use a pointer value. In other cases, pick pointers for large types or as future-proofing if you don't have a good sense of how the code will grow, and use values for simple [plain old data]. The list below spells out each case in further detail: * If the receiver is a slice and the method doesn't reslice or reallocate the slice, use a value rather than a pointer. ```go // Good: type Buffer []byte func (b Buffer) Len() int { return len(b) } ``` * If the method needs to mutate the receiver, the receiver must be a pointer. ```go // Good: type Counter int func (c *Counter) Inc() { *c++ } // See https://pkg.go.dev/container/heap. type Queue []Item func (q *Queue) Push(x Item) { *q = append([]Item{x}, *q...) } ``` * If the receiver is a struct containing fields that [cannot safely be copied](#copying), use a pointer receiver. Common examples are [`sync.Mutex`] and other synchronization types. ```go // Good: type Counter struct { mu sync.Mutex total int } func (c *Counter) Inc() { c.mu.Lock() defer c.mu.Unlock() c.total++ } ``` **Tip:** Check the type's [Godoc] for information about whether it is safe or unsafe to copy. * If the receiver is a "large" struct or array, a pointer receiver may be more efficient. Passing a struct is equivalent to passing all of its fields or elements as arguments to the method. If that seems too large to [pass by value](#pass-values), a pointer is a good choice. * For methods that will call or run concurrently with other functions that modify the receiver, use a value if those modifications should not be visible to your method; otherwise use a pointer. * If the receiver is a struct or array, any of whose elements is a pointer to something that may be mutated, prefer a pointer receiver to make the intention of mutability clear to the reader. ```go // Good: type Counter struct { m *Metric } func (c *Counter) Inc() { c.m.Add(1) } ``` * If the receiver is a [built-in type], such as an integer or a string, that does not need to be modified, use a value. ```go // Good: type User string func (u User) String() { return string(u) } ``` * If the receiver is a map, function, or channel, use a value rather than a pointer. ```go // Good: // See https://pkg.go.dev/net/http#Header. type Header map[string][]string func (h Header) Add(key, value string) { /* omitted */ } ``` * If the receiver is a "small" array or struct that is naturally a value type with no mutable fields and no pointers, a value receiver is usually the right choice. ```go // Good: // See https://pkg.go.dev/time#Time. type Time struct { /* omitted */ } func (t Time) Add(d Duration) Time { /* omitted */ } ``` * When in doubt, use a pointer receiver. As a general guideline, prefer to make the methods for a type either all pointer methods or all value methods. **Note:** There is a lot of misinformation about whether passing a value or a pointer to a function can affect performance. The compiler can choose to pass pointers to values on the stack as well as copying values on the stack, but these considerations should not outweigh the readability and correctness of the code in most circumstances. When the performance does matter, it is important to profile both approaches with a realistic benchmark before deciding that one approach outperforms the other. [plain old data]: https://en.wikipedia.org/wiki/Passive_data_structure [`sync.Mutex`]: https://pkg.go.dev/sync#Mutex [built-in type]: https://pkg.go.dev/builtin <a id="switch-break"></a> ### `switch` and `break` <a id="TOC-SwitchBreak"></a> Do not use `break` statements without target labels at the ends of `switch` clauses; they are redundant. Unlike in C and Java, `switch` clauses in Go automatically break, and a `fallthrough` statement is needed to achieve the C-style behavior. Use a comment rather than `break` if you want to clarify the purpose of an empty clause. ```go // Good: switch x { case "A", "B": buf.WriteString(x) case "C": // handled outside of the switch statement default: return fmt.Errorf("unknown value: %q", x) } ``` ```go // Bad: switch x { case "A", "B": buf.WriteString(x) break // this break is redundant case "C": break // this break is redundant default: return fmt.Errorf("unknown value: %q", x) } ``` > **Note:** If a `switch` clause is within a `for` loop, using `break` within > `switch` does not exit the enclosing `for` loop. > > ```go > for { > switch x { > case "A": > break // exits the switch, not the loop > } > } > ``` > > To escape the enclosing loop, use a label on the `for` statement: > > ```go > loop: > for { > switch x { > case "A": > break loop // exits the loop > } > } > ``` <a id="synchronous-functions"></a> ### Synchronous functions <a id="TOC-SynchronousFunctions"></a> Synchronous functions return their results directly and finish any callbacks or channel operations before returning. Prefer synchronous functions over asynchronous functions. Synchronous functions keep goroutines localized within a call. This helps to reason about their lifetimes, and avoid leaks and data races. Synchronous functions are also easier to test, since the caller can pass an input and check the output without the need for polling or synchronization. If necessary, the caller can add concurrency by calling the function in a separate goroutine. However, it is quite difficult (sometimes impossible) to remove unnecessary concurrency at the caller side. See also: * "Rethinking Classical Concurrency Patterns", talk by Bryan Mills: [slides][rethinking-slides], [video][rethinking-video] <a id="type-aliases"></a> ### Type aliases <a id="TOC-TypeAliases"></a> Use a *type definition*, `type T1 T2`, to define a new type. Use a [*type alias*], `type T1 = T2`, to refer to an existing type without defining a new type. Type aliases are rare; their primary use is to aid migrating packages to new source code locations. Don't use type aliasing when it is not needed. [*type alias*]: http://golang.org/ref/spec#Type_declarations <a id="use-percent-q"></a> ### Use %q <a id="TOC-UsePercentQ"></a> Go's format functions (`fmt.Printf` etc.) have a `%q` verb which prints strings inside double-quotation marks. ```go // Good: fmt.Printf("value %q looks like English text", someText) ``` Prefer using `%q` over doing the equivalent manually, using `%s`: ```go // Bad: fmt.Printf("value \"%s\" looks like English text", someText) // Avoid manually wrapping strings with single-quotes too: fmt.Printf("value '%s' looks like English text", someText) ``` Using `%q` is recommended in output intended for humans where the input value could possibly be empty or contain control characters. It can be very hard to notice a silent empty string, but `""` stands out clearly as such. <a id="use-any"></a> ### Use any Go 1.18 introduces an `any` type as an [alias] to `interface{}`. Because it is an alias, `any` is equivalent to `interface{}` in many situations and in others it is easily interchangeable via an explicit conversion. Prefer to use `any` in new code. [alias]: https://go.googlesource.com/proposal/+/master/design/18130-type-alias.md ## Common libraries <a id="flags"></a> ### Flags <a id="TOC-Flags"></a> Go programs in the Google codebase use an internal variant of the [standard `flag` package]. It has a similar interface but interoperates well with internal Google systems. Flag names in Go binaries should prefer to use underscores to separate words, though the variables that hold a flag's value should follow the standard Go name style ([mixed caps]). Specifically, the flag name should be in snake case, and the variable name should be the equivalent name in camel case. ```go // Good: var ( pollInterval = flag.Duration("poll_interval", time.Minute, "Interval to use for polling.") ) ``` ```go // Bad: var ( poll_interval = flag.Int("pollIntervalSeconds", 60, "Interval to use for polling in seconds.") ) ``` Flags must only be defined in `package main` or equivalent. General-purpose packages should be configured using Go APIs, not by punching through to the command-line interface; don't let importing a library export new flags as a side effect. That is, prefer explicit function arguments or struct field assignment or much less frequently and under the strictest of scrutiny exported global variables. In the extremely rare case that it is necessary to break this rule, the flag name must clearly indicate the package that it configures. If your flags are global variables, place them in their own `var` group, following the imports section. There is additional discussion around best practices for creating [complex CLIs] with subcommands. See also: * [Tip of the Week #45: Avoid Flags, Especially in Library Code][totw-45] * [Go Tip #10: Configuration Structs and Flags](https://google.github.io/styleguide/go/index.html#gotip) * [Go Tip #80: Dependency Injection Principles](https://google.github.io/styleguide/go/index.html#gotip) [standard `flag` package]: https://golang.org/pkg/flag/ [mixed caps]: guide#mixed-caps [complex CLIs]: best-practices#complex-clis [totw-45]: https://abseil.io/tips/45 <a id="logging"></a> ### Logging Go programs in the Google codebase use a variant of the standard [`log`] package. It has a similar but more powerful interface and interoperates well with internal Google systems. An open source version of this library is available as [package `glog`], and open source Google projects may use that, but this guide refers to it as `log` throughout. **Note:** For abnormal program exits, this library uses `log.Fatal` to abort with a stacktrace, and `log.Exit` to stop without one. There is no `log.Panic` function as in the standard library. **Tip:** `log.Info(v)` is equivalent `log.Infof("%v", v)`, and the same goes for other logging levels. Prefer the non-formatting version when you have no formatting to do. See also: * Best practices on [logging errors](best-practices#error-logging) and [custom verbosity levels](best-practices#vlog) * When and how to use the log package to [stop the program](best-practices#checks-and-panics) [`log`]: https://pkg.go.dev/log [`log/slog`]: https://pkg.go.dev/log/slog [package `glog`]: https://pkg.go.dev/github.com/golang/glog [`log.Exit`]: https://pkg.go.dev/github.com/golang/glog#Exit [`log.Fatal`]: https://pkg.go.dev/github.com/golang/glog#Fatal <a id="contexts"></a> ### Contexts <a id="TOC-Contexts"></a> Values of the [`context.Context`] type carry security credentials, tracing information, deadlines, and cancellation signals across API and process boundaries. Unlike C++ and Java, which in the Google codebase use thread-local storage, Go programs pass contexts explicitly along the entire function call chain from incoming RPCs and HTTP requests to outgoing requests. [`context.Context`]: https://pkg.go.dev/context When passed to a function or method, [`context.Context`] is always the first parameter. ```go func F(ctx context.Context /* other arguments */) {} ``` Exceptions are: * In an HTTP handler, where the context comes from [`req.Context()`](https://pkg.go.dev/net/http#Request.Context). * In streaming RPC methods, where the context comes from the stream. Code using gRPC streaming accesses a context from a `Context()` method in the generated server type, which implements `grpc.ServerStream`. See [gRPC Generated Code documentation](https://grpc.io/docs/languages/go/generated-code/). * In test functions (e.g. `TestXXX`, `BenchmarkXXX`, `FuzzXXX`), where the context comes from [`(testing.TB).Context()`](https://pkg.go.dev/testing#TB.Context). * In other entrypoint functions (see below for examples of such functions), use [`context.Background()`]. * In binary targets: `main` * In general purpose code and libraries: `init` > **Note**: It is very rare for code in the middle of a callchain to require > creating a base context of its own using [`context.Background()`]. Always > prefer taking a context from your caller, unless it's the wrong context. > > You may come across server libraries (the implementation of Stubby, gRPC, or > HTTP in Google's server framework for Go) that construct a fresh context > object per request. These contexts are immediately filled with information > from the incoming request, so that when passed to the request handler, the > context's attached values have been propagated to it across the network > boundary from the client caller. Moreover, these contexts' lifetimes are > scoped to that of the request: when the request is finished, the context is > cancelled. > > Unless you are implementing a server framework, you shouldn't create contexts > with [`context.Background()`] in library code. Instead, prefer using context > detachment, which is mentioned below, if there is an existing context > available. If you think you do need [`context.Background()`] outside of > entrypoint functions, discuss it with the Google Go style mailing list before > committing to an implementation. The convention that [`context.Context`] comes first in functions also applies to test helpers. ```go // Good: func readTestFile(ctx context.Context, t *testing.T, path string) string {} ``` Do not add a context member to a struct type. Instead, add a context parameter to each method on the type that needs to pass it along. The one exception is for methods whose signature must match an interface in the standard library or in a third party library outside Google's control. Such cases are very rare, and should be discussed with the Google Go style mailing list before implementation and readability review. **Note:** Go 1.24 added a [`(testing.TB).Context()`] method. In tests, prefer using [`(testing.TB).Context()`] over [`context.Background()`] to provide the initial [`context.Context`] used by the test. Helper functions, environment or test double setup, and other functions called from the test function body that require a context should have one explicitly passed. [`(testing.TB).Context()`]: https://pkg.go.dev/testing#TB.Context Code in the Google codebase that must spawn background operations which can run after the parent context has been cancelled can use an internal package for detachment. Follow [issue #40221](https://github.com/golang/go/issues/40221) for discussions on an open source alternative. Since contexts are immutable, it is fine to pass the same context to multiple calls that share the same deadline, cancellation signal, credentials, parent trace, and so on. See also: * [Contexts and structs] [`context.Background()`]: https://pkg.go.dev/context/#Background [Contexts and structs]: https://go.dev/blog/context-and-structs <a id="custom-contexts"></a> #### Custom contexts Do not create custom context types or use interfaces other than [`context.Context`] in function signatures. There are no exceptions to this rule. Imagine if every team had a custom context. Every function call from package `p` to package `q` would have to determine how to convert a `p.Context` to a `q.Context`, for all pairs of packages `p` and `q`. This is impractical and error-prone for humans, and it makes automated refactorings that add context parameters nearly impossible. If you have application data to pass around, put it in a parameter, in the receiver, in globals, or in a `Context` value if it truly belongs there. Creating your own context type is not acceptable since it undermines the ability of the Go team to make Go programs work properly in production. <a id="crypto-rand"></a> ### crypto/rand <a id="TOC-CryptoRand"></a> Do not use package `math/rand` to generate keys, even throwaway ones. If unseeded, the generator is completely predictable. Seeded with `time.Nanoseconds()`, there are just a few bits of entropy. Instead, use `crypto/rand`'s Reader, and if you need text, print to hexadecimal or base64. ```go // Good: import ( "crypto/rand" // "encoding/base64" // "encoding/hex" "fmt" // ... ) func Key() string { buf := make([]byte, 16) if _, err := rand.Read(buf); err != nil { log.Fatalf("Out of randomness, should never happen: %v", err) } return fmt.Sprintf("%x", buf) // or hex.EncodeToString(buf) // or base64.StdEncoding.EncodeToString(buf) } ``` **Note:** `log.Fatalf` is not the standard library log. See [#logging]. <a id="useful-test-failures"></a> ## Useful test failures <a id="TOC-UsefulTestFailures"></a> It should be possible to diagnose a test's failure without reading the test's source. Tests should fail with helpful messages detailing: * What caused the failure * What inputs resulted in an error * The actual result * What was expected Specific conventions for achieving this goal are outlined below. <a id="assert"></a> ### Assertion libraries <a id="TOC-Assert"></a> Do not create "assertion libraries" as helpers for testing. Assertion libraries are libraries that attempt to combine the validation and production of failure messages within a test (though the same pitfalls can apply to other test helpers as well). For more on the distinction between test helpers and assertion libraries, see [best practices](best-practices#test-functions). ```go // Bad: var obj BlogPost assert.IsNotNil(t, "obj", obj) assert.StringEq(t, "obj.Type", obj.Type, "blogPost") assert.IntEq(t, "obj.Comments", obj.Comments, 2) assert.StringNotEq(t, "obj.Body", obj.Body, "") ``` Assertion libraries tend to either stop the test early (if `assert` calls `t.Fatalf` or `panic`) or omit relevant information about what the test got right: ```go // Bad: package assert func IsNotNil(t *testing.T, name string, val any) { if val == nil { t.Fatalf("Data %s = nil, want not nil", name) } } func StringEq(t *testing.T, name, got, want string) { if got != want { t.Fatalf("Data %s = %q, want %q", name, got, want) } } ``` Complex assertion functions often do not provide [useful failure messages] and context that exists within the test function. Too many assertion functions and libraries lead to a fragmented developer experience: which assertion library should I use, what style of output format should it emit, etc.? Fragmentation produces unnecessary confusion, especially for library maintainers and authors of large-scale changes, who are responsible for fixing potential downstream breakages. Instead of creating a domain-specific language for testing, use Go itself. Assertion libraries often factor out comparisons and equality checks. Prefer using standard libraries such as [`cmp`] and [`fmt`] instead: ```go // Good: var got BlogPost want := BlogPost{ Comments: 2, Body: "Hello, world!", } if !cmp.Equal(got, want) { t.Errorf("Blog post = %v, want = %v", got, want) } ``` For more domain-specific comparison helpers, prefer returning a value or an error that can be used in the test's failure message instead of passing `*testing.T` and calling its error reporting methods: ```go // Good: func postLength(p BlogPost) int { return len(p.Body) } func TestBlogPost_VeritableRant(t *testing.T) { post := BlogPost{Body: "I am Gunnery Sergeant Hartman, your senior drill instructor."} if got, want := postLength(post), 60; got != want { t.Errorf("Length of post = %v, want %v", got, want) } } ``` **Best Practice:** Were `postLength` non-trivial, it would make sense to test it directly, independently of any tests that use it. See also: * [Equality comparison and diffs](#types-of-equality) * [Print diffs](#print-diffs) * For more on the distinction between test helpers and assertion helpers, see [best practices](best-practices#test-functions) * [Go FAQ] section on [testing frameworks] and their opinionated absence [useful failure messages]: #useful-test-failures [`fmt`]: https://golang.org/pkg/fmt/ [marking test helpers]: #mark-test-helpers [Go FAQ]: https://go.dev/doc/faq [testing frameworks]: https://go.dev/doc/faq#testing_framework <a id="identify-the-function"></a> ### Identify the function In most tests, failure messages should include the name of the function that failed, even though it seems obvious from the name of the test function. Specifically, your failure message should be `YourFunc(%v) = %v, want %v` instead of just `got %v, want %v`. <a id="identify-the-input"></a> ### Identify the input In most tests, failure messages should include the function inputs if they are short. If the relevant properties of the inputs are not obvious (for example, because the inputs are large or opaque), you should name your test cases with a description of what's being tested and print the description as part of your error message. <a id="got-before-want"></a> ### Got before want Test outputs should include the actual value that the function returned before printing the value that was expected. A standard format for printing test outputs is `YourFunc(%v) = %v, want %v`. Where you would write "actual" and "expected", prefer using the words "got" and "want", respectively. For diffs, directionality is less apparent, and as such it is important to include a key to aid in interpreting the failure. See the [section on printing diffs]. Whichever diff order you use in your failure messages, you should explicitly indicate it as a part of the failure message, because existing code is inconsistent about the ordering. [section on printing diffs]: #print-diffs <a id="compare-full-structures"></a> ### Full structure comparisons If your function returns a struct (or any data type with multiple fields such as slices, arrays, and maps), avoid writing test code that performs a hand-coded field-by-field comparison of the struct. Instead, construct the data that you're expecting your function to return, and compare directly using a [deep comparison]. **Note:** This does not apply if your data contains irrelevant fields that obscure the intention of the test. If your struct needs to be compared for approximate (or equivalent kind of semantic) equality or it contains fields that cannot be compared for equality (e.g., if one of the fields is an `io.Reader`), tweaking a [`cmp.Diff`] or [`cmp.Equal`] comparison with [`cmpopts`] options such as [`cmpopts.IgnoreInterfaces`] may meet your needs ([example](https://play.golang.org/p/vrCUNVfxsvF)). If your function returns multiple return values, you don't need to wrap those in a struct before comparing them. Just compare the return values individually and print them. ```go // Good: val, multi, tail, err := strconv.UnquoteChar(`\"Fran & Freddie's Diner\"`, '"') if err != nil { t.Fatalf(...) } if val != `"` { t.Errorf(...) } if multi { t.Errorf(...) } if tail != `Fran & Freddie's Diner"` { t.Errorf(...) } ``` [deep comparison]: #types-of-equality [`cmpopts`]: https://pkg.go.dev/github.com/google/go-cmp/cmp/cmpopts [`cmpopts.IgnoreInterfaces`]: https://pkg.go.dev/github.com/google/go-cmp/cmp/cmpopts#IgnoreInterfaces <a id="compare-stable-results"></a> ### Compare stable results Avoid comparing results that may depend on output stability of a package that you do not own. Instead, the test should compare on semantically relevant information that is stable and resistant to changes in dependencies. For functionality that returns a formatted string or serialized bytes, it is generally not safe to assume that the output is stable. For example, [`json.Marshal`] can change (and has changed in the past) the specific bytes that it emits. Tests that perform string equality on the JSON string may break if the `json` package changes how it serializes the bytes. Instead, a more robust test would parse the contents of the JSON string and ensure that it is semantically equivalent to some expected data structure. [`json.Marshal`]: https://golang.org/pkg/encoding/json/#Marshal <a id="keep-going"></a> ### Keep going Tests should keep going for as long as possible, even after a failure, in order to print out all of the failed checks in a single run. This way, a developer who is fixing the failing test doesn't have to re-run the test after fixing each bug to find the next bug. Prefer calling `t.Error` over `t.Fatal` for reporting a mismatch. When comparing several different properties of a function's output, use `t.Error` for each of those comparisons. ```go // Good: gotMean, gotVariance, err := MyDistribution(input) if err != nil { t.Fatalf("MyDistribution(%v) returned unexpected error: %v", input, err) } if diff := cmp.Diff(wantMean, gotMean); diff != "" { t.Errorf("MyDistribution(%v) returned unexpected difference in mean value (-want +got):\n%s", input, diff) } if diff := cmp.Diff(wantVariance, gotVariance); diff != "" { t.Errorf("MyDistribution(%v) returned unexpected difference in variance value (-want +got):\n%s", input, diff) } ``` Calling `t.Fatal` is primarily useful for reporting an unexpected condition (such as an error or output mismatch) when subsequent failures would be meaningless or even mislead the investigator. Note how the code below calls `t.Fatalf` and *then* `t.Errorf`: ```go // Good: gotEncoded := Encode(input) if gotEncoded != wantEncoded { t.Fatalf("Encode(%q) = %q, want %q", input, gotEncoded, wantEncoded) // It doesn't make sense to decode from unexpected encoded input. } gotDecoded, err := Decode(gotEncoded) if err != nil { t.Fatalf("Decode(%q) returned unexpected error: %v", gotEncoded, err) } if gotDecoded != input { t.Errorf("Decode(%q) = %q, want %q", gotEncoded, gotDecoded, input) } ``` For table-driven test, consider using subtests and use `t.Fatal` rather than `t.Error` and `continue`. See also [GoTip #25: Subtests: Making Your Tests Lean](https://google.github.io/styleguide/go/index.html#gotip). **Best practice:** For more discussion about when `t.Fatal` should be used, see [best practices](best-practices#t-fatal). <a id="types-of-equality"></a> ### Equality comparison and diffs The `==` operator evaluates equality using [language-defined comparisons]. Scalar values (numbers, booleans, etc) are compared based on their values, but only some structs and interfaces can be compared in this way. Pointers are compared based on whether they point to the same variable, rather than based on the equality of the values to which they point. The [`cmp`] package can compare more complex data structures not appropriately handled by `==`, such as slices. Use [`cmp.Equal`] for equality comparison and [`cmp.Diff`] to obtain a human-readable diff between objects. ```go // Good: want := &Doc{ Type: "blogPost", Comments: 2, Body: "This is the post body.", Authors: []string{"isaac", "albert", "emmy"}, } if !cmp.Equal(got, want) { t.Errorf("AddPost() = %+v, want %+v", got, want) } ``` As a general-purpose comparison library, `cmp` may not know how to compare certain types. For example, it can only compare protocol buffer messages if passed the [`protocmp.Transform`] option. <!-- The order of want and got here is deliberate. See comment in #print-diffs. --> ```go // Good: if diff := cmp.Diff(want, got, protocmp.Transform()); diff != "" { t.Errorf("Foo() returned unexpected difference in protobuf messages (-want +got):\n%s", diff) } ``` Although the `cmp` package is not part of the Go standard library, it is maintained by the Go team and should produce stable equality results over time. It is user-configurable and should serve most comparison needs. [language-defined comparisons]: http://golang.org/ref/spec#Comparison_operators [`cmp`]: https://pkg.go.dev/github.com/google/go-cmp/cmp [`cmp.Equal`]: https://pkg.go.dev/github.com/google/go-cmp/cmp#Equal [`cmp.Diff`]: https://pkg.go.dev/github.com/google/go-cmp/cmp#Diff [`protocmp.Transform`]: https://pkg.go.dev/google.golang.org/protobuf/testing/protocmp#Transform Existing code may make use of the following older libraries, and may continue using them for consistency: * [`pretty`] produces aesthetically pleasing difference reports. However, it quite deliberately considers values that have the same visual representation as equal. In particular, `pretty` does not catch differences between nil slices and empty ones, is not sensitive to different interface implementations with identical fields, and it is possible to use a nested map as the basis for comparison with a struct value. It also serializes the entire value into a string before producing a diff, and as such is not a good choice for comparing large values. By default, it compares unexported fields, which makes it sensitive to changes in implementation details in your dependencies. For this reason, it is not appropriate to use `pretty` on protobuf messages. [`pretty`]: https://pkg.go.dev/github.com/kylelemons/godebug/pretty Prefer using `cmp` for new code, and it is worth considering updating older code to use `cmp` where and when it is practical to do so. Older code may use the standard library `reflect.DeepEqual` function to compare complex structures. `reflect.DeepEqual` should not be used for checking equality, as it is sensitive to changes in unexported fields and other implementation details. Code that is using `reflect.DeepEqual` should be updated to one of the above libraries. **Note:** The `cmp` package is designed for testing, rather than production use. As such, it may panic when it suspects that a comparison is performed incorrectly to provide instruction to users on how to improve the test to be less brittle. Given cmp's propensity towards panicking, it makes it unsuitable for code that is used in production as a spurious panic may be fatal. <a id="level-of-detail"></a> ### Level of detail The conventional failure message, which is suitable for most Go tests, is `YourFunc(%v) = %v, want %v`. However, there are cases that may call for more or less detail: * Tests performing complex interactions should describe the interactions too. For example, if the same `YourFunc` is called several times, identify which call failed the test. If it's important to know any extra state of the system, include that in the failure output (or at least in the logs). * If the data is a complex struct with significant boilerplate, it is acceptable to describe only the important parts in the message, but do not overly obscure the data. * Setup failures do not require the same level of detail. If a test helper populates a Spanner table but Spanner was down, you probably don't need to include which test input you were going to store in the database. `t.Fatalf("Setup: Failed to set up test database: %s", err)` is usually helpful enough to resolve the issue. **Tip:** Make your failure mode trigger during development. Review what the failure message looks like and whether a maintainer can effectively deal with the failure. There are some techniques for reproducing test inputs and outputs clearly: * When printing string data, [`%q` is often useful](#use-percent-q) to emphasize that the value is important and to more easily spot bad values. * When printing (small) structs, `%+v` can be more useful than `%v`. * When validation of larger values fails, [printing a diff](#print-diffs) can make it easier to understand the failure. <a id="print-diffs"></a> ### Print diffs If your function returns large output then it can be hard for someone reading the failure message to find the differences when your test fails. Instead of printing both the returned value and the wanted value, make a diff. To compute diffs for such values, `cmp.Diff` is preferred, particularly for new tests and new code, but other tools may be used. See [types of equality] for guidance regarding the strengths and weaknesses of each function. * [`cmp.Diff`] * [`pretty.Compare`] You can use the [`diff`] package to compare multi-line strings or lists of strings. You can use this as a building block for other kinds of diffs. [types of equality]: #types-of-equality [`diff`]: https://pkg.go.dev/github.com/kylelemons/godebug/diff [`pretty.Compare`]: https://pkg.go.dev/github.com/kylelemons/godebug/pretty#Compare Add some text to your failure message explaining the direction of the diff. <!-- The reversed order of want and got in these examples is intentional, as this is the prevailing order across the Google codebase. The lack of a stance on which order to use is also intentional, as there is no consensus which is "most readable." --> * Something like `diff (-want +got)` is good when you're using the `cmp`, `pretty`, and `diff` packages (if you pass `(want, got)` to the function), because the `-` and `+` that you add to your format string will match the `-` and `+` that actually appear at the beginning of the diff lines. If you pass `(got, want)` to your function, the correct key would be `(-got +want)` instead. * The `messagediff` package uses a different output format, so the message `diff (want -> got)` is appropriate when you're using it (if you pass `(want, got)` to the function), because the direction of the arrow will match the direction of the arrow in the "modified" lines. The diff will span multiple lines, so you should print a newline before you print the diff. <a id="test-error-semantics"></a> ### Test error semantics When a unit test performs string comparisons or uses a vanilla `cmp` to check that particular kinds of errors are returned for particular inputs, you may find that your tests are brittle if any of those error messages are reworded in the future. Since this has the potential to turn your unit test into a change detector (see [TotT: Change-Detector Tests Considered Harmful][tott-350] ), don't use string comparison to check what type of error your function returns. However, it is permissible to use string comparisons to check that error messages coming from the package under test satisfy certain properties, for example, that it includes the parameter name. Error values in Go typically have a component intended for human eyes and a component intended for semantic control flow. Tests should seek to only test semantic information that can be reliably observed, rather than display information that is intended for human debugging, as this is often subject to future changes. For guidance on constructing errors with semantic meaning see [best-practices regarding errors](best-practices#error-handling). If an error with insufficient semantic information is coming from a dependency outside your control, consider filing a bug against the owner to help improve the API, rather than relying on parsing the error message. Within unit tests, it is common to only care whether an error occurred or not. If so, then it is sufficient to only test whether the error was non-nil when you expected an error. If you would like to test that the error semantically matches some other error, then consider using [`errors.Is`] or `cmp` with [`cmpopts.EquateErrors`]. > **Note:** If a test uses [`cmpopts.EquateErrors`] but all of its `wantErr` > values are either `nil` or `cmpopts.AnyError`, then using `cmp` is > [unnecessary mechanism](guide#least-mechanism). Simplify the code by making > the want field a `bool`. You can then use a simple comparison with `!=`. > > ```go > // Good: > err := f(test.input) > if gotErr := err != nil; gotErr != test.wantErr { > t.Errorf("f(%q) = %v, want error presence = %v", test.input, err, test.wantErr) > } > ``` See also [GoTip #13: Designing Errors for Checking](https://google.github.io/styleguide/go/index.html#gotip). [tott-350]: https://testing.googleblog.com/2015/01/testing-on-toilet-change-detector-tests.html [`cmpopts.EquateErrors`]: https://pkg.go.dev/github.com/google/go-cmp/cmp/cmpopts#EquateErrors [`errors.Is`]: https://pkg.go.dev/errors#Is <a id="test-structure"></a> ## Test structure <a id="subtests"></a> ### Subtests The standard Go testing library offers a facility to [define subtests]. This allows flexibility in setup and cleanup, controlling parallelism, and test filtering. Subtests can be useful (particularly for table-driven tests), but using them is not mandatory. See also the [Go blog post about subtests](https://blog.golang.org/subtests). Subtests should not depend on the execution of other cases for success or initial state, because subtests are expected to be able to be run individually with using `go test -run` flags or with Bazel [test filter] expressions. [define subtests]: https://pkg.go.dev/testing#hdr-Subtests_and_Sub_benchmarks [test filter]: https://bazel.build/docs/user-manual#test-filter <a id="subtest-names"></a> #### Subtest names Name your subtest such that it is readable in test output and useful on the command line for users of test filtering. When you use `t.Run` to create a subtest, the first argument is used as a descriptive name for the test. To ensure that test results are legible to humans reading the logs, choose subtest names that will remain useful and readable after escaping. Think of subtest names more like a function identifier than a prose description. The test runner replaces spaces with underscores, and escapes non-printing characters. To ensure accurate correlation between test logs and source code, it is recommended to avoid using these characters in subtest names. If your test data benefits from a longer description, consider putting the description in a separate field (perhaps to be printed using `t.Log` or alongside failure messages). Subtests may be run individually using flags to the [Go test runner] or Bazel [test filter], so choose descriptive names that are also easy to type. > **Warning:** Slash characters are particularly unfriendly in subtest names, > since they have [special meaning for test filters]. > > > ```sh > > # Bad: > > # Assuming TestTime and t.Run("America/New_York", ...) > > bazel test :mytest --test_filter="Time/New_York" # Runs nothing! > > bazel test :mytest --test_filter="Time//New_York" # Correct, but awkward. > > ``` To [identify the inputs] of the function, include them in the test's failure messages, where they won't be escaped by the test runner. ```go // Good: func TestTranslate(t *testing.T) { data := []struct { name, desc, srcLang, dstLang, srcText, wantDstText string }{ { name: "hu=en_bug-1234", desc: "regression test following bug 1234. contact: cleese", srcLang: "hu", srcText: "cigarettát és egy öngyújtót kérek", dstLang: "en", wantDstText: "cigarettes and a lighter please", }, // ... } for _, d := range data { t.Run(d.name, func(t *testing.T) { got := Translate(d.srcLang, d.dstLang, d.srcText) if got != d.wantDstText { t.Errorf("%s\nTranslate(%q, %q, %q) = %q, want %q", d.desc, d.srcLang, d.dstLang, d.srcText, got, d.wantDstText) } }) } } ``` Here are a few examples of things to avoid: ```go // Bad: // Too wordy. t.Run("check that there is no mention of scratched records or hovercrafts", ...) // Slashes cause problems on the command line. t.Run("AM/PM confusion", ...) ``` See also [Go Tip #117: Subtest Names](https://google.github.io/styleguide/go/index.html#gotip). [Go test runner]: https://golang.org/cmd/go/#hdr-Testing_flags [identify the inputs]: #identify-the-input [special meaning for test filters]: https://blog.golang.org/subtests#:~:text=Perhaps%20a%20bit,match%20any%20tests <a id="table-driven-tests"></a> ### Table-driven tests Use table-driven tests when many different test cases can be tested using similar testing logic. * When testing whether the actual output of a function is equal to the expected output. For example, the many [tests of `fmt.Sprintf`] or the minimal snippet below. * When testing whether the outputs of a function always conform to the same set of invariants. For example, [tests for `net.Dial`]. [tests of `fmt.Sprintf`]: https://cs.opensource.google/go/go/+/master:src/fmt/fmt_test.go [tests for `net.Dial`]: https://cs.opensource.google/go/go/+/master:src/net/dial_test.go;l=318;drc=5b606a9d2b7649532fe25794fa6b99bd24e7697c Here is the minimal structure of a table-driven test. If needed, you may use different names or add extra facilities such as subtests or setup and cleanup functions. Always keep [useful test failures](#useful-test-failures) in mind. ```go // Good: func TestCompare(t *testing.T) { compareTests := []struct { a, b string want int }{ {"", "", 0}, {"a", "", 1}, {"", "a", -1}, {"abc", "abc", 0}, {"ab", "abc", -1}, {"abc", "ab", 1}, {"x", "ab", 1}, {"ab", "x", -1}, {"x", "a", 1}, {"b", "x", -1}, // test runtime·memeq's chunked implementation {"abcdefgh", "abcdefgh", 0}, {"abcdefghi", "abcdefghi", 0}, {"abcdefghi", "abcdefghj", -1}, } for _, test := range compareTests { got := Compare(test.a, test.b) if got != test.want { t.Errorf("Compare(%q, %q) = %v, want %v", test.a, test.b, got, test.want) } } } ``` **Note**: The failure messages in this example above fulfill the guidance to [identify the function](#identify-the-function) and [identify the input](#identify-the-input). There's no need to [identify the row numerically](#table-tests-identifying-the-row). When some test cases need to be checked using different logic from other test cases, it is appropriate to write multiple test functions, as explained in [GoTip #50: Disjoint Table Tests]. When the additional test cases are simple (e.g., basic error checking) and don't introduce conditionalized code flow in the table test's loop body, it's permissible to include that case in the existing test, though be careful using logic like this. What starts simple today can organically grow into something unmaintainable. For example: ```go func TestDivide(t *testing.T) { tests := []struct { dividend, divisor int want int wantErr bool }{ { dividend: 4, divisor: 2, want: 2, }, { dividend: 10, divisor: 2, want: 5, }, { dividend: 1, divisor: 0, wantErr: true, }, } for _, test := range tests { got, err := Divide(test.dividend, test.divisor) if (err != nil) != test.wantErr { t.Errorf("Divide(%d, %d) error = %v, want error presence = %t", test.dividend, test.divisor, err, test.wantErr) } // In this example, we're only testing the value result when the tested function didn't fail. if err != nil { continue } if got != test.want { t.Errorf("Divide(%d, %d) = %d, want %d", test.dividend, test.divisor, got, test.want) } } } ``` More complicated logic in your test code, like complex error checking based on conditional differences in test setup (often based on table test input parameters), can be [difficult to understand](guide#maintainability) when each entry in a table has specialized logic based on the inputs. If test cases have different logic but identical setup, a sequence of [subtests](#subtests) within a single test function might be more readable. A test helper may also be useful for simplifying test setup in order to maintain the readability of a test body. You can combine table-driven tests with multiple test functions. For example, when testing that a function's output exactly matches the expected output and that the function returns a non-nil error for an invalid input, then writing two separate table-driven test functions is the best approach: one for normal non-error outputs, and one for error outputs. [GoTip #50: Disjoint Table Tests]: https://google.github.io/styleguide/go/index.html#gotip <a id="table-tests-data-driven"></a> #### Data-driven test cases Table test rows can sometimes become complicated, with the row values dictating conditional behavior inside the test case. The extra clarity from the duplication between the test cases is necessary for readability. ```go // Good: type decodeCase struct { name string input string output string err error } func TestDecode(t *testing.T) { // setupCodex is slow as it creates a real Codex for the test. codex := setupCodex(t) var tests []decodeCase // rows omitted for brevity for _, test := range tests { t.Run(test.name, func(t *testing.T) { output, err := Decode(test.input, codex) if got, want := output, test.output; got != want { t.Errorf("Decode(%q) = %v, want %v", test.input, got, want) } if got, want := err, test.err; !cmp.Equal(got, want) { t.Errorf("Decode(%q) err %q, want %q", test.input, got, want) } }) } } func TestDecodeWithFake(t *testing.T) { // A fakeCodex is a fast approximation of a real Codex. codex := newFakeCodex() var tests []decodeCase // rows omitted for brevity for _, test := range tests { t.Run(test.name, func(t *testing.T) { output, err := Decode(test.input, codex) if got, want := output, test.output; got != want { t.Errorf("Decode(%q) = %v, want %v", test.input, got, want) } if got, want := err, test.err; !cmp.Equal(got, want) { t.Errorf("Decode(%q) err %q, want %q", test.input, got, want) } }) } } ``` In the counterexample below, note how hard it is to distinguish between which type of `Codex` is used per test case in the case setup. (The highlighted parts run afoul of the advice from [TotT: Data Driven Traps!][tott-97] .) ```go // Bad: type decodeCase struct { name string input string codex testCodex output string err error } type testCodex int const ( fake testCodex = iota prod ) func TestDecode(t *testing.T) { var tests []decodeCase // rows omitted for brevity for _, test := tests { t.Run(test.name, func(t *testing.T) { var codex Codex switch test.codex { case fake: codex = newFakeCodex() case prod: codex = setupCodex(t) default: t.Fatalf("Unknown codex type: %v", codex) } output, err := Decode(test.input, codex) if got, want := output, test.output; got != want { t.Errorf("Decode(%q) = %q, want %q", test.input, got, want) } if got, want := err, test.err; !cmp.Equal(got, want) { t.Errorf("Decode(%q) err %q, want %q", test.input, got, want) } }) } } ``` [tott-97]: https://testing.googleblog.com/2008/09/tott-data-driven-traps.html <a id="table-tests-identifying-the-row"></a> #### Identifying the row Do not use the index of the test in the test table as a substitute for naming your tests or printing the inputs. Nobody wants to go through your test table and count the entries in order to figure out which test case is failing. ```go // Bad: tests := []struct { input, want string }{ {"hello", "HELLO"}, {"wORld", "WORLD"}, } for i, d := range tests { if strings.ToUpper(d.input) != d.want { t.Errorf("Failed on case #%d", i) } } ``` Add a test description to your test struct and print it along failure messages. When using subtests, your subtest name should be effective in identifying the row. **Important:** Even though `t.Run` scopes the output and execution, you must always [identify the input]. The table test row names must follow the [subtest naming] guidance. [identify the input]: #identify-the-input [subtest naming]: #subtest-names <a id="mark-test-helpers"></a> ### Test helpers A test helper is a function that performs a setup or cleanup task. All failures that occur in test helpers are expected to be failures of the environment (not from the code under test) — for example when a test database cannot be started because there are no more free ports on this machine. If you pass a `*testing.T`, call [`t.Helper`] to attribute failures in the test helper to the line where the helper is called. This parameter should come after a [context](#contexts) parameter, if present, and before any remaining parameters. ```go // Good: func TestSomeFunction(t *testing.T) { golden := readFile(t, "testdata/golden-result.txt") // ... tests against golden ... } // readFile returns the contents of a data file. // It must only be called from the same goroutine as started the test. func readFile(t *testing.T, filename string) string { t.Helper() contents, err := runfiles.ReadFile(filename) if err != nil { t.Fatal(err) } return string(contents) } ``` Do not use this pattern when it obscures the connection between a test failure and the conditions that led to it. Specifically, the guidance about [assert libraries](#assert) still applies, and [`t.Helper`] should not be used to implement such libraries. **Tip:** For more on the distinction between test helpers and assertion helpers, see [best practices](best-practices#test-functions). Although the above refers to `*testing.T`, much of the advice stays the same for benchmark and fuzz helpers. [`t.Helper`]: https://pkg.go.dev/testing#T.Helper <a id="test-package"></a> ### Test package <a id="TOC-TestPackage"></a> <a id="test-same-package"></a> #### Tests in the same package Tests may be defined in the same package as the code being tested. To write a test in the same package: * Place the tests in a `foo_test.go` file * Use `package foo` for the test file * Do not explicitly import the package to be tested ```build # Good: go_library( name = "foo", srcs = ["foo.go"], deps = [ ... ], ) go_test( name = "foo_test", size = "small", srcs = ["foo_test.go"], library = ":foo", deps = [ ... ], ) ``` A test in the same package can access unexported identifiers in the package. This may enable better test coverage and more concise tests. Be aware that any [examples] declared in the test will not have the package names that a user will need in their code. [`library`]: https://github.com/bazelbuild/rules_go/blob/master/docs/go/core/rules.md#go_library [examples]: #examples <a id="test-different-package"></a> #### Tests in a different package It is not always appropriate or even possible to define a test in the same package as the code being tested. In these cases, use a package name with the `_test` suffix. This is an exception to the "no underscores" rule to [package names](#package-names). For example: * If an integration test does not have an obvious library that it belongs to ```go // Good: package gmailintegration_test import "testing" ``` * If defining the tests in the same package results in circular dependencies ```go // Good: package fireworks_test import ( "fireworks" "fireworkstestutil" // fireworkstestutil also imports fireworks ) ``` <a id="use-package-testing"></a> ### Use package `testing` The Go standard library provides the [`testing` package]. This is the only testing framework permitted for Go code in the Google codebase. In particular, [assertion libraries](#assert) and third-party testing frameworks are not allowed. The `testing` package provides a minimal but complete set of functionality for writing good tests: * Top-level tests * Benchmarks * [Runnable examples](https://blog.golang.org/examples) * Subtests * Logging * Failures and fatal failures These are designed to work cohesively with core language features like [composite literal] and [if-with-initializer] syntax to enable test authors to write [clear, readable, and maintainable tests]. [`testing` package]: https://pkg.go.dev/testing [composite literal]: https://go.dev/ref/spec#Composite_literals [if-with-initializer]: https://go.dev/ref/spec#If_statements <a id="non-decisions"></a> ## Non-decisions A style guide cannot enumerate positive prescriptions for all matters, nor can it enumerate all matters about which it does not offer an opinion. That said, here are a few things where the readability community has previously debated and has not achieved consensus about. * **Local variable initialization with zero value**. `var i int` and `i := 0` are equivalent. See also [initialization best practices]. * **Empty composite literal vs. `new` or `make`**. `&File{}` and `new(File)` are equivalent. So are `map[string]bool{}` and `make(map[string]bool)`. See also [composite declaration best practices]. * **got, want argument ordering in cmp.Diff calls**. Be locally consistent, and [include a legend](#print-diffs) in your failure message. * **`errors.New` vs `fmt.Errorf` on non-formatted strings**. `errors.New("foo")` and `fmt.Errorf("foo")` may be used interchangeably. If there are special circumstances where they come up again, the readability mentor might make an optional comment, but in general the author is free to pick the style they prefer in the given situation. Naturally, if anything not covered by the style guide does need more discussion, authors are welcome to ask -- either in the specific review, or on internal message boards. [composite declaration best practices]: https://google.github.io/styleguide/go/best-practices#vardeclcomposite [initialization best practices]: https://google.github.io/styleguide/go/best-practices#vardeclinitialization <!-- --> {% endraw %} ================================================ FILE: go/guide.md ================================================ <!--* toc_depth: 3 *--> # Go Style Guide https://google.github.io/styleguide/go/guide [Overview](index) | [Guide](guide) | [Decisions](decisions) | [Best practices](best-practices) <!-- --> {% raw %} **Note:** This is part of a series of documents that outline [Go Style](index) at Google. This document is **[normative](index#normative) and [canonical](index#canonical)**. See [the overview](index#about) for more information. <a id="principles"></a> ## Style principles There are a few overarching principles that summarize how to think about writing readable Go code. The following are attributes of readable code, in order of importance: 1. **[Clarity]**: The code's purpose and rationale is clear to the reader. 1. **[Simplicity]**: The code accomplishes its goal in the simplest way possible. 1. **[Concision]**: The code has a high signal-to-noise ratio. 1. **[Maintainability]**: The code is written such that it can be easily maintained. 1. **[Consistency]**: The code is consistent with the broader Google codebase. [Clarity]: #clarity [Simplicity]: #simplicity [Concision]: #concision [Maintainability]: #maintainability [Consistency]: #consistency <a id="clarity"></a> ### Clarity The core goal of readability is to produce code that is clear to the reader. Clarity is primarily achieved with effective naming, helpful commentary, and efficient code organization. Clarity is to be viewed through the lens of the reader, not the author of the code. It is more important that code be easy to read than easy to write. Clarity in code has two distinct facets: * [What is the code actually doing?](#clarity-purpose) * [Why is the code doing what it does?](#clarity-rationale) <a id="clarity-purpose"></a> #### What is the code actually doing? Go is designed such that it should be relatively straightforward to see what the code is doing. In cases of uncertainty or where a reader may require prior knowledge in order to understand the code, it is worth investing time in order to make the code's purpose clearer for future readers. For example, it may help to: * Use more descriptive variable names * Add additional commentary * Break up the code with whitespace and comments * Refactor the code into separate functions/methods to make it more modular There is no one-size-fits-all approach here, but it is important to prioritize clarity when developing Go code. <a id="clarity-rationale"></a> #### Why is the code doing what it does? The code's rationale is often sufficiently communicated by the names of variables, functions, methods, or packages. Where it is not, it is important to add commentary. The "Why?" is especially important when the code contains nuances that a reader may not be familiar with, such as: * A nuance in the language, e.g., a closure will be capturing a loop variable, but the closure is many lines away * A nuance of the business logic, e.g., an access control check that needs to distinguish between the actual user and someone impersonating a user An API might require care to use correctly. For example, a piece of code may be intricate and difficult to follow for performance reasons, or a complex sequence of mathematical operations may use type conversions in an unexpected way. In these cases and many more, it is important that accompanying commentary and documentation explain these aspects so that future maintainers don't make a mistake and so that readers can understand the code without needing to reverse-engineer it. It is also important to be aware that some attempts to provide clarity (such as adding extra commentary) can actually obscure the code's purpose by adding clutter, restating what the code already says, contradicting the code, or adding maintenance burden to keep the comments up-to-date. Allow the code to speak for itself (e.g., by making the symbol names themselves self-describing) rather than adding redundant comments. It is often better for comments to explain why something is done, not what the code is doing. The Google codebase is largely uniform and consistent. It is often the case that code that stands out (e.g., by using an unfamiliar pattern) is doing so for a good reason, typically for performance. Maintaining this property is important to make it clear to readers where they should focus their attention when reading a new piece of code. The standard library contains many examples of this principle in action. Among them: * Maintainer comments in [`package sort`](https://cs.opensource.google/go/go/+/refs/tags/go1.19.2:src/sort/sort.go). * Good [runnable examples in the same package](https://cs.opensource.google/go/go/+/refs/tags/go1.19.2:src/sort/example_search_test.go), which benefit both users (they [show up in godoc](https://pkg.go.dev/sort#pkg-examples)) and maintainers (they [run as part of tests](decisions#examples)). * [`strings.Cut`](https://pkg.go.dev/strings#Cut) is only four lines of code, but they improve the [clarity and correctness of callsites](https://github.com/golang/go/issues/46336). <a id="simplicity"></a> ### Simplicity Your Go code should be simple for those using, reading, and maintaining it. Go code should be written in the simplest way that accomplishes its goals, both in terms of behavior and performance. Within the Google Go codebase, simple code: * Is easy to read from top to bottom * Does not assume that you already know what it is doing * Does not assume that you can memorize all of the preceding code * Does not have unnecessary levels of abstraction * Does not have names that call attention to something mundane * Makes the propagation of values and decisions clear to the reader * Has comments that explain why, not what, the code is doing to avoid future deviation * Has documentation that stands on its own * Has useful errors and useful test failures * May often be mutually exclusive with "clever" code Tradeoffs can arise between code simplicity and API usage simplicity. For example, it may be worthwhile to have the code be more complex so that the end user of the API may more easily call the API correctly. In contrast, it may also be worthwhile to leave a bit of extra work to the end user of the API so that the code remains simple and easy to understand. When code needs complexity, the complexity should be added deliberately. This is typically necessary if additional performance is required or where there are multiple disparate customers of a particular library or service. Complexity may be justified, but it should come with accompanying documentation so that clients and future maintainers are able to understand and navigate the complexity. This should be supplemented with tests and examples that demonstrate its correct usage, especially if there is both a "simple" and a "complex" way to use the code. This principle does not imply that complex code cannot or should not be written in Go or that Go code is not allowed to be complex. We strive for a codebase that avoids unnecessary complexity so that when complexity does appear, it indicates that the code in question requires care to understand and maintain. Ideally, there should be accompanying commentary that explains the rationale and identifies the care that should be taken. This often arises when optimizing code for performance; doing so often requires a more complex approach, like preallocating a buffer and reusing it throughout a goroutine lifetime. When a maintainer sees this, it should be a clue that the code in question is performance-critical, and that should influence the care that is taken when making future changes. If employed unnecessarily, on the other hand, this complexity is a burden on those who need to read or change the code in the future. If code turns out to be very complex when its purpose should be simple, this is often a signal to revisit the implementation to see if there is a simpler way to accomplish the same thing. <a id="least-mechanism"></a> #### Least mechanism Where there are several ways to express the same idea, prefer the one that uses the most standard tools. Sophisticated machinery often exists, but should not be employed without reason. It is easy to add complexity to code as needed, whereas it is much harder to remove existing complexity after it has been found to be unnecessary. 1. Aim to use a core language construct (for example a channel, slice, map, loop, or struct) when sufficient for your use case. 2. If there isn't one, look for a tool within the standard library (like an HTTP client or a template engine). 3. Finally, consider whether there is a core library in the Google codebase that is sufficient before introducing a new dependency or creating your own. As an example, consider production code that contains a flag bound to a variable with a default value which must be overridden in tests. Unless intending to test the program's command-line interface itself (say, with `os/exec`), it is simpler and therefore preferable to override the bound value directly rather than by using `flag.Set`. Similarly, if a piece of code requires a set membership check, a boolean-valued map (e.g., `map[string]bool`) often suffices. Libraries that provide set-like types and functionality should only be used if more complicated operations are required that are impossible or overly complicated with a map. <a id="concision"></a> ### Concision Concise Go code has a high signal-to-noise ratio. It is easy to discern the relevant details, and the naming and structure guide the reader through these details. There are many things that can get in the way of surfacing the most salient details at any given time: * Repetitive code * Extraneous syntax * [Opaque names](#naming) * Unnecessary abstraction * Whitespace Repetitive code especially obscures the differences between each nearly-identical section, and requires a reader to visually compare similar lines of code to find the changes. [Table-driven testing] is a good example of a mechanism that can concisely factor out the common code from the important details of each repetition, but the choice of which pieces to include in the table will have an impact on how easy the table is to understand. When considering multiple ways to structure code, it is worth considering which way makes important details the most apparent. Understanding and using common code constructions and idioms are also important for maintaining a high signal-to-noise ratio. For example, the following code block is very common in [error handling], and the reader can quickly understand the purpose of this block. ```go // Good: if err := doSomething(); err != nil { // ... } ``` If code looks very similar to this but is subtly different, a reader may not notice the change. In cases like this, it is worth intentionally ["boosting"] the signal of the error check by adding a comment to call attention to it. ```go // Good: if err := doSomething(); err == nil { // if NO error // ... } ``` [Table-driven testing]: https://go.dev/wiki/TableDrivenTests [error handling]: https://go.dev/blog/errors-are-values ["boosting"]: best-practices#signal-boost <a id="maintainability"></a> ### Maintainability Code is edited many more times than it is written. Readable code not only makes sense to a reader who is trying to understand how it works, but also to the programmer who needs to change it. Clarity is key. Maintainable code: * Is easy for a future programmer to modify correctly * Has APIs that are structured so that they can grow gracefully * Is clear about the assumptions that it makes and chooses abstractions that map to the structure of the problem, not to the structure of the code * Avoids unnecessary coupling and doesn't include features that are not used * Has a comprehensive test suite to ensure promised behaviors are maintained and important logic is correct, and the tests provide clear, actionable diagnostics in case of failure When using abstractions like interfaces and types which by definition remove information from the context in which they are used, it is important to ensure that they provide sufficient benefit. Editors and IDEs can connect directly to a method definition and show the corresponding documentation when a concrete type is used, but can only refer to an interface definition otherwise. Interfaces are a powerful tool, but come with a cost, since the maintainer may need to understand the specifics of the underlying implementation in order to correctly use the interface, which must be explained within the interface documentation or at the call-site. Maintainable code also avoids hiding important details in places that are easy to overlook. For example, in each of the following lines of code, the presence or lack of a single character is critical to understand the line: ```go // Bad: // The use of = instead of := can change this line completely. if user, err = db.UserByID(userID); err != nil { // ... } ``` ```go // Bad: // The ! in the middle of this line is very easy to miss. leap := (year%4 == 0) && (!(year%100 == 0) || (year%400 == 0)) ``` Neither of these are incorrect, but both could be written in a more explicit fashion, or could have an accompanying comment that calls attention to the important behavior: ```go // Good: u, err := db.UserByID(userID) if err != nil { return fmt.Errorf("invalid origin user: %s", err) } user = u ``` ```go // Good: // Gregorian leap years aren't just year%4 == 0. // See https://en.wikipedia.org/wiki/Leap_year#Algorithm. var ( leap4 = year%4 == 0 leap100 = year%100 == 0 leap400 = year%400 == 0 ) leap := leap4 && (!leap100 || leap400) ``` In the same way, a helper function that hides critical logic or an important edge-case could make it easy for a future change to fail to account for it properly. Predictable names are another feature of maintainable code. A user of a package or a maintainer of a piece of code should be able to predict the name of a variable, method, or function in a given context. Function parameters and receiver names for identical concepts should typically share the same name, both to keep documentation understandable and to facilitate refactoring code with minimal overhead. Maintainable code minimizes its dependencies (both implicit and explicit). Depending on fewer packages means fewer lines of code that can affect behavior. Avoiding dependencies on internal or undocumented behavior makes code less likely to impose a maintenance burden when those behaviors change in the future. When considering how to structure or write code, it is worth taking the time to think through ways in which the code may evolve over time. If a given approach is more conducive to easier and safer future changes, that is often a good trade-off, even if it means a slightly more complicated design. <a id="consistency"></a> ### Consistency Consistent code is code that looks, feels, and behaves like similar code throughout the broader codebase, within the context of a team or package, and even within a single file. Consistency concerns do not override any of the principles above, but if a tie must be broken, it is often beneficial to break it in favor of consistency. Consistency within a package is often the most immediately important level of consistency. It can be very jarring if the same problem is approached in multiple ways throughout a package, or if the same concept has many names within a file. However, even this should not override documented style principles or global consistency. <a id="core"></a> ## Core guidelines These guidelines collect the most important aspects of Go style that all Go code is expected to follow. We expect that these principles be learned and followed by the time readability is granted. These are not expected to change frequently, and new additions will have to clear a high bar. The guidelines below expand on the recommendations in [Effective Go], which provide a common baseline for Go code across the entire community. [Effective Go]: https://go.dev/doc/effective_go <a id="formatting"></a> ### Formatting All Go source files must conform to the format outputted by the `gofmt` tool. This format is enforced by a presubmit check in the Google codebase. [Generated code] should generally also be formatted (e.g., by using [`format.Source`]), as it is also browsable in Code Search. [Generated code]: https://docs.bazel.build/versions/main/be/general.html#genrule [`format.Source`]: https://pkg.go.dev/go/format#Source <a id="mixed-caps"></a> ### MixedCaps Go source code uses `MixedCaps` or `mixedCaps` (camel case) rather than underscores (snake case) when writing multi-word names. This applies even when it breaks conventions in other languages. For example, a constant is `MaxLength` (not `MAX_LENGTH`) if exported and `maxLength` (not `max_length`) if unexported. Local variables are considered [unexported] for the purpose of choosing the initial capitalization. <!--#include file="/go/g3doc/style/includes/special-name-exception.md"--> [unexported]: https://go.dev/ref/spec#Exported_identifiers <a id="line-length"></a> ### Line length There is no fixed line length for Go source code. If a line feels too long, prefer refactoring instead of splitting it. If it is already as short as it is practical for it to be, the line should be allowed to remain long. Do not split a line: * Before an [indentation change](decisions#indentation-confusion) (e.g., function declaration, conditional) * To make a long string (e.g., a URL) fit into multiple shorter lines <a id="naming"></a> ### Naming Naming is more art than science. In Go, names tend to be somewhat shorter than in many other languages, but the same [general guidelines] apply. Names should: * Not feel [repetitive](decisions#repetition) when they are used * Take the context into consideration * Not repeat concepts that are already clear You can find more specific guidance on naming in [decisions](decisions#naming). [general guidelines]: https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html <a id="local-consistency"></a> ### Local consistency Where the style guide has nothing to say about a particular point of style, authors are free to choose the style that they prefer, unless the code in close proximity (usually within the same file or package, but sometimes within a team or project directory) has taken a consistent stance on the issue. Examples of **valid** local style considerations: * Use of `%s` or `%v` for formatted printing of errors * Usage of buffered channels in lieu of mutexes Examples of **invalid** local style considerations: * Line length restrictions for code * Use of assertion-based testing libraries If the local style disagrees with the style guide but the readability impact is limited to one file, it will generally be surfaced in a code review for which a consistent fix would be outside the scope of the CL in question. At that point, it is appropriate to file a bug to track the fix. If a change would worsen an existing style deviation, expose it in more API surfaces, expand the number of files in which the deviation is present, or introduce an actual bug, then local consistency is no longer a valid justification for violating the style guide for new code. In these cases, it is appropriate for the author to clean up the existing codebase in the same CL, perform a refactor in advance of the current CL, or find an alternative that at least does not make the local problem worse. <!-- --> {% endraw %} ================================================ FILE: go/index.md ================================================ # Go Style https://google.github.io/styleguide/go [Overview](index) | [Guide](guide) | [Decisions](decisions) | [Best practices](best-practices) <!-- --> {% raw %} <a id="about"></a> ## About The Go Style Guide and accompanying documents codify the current best approaches for writing readable and idiomatic Go. Adherence to the Style Guide is not intended to be absolute, and these documents will never be exhaustive. Our intention is to minimize the guesswork of writing readable Go so that newcomers to the language can avoid common mistakes. The Style Guide also serves to unify the style guidance given by anyone reviewing Go code at Google. Document | Link | Primary Audience | [Normative] | [Canonical] ------------------- | ----------------------------------------------------- | ------------------- | ----------- | ----------- **Style Guide** | https://google.github.io/styleguide/go/guide | Everyone | Yes | Yes **Style Decisions** | https://google.github.io/styleguide/go/decisions | Readability Mentors | Yes | No **Best Practices** | https://google.github.io/styleguide/go/best-practices | Anyone interested | No | No [Normative]: #normative [Canonical]: #canonical <a id="docs"></a> ### Documents 1. The **[Style Guide](https://google.github.io/styleguide/go/guide)** outlines the foundation of Go style at Google. This document is definitive and is used as the basis for the recommendations in Style Decisions and Best Practices. 1. **[Style Decisions](https://google.github.io/styleguide/go/decisions)** is a more verbose document that summarizes decisions on specific style points and discusses the reasoning behind the decisions where appropriate. These decisions may occasionally change based on new data, new language features, new libraries, or emerging patterns, but it is not expected that individual Go programmers at Google should keep up-to-date with this document. 1. **[Best Practices](https://google.github.io/styleguide/go/best-practices)** documents some of the patterns that have evolved over time that solve common problems, read well, and are robust to code maintenance needs. These best practices are not canonical, but Go programmers at Google are encouraged to use them where possible to keep the codebase uniform and consistent. These documents intend to: * Agree on a set of principles for weighing alternate styles * Codify settled matters of Go style * Document and provide canonical examples for Go idioms * Document the pros and cons of various style decisions * Help minimize surprises in Go readability reviews * Help readability mentors use consistent terminology and guidance These documents do **not** intend to: * Be an exhaustive list of comments that can be given in a readability review * List all of the rules everyone is expected to remember and follow at all times * Replace good judgment in the use of language features and style * Justify large-scale changes to get rid of style differences There will always be differences from one Go programmer to another and from one team's codebase to another. However, it is in the best interest of Google and Alphabet that our codebase be as consistent as possible. (See [guide](guide#consistency) for more on consistency.) To that end, feel free to make style improvements as you see fit, but you do not need to nit-pick every violation of the Style Guide that you find. In particular, these documents may change over time, and that is no reason to cause extra churn in existing codebases; it suffices to write new code using the latest best practices and address nearby issues over time. It is important to recognize that issues of style are inherently personal and that there are always inherent trade-offs. Much of the guidance in these documents is subjective, but just like with `gofmt`, there is significant value in the uniformity they provide. As such, style recommendations will not be changed without due discourse, Go programmers at Google are encouraged to follow the style guide even where they might disagree. <a id="definitions"></a> ## Definitions The following words, which are used throughout the style documents, are defined below: * **Canonical**: Establishes prescriptive and enduring rules <a id="canonical"></a> Within these documents, "canonical" is used to describe something that is considered a standard that all code (old and new) should follow and that is not expected to change substantially over time. Principles in the canonical documents should be understood by authors and reviewers alike, so everything included within a canonical document must meet a high bar. As such, canonical documents are generally shorter and prescribe fewer elements of style than non-canonical documents. https://google.github.io/styleguide/go#canonical * **Normative**: Intended to establish consistency <a id="normative"></a> Within these documents, "normative" is used to describe something that is an agreed-upon element of style for use by Go code reviewers, in order that the suggestions, terminology, and justifications are consistent. These elements may change over time, and these documents will reflect such changes so that reviewers can remain consistent and up-to-date. Authors of Go code are not expected to be familiar with the normative documents, but the documents will frequently be used as a reference by reviewers in readability reviews. https://google.github.io/styleguide/go#normative * **Idiomatic**: Common and familiar <a id="idiomatic"></a> Within these documents, "idiomatic" is used to refer to something that is prevalent in Go code and has become a familiar pattern that is easy to recognize. In general, an idiomatic pattern should be preferred to something unidiomatic if both serve the same purpose in context, as this is what will be the most familiar to readers. https://google.github.io/styleguide/go#idiomatic <a id="references"></a> ## Additional references This guide assumes the reader is familiar with [Effective Go], as it provides a common baseline for Go code across the entire Go community. Below are some additional resources for those looking to self-educate about Go style and for reviewers looking to provide further linkable context in their reviews. Participants in the Go readability process are not expected to be familiar with these resources, but they may arise as context in readability reviews. [Effective Go]: https://go.dev/doc/effective_go **External References** * [Go Language Specification](https://go.dev/ref/spec) * [Go FAQ](https://go.dev/doc/faq) * [Go Memory Model](https://go.dev/ref/mem) * [Go Data Structures](https://research.swtch.com/godata) * [Go Interfaces](https://research.swtch.com/interfaces) * [Go Proverbs](https://go-proverbs.github.io/) * <a id="gotip"></a> Go Tip Episodes - stay tuned. * <a id="unit-testing-practices"></a> Unit Testing Practices - stay tuned. **Relevant Testing-on-the-Toilet articles** * [TotT: Identifier Naming][tott-431] * [TotT: Testing State vs. Testing Interactions][tott-281] * [TotT: Effective Testing][tott-324] * [TotT: Risk-driven Testing][tott-329] * [TotT: Change-detector Tests Considered Harmful][tott-350] [tott-431]: https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html [tott-281]: https://testing.googleblog.com/2013/03/testing-on-toilet-testing-state-vs.html [tott-324]: https://testing.googleblog.com/2014/05/testing-on-toilet-effective-testing.html [tott-329]: https://testing.googleblog.com/2014/05/testing-on-toilet-risk-driven-testing.html [tott-350]: https://testing.googleblog.com/2015/01/testing-on-toilet-change-detector-tests.html **Additional External Writings** * [Go and Dogma](https://research.swtch.com/dogma) * [Less is exponentially more](https://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html) * [Esmerelda's Imagination](https://commandcenter.blogspot.com/2011/12/esmereldas-imagination.html) * [Regular expressions for parsing](https://commandcenter.blogspot.com/2011/08/regular-expressions-in-lexing-and.html) * [Gofmt's style is no one's favorite, yet Gofmt is everyone's favorite](https://www.youtube.com/watch?v=PAAkCSZUG1c&t=8m43s) (YouTube) <!-- --> {% endraw %} ================================================ FILE: google-c-style.el ================================================ ;;; google-c-style.el --- Google's C/C++ style for c-mode ;; Keywords: c, tools ;; google-c-style.el is Copyright (C) 2008 Google Inc. All Rights Reserved. ;; ;; It is free software; you can redistribute it and/or modify it under the ;; terms of either: ;; ;; a) the GNU General Public License as published by the Free Software ;; Foundation; either version 1, or (at your option) any later version, or ;; ;; b) the "Artistic License". ;;; Commentary: ;; Provides the google C/C++ coding style. You may wish to add ;; `google-set-c-style' to your `c-mode-common-hook' after requiring this ;; file. For example: ;; ;; (add-hook 'c-mode-common-hook 'google-set-c-style) ;; ;; If you want the RETURN key to go to the next line and space over ;; to the right place, add this to your .emacs right after the load-file: ;; ;; (add-hook 'c-mode-common-hook 'google-make-newline-indent) ;;; Code: ;; For some reason 1) c-backward-syntactic-ws is a macro and 2) under Emacs 22 ;; bytecode cannot call (unexpanded) macros at run time: (eval-when-compile (require 'cc-defs)) ;; Wrapper function needed for Emacs 21 and XEmacs (Emacs 22 offers the more ;; elegant solution of composing a list of lineup functions or quantities with ;; operators such as "add") (defun google-c-lineup-expression-plus-4 (langelem) "Indents to the beginning of the current C expression plus 4 spaces. This implements title \"Function Declarations and Definitions\" of the Google C++ Style Guide for the case where the previous line ends with an open parenthesis. \"Current C expression\", as per the Google Style Guide and as clarified by subsequent discussions, means the whole expression regardless of the number of nested parentheses, but excluding non-expression material such as \"if(\" and \"for(\" control structures. Suitable for inclusion in `c-offsets-alist'." (save-excursion (back-to-indentation) ;; Go to beginning of *previous* line: (c-backward-syntactic-ws) (back-to-indentation) (cond ;; We are making a reasonable assumption that if there is a control ;; structure to indent past, it has to be at the beginning of the line. ((looking-at "\\(\\(if\\|for\\|while\\)\\s *(\\)") (goto-char (match-end 1))) ;; For constructor initializer lists, the reference point for line-up is ;; the token after the initial colon. ((looking-at ":\\s *") (goto-char (match-end 0)))) (vector (+ 4 (current-column))))) ;;;###autoload (defconst google-c-style `((c-recognize-knr-p . nil) (c-enable-xemacs-performance-kludge-p . t) ; speed up indentation in XEmacs (c-basic-offset . 2) (indent-tabs-mode . nil) (c-comment-only-line-offset . 0) (c-hanging-braces-alist . ((defun-open after) (defun-close before after) (class-open after) (class-close before after) (inexpr-class-open after) (inexpr-class-close before) (namespace-open after) (inline-open after) (inline-close before after) (block-open after) (block-close . c-snug-do-while) (extern-lang-open after) (extern-lang-close after) (statement-case-open after) (substatement-open after))) (c-hanging-colons-alist . ((case-label) (label after) (access-label after) (member-init-intro before) (inher-intro))) (c-hanging-semi&comma-criteria . (c-semi&comma-no-newlines-for-oneline-inliners c-semi&comma-inside-parenlist c-semi&comma-no-newlines-before-nonblanks)) (c-indent-comments-syntactically-p . t) (comment-column . 40) (c-indent-comment-alist . ((other . (space . 2)))) (c-cleanup-list . (brace-else-brace brace-elseif-brace brace-catch-brace empty-defun-braces defun-close-semi list-close-comma scope-operator)) (c-offsets-alist . ((arglist-intro google-c-lineup-expression-plus-4) (func-decl-cont . ++) (member-init-intro . ++) (inher-intro . ++) (comment-intro . 0) (arglist-close . c-lineup-arglist) (topmost-intro . 0) (block-open . 0) (inline-open . 0) (substatement-open . 0) (statement-cont . (,(when (fboundp 'c-no-indent-after-java-annotations) 'c-no-indent-after-java-annotations) ,(when (fboundp 'c-lineup-assignments) 'c-lineup-assignments) ++)) (label . /) (case-label . +) (statement-case-open . +) (statement-case-intro . +) ; case w/o { (access-label . /) (innamespace . 0)))) "Google C/C++ Programming Style.") ;;;###autoload (defun google-set-c-style () "Set the current buffer's c-style to Google C/C++ Programming Style. Meant to be added to `c-mode-common-hook'." (interactive) (make-local-variable 'c-tab-always-indent) (setq c-tab-always-indent t) (c-add-style "Google" google-c-style t)) ;;;###autoload (defun google-make-newline-indent () "Sets up preferred newline behavior. Not set by default. Meant to be added to `c-mode-common-hook'." (interactive) (define-key c-mode-base-map "\C-m" 'newline-and-indent) (define-key c-mode-base-map [ret] 'newline-and-indent)) (provide 'google-c-style) ;;; google-c-style.el ends here ================================================ FILE: google-r-style.html ================================================ <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="refresh" content="1; url=Rguide.html"> <title>Redirecting Redirecting you to Rguide.html. ================================================ FILE: google_python_style.vim ================================================ " Copyright 2019 Google LLC " " Licensed under the Apache License, Version 2.0 (the "License"); " you may not use this file except in compliance with the License. " You may obtain a copy of the License at " " https://www.apache.org/licenses/LICENSE-2.0 " " Unless required by applicable law or agreed to in writing, software " distributed under the License is distributed on an "AS IS" BASIS, " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. " See the License for the specific language governing permissions and " limitations under the License. " Indent Python in the Google way. setlocal indentexpr=GetGooglePythonIndent(v:lnum) let s:maxoff = 50 " maximum number of lines to look backwards. function GetGooglePythonIndent(lnum) " Indent inside parens. " Align with the open paren unless it is at the end of the line. " E.g. " open_paren_not_at_EOL(100, " (200, " 300), " 400) " open_paren_at_EOL( " 100, 200, 300, 400) call cursor(a:lnum, 1) let [par_line, par_col] = searchpairpos('(\|{\|\[', '', ')\|}\|\]', 'bW', \ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :" \ . " synIDattr(synID(line('.'), col('.'), 1), 'name')" \ . " =~ '\\(Comment\\|String\\)$'") if par_line > 0 call cursor(par_line, 1) if par_col != col("$") - 1 return par_col endif endif " Delegate the rest to the original function. return GetPythonIndent(a:lnum) endfunction let pyindent_nested_paren="&sw*2" let pyindent_open_paren="&sw*2" ================================================ FILE: htmlcssguide.html ================================================ Google HTML/CSS Style Guide

Google HTML/CSS Style Guide

Background

This document defines formatting and style rules for HTML and CSS. It aims at improving collaboration, code quality, and enabling supporting infrastructure. It applies to raw, working files that use HTML and CSS, including Sass and GSS files. Tools are free to obfuscate, minify, and compile as long as the general code quality is maintained.

General

General Style Rules

Protocol

Use HTTPS for embedded resources where possible.

Always use HTTPS (https:) for images and other media files, style sheets, and scripts, unless the respective files are not available over HTTPS.

<!-- Not recommended: omits the protocol -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>

<!-- Not recommended: uses HTTP -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<!-- Recommended -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
/* Not recommended: omits the protocol */
@import '//fonts.googleapis.com/css?family=Open+Sans';

/* Not recommended: uses HTTP */
@import 'http://fonts.googleapis.com/css?family=Open+Sans';
/* Recommended */
@import 'https://fonts.googleapis.com/css?family=Open+Sans';

General Formatting Rules

Indentation

Indent by 2 spaces at a time.

Don’t use tabs or mix tabs and spaces for indentation.

<ul>
  <li>Fantastic
  <li>Great
</ul>
.example {
  color: blue;
}

Capitalization

Use only lowercase.

All code has to be lowercase: This applies to HTML element names, attributes, attribute values (unless text/CDATA), CSS selectors, properties, and property values (with the exception of strings).

<!-- Not recommended -->
<A HREF="/">Home</A>
<!-- Recommended -->
<img src="google.png" alt="Google">
/* Not recommended */
color: #E5E5E5;
/* Recommended */
color: #e5e5e5;

Trailing Whitespace

Remove trailing white spaces.

Trailing white spaces are unnecessary and can complicate diffs.

<!-- Not recommended -->
<p>What?_
<!-- Recommended -->
<p>Yes please.

General Meta Rules

Encoding

Use UTF-8 (no BOM).

Make sure your editor uses UTF-8 as character encoding, without a byte order mark.

Specify the encoding in HTML templates and documents via <meta charset="utf-8">. Do not specify the encoding of style sheets as these assume UTF-8.

(More on encodings and when and how to specify them can be found in Handling character encodings in HTML and CSS.)

Comments

Explain code as needed, where possible.

Use comments to explain code: What does it cover, what purpose does it serve, why is respective solution used or preferred?

(This item is optional as it is not deemed a realistic expectation to always demand fully documented code. Mileage may vary heavily for HTML and CSS code and depends on the project’s complexity.)

Action Items

Mark todos and action items with TODO.

Highlight todos by using the keyword TODO only, not other common formats like @@.

Append action items after a colon as in TODO: action item.

{# TODO: Revisit centering. #}
<center>Test</center>
<!-- TODO: Remove optional tags. -->
<ul>
  <li>Apples</li>
  <li>Oranges</li>
</ul>

HTML

HTML Style Rules

Document Type

Use <!doctype html>.

Always put your HTML in no-quirks mode by including <!doctype html> at the beginning of the document.

A document without a doctype is rendered in “quirks mode”, and one with a different doctype may be rendered in “limited-quirks mode”. These modes don’t follow the widely-understood, widely-documented behavior for various core HTML and CSS constructs, and are likely to cause subtle failures and incompatibilities especially when re-using code that expects no-quirks mode.

HTML Validity

Use valid HTML where possible.

Use valid HTML code unless that is not possible due to otherwise unattainable performance goals regarding file size.

Use tools such as the W3C HTML validator to test.

Using valid HTML is a measurable baseline quality attribute that contributes to learning about technical requirements and constraints, and that ensures proper HTML usage.

<!-- Not recommended -->
<title>Test</title>
<article>This is only a test.
<!-- Recommended -->
<!doctype html>
<meta charset="utf-8">
<title>Test</title>
<article>This is only a test.</article>

Semantics

Use HTML according to its purpose.

Use elements (sometimes incorrectly called “tags”) for what they have been created for. For example, use heading elements for headings, p elements for paragraphs, a elements for anchors, etc.

Using HTML according to its purpose is important for accessibility, reuse, and code efficiency reasons.

<!-- Not recommended -->
<div onclick="goToRecommendations();">All recommendations</div>
<!-- Recommended -->
<a href="recommendations/">All recommendations</a>

Multimedia Fallback

Provide alternative contents for multimedia.

For multimedia, such as images, videos, animated objects via canvas, make sure to offer alternative access. For images that means use of meaningful alternative text (alt) and for video and audio transcripts and captions, if available.

Providing alternative contents is important for accessibility reasons: A blind user has few cues to tell what an image is about without @alt, and other users may have no way of understanding what video or audio contents are about either.

(For images whose alt attributes would introduce redundancy, and for images whose purpose is purely decorative which you cannot immediately use CSS for, use no alternative text, as in alt="".)

<!-- Not recommended -->
<img src="spreadsheet.png">
<!-- Recommended -->
<img src="spreadsheet.png" alt="Spreadsheet screenshot.">

Separation of Concerns

Separate structure from presentation from behavior.

Strictly keep structure (markup), presentation (styling), and behavior (scripting) apart, and try to keep the interaction between the three to an absolute minimum.

That is, make sure documents and templates contain only HTML and HTML that is solely serving structural purposes. Move everything presentational into style sheets, and everything behavioral into scripts.

In addition, keep the contact area as small as possible by linking as few style sheets and scripts as possible from documents and templates.

Separating structure from presentation from behavior is important for maintenance reasons. It is always more expensive to change HTML documents and templates than it is to update style sheets and scripts.

<!-- Not recommended -->
<!doctype html>
<title>HTML sucks</title>
<link rel="stylesheet" href="base.css" media="screen">
<link rel="stylesheet" href="grid.css" media="screen">
<link rel="stylesheet" href="print.css" media="print">
<h1 style="font-size: 1em;">HTML sucks</h1>
<p>I’ve read about this on a few sites but now I’m sure:
  <u>HTML is stupid!!1</u>
<center>I can’t believe there’s no way to control the styling of
  my website without doing everything all over again!</center>
<!-- Recommended -->
<!doctype html>
<title>My first CSS-only redesign</title>
<link rel="stylesheet" href="default.css">
<h1>My first CSS-only redesign</h1>
<p>I’ve read about this on a few sites but today I’m actually
  doing it: separating concerns and avoiding anything in the HTML of
  my website that is presentational.
<p>It’s awesome!

Entity References

Do not use entity references.

There is no need to use entity references like &mdash;, &rdquo;, or &#x263a;, assuming the same encoding (UTF-8) is used for files and editors as well as among teams.

The only exceptions apply to characters with special meaning in HTML (like < and &) as well as control or “invisible” characters (like no-break spaces).

<!-- Not recommended -->
The currency symbol for the Euro is &ldquo;&eur;&rdquo;.
<!-- Recommended -->
The currency symbol for the Euro is “€”.

Optional Tags

Omit optional tags (optional).

For file size optimization and scannability purposes, consider omitting optional tags. The HTML5 specification defines what tags can be omitted.

(This approach may require a grace period to be established as a wider guideline as it’s significantly different from what web developers are typically taught. For consistency and simplicity reasons it’s best served omitting all optional tags, not just a selection.)

<!-- Not recommended -->
<!doctype html>
<html>
  <head>
    <title>Spending money, spending bytes</title>
  </head>
  <body>
    <p>Sic.</p>
  </body>
</html>
<!-- Recommended -->
<!doctype html>
<title>Saving money, saving bytes</title>
<p>Qed.

type Attributes

Omit type attributes for style sheets and scripts.

Do not use type attributes for style sheets (unless not using CSS) and scripts (unless not using JavaScript).

Specifying type attributes in these contexts is not necessary as HTML5 implies text/css and text/javascript as defaults. This can be safely done even for older browsers.

<!-- Not recommended -->
<link rel="stylesheet" href="https://www.google.com/css/maia.css"
    type="text/css">
<!-- Recommended -->
<link rel="stylesheet" href="https://www.google.com/css/maia.css">
<!-- Not recommended -->
<script src="https://www.google.com/js/gweb/analytics/autotrack.js"
    type="text/javascript"></script>
<!-- Recommended -->
<script src="https://www.google.com/js/gweb/analytics/autotrack.js"></script>

id Attributes

Avoid unnecessary id attributes.

Prefer class attributes for styling and data attributes for scripting.

Where id attributes are strictly required, always include a hyphen in the value to ensure it does not match the JavaScript identifier syntax, e.g. use user-profile rather than just profile or userProfile.

When an element has an id attribute, browsers will make that available as a named property on the global window prototype, which may cause unexpected behavior. While id attribute values containing a hyphen are still available as property names, these cannot be referenced as global JavaScript variables.

<!-- Not recommended: `window.userProfile` will resolve to reference the <div> node -->
<div id="userProfile"></div>
<!-- Recommended: `id` attribute is required and its value includes a hyphen -->
<div aria-describedby="user-profile">
  …
  <div id="user-profile"></div>
  …
</div>

HTML Formatting Rules

General Formatting

Use a new line for every block, list, or table element, and indent every such child element.

Independent of the styling of an element (as CSS allows elements to assume a different role per display property), put every block, list, or table element on a new line.

Also, indent them if they are child elements of a block, list, or table element.

(If you run into issues around whitespace between list items it’s acceptable to put all li elements in one line. A linter is encouraged to throw a warning instead of an error.)

<blockquote>
  <p><em>Space</em>, the final frontier.</p>
</blockquote>
<ul>
  <li>Moe
  <li>Larry
  <li>Curly
</ul>
<table>
  <thead>
    <tr>
      <th scope="col">Income
      <th scope="col">Taxes
  <tbody>
    <tr>
      <td>$ 5.00
      <td>$ 4.50
</table>

HTML Line-Wrapping

Break long lines (optional).

While there is no column limit recommendation for HTML, you may consider wrapping long lines if it significantly improves readability.

When line-wrapping, each continuation line should be indented to distinguish wrapped attributes from child elements. Lines should be wrapped consistently within a project, ideally enforced by automated code formatting tools.

<button
  mat-icon-button
  color="primary"
  class="menu-button"
  (click)="openMenu()"
>
  <mat-icon>menu</mat-icon>
</button>
<button mat-icon-button color="primary" class="menu-button"
    (click)="openMenu()">
  <mat-icon>menu</mat-icon>
</button>
<button
    mat-icon-button
    color="primary"
    class="menu-button"
    (click)="openMenu()">
  <mat-icon>menu</mat-icon>
</button>
<button mat-icon-button
        color="primary"
        class="menu-button"
        (click)="openMenu()">
  <mat-icon>menu</mat-icon>
</button>

HTML Quotation Marks

When quoting attributes values, use double quotation marks.

Use double ("") rather than single quotation marks ('') around attribute values.

<!-- Not recommended -->
<a class='maia-button maia-button-secondary'>Sign in</a>
<!-- Recommended -->
<a class="maia-button maia-button-secondary">Sign in</a>

CSS

CSS Style Rules

CSS Validity

Use valid CSS where possible.

Unless dealing with CSS validator bugs or requiring proprietary syntax, use valid CSS code.

Use tools such as the W3C CSS validator to test.

Using valid CSS is a measurable baseline quality attribute that allows to spot CSS code that may not have any effect and can be removed, and that ensures proper CSS usage.

Class Naming

Use meaningful or generic class names.

Instead of presentational or cryptic names, always use class names that reflect the purpose of the element in question, or that are otherwise generic.

Names that are specific and reflect the purpose of the element should be preferred as these are most understandable and the least likely to change.

Generic names are simply a fallback for elements that have no particular or no meaning different from their siblings. They are typically needed as “helpers.”

Using functional or generic names reduces the probability of unnecessary document or template changes.

/* Not recommended: meaningless */
.yee-1901 {}

/* Not recommended: presentational */
.button-green {}
.clear {}
/* Recommended: specific */
.gallery {}
.login {}
.video {}

/* Recommended: generic */
.aux {}
.alt {}

Class Name Style

Use class names that are as short as possible but as long as necessary.

Try to convey what a class is about while being as brief as possible.

Using class names this way contributes to acceptable levels of understandability and code efficiency.

/* Not recommended */
.navigation {}
.atr {}
/* Recommended */
.nav {}
.author {}

Class Name Delimiters

Separate words in class names by a hyphen.

Do not concatenate words and abbreviations in selectors by any characters (including none at all) other than hyphens, in order to improve understanding and scannability.

/* Not recommended: does not separate the words “demo” and “image” */
.demoimage {}

/* Not recommended: uses underscore instead of hyphen */
.error_status {}
/* Recommended */
.video-id {}
.ads-sample {}

Prefixes

Prefix selectors with an application-specific prefix (optional).

In large projects as well as for code that gets embedded in other projects or on external sites use prefixes (as namespaces) for class names. Use short, unique identifiers followed by a dash.

Using namespaces helps preventing naming conflicts and can make maintenance easier, for example in search and replace operations.

.adw-help {} /* AdWords */
.maia-note {} /* Maia */

Type Selectors

Avoid qualifying class names with type selectors.

Unless necessary (for example with helper classes), do not use element names in conjunction with classes.

Avoiding unnecessary ancestor selectors is useful for performance reasons.

/* Not recommended */
ul.example {}
div.error {}
/* Recommended */
.example {}
.error {}

ID Selectors

Avoid ID selectors.

ID attributes are expected to be unique across an entire page, which is difficult to guarantee when a page contains many components worked on by many different engineers. Class selectors should be preferred in all situations.

/* Not recommended */
#example {}
/* Recommended */
.example {}

Shorthand Properties

Use shorthand properties where possible.

CSS offers a variety of shorthand properties (like font) that should be used whenever possible, even in cases where only one value is explicitly set.

Using shorthand properties is useful for code efficiency and understandability.

/* Not recommended */
border-top-style: none;
font-family: palatino, georgia, serif;
font-size: 100%;
line-height: 1.6;
padding-bottom: 2em;
padding-left: 1em;
padding-right: 1em;
padding-top: 0;
/* Recommended */
border-top: 0;
font: 100%/1.6 palatino, georgia, serif;
padding: 0 1em 2em;

0 and Units

Omit unit specification after “0” values, unless required.

Do not use units after 0 values unless they are required.

flex: 0px; /* This flex-basis component requires a unit. */
flex: 1 1 0px; /* Not ambiguous without the unit, but needed in IE11. */
margin: 0;
padding: 0;

Leading 0s

Always include leading “0”s in values.

Put 0s in front of values or lengths between -1 and 1.

font-size: 0.8em;

Hexadecimal Notation

Use 3 character hexadecimal notation where possible.

For color values that permit it, 3 character hexadecimal notation is shorter and more succinct.

/* Not recommended */
color: #eebbcc;
/* Recommended */
color: #ebc;

Important Declarations

Avoid using !important declarations.

These declarations break the natural cascade of CSS and make it difficult to reason about and compose styles. Use selector specificity to override properties instead.

/* Not recommended */
.example {
  font-weight: bold !important;
}
/* Recommended */
.example {
  font-weight: bold;
}

Hacks

Avoid user agent detection as well as CSS “hacks”—try a different approach first.

It’s tempting to address styling differences over user agent detection or special CSS filters, workarounds, and hacks. Both approaches should be considered last resort in order to achieve and maintain an efficient and manageable code base. Put another way, giving detection and hacks a free pass will hurt projects in the long run as projects tend to take the way of least resistance. That is, allowing and making it easy to use detection and hacks means using detection and hacks more frequently—and more frequently is too frequently.

CSS Formatting Rules

Declaration Order

Alphabetize declarations (optional).

Sort declarations consistently within a project. In the absence of tooling to automate and enforce a consistent sort order, consider putting declarations in alphabetical order in order to achieve consistent code in a way that is easy to learn, remember, and manually maintain.

Ignore vendor-specific prefixes for sorting purposes. However, multiple vendor-specific prefixes for a certain CSS property should be kept sorted (e.g. -moz prefix comes before -webkit).

background: fuchsia;
border: 1px solid;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
color: black;
text-align: center;
text-indent: 2em;

Block Content Indentation

Indent all block content.

Indent all block content, that is rules within rules as well as declarations, so to reflect hierarchy and improve understanding.

@media screen, projection {

  html {
    background: #fff;
    color: #444;
  }

}

Declaration Stops

Use a semicolon after every declaration.

End every declaration with a semicolon for consistency and extensibility reasons.

/* Not recommended */
.test {
  display: block;
  height: 100px
}
/* Recommended */
.test {
  display: block;
  height: 100px;
}

Property Name Stops

Use a space after a property name’s colon.

Always use a single space between property and value (but no space between property and colon) for consistency reasons.

/* Not recommended */
h3 {
  font-weight:bold;
}
/* Recommended */
h3 {
  font-weight: bold;
}

Declaration Block Separation

Use a space between the last selector and the declaration block.

Always use a single space between the last selector and the opening brace that begins the declaration block.

The opening brace should be on the same line as the last selector in a given rule.

/* Not recommended: missing space */
.video{
  margin-top: 1em;
}

/* Not recommended: unnecessary line break */
.video
{
  margin-top: 1em;
}
/* Recommended */
.video {
  margin-top: 1em;
}

Selector and Declaration Separation

Separate selectors and declarations by new lines.

Always start a new line for each selector and declaration.

/* Not recommended */
a:focus, a:active {
  position: relative; top: 1px;
}
/* Recommended */
h1,
h2,
h3 {
  font-weight: normal;
  line-height: 1.2;
}

Rule Separation

Separate rules by new lines.

Always put a blank line (two line breaks) between rules.

html {
  background: #fff;
}

body {
  margin: auto;
  width: 50%;
}

CSS Quotation Marks

Use single ('') rather than double ("") quotation marks for attribute selectors and property values.

Do not use quotation marks in URI values (url()).

Exception: If you do need to use the @charset rule, use double quotation marks—single quotation marks are not permitted.

/* Not recommended */
@import url("https://www.google.com/css/maia.css");

html {
  font-family: "open sans", arial, sans-serif;
}
/* Recommended */
@import url(https://www.google.com/css/maia.css);

html {
  font-family: 'open sans', arial, sans-serif;
}

CSS Meta Rules

Section Comments

Group sections by a section comment (optional).

If possible, group style sheet sections together by using comments. Separate sections with new lines.

/* Header */

.adw-header {}

/* Footer */

.adw-footer {}

/* Gallery */

.adw-gallery {}

Parting Words

Be consistent.

If you’re editing code, take a few minutes to look at the code around you and determine its style. If they use spaces around all their arithmetic operators, you should too. If their comments have little boxes of hash marks around them, make your comments have little boxes of hash marks around them too.

The point of having style guidelines is to have a common vocabulary of coding so people can concentrate on what you’re saying rather than on how you’re saying it. We present global style rules here so people know the vocabulary, but local style is also important. If code you add to a file looks drastically different from the existing code around it, it throws readers out of their rhythm when they go to read it. Avoid this.

================================================ FILE: htmlcssguide.xml ================================================

The style guide has moved to htmlcssguide.html

================================================ FILE: include/jsguide.js ================================================ window.initStyleGuide = function(init) { // Runs the callback on every element matched by the query selector. function find(querySelector, callback) { var elements = [].slice.call(document.querySelectorAll(querySelector)); for (var i = 0; i < elements.length; i++) { callback(elements[i]); } } // Add the tocDiv at the top. var title = document.getElementsByTagName('h1')[0]; var toc = document.createElement('div'); toc.id = 'tocDiv'; toc.className = 'vertical_toc'; title.parentNode.insertBefore(toc, title.nextSibling); // If a paragraph starts with (e.g.) "Note:" or "Tip:" then add // that "callout class" to its element. find('p', function(paragraph) { var match = /^([a-z]+):/i.exec(paragraph.textContent); if (match) { paragraph.classList.add(match[1].toLowerCase()); } }); // Fill in text for intra-document links, ensuring that links // remain up-to-date even if sections are moved or renumbered. // This triggers on any link with "??" as its text and a URL // starting with "#", and the filled-in text is exactly the same // as the text of the referenced section heading. find('a[href^="#"]', function(link) { var href = link.getAttribute('href'); var heading = document.getElementById(href.substring(1)); // Fill in link text with heading title if (heading && link.textContent == '??') { link.textContent = heading.textContent; } }); // Hoedown renders fenced code blocks incompatibly with what // prettify expects. As a result, prettify doesn't handle them // properly. Fix it by moving the code directly into the pre. find('pre > code', function(code) { var pre = code.parentElement; // Internal HTML/CSS & TS style guides do not use prettyprint. if (code.classList.contains('language-css') || code.classList.contains('language-django') || code.classList.contains('language-html') || code.classList.contains('language-ts')) { code.classList.add('prettyprint'); } pre.className = code.className; pre.innerHTML = code.innerHTML; }); // Run the normal init function. init(); // Call the pretty-printer after we've fixed up the code blocks. var pretty = document.createElement('script'); pretty.src = 'https://cdn.jsdelivr.net/gh/google/code-prettify@master/' + 'loader/run_prettify.js'; document.body.appendChild(pretty); }.bind(null, window.initStyleGuide); ================================================ FILE: include/styleguide.css ================================================ /* General CSS */ body { background-color: #fff; color: #333; font-family: sans-serif; font-size: 10pt; margin-right: 100px; margin-left: 100px; } h1 { text-align: center; font-size: 18pt; } h1, h2, h3, h4, h5, h6 { color: #06c; margin-top: 2em; margin-bottom: 1em; padding: 25px; font-weight:bold; } h2, h3, h4, h5, h6 { margin-top:1.5em; margin-bottom:.75em; } h1 {font-size:200%;} h2 {font-size:167%;} h3 {font-size:133%;} h4 {font-size:120%;} h5 {font-size:110%;} table { border: 1px solid #bbb; border-spacing: 0; border-collapse: collapse; margin: 0 0 1.5em; vertical-align: middle; width: 100% } td, th { border: 1px solid #ccc; padding: 2px 12px; font-size: 10pt; } code, samp, var { background-color:#FAFAFA; white-space: nowrap } pre { background-color: #e9e9e9; color: #333; border-color: #f9f9f9; border-style: solid; border-width: 1px 1px 1px 5px; overflow: auto; padding: 6px 12px; } pre.prettyprint { padding:6px 10px !important; border:1px solid #bbb !important; } pre.bad, pre.badcode { background-color: #ffe6d8; border-color: #fff0f0; color: #c00; } pre.good, pre.goodcode { background-color: #e8fff6; color: #060; border-color: #f0fff0; } hr { margin-top: 3.5em; border-width: 1px; color: #fff; } /* TOC CSS */ table.columns { border: none; } td.two_columns { -webkit-column-count: 2; column-count: 2; } .toc_category { font-size: 10pt; padding-top: 1em; padding-bottom: 1em; border-left-width: 2px; border-right-width: 2px; border-color: grey; } .toc_stylepoint { font-size: 10pt; padding-top: 1em; padding-bottom: 1em; } li.toc_entry { padding-right: 1em; display: inline; list-style-type: none; } /* * This space is required to trigger the linewrap on the links * at href boundaries */ li.toc_entry::after { content: " "; } li.toc_entry a { white-space: nowrap; } /* Horizontal TOC */ .toc td, .toc th { border-width: 1px 5px; overflow: hidden; } /* Vertical TOC */ .toc td.two_columns { border-width: 0px; } /* Special Sections */ address { text-align: right; } .revision { text-align: right; } .headerbox { margin-left: 50%; font-size: 75%; } .legend { padding-top: 1em; margin-left: 50%; font-size: 10pt; } .link_button { float: left; display: none; background-color: #f8f8ff; border-color: #f0f0ff; border-style: solid; border-width: 1px; font-size: 75%; margin-top: 0; margin-left: -50px; padding: 24px; border-radius: 3px; -webkit-border-radius: 3px; -moz-border-radius: 3px; } .ignoreLink { padding: 0px; } .divider{ width:5px; height:auto; display:inline-block; } /* Style Guide semantic CSS */ .summary { margin-top: 1em; margin-bottom: 1em; } .stylebody { margin-top: 1em; margin-bottom: 1em; } .stylepoint_section { display: block; margin-bottom: 1em; font-family: sans-serif; font-weight: bold; } .stylepoint_subsection { display: block; margin-bottom: 1em; } .stylepoint_subsubsection { display: block; margin-bottom: 1em; } .definition:before { content: "Definition: "; font-weight: bold; display: block; margin-bottom: 1em; } .pros:before { content: "Pros: "; font-weight: bold; display: block; margin-bottom: 1em; } .cons:before { content: "Cons: "; font-weight: bold; display: block; margin-bottom: 1em; } .decision:before { content: "Decision: "; font-weight: bold; display: block; margin-bottom: 1em; } .exception:before { content: "Exception: "; font-weight: bold; display: block; margin-bottom: 1em; } .note:before { content: "Note: "; font-weight: bold; display: block; margin-bottom: 1em; } ================================================ FILE: include/styleguide.js ================================================ TocTypeEnum = { VERTICAL: 1, HORIZONTAL: 2 }; function CreateTOC(tocElement) { // Find the toc element DIV. We'll place our TOC there. var toc = document.getElementById(tocElement); var tocTypeClass = toc.className; var tocType; switch (tocTypeClass) { case 'horizontal_toc': tocType = TocTypeEnum.HORIZONTAL; break; case 'vertical_toc': tocType = TocTypeEnum.VERTICAL; break; default: tocType = TocTypeEnum.VERTICAL; break; } // If toc_levels is defined, set headingLevels to it. // Otherwise, use default value of "h2,h3" var headingLevels; if (typeof toc_levels === 'undefined') { headingLevels = 'h2,h3'; } else { } // Collect all section heading elements in an array var headings = document.querySelectorAll(headingLevels); // Add TOC title elements var tocHeadingDiv = document.createElement('div'); toc.appendChild(tocHeadingDiv); tocHeadingDiv.className = 'toc_title'; var tocHeading = document.createElement('h3'); toc.appendChild(tocHeading); tocHeading.className = 'ignoreLink'; tocHeading.id = 'toc'; var tocText = document.createTextNode('Table of Contents'); tocHeading.appendChild(tocText); // Add table and tbody var tocTable = document.createElement('table'); if (tocType == TocTypeEnum.VERTICAL) { tocTable.className = 'columns'; } toc.appendChild(tocTable); var tbody_element = document.createElement('tbody'); tbody_element.setAttribute('valign', 'top'); tbody_element.className = 'toc'; tocTable.appendChild(tbody_element); // Get the highest level heading var firstHeading = headings[0]; var masterLevel = parseInt(headingLevels.charAt(1)); // Get the lowest heading level var lowestLevel = parseInt(headingLevels.charAt(headingLevels - 1)); switch (tocType) { case TocTypeEnum.HORIZONTAL: CreateHorizontalTOC(headings, masterLevel, lowestLevel, tbody_element); break; case TocTypeEnum.VERTICAL: CreateVerticalTOC(headings, masterLevel, lowestLevel, tbody_element); break; default: } } function CreateHorizontalTOC( headings, masterLevel, lowestLevel, tbody_element) { // Initialize the header counter var h = 0; var ignoreChildren = false; while (h < headings.length) { // Get current heading var heading = headings[h]; // Get the current heading level var level = parseInt(heading.tagName.charAt(1)); if (isNaN(level) || level < 1 || level > lowestLevel) continue; // If level is a masterLevel, make it a TOC parent category if ((level == masterLevel) && (!hasClass(heading, 'ignoreLink'))) { toc_current_row = AddTOCMaster(tbody_element, heading); ignoreChildren = false; } if ((level == masterLevel) && (hasClass(heading, 'ignoreLink'))) { ignoreChildren = true; } if ((level != masterLevel) && (!ignoreChildren)) { AddTOCElements(toc_current_row, heading); } // Advance the header counter h++; } } // Adds a master Table of Content heading function AddTOCMaster(tocTable, heading) { // Add the table row scaffolding var toc_tr = document.createElement('tr'); tocTable.appendChild(toc_tr); toc_tr.setAttribute('valign', 'top'); var toc_tr_td = document.createElement('td'); toc_tr.appendChild(toc_tr_td); var toc_category = document.createElement('div'); toc_tr_td.appendChild(toc_category); toc_category.className = 'toc_category'; // Create the link to this header var link = document.createElement('a'); link.href = '#' + heading.id; // Create the anchor link link.textContent = heading.textContent; // Link text is same as heading toc_category.appendChild(link); // Add the container table cell for its children var toc_td = document.createElement('td'); toc_tr.appendChild(toc_td); var toc_td_div = document.createElement('div'); toc_td_div.className = 'toc_stylepoint'; toc_td.appendChild(toc_td_div); return (toc_td_div); } // Adds Table of Contents element to a master heading as children function AddTOCElements(toc_div, heading) { if (heading.offsetParent === null) { // The element is currently hidden, so don't create a TOC entry } else { // Create the list item element var toc_list_element = document.createElement('li'); toc_list_element.className = 'toc_entry'; toc_div.appendChild(toc_list_element); // Create the link to this header var link = document.createElement('a'); link.href = '#' + heading.id; // Create the anchor link link.textContent = heading.textContent; // Link text is same as heading toc_list_element.appendChild(link); } } function CreateVerticalTOC(headings, masterLevel, lowestLevel, tbody_element) { // Create the Column scaffolding var toc_tr = document.createElement('tr'); tbody_element.appendChild(toc_tr); var toc_tr_td = document.createElement('td'); toc_tr_td.className = 'two_columns'; toc_tr.appendChild(toc_tr_td); // Initialize the header counter and the current row var h = 0; var toc_current_col = null; var ignoreChildren = false; while (h < headings.length) { // Get current heading var heading = headings[h]; // Get the current heading level var level = parseInt(heading.tagName.charAt(1)); if (isNaN(level) || level < 1 || level > lowestLevel) continue; // If level is a masterLevel, make it a TOC parent category if ((level == masterLevel) && (!hasClass(heading, 'ignoreLink'))) { if (heading.offsetParent === null) { // The element is currently hidden, so don't create a TOC entry } else { var td_dl = document.createElement('dl'); toc_tr_td.appendChild(td_dl); var td_dt = document.createElement('dt'); td_dl.appendChild(td_dt); toc_current_col = td_dl; // Create the link to this header var link = document.createElement('a'); link.href = '#' + heading.id; // Create the anchor link link.textContent = heading.textContent; // Link text is same as heading td_dt.appendChild(link); ignoreChildren = false; } } // If level is a masterLevel but it's specified to ignore links, skip it // and its children. if ((level == masterLevel) && (hasClass(heading, 'ignoreLink'))) { ignoreChildren = true; } if ((level != masterLevel) && (!ignoreChildren)) { if (heading.offsetParent === null) { // The element is currently hidden, so don't create a TOC entry } else { var td_dd = document.createElement('dd'); toc_current_col.appendChild(td_dd); // Create the link to this header var link = document.createElement('a'); link.href = '#' + heading.id; // Create the anchor link link.textContent = heading.textContent; // Link text is same as heading td_dd.appendChild(link); } } // Advance the header counter h++; } } /* * Utility function for finding elements with a given * class. */ function hasClass(element, cls) { return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1; } /* * Linkify all h2 through h4 headers, except for those marked * "ignoreLink" */ // Add the link image to the element. function LinkifyHeader(header, fileName, sizePixels) { var link = document.createElement('a'); link.href = '#' + header.id; link.setAttribute('alt', 'link to ' + header.id); link.innerHTML = ''; header.appendChild(link); } // Find all elements of the given tag and linkify if // they don't have 'ignoreLink' in their class. function LinkifyHeadersForTag(tagName) { var headers = document.getElementsByTagName(tagName); var header; for (var j = 0; j != headers.length; j++) { header = headers[j]; if (!hasClass(header, 'ignoreLink') && ('id' in header)) { if (header.id != '') { LinkifyHeader(header, 'link.png', 21); header.style.left = '-46px'; header.style.position = 'relative'; } } } } // Linkify all h2, h3, and h4s. h1s are titles. function LinkifyHeaders() { LinkifyHeadersForTag('h2'); LinkifyHeadersForTag('h3'); LinkifyHeadersForTag('h4'); } /* * Initialize the style guide by showing all internal * elements and then linkifying the headers. */ function initStyleGuide() { LinkifyHeaders(); CreateTOC('tocDiv'); } ================================================ FILE: intellij-java-google-style.xml ================================================ ================================================ FILE: javaguide.css ================================================ table { border-collapse: collapse; } td, th { border: 1px solid #ccc; padding: 2px 12px; font-size: 10pt; } code, samp, var { color: #060; } pre { font-size: 10pt; display: block; color: #060; background-color: #e8fff6; border: 1px solid #f0fff0; border-left-width: 5px; padding: 4px 12px; } pre.badcode { color: #c00; background-color: #ffe6d8; border-color: #fff0f0; } hr { margin-top: 3.5em; border-width: 1px; color: #fff; } html { margin: 2em 10% 0; padding: 0; } .bp-reset-element, body, h1, h2, h3, h4, h5, h6, article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary, blockquote, q, th, td, caption, table, div, span, object, iframe, p, pre, a, abbr, acronym, address, code, del, dfn, em, img, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, caption, tbody, tfoot, thead, tr { margin: 0; padding: 0; border: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit; vertical-align: baseline; } body { font-family: 'Arial', sans-serif; font-size: 81.25%; color: #222; background-color: #fff; line-height: 1.67; overflow: auto; } .change { text-align: right; margin-bottom: 1em; } em { font-style: italic; } h1, h2, h3, h4, h5, h6 { font-weight: bold; } h1 { margin-bottom: 0.5em; text-align: center; } h2, h3, h4, h5, h6 { margin-top: 1.5em; margin-bottom: 0.75em; } h1 { font-size: 200%; } h2 { font-size: 167%; } h3 { font-size: 133%; } h4 { font-size: 120%; } h5 { font-size: 110%; } p { margin: 0 0 1.5em; } a[href=''] { cursor: default; } h1 img, h2 img, h3 img, h4 img, h5 img, h6 img { margin: 0; } a img { border: none; } pre { margin: 1.5em 0; white-space: pre; } pre, code, kbd, tt { font: 1em 'Droid Sans Mono', monospace; line-height: 1.5; } dl { margin: 0 0 1.5em; } dl dt { font-weight: bold; } dd { margin-left: 1.5em; } dd.toc3 { margin-left: 3em; } hr { height: 0; border: 0; border-top: 1px solid #ccc; background-color: #ccc; } table { border: 1px solid #bbb; border-spacing: 0; border-collapse: collapse; margin: 0 0 1.5em; vertical-align: middle; width: 100%; } table.unlined, table.unlined th, table.unlined tr, table.unlined td { border: 0; } th, td, caption { float: none !important; text-align: left; font-weight: normal; vertical-align: middle; padding: 4px; } caption { padding: 0; } td { border: 1px solid #bbb; vertical-align: top; } th { border: 0; border-bottom: 1px solid black; font-weight: bold; background: rgb(229, 236, 249); } table th code { background-color: inherit; color: inherit; } table tfoot th { border: 1px solid #bbb; } tfoot { font-style: italic; } caption { background: #eee; } table[border='0'] { border: none; } table[border='0'] > tbody > tr > td, table[border='0'] > tr > td { border: none; } tr.alt td, td.alt { background-color: #efefef; } table.striped tr:nth-child(even) td, table tr.even td { background: #efefef; } table.columns { border: none; } table.columns > tbody > tr > td, table.columns > tr > td { border: none; padding: 0 3em 0 0; } table.columns > tbody > tr > td:last-child, table.columns > tr > td:last-child { border: none; padding: 0; } ul, ol { margin: 0 1.5em 1.5em 0; padding-left: 2em; } li ul, li ol { margin: 0; } ul { list-style-type: disc; } ol { list-style-type: decimal; } ul { list-style-type: disc; } ul ul { list-style-type: circle; } ul ul ul { list-style-type: square; } ul.disc { list-style-type: disc; } ul.circle { list-style-type: circle; } ul.square { list-style-type: square; } ol { list-style-type: decimal; } ol ol { list-style-type: lower-alpha; } ol ol ol { list-style-type: lower-roman; } ol ul { list-style-type: circle; } ol.decimal { list-style-type: decimal; } ol.upper-alpha { list-style-type: upper-alpha; } ol.lower-alpha { list-style-type: lower-alpha; } ol.upper-roman { list-style-type: upper-roman; } ol.lower-roman { list-style-type: lower-roman; } ol.nolist, ul.nolist { padding-left: 0; list-style-image: none; list-style-type: none; margin-left: 0; } .center { text-align: center; } code, kbd, pre { color: #090; } kbd { font-weight: bold; } table.striped code { background-color: inherit; } pre { padding: 6px 10px; background-color: #fafafa; border: 1px solid #bbb; overflow: auto; } pre.prettyprint { padding: 6px 10px !important; border: 1px solid #bbb !important; } code.bad, code.badcode { color: magenta; } pre.bad, pre.badcode { background-color: #ffe6d8; border-top: 1px inset #a03; border-left: 1px inset #a03; } .tip { background-color: #fffbd9; padding: 6px 8px 6px 10px; border-left: 6px solid #ffef70; } .note { background-color: #e5ecf9; padding: 6px 8px 6px 10px; border-left: 6px solid #36c; } @media print { .str { color: #060; } .kwd { color: #006; font-weight: bold; } .com { color: #600; font-style: italic; } .typ { color: #404; font-weight: bold; } .lit { color: #044; } .pun, .opn, .clo { color: #440; } .pln { color: #000; } .tag { color: #006; font-weight: bold; } .atn { color: #404; } .atv { color: #060; } h1 { font-style: italic; } } ol.linenums { margin-top: 0; margin-bottom: 0; } code { background-color: #fafafa; padding: 0.25em 0.5em; white-space: nowrap; } /* TOC CSS */ table.columns { border: none; } td.two_columns { -webkit-column-count: 2; column-count: 2; } .toc_category { font-size: 10pt; padding-top: 1em; padding-bottom: 1em; border-left-width: 2px; border-right-width: 2px; border-color: grey; } .toc_stylepoint { font-size: 10pt; padding-top: 1em; padding-bottom: 1em; } li.toc_entry { padding-right: 1em; display: inline; list-style-type: none; } /* * This space is required to trigger the linewrap on the links * at href boundaries */ li.toc_entry::after { content: ' '; } li.toc_entry a { white-space: nowrap; } /* Horizontal TOC */ .toc td, .toc th { border-width: 1px 5px; overflow: hidden; } /* Vertical TOC */ .toc td.two_columns { border-width: 0; } /* Numbered sections */ h1 { counter-reset: h2; } h2.numbered { counter-reset: h3; } h3.numbered { counter-reset: h4; } h2.numbered::before { content: counter(h2) ' '; counter-increment: h2; } h3.numbered::before { content: counter(h2) '.' counter(h3) ' '; counter-increment: h3; } h4.numbered::before { content: counter(h2) '.' counter(h3) '.' counter(h4) ' '; counter-increment: h4; } ================================================ FILE: javaguide.html ================================================ Google Java Style Guide

Google Java Style Guide

1 Introduction

This document serves as the complete definition of Google's coding standards for source code in the Java™ Programming Language. A Java source file is described as being in Google Style if and only if it adheres to the rules herein.

Like other programming style guides, the issues covered span not only aesthetic issues of formatting, but other types of conventions or coding standards as well. However, this document focuses primarily on the hard-and-fast rules that we follow universally, and avoids giving advice that isn't clearly enforceable (whether by human or tool).

1.1 Terminology notes

In this document, unless otherwise clarified:

  1. The term class is used inclusively to mean a normal class, record class, enum class, interface or annotation type (@interface).
  2. The term member (of a class) is used inclusively to mean a nested class, field, method, or constructor; that is, all top-level contents of a class except initializers.
  3. The term comment always refers to implementation comments. We do not use the phrase "documentation comments", and instead use the common term "Javadoc."

Other "terminology notes" will appear occasionally throughout the document.

1.2 Guide notes

Example code in this document is non-normative. That is, while the examples are in Google Style, they may not illustrate the only stylish way to represent the code. Optional formatting choices made in examples should not be enforced as rules.

2 Source file basics

2.1 File name

For a source file containing classes, the file name consists of the case-sensitive name of the top-level class (of which there is exactly one), plus the .java extension.

2.2 File encoding: UTF-8

Source files are encoded in UTF-8.

2.3 Special characters

2.3.1 Whitespace characters

Aside from the line terminator sequence, the ASCII horizontal space character (0x20) is the only whitespace character that appears anywhere in a source file. This implies that:

  1. All other whitespace characters are escaped in char and string literals and in text blocks.
  2. Tab characters are not used for indentation.

2.3.2 Special escape sequences

For any character that has a special escape sequence (\b, \t, \n, \f, \r, \s, \", \' and \\), that sequence is used rather than the corresponding octal (e.g. \012) or Unicode (e.g. \u000a) escape.

2.3.3 Non-ASCII characters

For the remaining non-ASCII characters, either the actual Unicode character (e.g. ) or the equivalent Unicode escape (e.g. \u221e) is used. The choice depends only on which makes the code easier to read and understand, although Unicode escapes outside string literals and comments are strongly discouraged.

Tip: In the Unicode escape case, and occasionally even when actual Unicode characters are used, an explanatory comment can be very helpful.

Examples:

Example Discussion
String unitAbbrev = "μs"; Best: perfectly clear even without a comment.
String unitAbbrev = "\u03bcs"; // "μs" Allowed, but there's no reason to do this.
String unitAbbrev = "\u03bcs"; // Greek letter mu, "s" Allowed, but awkward and prone to mistakes.
String unitAbbrev = "\u03bcs"; Poor: the reader has no idea what this is.
return '\ufeff' + content; // byte order mark Good: use escapes for non-printable characters, and comment if necessary.

Tip: Never make your code less readable simply out of fear that some programs might not handle non-ASCII characters properly. If that should happen, those programs are broken and they must be fixed.

3 Source file structure

An ordinary source file consists of these sections, in order:

  1. License or copyright information, if present
  2. Package declaration
  3. Imports
  4. Exactly one top-level class declaration

Exactly one blank line separates each section that is present.

A package-info.java file is the same, but without the class declaration.

A module-info.java file does not contain a package declaration and replaces the class declaration with a module declaration, but otherwise follows the same structure.

If license or copyright information belongs in a file, it belongs here.

3.2 Package declaration

The package declaration is not line-wrapped. The column limit (Section 4.4, Column limit: 100) does not apply to package declarations.

3.3 Imports

3.3.1 No wildcard imports

Wildcard ("on-demand") imports, static or otherwise, are not used.

3.3.2 No line-wrapping

Imports are not line-wrapped. The column limit (Section 4.4, Column limit: 100) does not apply to imports.

3.3.3 Ordering and spacing

Imports are ordered as follows:

  1. All static imports in a single group.
  2. All non-static imports in a single group.

If there are both static and non-static imports, a single blank line separates the two groups. There are no other blank lines between imports.

Within each group the imported names appear in ASCII sort order. (Note: this is not the same as the import lines being in ASCII sort order, since '.' sorts before ';'.)

3.3.4 No static import for classes

Static import is not used for static nested classes. They are imported with normal imports.

3.4 Class declaration

3.4.1 Exactly one top-level class declaration

Each top-level class resides in a source file of its own.

3.4.2 Ordering of class contents

The order you choose for the members and initializers of your class can have a great effect on learnability. However, there's no single correct recipe for how to do it; different classes may order their contents in different ways.

What is important is that each class uses some logical order, which its maintainer could explain if asked. For example, new methods are not just habitually added to the end of the class, as that would yield "chronological by date added" ordering, which is not a logical ordering.

3.4.2.1 Overloads: never split

Methods of a class that share the same name appear in a single contiguous group with no other members in between. The same applies to multiple constructors. This rule applies even when modifiers such as static or private differ between the methods or constructors.

3.5 Module declaration

3.5.1 Ordering and spacing of module directives

Module directives are ordered as follows:

  1. All requires directives in a single block.
  2. All exports directives in a single block.
  3. All opens directives in a single block.
  4. All uses directives in a single block.
  5. All provides directives in a single block.

A single blank line separates each block that is present.

4 Formatting

Terminology Note: block-like construct refers to the body of a class, method, constructor, or switch. Note that, by Section 4.8.3.1 on array initializers, any array initializer may optionally be treated as if it were a block-like construct.

4.1 Braces

4.1.1 Use of optional braces

Braces are used with if, else, for, do and while statements, even when the body is empty or contains only a single statement.

Other optional braces, such as those in a lambda expression, remain optional.

4.1.2 Nonempty blocks: K & R style

Braces follow the Kernighan and Ritchie style for nonempty blocks and block-like constructs:

  • No line break before the opening brace, except as detailed below.
  • Line break after the opening brace.
  • Line break before the closing brace.
  • Line break after the closing brace, only if that brace terminates a statement or terminates the body of a method, constructor, or named class. For example, there is no line break after the brace if it is followed by else or a comma.

Exception: In places where these rules allow a single statement ending with a semicolon (;), a block of statements can appear, and the opening brace of this block is preceded by a line break. Blocks like these are typically introduced to limit the scope of local variables.

Examples:

return () -> {
  while (condition()) {
    method();
  }
};

return new MyClass() {
  @Override public void method() {
    if (condition()) {
      try {
        something();
      } catch (ProblemException e) {
        recover();
      }
    } else if (otherCondition()) {
      somethingElse();
    } else {
      lastThing();
    }
    {
      int x = foo();
      frob(x);
    }
  }
};

A few exceptions for enum classes are given in Section 4.8.1, Enum classes.

4.1.3 Empty blocks: may be concise

An empty block or block-like construct may be in K & R style (as described in Section 4.1.2). Alternatively, it may be closed immediately after it is opened, with no characters or line break in between ({}), unless it is part of a multi-block statement (one that directly contains multiple blocks: if/else or try/catch/finally).

Examples:

  // This is acceptable
  void doNothing() {}

  // This is equally acceptable
  void doNothingElse() {
  }
  // This is not acceptable: No concise empty blocks in a multi-block statement
  try {
    doSomething();
  } catch (Exception e) {}

4.2 Block indentation: +2 spaces

Each time a new block or block-like construct is opened, the indent increases by two spaces. When the block ends, the indent returns to the previous indent level. The indent level applies to both code and comments throughout the block. (See the example in Section 4.1.2, Nonempty blocks: K & R Style.)

4.3 One statement per line

Each statement is followed by a line break.

4.4 Column limit: 100

Java code has a column limit of 100 characters. A "character" means any Unicode code point. Except as noted below, any line that would exceed this limit must be line-wrapped, as explained in Section 4.5, Line-wrapping.

Each Unicode code point counts as one character, even if its display width is greater or less. For example, if using fullwidth characters, you may choose to wrap the line earlier than where this rule strictly requires.

Exceptions:

  1. Lines where obeying the column limit is not possible (for example, a long URL in Javadoc, or a long JSNI method reference).
  2. package declarations and imports (see Sections 3.2 Package declarations and 3.3 Imports).
  3. Contents of text blocks.
  4. Command lines in a comment that may be copied-and-pasted into a shell.
  5. Very long identifiers, on the rare occasions they are called for, are allowed to exceed the column limit. In that case, the valid wrapping for the surrounding code is as produced by google-java-format.

4.5 Line-wrapping

Terminology Note: When code that might otherwise occupy a single line is divided into multiple lines, this activity is called line-wrapping.

There is no comprehensive, deterministic formula showing exactly how to line-wrap in every situation. Very often there are several valid ways to line-wrap the same piece of code.

Note: While the typical reason for line-wrapping is to avoid overflowing the column limit, even code that would in fact fit within the column limit may be line-wrapped at the author's discretion.

Tip: Extracting a method or local variable may solve the problem without the need to line-wrap.

4.5.1 Where to break

The prime directive of line-wrapping is: prefer to break at a higher syntactic level. Also:

  1. When a line is broken at a non-assignment operator the break comes before the symbol. (Note that this is not the same practice used in Google style for other languages, such as C++ and JavaScript.)
    • This also applies to the following "operator-like" symbols:
      • the dot separator (.)
      • the two colons of a method reference (::)
      • an ampersand in a type bound (<T extends Foo & Bar>)
      • a pipe in a catch block (catch (FooException | BarException e)).
  2. When a line is broken at an assignment operator the break typically comes after the symbol, but either way is acceptable.
    • This also applies to the colon in an enhanced for ("foreach") statement.
  3. A method, constructor, or record-class name stays attached to the open parenthesis (() that follows it.
  4. A comma (,) stays attached to the token that precedes it.
  5. A line is never broken adjacent to the arrow in a lambda or a switch rule, except that a break may come immediately after the arrow if the text following it consists of a single unbraced expression. Examples:
    MyLambda<String, Long, Object> lambda =
        (String label, Long value, Object obj) -> {
          ...
        };
    
    Predicate<String> predicate = str ->
        longExpressionInvolving(str);
    
    switch (x) {
      case ColorPoint(Color color, Point(int x, int y)) ->
          handleColorPoint(color, x, y);
      ...
    }
    

Note: The primary goal for line wrapping is to have clear code, not necessarily code that fits in the smallest number of lines.

4.5.2 Indent continuation lines at least +4 spaces

When line-wrapping, each line after the first (each continuation line) is indented at least +4 from the original line.

When there are multiple continuation lines, indentation may be varied beyond +4 as desired. In general, two continuation lines use the same indentation level if and only if they begin with syntactically parallel elements.

Section 4.6.3 on Horizontal alignment addresses the discouraged practice of using a variable number of spaces to align certain tokens with previous lines.

4.6 Whitespace

4.6.1 Vertical whitespace (blank lines)

A single blank line always appears:

  1. Between consecutive members or initializers of a class: fields, constructors, methods, nested classes, static initializers, and instance initializers.
    • Exception: A blank line between two consecutive fields (having no other code between them) is optional. Such blank lines are used as needed to create logical groupings of fields.
    • Exception: Blank lines between enum constants are covered in Section 4.8.1.
  2. As required by other sections of this document (such as Section 3, Source file structure, and Section 3.3, Imports).

A single blank line may also appear anywhere it improves readability, for example between statements to organize the code into logical subsections. A blank line before the first member or initializer, or after the last member or initializer of the class, is neither encouraged nor discouraged.

Multiple consecutive blank lines are permitted, but never required (or encouraged).

4.6.2 Horizontal whitespace

Beyond where required by the language or other style rules, and apart from within literals, comments and Javadoc, a single ASCII space also appears in the following places only.

  1. Separating any keyword, such as if, for or catch, from an open parenthesis (() that follows it on that line
  2. Separating any keyword, such as else or catch, from a closing curly brace (}) that precedes it on that line
  3. Before any open curly brace ({), with two exceptions:
    • @SomeAnnotation({a, b}) (no space is used)
    • String[][] x = {{"foo"}}; (no space is required between {{, by item 10 below)
  4. On both sides of any binary or ternary operator. This also applies to the following "operator-like" symbols:
    • the ampersand that separates multiple type bounds: <T extends Foo & Bar>
    • the pipe for a catch block that handles multiple exceptions: catch (FooException | BarException e)
    • the colon (:) in an enhanced for ("foreach") statement
    • the arrow in a lambda expression: (String str) -> str.length()
      or switch rule: case "FOO" -> bar();
    but not
    • the two colons (::) of a method reference, which is written like Object::toString
    • the dot separator (.), which is written like object.toString()
  5. After ,:; or the closing parenthesis ()) of a cast
  6. Between any content and a double slash (//) which begins a comment. Multiple spaces are allowed.
  7. Between a double slash (//) which begins a comment and the comment's text. Multiple spaces are allowed.
  8. Between the type and identifier of a declaration: List<String> list
  9. Optional just inside both braces of an array initializer
    • new int[] {5, 6} and new int[] { 5, 6 } are both valid
  10. Between a type annotation and [] or ....

This rule is never interpreted as requiring or forbidding additional space at the start or end of a line; it addresses only interior space.

4.6.3 Horizontal alignment: never required

Terminology Note: Horizontal alignment is the practice of adding a variable number of additional spaces in your code with the goal of making certain tokens appear directly below certain other tokens on previous lines.

This practice is permitted, but is never required by Google Style. It is not even required to maintain horizontal alignment in places where it was already used.

Here is an example without alignment, then using alignment:

private int x; // this is fine
private Color color; // this too

private int   x;      // permitted, but future edits
private Color color;  // may leave it unaligned

Tip: Alignment can aid readability, but attempting to preserve alignment for its own sake creates future problems. For example, consider a change that touches only one line. If that change disrupts the previous alignment, it's important **not** to introduce additional changes on nearby lines simply to realign them. Introducing formatting changes on otherwise unaffected lines corrupts version history, slows down reviewers, and exacerbates merge conflicts. These practical concerns take priority over alignment.

4.7 Grouping parentheses: recommended

Optional grouping parentheses are omitted only when author and reviewer agree that there is no reasonable chance the code will be misinterpreted without them, nor would they have made the code easier to read. It is not reasonable to assume that every reader has the entire Java operator precedence table memorized.

4.8 Specific constructs

4.8.1 Enum classes

After the comma that follows an enum constant, a line break is optional. Additional blank lines (usually just one) are also allowed. This is one possibility:

private enum Answer {
  YES {
    @Override public String toString() {
      return "yes";
    }
  },

  NO,
  MAYBE
}

An enum class with no methods and no documentation on its constants may optionally be formatted as if it were an array initializer (see Section 4.8.3.1 on array initializers).

private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }

Since enum classes are classes, all other rules for formatting classes apply.

4.8.2 Variable declarations

4.8.2.1 One variable per declaration

Every variable declaration (field or local) declares only one variable: declarations such as int a, b; are not used.

Exception: Multiple variable declarations are acceptable in the header of a for loop.

4.8.2.2 Declared when needed

Local variables are not habitually declared at the start of their containing block or block-like construct. Instead, local variables are declared close to the point they are first used (within reason), to minimize their scope. Local variable declarations typically have initializers, or are initialized immediately after declaration.

4.8.3 Arrays

4.8.3.1 Array initializers: can be "block-like"

Any array initializer may optionally be formatted as if it were a "block-like construct." For example, the following are all valid (not an exhaustive list):

new int[] {           new int[] {
  0, 1, 2, 3            0,
}                       1,
                        2,
new int[] {             3,
  0, 1,               }
  2, 3
}                     new int[]
                          {0, 1, 2, 3}
4.8.3.2 No C-style array declarations

The square brackets form a part of the type, not the variable: String[] args, not String args[].

4.8.4 Switch statements and expressions

For historical reasons, the Java language has two distinct syntaxes for switch, which we can call old-style and new-style. New-style switches use an arrow (->) after the switch labels, while old-style switches use a colon (:).

Terminology Note: Inside the braces of a switch block are either one or more switch rules (new-style); or one or more statement groups (old-style). A switch rule consists of a switch label (case ... or default) followed by -> and an expression, block, or throw. A statement group consists of one or more switch labels each followed by a colon, then one or more statements, or, for the last statement group, zero or more statements. (These definitions match the Java Language Specification, §14.11.)

4.8.4.1 Indentation

As with any other block, the contents of a switch block are indented +2. Each switch label starts with this +2 indentation.

In a new-style switch, a switch rule can be written on a single line if it otherwise follows Google style. (It must not exceed the column limit, and if it contains a non-empty block then there must be a line break after {.) The line-wrapping rules of Section 4.5 apply, including the +4 indent for continuation lines. For a switch rule with a non-empty block after the arrow, the same rules apply as for blocks elsewhere: lines between { and } are indented a further +2 relative to the line with the switch label.

switch (number) {
  case 0, 1 -> handleZeroOrOne();
  case 2 ->
      handleTwoWithAnExtremelyLongMethodCallThatWouldNotFitOnTheSameLine();
  default -> {
    logger.atInfo().log("Surprising number %s", number);
    handleSurprisingNumber(number);
  }
}

In an old-style switch, the colon of each switch label is followed by a line break. The statements within a statement group are indented a further +2.

4.8.4.2 Fall-through: commented

Within an old-style switch block, each statement group either terminates abruptly (with a break, continue, return or thrown exception), or is marked with a comment to indicate that execution will or might continue into the next statement group. Any comment that communicates the idea of fall-through is sufficient (typically // fall through). This special comment is not required in the last statement group of the switch block. Example:

switch (input) {
  case 1:
  case 2:
    prepareOneOrTwo();
  // fall through
  case 3:
    handleOneTwoOrThree();
    break;
  default:
    handleLargeNumber(input);
}

Notice that no comment is needed after case 1:, only at the end of the statement group.

There is no fall-through in new-style switches.

4.8.4.3 Exhaustiveness and presence of the default label

The Java language requires switch expressions and many kinds of switch statements to be exhaustive. That effectively means that every possible value that could be switched on will be matched by one of the switch labels. A switch is exhaustive if it has a default label, but also for example if the value being switched on is an enum and every value of the enum is matched by a switch label. Google Style requires every switch to be exhaustive, even those where the language itself does not require it. This may require adding a default label, even if it contains no code.

4.8.4.4 Switch expressions

Switch expressions must be new-style switches:

  return switch (list.size()) {
    case 0 -> "";
    case 1 -> list.getFirst();
    default -> String.join(", ", list);
  };

4.8.5 Annotations

4.8.5.1 Type-use annotations

Type-use annotations appear immediately before the annotated type. An annotation is a type-use annotation if it is meta-annotated with @Target(ElementType.TYPE_USE). Example:

final @Nullable String name;

public @Nullable Person getPersonByName(String name);
4.8.5.2 Class, package, and module annotations

Annotations applying to a class, package, or module declaration appear immediately after the documentation block, and each annotation is listed on a line of its own (that is, one annotation per line). These line breaks do not constitute line-wrapping (Section 4.5, Line-wrapping), so the indentation level is not increased. Examples:

/** This is a class. */
@Deprecated
@CheckReturnValue
public final class Frozzler { ... }
/** This is a package. */
@Deprecated
@CheckReturnValue
package com.example.frozzler;
/** This is a module. */
@Deprecated
@SuppressWarnings("CheckReturnValue")
module com.example.frozzler { ... }
4.8.5.3 Method and constructor annotations

The rules for annotations on method and constructor declarations are the same as the previous section. Example:

@Deprecated
@Override
public String getNameIfPresent() { ... }

Exception: A single parameterless annotation may instead appear together with the first line of the signature, for example:

@Override public int hashCode() { ... }
4.8.5.4 Field annotations

Annotations applying to a field also appear immediately after the documentation block, but in this case, multiple annotations (possibly parameterized) may be listed on the same line; for example:

@Partial @Mock DataLoader loader;
4.8.5.5 Parameter and local variable annotations

There are no specific rules for formatting annotations on parameters or local variables (except, of course, when the annotation is a type-use annotation).

4.8.6 Comments

This section addresses implementation comments. Javadoc is addressed separately in Section 7, Javadoc.

Any line break may be preceded by arbitrary whitespace followed by an implementation comment. Such a comment renders the line non-blank.

4.8.6.1 Block comment style

Block comments are indented at the same level as the surrounding code. They may be in /* ... */ style or // ... style. For multi-line /* ... */ comments, subsequent lines must start with * aligned with the * on the previous line.

/*
 * This is          // And so           /* Or you can
 * okay.            // is this.          * even do this. */
 */

Comments are not enclosed in boxes drawn with asterisks or other characters.

Tip: When writing multi-line comments, use the /* ... */ style if you want automatic code formatters to re-wrap the lines when necessary (paragraph-style). Most formatters don't re-wrap lines in // ... style comment blocks.

4.8.6.2 TODO comments

Use TODO comments for code that is temporary, a short-term solution, or good-enough but not perfect.

A TODO comment begins with the word TODO in all caps, a following colon, and a link to a resource that contains the context, ideally a bug reference. A bug reference is preferable because bugs are tracked and have follow-up comments. Follow this piece of context with an explanatory string introduced with a hyphen -.

The purpose is to have a consistent TODO format that can be searched to find out how to get more details.

// TODO: crbug.com/12345678 - Remove this after the 2047q4 compatibility window expires.

Avoid adding TODOs that refer to an individual or team as the context:

// TODO: @yourusername - File an issue and use a '*' for repetition.

If your TODO is of the form "At a future date do something" make sure that you either include a very specific date ("Fix by November 2005") or a very specific event ("Remove this code when all clients can handle XML responses.").

4.8.7 Modifiers

Class and member modifiers, when present, appear in the order recommended by the Java Language Specification:

public protected private abstract default static final sealed non-sealed
  transient volatile synchronized native strictfp

Modifiers on requires module directives, when present, appear in the following order:

transitive static

4.8.8 Numeric Literals

long-valued integer literals use an uppercase L suffix, never lowercase (to avoid confusion with the digit 1). For example, 3000000000L rather than 3000000000l.

4.8.9 Text Blocks

The opening """ of a text block is always on a new line. That line may either follow the same indentation rules as other constructs, or it may have no indentation at all (so it starts at the left margin). The closing """ is on a new line with the same indentation as the opening """, and may be followed on the same line by further code. Each line of text in the text block is indented at least as much as the opening and closing """. (If a line is indented further, then the string literal defined by the text block will have space at the start of that line.)

The contents of a text block may exceed the column limit.

5 Naming

5.1 Rules common to all identifiers

Identifiers use only ASCII letters and digits, and, in a small number of cases noted below, underscores. Thus each valid identifier name is matched by the regular expression \w+ .

In Google Style, special prefixes or suffixes are not used. For example, these names are not Google Style: name_, mName, s_name and kName.

5.2 Rules by identifier type

5.2.1 Package and module names

Package and module names use only lowercase letters and digits (no underscores). Consecutive words are simply concatenated together. For example, com.example.deepspace, not com.example.deepSpace or com.example.deep_space.

5.2.2 Class names

Class names are written in UpperCamelCase.

Class names are typically nouns or noun phrases. For example, Character or ImmutableList. Interface names may also be nouns or noun phrases (for example, List), but may sometimes be adjectives or adjective phrases instead (for example, Readable).

There are no specific rules or even well-established conventions for naming annotation types.

A test class has a name that ends with Test, for example, HashIntegrationTest. If it covers a single class, its name is the name of that class plus Test, for example HashImplTest.

5.2.3 Method names

Method names are written in lowerCamelCase.

Method names are typically verbs or verb phrases. For example, sendMessage or stop.

Underscores may appear in JUnit test method names to separate logical components of the name, with each component written in lowerCamelCase, for example transferMoney_deductsFromSource. There is no One Correct Way to name test methods.

5.2.4 Constant names

Constant names use UPPER_SNAKE_CASE: all uppercase letters, with each word separated from the next by a single underscore. But what is a constant, exactly?

Constants are static final fields whose contents are deeply immutable and whose methods have no detectable side effects. Examples include primitives, strings, immutable value classes, and anything set to null. If any of the instance's observable state can change, it is not a constant. Merely intending to never mutate the object is not enough. Examples:

// Constants
static final int NUMBER = 5;
static final ImmutableList<String> NAMES = ImmutableList.of("Ed", "Ann");
static final Map<String, Integer> AGES = ImmutableMap.of("Ed", 35, "Ann", 32);
static final Joiner COMMA_JOINER = Joiner.on(','); // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};

// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final Set<String> mutableCollection = new HashSet<String>();
static final ImmutableSet<SomeMutableType> mutableElements = ImmutableSet.of(mutable);
static final ImmutableMap<String, SomeMutableType> mutableValues =
    ImmutableMap.of("Ed", mutableInstance, "Ann", mutableInstance2);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};

These names are typically nouns or noun phrases.

5.2.5 Non-constant field names

Non-constant field names (static or otherwise) are written in lowerCamelCase.

These names are typically nouns or noun phrases. For example, computedValues or index.

5.2.6 Parameter names

Parameter names are written in lowerCamelCase.

One-character parameter names in public methods should be avoided.

5.2.7 Local variable names

Local variable names are written in lowerCamelCase.

Even when final and immutable, local variables are not considered to be constants, and should not be styled as constants.

5.2.8 Type variable names

Each type variable is named in one of two styles:

  • A single capital letter, optionally followed by a single numeral (such as E, T, X, T2)
  • A name in the form used for classes (see Section 5.2.2, Class names), followed by the capital letter T (examples: RequestT, FooBarT).

5.3 Camel case: defined

Sometimes there is more than one reasonable way to convert an English phrase into camel case, such as when acronyms or unusual constructs like "IPv6" or "iOS" are present. To improve predictability, Google Style specifies the following (nearly) deterministic scheme.

Beginning with the prose form of the name:

  1. Convert the phrase to plain ASCII and remove any apostrophes. For example, "Müller's algorithm" might become "Muellers algorithm".
  2. Divide this result into words, splitting on spaces and any remaining punctuation (typically hyphens).
    • Recommended: if any word already has a conventional camel-case appearance in common usage, split this into its constituent parts (e.g., "AdWords" becomes "ad words"). Note that a word such as "iOS" is not really in camel case per se; it defies any convention, so this recommendation does not apply.
  3. Now lowercase everything (including acronyms), then uppercase only the first character of:
    • ... each word, to yield upper camel case, or
    • ... each word except the first, to yield lower camel case
  4. Finally, join all the words into a single identifier. Note that the casing of the original words is almost entirely disregarded.

In very rare circumstances (for example, multipart version numbers), you may need to use underscores to separate adjacent numbers, since numbers do not have upper and lower case variants.

Examples:

Prose form Correct Incorrect
"XML HTTP request" XmlHttpRequest XMLHTTPRequest
"new customer ID" newCustomerId newCustomerID
"inner stopwatch" innerStopwatch innerStopWatch
"supports IPv6 on iOS?" supportsIpv6OnIos supportsIPv6OnIOS
"YouTube importer" YouTubeImporter
YoutubeImporter*
"Turn on 2SV" turnOn2sv turnOn2Sv
"Guava 33.4.6" guava33_4_6 guava3346

*Acceptable, but not recommended.

Note: Some words are ambiguously hyphenated in the English language: for example "nonempty" and "non-empty" are both correct, so the method names checkNonempty and checkNonEmpty are likewise both correct.

6 Programming Practices

6.1 @Override: always used

A method is marked with the @Override annotation whenever it is legal. This includes a class method overriding a superclass method, a class method implementing an interface method, an interface method respecifying a superinterface method, and an explicitly declared accessor method for a record component.

Exception: @Override may be omitted when the parent method is @Deprecated.

6.2 Caught exceptions: not ignored

It is very rarely correct to do nothing in response to a caught exception. (Typical responses are to log it, or if it is considered "impossible", rethrow it as an AssertionError.)

When it truly is appropriate to take no action whatsoever in a catch block, the reason this is justified is explained in a comment.

try {
  int i = Integer.parseInt(response);
  return handleNumericResponse(i);
} catch (NumberFormatException ok) {
  // it's not numeric; that's fine, just continue
}
return handleTextResponse(response);

6.3 Static members: qualified using class

When a reference to a static class member must be qualified, it is qualified with that class's name, not with a reference or expression of that class's type.

Foo aFoo = ...;
Foo.aStaticMethod(); // good
aFoo.aStaticMethod(); // bad
somethingThatYieldsAFoo().aStaticMethod(); // very bad

6.4 Finalizers: not used

Do not override Object.finalize. Finalization support is scheduled for removal.

7 Javadoc

7.1 Formatting

7.1.1 General form

The basic formatting of Javadoc blocks is as seen in this example:

/**
 * Multiple lines of Javadoc text are written here,
 * wrapped normally...
 */
public int method(String p1) { ... }

... or in this single-line example:

/** An especially short bit of Javadoc. */

The basic form is always acceptable. The single-line form may be substituted when the entirety of the Javadoc block (including comment markers) can fit on a single line. Note that this only applies when there are no block tags such as @param.

7.1.2 Paragraphs

One blank line—that is, a line containing only the aligned leading asterisk (*)—appears between paragraphs, and before the group of block tags if present. Each paragraph except the first has <p> immediately before the first word, with no space after it. HTML tags for other block-level elements, such as <ul> or <table>, are not preceded with <p>.

7.1.3 Block tags

Any of the standard "block tags" that are used appear in the order @param, @return, @throws, @deprecated, and these four types never appear with an empty description. When a block tag doesn't fit on a single line, continuation lines are indented four (or more) spaces from the position of the @.

7.2 The summary fragment

Each Javadoc block begins with a brief summary fragment. This fragment is very important: it is the only part of the text that appears in certain contexts such as class and method indexes.

This is a fragment—a noun phrase or verb phrase, not a complete sentence. It does not begin with A {@code Foo} is a..., or This method returns..., nor does it form a complete imperative sentence like Save the record.. However, the fragment is capitalized and punctuated as if it were a complete sentence.

Tip: A common mistake is to write simple Javadoc in the form /** @return the customer ID */. This is incorrect, and should be changed to /** Returns the customer ID. */ or /** {@return the customer ID} */.

7.3 Where Javadoc is used

At the minimum, Javadoc is present for every visible class, member, or record component, with a few exceptions noted below. A top-level class is visible if it is public; a member is visible if it is public or protected and its containing class is visible; and a record component is visible if its containing record is visible.

Additional Javadoc content may also be present, as explained in Section 7.3.4, Non-required Javadoc.

7.3.1 Exception: self-explanatory members

Javadoc is optional for "simple, obvious" members and record components, such as a getFoo() method, if there really and truly is nothing else worthwhile to say but "the foo".

Important: it is not appropriate to cite this exception to justify omitting relevant information that a typical reader might need to know. For example, for a record component named canonicalName, don't omit its documentation (with the rationale that it would say only @param canonicalName the canonical name) if a typical reader may have no idea what the term "canonical name" means!

7.3.2 Exception: overrides

Javadoc is not always present on a method that overrides a supertype method.

7.3.4 Non-required Javadoc

Other classes, members, and record components have Javadoc as needed or desired.

Whenever an implementation comment would be used to define the overall purpose or behavior of a class or member, that comment is written as Javadoc instead (using /**).

Non-required Javadoc is not strictly required to follow the formatting rules of Sections 7.1.1, 7.1.2, 7.1.3, and 7.2, though it is of course recommended.

================================================ FILE: javascriptguide.xml ================================================

Please note: This guide is old and is not being updated. It is retained as a reference as it was written for pre-ECMAScript 6th Edition features. Please use the newer guide instead.

Revision 2.93

Aaron Whyte
Bob Jervis
Dan Pupius
Erik Arvidsson
Fritz Schneider
Robby Walker
This style guide contains many details that are initially hidden from view. They are marked by the triangle icon, which you see here on your left. Click it now. You should see "Hooray" appear below.

Hooray! Now you know you can expand points to get more details. Alternatively, there's a "toggle all" at the top of this document.

JavaScript is the main client-side scripting language used by many of Google's open-source projects. This style guide is a list of dos and don'ts for JavaScript programs.

Declarations with var: Always When you fail to specify var, the variable gets placed in the global context, potentially clobbering existing values. Also, if there's no declaration, it's hard to tell in what scope a variable lives (e.g., it could be in the Document or Window just as easily as in the local scope). So always declare with var.
  • Use NAMES_LIKE_THIS for constant values.
  • Use @const to indicate a constant (non-overwritable) pointer (a variable or property).
  • Never use the const keyword as it's not supported in Internet Explorer.

If a value is intended to be constant and immutable, it should be given a name in CONSTANT_VALUE_CASE. ALL_CAPS additionally implies @const (that the value is not overwritable).

Primitive types (number, string, boolean) are constant values.

Objects' immutability is more subjective — objects should be considered immutable only if they do not demonstrate observable state change. This is not enforced by the compiler.

The @const annotation on a variable or property implies that it is not overwritable. This is enforced by the compiler at build time. This behavior is consistent with the const keyword (which we do not use due to the lack of support in Internet Explorer).

A @const annotation on a method additionally implies that the method cannot not be overridden in subclasses.

A @const annotation on a constructor implies the class cannot be subclassed (akin to final in Java).

Note that @const does not necessarily imply CONSTANT_VALUES_CASE. However, CONSTANT_VALUES_CASE does imply @const.

/** * Request timeout in milliseconds. * @type {number} */ goog.example.TIMEOUT_IN_MILLISECONDS = 60;

The number of seconds in a minute never changes. It is a constant value. ALL_CAPS also implies @const, so the constant cannot be overwritten.

The open source compiler will allow the symbol to be overwritten because the constant is not marked as @const.

/** * Map of URL to response string. * @const */ MyClass.fetchedUrlCache_ = new goog.structs.Map(); /** * Class that cannot be subclassed. * @const * @constructor */ sloth.MyFinalClass = function() {};

In this case, the pointer can never be overwritten, but value is highly mutable and not constant (and thus in camelCase, not ALL_CAPS).

Always use semicolons.

Relying on implicit insertion can cause subtle, hard to debug problems. Don't do it. You're better than that.

There are a couple places where missing semicolons are particularly dangerous:

// 1. MyClass.prototype.myMethod = function() { return 42; } // No semicolon here. (function() { // Some initialization code wrapped in a function to create a scope for locals. })(); var x = { 'i': 1, 'j': 2 } // No semicolon here. // 2. Trying to do one thing on Internet Explorer and another on Firefox. // I know you'd never write code like this, but throw me a bone. [ffVersion, ieVersion][isIE](); var THINGS_TO_EAT = [apples, oysters, sprayOnCheese] // No semicolon here. // 3. conditional execution a la bash -1 == resultOfOperation() || die();
  1. JavaScript error - first the function returning 42 is called with the second function as a parameter, then the number 42 is "called" resulting in an error.
  2. You will most likely get a 'no such property in undefined' error at runtime as it tries to call x[ffVersion, ieVersion][isIE]().
  3. die is always called since the array minus 1 is NaN which is never equal to anything (not even if resultOfOperation() returns NaN) and THINGS_TO_EAT gets assigned the result of die().

JavaScript requires statements to end with a semicolon, except when it thinks it can safely infer their existence. In each of these examples, a function declaration or object or array literal is used inside a statement. The closing brackets are not enough to signal the end of the statement. Javascript never ends a statement if the next token is an infix or bracket operator.

This has really surprised people, so make sure your assignments end with semicolons.

Semicolons should be included at the end of function expressions, but not at the end of function declarations. The distinction is best illustrated with an example:

var foo = function() { return true; }; // semicolon here. function foo() { return true; } // no semicolon here.
Yes

Nested functions can be very useful, for example in the creation of continuations and for the task of hiding helper functions. Feel free to use them.

No

Do not do this:

if (x) { function foo() {} }

While most script engines support Function Declarations within blocks it is not part of ECMAScript (see ECMA-262, clause 13 and 14). Worse implementations are inconsistent with each other and with future EcmaScript proposals. ECMAScript only allows for Function Declarations in the root statement list of a script or function. Instead use a variable initialized with a Function Expression to define a function within a block:

if (x) { var foo = function() {}; }
Yes

You basically can't avoid exceptions if you're doing something non-trivial (using an application development framework, etc.). Go for it.

Yes

Without custom exceptions, returning error information from a function that also returns a value can be tricky, not to mention inelegant. Bad solutions include passing in a reference type to hold error information or always returning Objects with a potential error member. These basically amount to a primitive exception handling hack. Feel free to use custom exceptions when appropriate.

Always preferred over non-standards features

For maximum portability and compatibility, always prefer standards features over non-standards features (e.g., string.charAt(3) over string[3] and element access with DOM functions instead of using an application-specific shorthand).

No

There's no reason to use wrapper objects for primitive types, plus they're dangerous:

var x = new Boolean(false); if (x) { alert('hi'); // Shows 'hi'. }

Don't do it!

However type casting is fine.

var x = Boolean(0); if (x) { alert('hi'); // This will never be alerted. } typeof Boolean(0) == 'boolean'; typeof new Boolean(0) == 'object';

This is very useful for casting things to number, string and boolean.

Not preferred

Multi-level prototype hierarchies are how JavaScript implements inheritance. You have a multi-level hierarchy if you have a user-defined class D with another user-defined class B as its prototype. These hierarchies are much harder to get right than they first appear!

For that reason, it is best to use goog.inherits() from the Closure Library or a similar library function.

function D() { goog.base(this) } goog.inherits(D, B); D.prototype.method = function() { ... };
/** @constructor */ function SomeConstructor() { this.someProperty = 1; } Foo.prototype.someMethod = function() { ... };

While there are several ways to attach methods and properties to an object created via "new", the preferred style for methods is:

Foo.prototype.bar = function() { /* ... */ };

The preferred style for other properties is to initialize the field in the constructor:

/** @constructor */ function Foo() { this.bar = value; }

Current JavaScript engines optimize based on the "shape" of an object, adding a property to an object (including overriding a value set on the prototype) changes the shape and can degrade performance.

Prefer this.foo = null. Foo.prototype.dispose = function() { this.property_ = null; };

Instead of:

Foo.prototype.dispose = function() { delete this.property_; };

In modern JavaScript engines, changing the number of properties on an object is much slower than reassigning the values. The delete keyword should be avoided except when it is necessary to remove a property from an object's iterated list of keys, or to change the result of if (key in obj).

Yes, but be careful.

The ability to create closures is perhaps the most useful and often overlooked feature of JS. Here is a good description of how closures work.

One thing to keep in mind, however, is that a closure keeps a pointer to its enclosing scope. As a result, attaching a closure to a DOM element can create a circular reference and thus, a memory leak. For example, in the following code:

function foo(element, a, b) { element.onclick = function() { /* uses a and b */ }; }

the function closure keeps a reference to element, a, and b even if it never uses element. Since element also keeps a reference to the closure, we have a cycle that won't be cleaned up by garbage collection. In these situations, the code can be structured as follows:

function foo(element, a, b) { element.onclick = bar(a, b); } function bar(a, b) { return function() { /* uses a and b */ }; }
Only for code loaders and REPL (Read–eval–print loop)

eval() makes for confusing semantics and is dangerous to use if the string being eval()'d contains user input. There's usually a better, clearer, and safer way to write your code, so its use is generally not permitted.

For RPC you can always use JSON and read the result using JSON.parse() instead of eval().

Let's assume we have a server that returns something like this:

{ "name": "Alice", "id": 31502, "email": "looking_glass@example.com" } var userInfo = eval(feed); var email = userInfo['email'];

If the feed was modified to include malicious JavaScript code, then if we use eval then that code will be executed.

var userInfo = JSON.parse(feed); var email = userInfo['email'];

With JSON.parse, invalid JSON (including all executable JavaScript) will cause an exception to be thrown.

No

Using with clouds the semantics of your program. Because the object of the with can have properties that collide with local variables, it can drastically change the meaning of your program. For example, what does this do?

with (foo) { var x = 3; return x; }

Answer: anything. The local variable x could be clobbered by a property of foo and perhaps it even has a setter, in which case assigning 3 could cause lots of other code to execute. Don't use with.

Only in object constructors, methods, and in setting up closures

The semantics of this can be tricky. At times it refers to the global object (in most places), the scope of the caller (in eval), a node in the DOM tree (when attached using an event handler HTML attribute), a newly created object (in a constructor), or some other object (if function was call()ed or apply()ed).

Because this is so easy to get wrong, limit its use to those places where it is required:

  • in constructors
  • in methods of objects (including in the creation of closures)
Only for iterating over keys in an object/map/hash

for-in loops are often incorrectly used to loop over the elements in an Array. This is however very error prone because it does not loop from 0 to length - 1 but over all the present keys in the object and its prototype chain. Here are a few cases where it fails:

function printArray(arr) { for (var key in arr) { print(arr[key]); } } printArray([0,1,2,3]); // This works. var a = new Array(10); printArray(a); // This is wrong. a = document.getElementsByTagName('*'); printArray(a); // This is wrong. a = [0,1,2,3]; a.buhu = 'wine'; printArray(a); // This is wrong again. a = new Array; a[3] = 3; printArray(a); // This is wrong again.

Always use normal for loops when using arrays.

function printArray(arr) { var l = arr.length; for (var i = 0; i < l; i++) { print(arr[i]); } }
Never use Array as a map/hash/associative array

Associative Arrays are not allowed... or more precisely you are not allowed to use non number indexes for arrays. If you need a map/hash use Object instead of Array in these cases because the features that you want are actually features of Object and not of Array. Array just happens to extend Object (like any other object in JS and therefore you might as well have used Date, RegExp or String).

No

Do not do this:

var myString = 'A rather long string of English text, an error message \ actually that just keeps going and going -- an error \ message to make the Energizer bunny blush (right through \ those Schwarzenegger shades)! Where was I? Oh yes, \ you\'ve got an error and all the extraneous whitespace is \ just gravy. Have a nice day.';

The whitespace at the beginning of each line can't be safely stripped at compile time; whitespace after the slash will result in tricky errors.

Use string concatenation instead:

var myString = 'A rather long string of English text, an error message ' + 'actually that just keeps going and going -- an error ' + 'message to make the Energizer bunny blush (right through ' + 'those Schwarzenegger shades)! Where was I? Oh yes, ' + 'you\'ve got an error and all the extraneous whitespace is ' + 'just gravy. Have a nice day.';
Yes

Use Array and Object literals instead of Array and Object constructors.

Array constructors are error-prone due to their arguments.

// Length is 3. var a1 = new Array(x1, x2, x3); // Length is 2. var a2 = new Array(x1, x2); // If x1 is a number and it is a natural number the length will be x1. // If x1 is a number but not a natural number this will throw an exception. // Otherwise the array will have one element with x1 as its value. var a3 = new Array(x1); // Length is 0. var a4 = new Array();

Because of this, if someone changes the code to pass 1 argument instead of 2 arguments, the array might not have the expected length.

To avoid these kinds of weird cases, always use the more readable array literal.

var a = [x1, x2, x3]; var a2 = [x1, x2]; var a3 = [x1]; var a4 = [];

Object constructors don't have the same problems, but for readability and consistency object literals should be used.

var o = new Object(); var o2 = new Object(); o2.a = 0; o2.b = 1; o2.c = 2; o2['strange key'] = 3;

Should be written as:

var o = {}; var o2 = { a: 0, b: 1, c: 2, 'strange key': 3 };
No

Modifying builtins like Object.prototype and Array.prototype are strictly forbidden. Modifying other builtins like Function.prototype is less dangerous but still leads to hard to debug issues in production and should be avoided.

No

Don't do this:

var f = function () { /*@cc_on if (@_jscript) { return 2* @*/ 3; /*@ } @*/ };

Conditional Comments hinder automated tools as they can vary the JavaScript syntax tree at runtime.

In general, use functionNamesLikeThis, variableNamesLikeThis, ClassNamesLikeThis, EnumNamesLikeThis, methodNamesLikeThis, CONSTANT_VALUES_LIKE_THIS, foo.namespaceNamesLikeThis.bar, and filenameslikethis.js.

  • Private properties and methods should be named with a trailing underscore.
  • Protected properties and methods should be named without a trailing underscore (like public ones).

For more information on private and protected, read the section on visibility.

Optional function arguments start with opt_.

Functions that take a variable number of arguments should have the last argument named var_args. You may not refer to var_args in the code; use the arguments array.

Optional and variable arguments can also be specified in @param annotations. Although either convention is acceptable to the compiler, using both together is preferred.

EcmaScript 5 getters and setters for properties are discouraged. However, if they are used, then getters must not change observable state.

/** * WRONG -- Do NOT do this. */ var foo = { get next() { return this.nextId++; } };

Getters and setters methods for properties are not required. However, if they are used, then getters must be named getFoo() and setters must be named setFoo(value). (For boolean getters, isFoo() is also acceptable, and often sounds more natural.)

JavaScript has no inherent packaging or namespacing support.

Global name conflicts are difficult to debug, and can cause intractable problems when two projects try to integrate. In order to make it possible to share common JavaScript code, we've adopted conventions to prevent collisions.

ALWAYS prefix identifiers in the global scope with a unique pseudo namespace related to the project or library. If you are working on "Project Sloth", a reasonable pseudo namespace would be sloth.*.

var sloth = {}; sloth.sleep = function() { ... };

Many JavaScript libraries, including the Closure Library and Dojo toolkit give you high-level functions for declaring your namespaces. Be consistent about how you declare your namespaces.

goog.provide('sloth'); sloth.sleep = function() { ... };

When choosing a child-namespace, make sure that the owners of the parent namespace know what you are doing. If you start a project that creates hats for sloths, make sure that the Sloth team knows that you're using sloth.hats.

"External code" is code that comes from outside your codebase, and is compiled independently. Internal and external names should be kept strictly separate. If you're using an external library that makes things available in foo.hats.*, your internal code should not define all its symbols in foo.hats.*, because it will break if the other team defines new symbols.

foo.require('foo.hats'); /** * WRONG -- Do NOT do this. * @constructor * @extends {foo.hats.RoundHat} */ foo.hats.BowlerHat = function() { };

If you need to define new APIs on an external namespace, then you should explicitly export the public API functions, and only those functions. Your internal code should call the internal APIs by their internal names, for consistency and so that the compiler can optimize them better.

foo.provide('googleyhats.BowlerHat'); foo.require('foo.hats'); /** * @constructor * @extends {foo.hats.RoundHat} */ googleyhats.BowlerHat = function() { ... }; goog.exportSymbol('foo.hats.BowlerHat', googleyhats.BowlerHat);

Use local aliases for fully-qualified types if doing so improves readability. The name of a local alias should match the last part of the type.

/** * @constructor */ some.long.namespace.MyClass = function() { }; /** * @param {some.long.namespace.MyClass} a */ some.long.namespace.MyClass.staticHelper = function(a) { ... }; myapp.main = function() { var MyClass = some.long.namespace.MyClass; var staticHelper = some.long.namespace.MyClass.staticHelper; staticHelper(new MyClass()); };

Do not create local aliases of namespaces. Namespaces should only be aliased using goog.scope.

myapp.main = function() { var namespace = some.long.namespace; namespace.MyClass.staticHelper(new namespace.MyClass()); };

Avoid accessing properties of an aliased type, unless it is an enum.

/** @enum {string} */ some.long.namespace.Fruit = { APPLE: 'a', BANANA: 'b' }; myapp.main = function() { var Fruit = some.long.namespace.Fruit; switch (fruit) { case Fruit.APPLE: ... case Fruit.BANANA: ... } }; myapp.main = function() { var MyClass = some.long.namespace.MyClass; MyClass.staticHelper(null); };

Never create aliases in the global scope. Use them only in function blocks.

Filenames should be all lowercase in order to avoid confusion on case-sensitive platforms. Filenames should end in .js, and should contain no punctuation except for - or _ (prefer - to _).

Must always succeed without side effects.

You can control how your objects string-ify themselves by defining a custom toString() method. This is fine, but you need to ensure that your method (1) always succeeds and (2) does not have side-effects. If your method doesn't meet these criteria, it's very easy to run into serious problems. For example, if toString() calls a method that does an assert, assert might try to output the name of the object in which it failed, which of course requires calling toString().

OK

It isn't always possible to initialize variables at the point of declaration, so deferred initialization is fine.

Always

Always use explicit scope - doing so increases portability and clarity. For example, don't rely on window being in the scope chain. You might want to use your function in another application for which window is not the content window.

Expand for more information.

We follow the C++ formatting rules in spirit, with the following additional clarifications.

Because of implicit semicolon insertion, always start your curly braces on the same line as whatever they're opening. For example:

if (something) { // ... } else { // ... }

Single-line array and object initializers are allowed when they fit on a line:

var arr = [1, 2, 3]; // No space after [ or before ]. var obj = {a: 1, b: 2, c: 3}; // No space after { or before }.

Multiline array initializers and object initializers are indented 2 spaces, with the braces on their own line, just like blocks.

// Object initializer. var inset = { top: 10, right: 20, bottom: 15, left: 12 }; // Array initializer. this.rows_ = [ '"Slartibartfast" <fjordmaster@magrathea.com>', '"Zaphod Beeblebrox" <theprez@universe.gov>', '"Ford Prefect" <ford@theguide.com>', '"Arthur Dent" <has.no.tea@gmail.com>', '"Marvin the Paranoid Android" <marv@googlemail.com>', 'the.mice@magrathea.com' ]; // Used in a method call. goog.dom.createDom(goog.dom.TagName.DIV, { id: 'foo', className: 'some-css-class', style: 'display:none' }, 'Hello, world!');

Long identifiers or values present problems for aligned initialization lists, so always prefer non-aligned initialization. For example:

CORRECT_Object.prototype = { a: 0, b: 1, lengthyName: 2 };

Not like this:

WRONG_Object.prototype = { a : 0, b : 1, lengthyName: 2 };

When possible, all function arguments should be listed on the same line. If doing so would exceed the 80-column limit, the arguments must be line-wrapped in a readable way. To save space, you may wrap as close to 80 as possible, or put each argument on its own line to enhance readability. The indentation may be either four spaces, or aligned to the parenthesis. Below are the most common patterns for argument wrapping:

// Four-space, wrap at 80. Works with very long function names, survives // renaming without reindenting, low on space. goog.foo.bar.doThingThatIsVeryDifficultToExplain = function( veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo, tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) { // ... }; // Four-space, one argument per line. Works with long function names, // survives renaming, and emphasizes each argument. goog.foo.bar.doThingThatIsVeryDifficultToExplain = function( veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo, tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) { // ... }; // Parenthesis-aligned indentation, wrap at 80. Visually groups arguments, // low on space. function foo(veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo, tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) { // ... } // Parenthesis-aligned, one argument per line. Emphasizes each // individual argument. function bar(veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo, tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) { // ... }

When the function call is itself indented, you're free to start the 4-space indent relative to the beginning of the original statement or relative to the beginning of the current function call. The following are all acceptable indentation styles.

if (veryLongFunctionNameA( veryLongArgumentName) || veryLongFunctionNameB( veryLongArgumentName)) { veryLongFunctionNameC(veryLongFunctionNameD( veryLongFunctioNameE( veryLongFunctionNameF))); }

When declaring an anonymous function in the list of arguments for a function call, the body of the function is indented two spaces from the left edge of the statement, or two spaces from the left edge of the function keyword. This is to make the body of the anonymous function easier to read (i.e. not be all squished up into the right half of the screen).

prefix.something.reallyLongFunctionName('whatever', function(a1, a2) { if (a1.equals(a2)) { someOtherLongFunctionName(a1); } else { andNowForSomethingCompletelyDifferent(a2.parrot); } }); var names = prefix.something.myExcellentMapFunction( verboselyNamedCollectionOfItems, function(item) { return item.name; });

goog.scope may be used to shorten references to namespaced symbols in programs using the Closure Library.

Only one goog.scope invocation may be added per file. Always place it in the global scope.

The opening goog.scope(function() { invocation must be preceded by exactly one blank line and follow any goog.provide statements, goog.require statements, or top-level comments. The invocation must be closed on the last line in the file. Append // goog.scope to the closing statement of the scope. Separate the comment from the semicolon by two spaces.

Similar to C++ namespaces, do not indent under goog.scope declarations. Instead, continue from the 0 column.

Only alias names that will not be re-assigned to another object (e.g., most constructors, enums, and namespaces). Do not do this (see below for how to alias a constructor):

goog.scope(function() { var Button = goog.ui.Button; Button = function() { ... }; ...

Names must be the same as the last property of the global that they are aliasing.

goog.provide('my.module.SomeType'); goog.require('goog.dom'); goog.require('goog.ui.Button'); goog.scope(function() { var Button = goog.ui.Button; var dom = goog.dom; // Alias new types after the constructor declaration. my.module.SomeType = function() { ... }; var SomeType = my.module.SomeType; // Declare methods on the prototype as usual: SomeType.prototype.findButton = function() { // Button as aliased above. this.button = new Button(dom.getElement('my-button')); }; ... }); // goog.scope

Except for array literals, object literals, and anonymous functions, all wrapped lines should be indented either left-aligned to a sibling expression above, or four spaces (not two spaces) deeper than a parent expression (where "sibling" and "parent" refer to parenthesis nesting level).

someWonderfulHtml = '
' + getEvenMoreHtml(someReallyInterestingValues, moreValues, evenMoreParams, 'a duck', true, 72, slightlyMoreMonkeys(0xfff)) + '
'; thisIsAVeryLongVariableName = hereIsAnEvenLongerOtherFunctionNameThatWillNotFitOnPrevLine(); thisIsAVeryLongVariableName = siblingOne + siblingTwo + siblingThree + siblingFour + siblingFive + siblingSix + siblingSeven + moreSiblingExpressions + allAtTheSameIndentationLevel; thisIsAVeryLongVariableName = operandOne + operandTwo + operandThree + operandFour + operandFive * ( aNestedChildExpression + shouldBeIndentedMore); someValue = this.foo( shortArg, 'Some really long string arg - this is a pretty common case, actually.', shorty2, this.bar()); if (searchableCollection(allYourStuff).contains(theStuffYouWant) && !ambientNotification.isActive() && (client.isAmbientSupported() || client.alwaysTryAmbientAnyways())) { ambientNotification.activate(); }

Use newlines to group logically related pieces of code. For example:

doSomethingTo(x); doSomethingElseTo(x); andThen(x); nowDoSomethingWith(y); andNowWith(z);

Always put the operator on the preceding line. Otherwise, line breaks and indentation follow the same rules as in other Google style guides. This operator placement was initially agreed upon out of concerns about automatic semicolon insertion. In fact, semicolon insertion cannot happen before a binary operator, but new code should stick to this style for consistency.

var x = a ? b : c; // All on one line if it will fit. // Indentation +4 is OK. var y = a ? longButSimpleOperandB : longButSimpleOperandC; // Indenting to the line position of the first operand is also OK. var z = a ? moreComplicatedB : moreComplicatedC;

This includes the dot operator.

var x = foo.bar(). doSomething(). doSomethingElse();
Only where required

Use sparingly and in general only where required by the syntax and semantics.

Never use parentheses for unary operators such as delete, typeof and void or after keywords such as return, throw as well as others (case, in or new).

Prefer ' over "

For consistency single-quotes (') are preferred to double-quotes ("). This is helpful when creating strings that include HTML:

var msg = 'This is some HTML';
Encouraged, use JSDoc annotations @private and @protected

We recommend the use of the JSDoc annotations @private and @protected to indicate visibility levels for classes, functions, and properties.

The --jscomp_warning=visibility compiler flag turns on compiler warnings for visibility violations. See Closure Compiler Warnings.

@private global variables and functions are only accessible to code in the same file.

Constructors marked @private may only be instantiated by code in the same file and by their static and instance members. @private constructors may also be accessed anywhere in the same file for their public static properties and by the instanceof operator.

Global variables, functions, and constructors should never be annotated @protected.

// File 1. // AA_PrivateClass_ and AA_init_ are accessible because they are global // and in the same file. /** * @private * @constructor */ AA_PrivateClass_ = function() { }; /** @private */ function AA_init_() { return new AA_PrivateClass_(); } AA_init_();

@private properties are accessible to all code in the same file, plus all static methods and instance methods of that class that "owns" the property, if the property belongs to a class. They cannot be accessed or overridden from a subclass in a different file.

@protected properties are accessible to all code in the same file, plus any static methods and instance methods of any subclass of a class that "owns" the property.

Note that these semantics differ from those of C++ and Java, in that they grant private and protected access to all code in the same file, not just in the same class or class hierarchy. Also, unlike in C++, private properties cannot be overridden by a subclass.

// File 1. /** @constructor */ AA_PublicClass = function() { /** @private */ this.privateProp_ = 2; /** @protected */ this.protectedProp = 4; }; /** @private */ AA_PublicClass.staticPrivateProp_ = 1; /** @protected */ AA_PublicClass.staticProtectedProp = 31; /** @private */ AA_PublicClass.prototype.privateMethod_ = function() {}; /** @protected */ AA_PublicClass.prototype.protectedMethod = function() {}; // File 2. /** * @return {number} The number of ducks we've arranged in a row. */ AA_PublicClass.prototype.method = function() { // Legal accesses of these two properties. return this.privateProp_ + AA_PublicClass.staticPrivateProp_; }; // File 3. /** * @constructor * @extends {AA_PublicClass} */ AA_SubClass = function() { // Legal access of a protected static property. AA_PublicClass.staticProtectedProp = this.method(); }; goog.inherits(AA_SubClass, AA_PublicClass); /** * @return {number} The number of ducks we've arranged in a row. */ AA_SubClass.prototype.method = function() { // Legal access of a protected instance property. return this.protectedProp; };

Notice that in JavaScript, there is no distinction between a type (like AA_PrivateClass_) and the constructor for that type. There is no way to express both that a type is public and its constructor is private (because the constructor could easily be aliased in a way that would defeat the privacy check).

Encouraged and enforced by the compiler.

When documenting a type in JSDoc, be as specific and accurate as possible. The types we support are based on the EcmaScript 4 spec.

The ES4 proposal contained a language for specifying JavaScript types. We use this language in JsDoc to express the types of function parameters and return values.

As the ES4 proposal has evolved, this language has changed. The compiler still supports old syntaxes for types, but those syntaxes are deprecated.

Syntax Name Syntax Description Deprecated Syntaxes
Primitive Type There are 5 primitive types in JavaScript: {null}, {undefined}, {boolean}, {number}, and {string}. Simply the name of a type.
Instance Type {Object}
An instance of Object or null.

{Function}
An instance of Function or null.

{EventTarget}
An instance of a constructor that implements the EventTarget interface, or null.

An instance of a constructor or interface function.

Constructor functions are functions defined with the @constructor JSDoc tag. Interface functions are functions defined with the @interface JSDoc tag.

By default, instance types will accept null. This is the only type syntax that makes the type nullable. Other type syntaxes in this table will not accept null.

Enum Type {goog.events.EventType}
One of the properties of the object literal initializer of goog.events.EventType.
An enum must be initialized as an object literal, or as an alias of another enum, annotated with the @enum JSDoc tag. The properties of this literal are the instances of the enum. The syntax of the enum is defined below.

Note that this is one of the few things in our type system that were not in the ES4 spec.

Type Application {Array.<string>}
An array of strings.

{Object.<string, number>}
An object in which the keys are strings and the values are numbers.

Parameterizes a type, by applying a set of type arguments to that type. The idea is analogous to generics in Java.
Type Union {(number|boolean)}
A number or a boolean.
Indicates that a value might have type A OR type B.

The parentheses may be omitted at the top-level expression, but the parentheses should be included in sub-expressions to avoid ambiguity.
{number|boolean}
{function(): (number|boolean)}

{(number,boolean)},
{(number||boolean)}
Nullable type {?number}
A number or null.
Shorthand for the union of the null type with any other type. This is just syntactic sugar. {number?}
Non-nullable type {!Object}
An Object, but never the null value.
Filters null out of nullable types. Most often used with instance types, which are nullable by default. {Object!}
Record Type {{myNum: number, myObject}}
An anonymous type with the given type members.

Indicates that the value has the specified members with the specified types. In this case, myNum with a type number and myObject with any type.

Notice that the braces are part of the type syntax. For example, to denote an Array of objects that have a length property, you might write Array.<{length}>.

Function Type {function(string, boolean)}
A function that takes two arguments (a string and a boolean), and has an unknown return value.
Specifies a function.
Function Return Type {function(): number}
A function that takes no arguments and returns a number.
Specifies a function return type.
Function this Type {function(this:goog.ui.Menu, string)}
A function that takes one argument (a string), and executes in the context of a goog.ui.Menu.
Specifies the context type of a function type.
Function new Type {function(new:goog.ui.Menu, string)}
A constructor that takes one argument (a string), and creates a new instance of goog.ui.Menu when called with the 'new' keyword.
Specifies the constructed type of a constructor.
Variable arguments {function(string, ...[number]): number}
A function that takes one argument (a string), and then a variable number of arguments that must be numbers.
Specifies variable arguments to a function.
Variable arguments (in @param annotations) @param {...number} var_args
A variable number of arguments to an annotated function.
Specifies that the annotated function accepts a variable number of arguments.
Function optional arguments {function(?string=, number=)}
A function that takes one optional, nullable string and one optional number as arguments. The = syntax is only for function type declarations.
Specifies optional arguments to a function.
Function optional arguments (in @param annotations) @param {number=} opt_argument
An optional parameter of type number.
Specifies that the annotated function accepts an optional argument.
The ALL type {*} Indicates that the variable can take on any type.
The UNKNOWN type {?} Indicates that the variable can take on any type, and the compiler should not type-check any uses of it.

Type Example Value Examples Description
number 1 1.0 -5 1e5 Math.PI
Number new Number(true) Number object
string 'Hello' "World" String(42) String value
String new String('Hello') new String(42) String object
boolean true false Boolean(0) Boolean value
Boolean new Boolean(true) Boolean object
RegExp new RegExp('hello') /world/g
Date new Date new Date()
null null
undefined undefined
void function f() { return; } No return value
Array ['foo', 0.3, null] [] Untyped Array
Array.<number> [11, 22, 33] An Array of numbers
Array.<Array.<string>> [['one', 'two', 'three'], ['foo', 'bar']] Array of Arrays of strings
Object {} {foo: 'abc', bar: 123, baz: null}
Object.<string> {'foo': 'bar'} An Object in which the values are strings.
Object.<number, string> var obj = {}; obj[1] = 'bar'; An Object in which the keys are numbers and the values are strings.

Note that in JavaScript, the keys are always implicitly converted to strings, so obj['1'] == obj[1]. So the key will always be a string in for...in loops. But the compiler will verify the type of the key when indexing into the object.

Function function(x, y) { return x * y; } Function object
function(number, number): number function(x, y) { return x * y; } function value
SomeClass /** @constructor */ function SomeClass() {} new SomeClass();
SomeInterface /** @interface */ function SomeInterface() {} SomeInterface.prototype.draw = function() {};
project.MyClass /** @constructor */ project.MyClass = function () {} new project.MyClass()
project.MyEnum /** @enum {string} */ project.MyEnum = { /** The color blue. */ BLUE: '#0000dd', /** The color red. */ RED: '#dd0000' }; Enumeration

JSDoc comments on enum values are optional.

Element document.createElement('div') Elements in the DOM.
Node document.body.firstChild Nodes in the DOM.
HTMLInputElement htmlDocument.getElementsByTagName('input')[0] A specific type of DOM element.

In cases where type-checking doesn't accurately infer the type of an expression, it is possible to add a type cast comment by adding a type annotation comment and enclosing the expression in parentheses. The parentheses are required.

/** @type {number} */ (x)

Because JavaScript is a loosely-typed language, it is very important to understand the subtle differences between optional, nullable, and undefined function parameters and class properties.

Instances of classes and interfaces are nullable by default. For example, the following declaration

/** * Some class, initialized with a value. * @param {Object} value Some value. * @constructor */ function MyClass(value) { /** * Some value. * @type {Object} * @private */ this.myValue_ = value; }

tells the compiler that the myValue_ property holds either an Object or null. If myValue_ must never be null, it should be declared like this:

/** * Some class, initialized with a non-null value. * @param {!Object} value Some value. * @constructor */ function MyClass(value) { /** * Some value. * @type {!Object} * @private */ this.myValue_ = value; }

This way, if the compiler can determine that somewhere in the code MyClass is initialized with a null value, it will issue a warning.

Optional parameters to functions may be undefined at runtime, so if they are assigned to class properties, those properties must be declared accordingly:

/** * Some class, initialized with an optional value. * @param {Object=} opt_value Some value (optional). * @constructor */ function MyClass(opt_value) { /** * Some value. * @type {Object|undefined} * @private */ this.myValue_ = opt_value; }

This tells the compiler that myValue_ may hold an Object, null, or remain undefined.

Note that the optional parameter opt_value is declared to be of type {Object=}, not {Object|undefined}. This is because optional parameters may, by definition, be undefined. While there is no harm in explicitly declaring an optional parameter as possibly undefined, it is both unnecessary and makes the code harder to read.

Finally, note that being nullable and being optional are orthogonal properties. The following four declarations are all different:

/** * Takes four arguments, two of which are nullable, and two of which are * optional. * @param {!Object} nonNull Mandatory (must not be undefined), must not be null. * @param {Object} mayBeNull Mandatory (must not be undefined), may be null. * @param {!Object=} opt_nonNull Optional (may be undefined), but if present, * must not be null! * @param {Object=} opt_mayBeNull Optional (may be undefined), may be null. */ function strangeButTrue(nonNull, mayBeNull, opt_nonNull, opt_mayBeNull) { // ... };

Sometimes types can get complicated. A function that accepts content for an Element might look like:

/** * @param {string} tagName * @param {(string|Element|Text|Array.<Element>|Array.<Text>)} contents * @return {!Element} */ goog.createElement = function(tagName, contents) { ... };

You can define commonly used type expressions with a @typedef tag. For example,

/** @typedef {(string|Element|Text|Array.<Element>|Array.<Text>)} */ goog.ElementContent; /** * @param {string} tagName * @param {goog.ElementContent} contents * @return {!Element} */ goog.createElement = function(tagName, contents) { ... };

The compiler has limited support for template types. It can only infer the type of this inside an anonymous function literal from the type of the this argument and whether the this argument is missing.

/** * @param {function(this:T, ...)} fn * @param {T} thisObj * @param {...*} var_args * @template T */ goog.bind = function(fn, thisObj, var_args) { ... }; // Possibly generates a missing property warning. goog.bind(function() { this.someProperty; }, new SomeClass()); // Generates an undefined this warning. goog.bind(function() { this.someProperty; });
Use JSDoc

We follow the C++ style for comments in spirit.

All files, classes, methods and properties should be documented with JSDoc comments with the appropriate tags and types. Textual descriptions for properties, methods, method parameters and method return values should be included unless obvious from the property, method, or parameter name.

Inline comments should be of the // variety.

Complete sentences are recommended but not required. Complete sentences should use appropriate capitalization and punctuation.

The JSDoc syntax is based on JavaDoc. Many tools extract metadata from JSDoc comments to perform code validation and optimizations. These comments must be well-formed.

/** * A JSDoc comment should begin with a slash and 2 asterisks. * Inline tags should be enclosed in braces like {@code this}. * @desc Block tags should always start on their own line. */

If you have to line break a block tag, you should treat this as breaking a code statement and indent it four spaces.

/** * Illustrates line wrapping for long param/return descriptions. * @param {string} foo This is a param with a description too long to fit in * one line. * @return {number} This returns something that has a description too long to * fit in one line. */ project.MyClass.prototype.method = function(foo) { return 5; };

You should not indent the @fileoverview command. You do not have to indent the @desc command.

Even though it is not preferred, it is also acceptable to line up the description.

/** * This is NOT the preferred indentation method. * @param {string} foo This is a param with a description too long to fit in * one line. * @return {number} This returns something that has a description too long to * fit in one line. */ project.MyClass.prototype.method = function(foo) { return 5; };

Like JavaDoc, JSDoc supports many HTML tags, like <code>, <pre>, <tt>, <strong>, <ul>, <ol>, <li>, <a>, and others.

This means that plaintext formatting is not respected. So, don't rely on whitespace to format JSDoc:

/** * Computes weight based on three factors: * items sent * items received * last timestamp */

It'll come out like this:

Computes weight based on three factors: items sent items received last timestamp

Instead, do this:

/** * Computes weight based on three factors: * <ul> * <li>items sent * <li>items received * <li>last timestamp * </ul> */ The JavaDoc style guide is a useful resource on how to write well-formed doc comments.

A copyright notice and author information are optional. File overviews are generally recommended whenever a file consists of more than a single class definition. The top level comment is designed to orient readers unfamiliar with the code to what is in this file. If present, it should provide a description of the file's contents and any dependencies or compatibility information. As an example:

/** * @fileoverview Description of file, its uses and information * about its dependencies. */

Classes must be documented with a description and a type tag that identifies the constructor.

/** * Class making something fun and easy. * @param {string} arg1 An argument that makes this more interesting. * @param {Array.<number>} arg2 List of numbers to be processed. * @constructor * @extends {goog.Disposable} */ project.MyClass = function(arg1, arg2) { // ... }; goog.inherits(project.MyClass, goog.Disposable);

Parameter and return types should be documented. The method description may be omitted if it is obvious from the parameter or return type descriptions. Method descriptions should start with a sentence written in the third person declarative voice.

/** * Operates on an instance of MyClass and returns something. * @param {project.MyClass} obj Instance of MyClass which leads to a long * comment that needs to be wrapped to two lines. * @return {boolean} Whether something occurred. */ function PR_someMethod(obj) { // ... }
/** @constructor */ project.MyClass = function() { /** * Maximum number of things per pane. * @type {number} */ this.someProperty = 4; }

Tag Template & Examples Description
@author @author username@google.com (first last)

For example:

/** * @fileoverview Utilities for handling textareas. * @author kuth@google.com (Uthur Pendragon) */
Document the author of a file or the owner of a test, generally only used in the @fileoverview comment.
@code {@code ...}

For example:

/** * Moves to the next position in the selection. * Throws {@code goog.iter.StopIteration} when it * passes the end of the range. * @return {Node} The node at the next position. */ goog.dom.RangeIterator.prototype.next = function() { // ... };
Indicates that a term in a JSDoc description is code so it may be correctly formatted in generated documentation.
@const @const
@const {type}

For example:

/** @const */ var MY_BEER = 'stout'; /** * My namespace's favorite kind of beer. * @const {string} */ mynamespace.MY_BEER = 'stout'; /** @const */ MyClass.MY_BEER = 'stout'; /** * Initializes the request. * @const */ mynamespace.Request.prototype.initialize = function() { // This method cannot be overridden in a subclass. };

Marks a variable (or property) as read-only and suitable for inlining.

A @const variable is an immutable pointer to a value. If a variable or property marked as @const is overwritten, JSCompiler will give warnings.

The type declaration of a constant value can be omitted if it can be clearly inferred. An additional comment about the variable is optional.

When @const is applied to a method, it implies the method is not only not overwritable, but also that the method is finalized — not overridable in subclasses.

For more on @const, see the Constants section.

@constructor @constructor

For example:

/** * A rectangle. * @constructor */ function GM_Rect() { ... }
Used in a class's documentation to indicate the constructor.
@define @define {Type} description

For example:

/** @define {boolean} */ var TR_FLAGS_ENABLE_DEBUG = true; /** * @define {boolean} Whether we know at compile-time that * the browser is IE. */ goog.userAgent.ASSUME_IE = false;
Indicates a constant that can be overridden by the compiler at compile-time. In the example, the compiler flag --define='goog.userAgent.ASSUME_IE=true' could be specified in the BUILD file to indicate that the constant goog.userAgent.ASSUME_IE should be replaced with true.
@deprecated @deprecated Description

For example:

/** * Determines whether a node is a field. * @return {boolean} True if the contents of * the element are editable, but the element * itself is not. * @deprecated Use isField(). */ BN_EditUtil.isTopEditableField = function(node) { // ... };
Used to tell that a function, method or property should not be used any more. Always provide instructions on what callers should use instead.
@dict @dict Description

For example:

/** * @constructor * @dict */ function Foo(x) { this['x'] = x; } var obj = new Foo(123); var num = obj.x; // warning (/** @dict */ { x: 1 }).x = 123; // warning
When a constructor (Foo in the example) is annotated with @dict, you can only use the bracket notation to access the properties of Foo objects. The annotation can also be used directly on object literals.
@enum @enum {Type}

For example:

/** * Enum for tri-state values. * @enum {number} */ project.TriState = { TRUE: 1, FALSE: -1, MAYBE: 0 };
@export @export

For example:

/** @export */ foo.MyPublicClass.prototype.myPublicMethod = function() { // ... };

Given the code on the left, when the compiler is run with the --generate_exports flag, it will generate the code:

goog.exportSymbol('foo.MyPublicClass.prototype.myPublicMethod', foo.MyPublicClass.prototype.myPublicMethod);

which will export the symbols to uncompiled code. Code that uses the @export annotation must either

  1. include //javascript/closure/base.js, or
  2. define both goog.exportSymbol and goog.exportProperty with the same method signature in their own codebase.
@expose @expose

For example:

/** @expose */ MyClass.prototype.exposedProperty = 3;

Declares an exposed property. Exposed properties will not be removed, or renamed, or collapsed, or optimized in any way by the compiler. No properties with the same name will be able to be optimized either.

@expose should never be used in library code, because it will prevent that property from ever getting removed.

@extends @extends Type
@extends {Type}

For example:

/** * Immutable empty node list. * @constructor * @extends goog.ds.BasicNodeList */ goog.ds.EmptyNodeList = function() { ... };
Used with @constructor to indicate that a class inherits from another class. Curly braces around the type are optional.
@externs @externs

For example:

/** * @fileoverview This is an externs file. * @externs */ var document;

Declares an externs file.

@fileoverview @fileoverview Description

For example:

/** * @fileoverview Utilities for doing things that require this very long * but not indented comment. * @author kuth@google.com (Uthur Pendragon) */
Makes the comment block provide file level information.
@implements @implements Type
@implements {Type}

For example:

/** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * @constructor * @implements {Shape} */ function Square() {}; Square.prototype.draw = function() { ... };
Used with @constructor to indicate that a class implements an interface. Curly braces around the type are optional.
@inheritDoc @inheritDoc

For example:

/** @inheritDoc */ project.SubClass.prototype.toString() { // ... };

Deprecated. Use @override instead.

Indicates that a method or property of a subclass intentionally hides a method or property of the superclass, and has exactly the same documentation. Notice that @inheritDoc implies @override
@interface @interface

For example:

/** * A shape. * @interface */ function Shape() {}; Shape.prototype.draw = function() {}; /** * A polygon. * @interface * @extends {Shape} */ function Polygon() {}; Polygon.prototype.getSides = function() {};
Used to indicate that the function defines an interface.
@lends @lends objectName
@lends {objectName}

For example:

goog.object.extend( Button.prototype, /** @lends {Button.prototype} */ { isButton: function() { return true; } });
Indicates that the keys of an object literal should be treated as properties of some other object. This annotation should only appear on object literals.

Notice that the name in braces is not a type name like in other annotations. It's an object name. It names the object on which the properties are "lent". For example, @type {Foo} means "an instance of Foo", but @lends {Foo} means "the constructor Foo".

The JSDoc Toolkit docs have more information on this annotation.

@license or @preserve @license Description

For example:

/** * @preserve Copyright 2009 SomeThirdParty. * Here is the full license text and copyright * notice for this file. Note that the notice can span several * lines and is only terminated by the closing star and slash: */
Anything marked by @license or @preserve will be retained by the compiler and output at the top of the compiled code for that file. This annotation allows important notices (such as legal licenses or copyright text) to survive compilation unchanged. Line breaks are preserved.
@noalias @noalias

For example:

/** @noalias */ function Range() {}
Used in an externs file to indicate to the compiler that the variable or function should not be aliased as part of the alias externals pass of the compiler.
@nocompile @nocompile

For example:

/** @nocompile */ // JavaScript code
Used at the top of a file to tell the compiler to parse this file but not compile it. Code that is not meant for compilation and should be omitted from compilation tests (such as bootstrap code) uses this annotation. Use sparingly.
@nosideeffects @nosideeffects

For example:

/** @nosideeffects */ function noSideEffectsFn1() { // ... } /** @nosideeffects */ var noSideEffectsFn2 = function() { // ... }; /** @nosideeffects */ a.prototype.noSideEffectsFn3 = function() { // ... };
This annotation can be used as part of function and constructor declarations to indicate that calls to the declared function have no side-effects. This annotation allows the compiler to remove calls to these functions if the return value is not used.
@override @override

For example:

/** * @return {string} Human-readable representation of project.SubClass. * @override */ project.SubClass.prototype.toString = function() { // ... };
Indicates that a method or property of a subclass intentionally hides a method or property of the superclass. If no other documentation is included, the method or property also inherits documentation from its superclass.
@param @param {Type} varname Description

For example:

/** * Queries a Baz for items. * @param {number} groupNum Subgroup id to query. * @param {string|number|null} term An itemName, * or itemId, or null to search everything. */ goog.Baz.prototype.query = function(groupNum, term) { // ... };
Used with method, function and constructor calls to document the arguments of a function.

Type names must be enclosed in curly braces. If the type is omitted, the compiler will not type-check the parameter.

@private @private
@private {type}

For example:

/** * Handlers that are listening to this logger. * @private {!Array.<Function>} */ this.handlers_ = [];
Used in conjunction with a trailing underscore on the method or property name to indicate that the member is private and final.
@protected @protected
@protected {type}

For example:

/** * Sets the component's root element to the given element. * @param {Element} element Root element for the component. * @protected */ goog.ui.Component.prototype.setElementInternal = function(element) { // ... };
Used to indicate that the member or property is protected. Should be used in conjunction with names with no trailing underscore.
@public @public
@public {type}

For example:

/** * Whether to cancel the event in internal capture/bubble processing. * @public {boolean} * @suppress {visibility} Referencing this outside this package is strongly * discouraged. */ goog.events.Event.prototype.propagationStopped_ = false;
Used to indicate that the member or property is public. Variables and properties are public by default, so this annotation is rarely necessary. Should only be used in legacy code that cannot be easily changed to override the visibility of members that were named as private variables.
@return @return {Type} Description

For example:

/** * @return {string} The hex ID of the last item. */ goog.Baz.prototype.getLastId = function() { // ... return id; };
Used with method and function calls to document the return type. When writing descriptions for boolean parameters, prefer "Whether the component is visible" to "True if the component is visible, false otherwise". If there is no return value, do not use an @return tag.

Type names must be enclosed in curly braces. If the type is omitted, the compiler will not type-check the return value.

@see @see Link

For example:

/** * Adds a single item, recklessly. * @see #addSafely * @see goog.Collect * @see goog.RecklessAdder#add ...
Reference a lookup to another class function or method.
@struct @struct Description

For example:

/** * @constructor * @struct */ function Foo(x) { this.x = x; } var obj = new Foo(123); var num = obj['x']; // warning obj.y = "asdf"; // warning Foo.prototype = /** @struct */ { method1: function() {} }; Foo.prototype.method2 = function() {}; // warning
When a constructor (Foo in the example) is annotated with @struct, you can only use the dot notation to access the properties of Foo objects. Also, you cannot add new properties to Foo objects after they have been created. The annotation can also be used directly on object literals.
@supported @supported Description

For example:

/** * @fileoverview Event Manager * Provides an abstracted interface to the * browsers' event systems. * @supported So far tested in IE6 and FF1.5 */
Used in a fileoverview to indicate what browsers are supported by the file.
@suppress @suppress {warning1|warning2} @suppress {warning1,warning2}

For example:

/** * @suppress {deprecated} */ function f() { deprecatedVersionOfF(); }
Suppresses warnings from tools. Warning categories are separated by | or ,.
@template @template

For example:

/** * @param {function(this:T, ...)} fn * @param {T} thisObj * @param {...*} var_args * @template T */ goog.bind = function(fn, thisObj, var_args) { ... };
This annotation can be used to declare a template typename.
@this @this Type
@this {Type}

For example:

pinto.chat.RosterWidget.extern('getRosterElement', /** * Returns the roster widget element. * @this pinto.chat.RosterWidget * @return {Element} */ function() { return this.getWrappedComponent_().getElement(); });
The type of the object in whose context a particular method is called. Required when the this keyword is referenced from a function that is not a prototype method.
@type @type Type
@type {Type}

For example:

/** * The message hex ID. * @type {string} */ var hexId = hexId;
Identifies the type of a variable, property, or expression. Curly braces are not required around most types, but some projects mandate them for all types, for consistency.
@typedef @typedef

For example:

/** @typedef {(string|number)} */ goog.NumberLike; /** @param {goog.NumberLike} x A number or a string. */ goog.readNumber = function(x) { ... }
This annotation can be used to declare an alias of a more complex type.

You may also see other types of JSDoc annotations in third-party code. These annotations appear in the JSDoc Toolkit Tag Reference but are currently discouraged in Google code. You should consider them "reserved" names for future use. These include:

  • @augments
  • @argument
  • @borrows
  • @class
  • @constant
  • @constructs
  • @default
  • @event
  • @example
  • @field
  • @function
  • @ignore
  • @inner
  • @link
  • @memberOf
  • @name
  • @namespace
  • @property
  • @public
  • @requires
  • @returns
  • @since
  • @static
  • @version

Only provide top-level symbols.

All members defined on a class should be in the same file. So, only top-level classes should be provided in a file that contains multiple members defined on the same class (e.g. enums, inner classes, etc).

Do this:

goog.provide('namespace.MyClass');

Not this:

goog.provide('namespace.MyClass'); goog.provide('namespace.MyClass.Enum'); goog.provide('namespace.MyClass.InnerClass'); goog.provide('namespace.MyClass.TypeDef'); goog.provide('namespace.MyClass.CONSTANT'); goog.provide('namespace.MyClass.staticMethod');

Members on namespaces may also be provided:

goog.provide('foo.bar'); goog.provide('foo.bar.method'); goog.provide('foo.bar.CONSTANT');
Required

Use of JS compilers such as the Closure Compiler is required for all customer-facing code.

JavaScript tidbits

The following are all false in boolean expressions:

  • null
  • undefined
  • '' the empty string
  • 0 the number

But be careful, because these are all true:

  • '0' the string
  • [] the empty array
  • {} the empty object

This means that instead of this:

while (x != null) {

you can write this shorter code (as long as you don't expect x to be 0, or the empty string, or false):

while (x) {

And if you want to check a string to see if it is null or empty, you could do this:

if (y != null && y != '') {

But this is shorter and nicer:

if (y) {

Caution: There are many unintuitive things about boolean expressions. Here are some of them:

  • Boolean('0') == true
    '0' != true
  • 0 != null
    0 == []
    0 == false
  • Boolean(null) == false
    null != true
    null != false
  • Boolean(undefined) == false
    undefined != true
    undefined != false
  • Boolean([]) == true
    [] != true
    [] == false
  • Boolean({}) == true
    {} != true
    {} != false

Instead of this:

if (val) { return foo(); } else { return bar(); }

you can write this:

return val ? foo() : bar();

The ternary conditional is also useful when generating HTML:

var html = '<input type="checkbox"' + (isChecked ? ' checked' : '') + (isEnabled ? '' : ' disabled') + ' name="foo">';

These binary boolean operators are short-circuited, and evaluate to the last evaluated term.

"||" has been called the 'default' operator, because instead of writing this:

/** @param {*=} opt_win */ function foo(opt_win) { var win; if (opt_win) { win = opt_win; } else { win = window; } // ... }

you can write this:

/** @param {*=} opt_win */ function foo(opt_win) { var win = opt_win || window; // ... }

"&&" is also useful for shortening code. For instance, instead of this:

if (node) { if (node.kids) { if (node.kids[index]) { foo(node.kids[index]); } } }

you could do this:

if (node && node.kids && node.kids[index]) { foo(node.kids[index]); }

or this:

var kid = node && node.kids && node.kids[index]; if (kid) { foo(kid); }

However, this is going a little too far:

node && node.kids && node.kids[index] && foo(node.kids[index]);

Node lists are often implemented as node iterators with a filter. This means that getting a property like length is O(n), and iterating over the list by re-checking the length will be O(n^2).

var paragraphs = document.getElementsByTagName('p'); for (var i = 0; i < paragraphs.length; i++) { doSomething(paragraphs[i]); }

It is better to do this instead:

var paragraphs = document.getElementsByTagName('p'); for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) { doSomething(paragraph); }

This works well for all collections and arrays as long as the array does not contain things that are treated as boolean false.

In cases where you are iterating over the childNodes you can also use the firstChild and nextSibling properties.

var parentNode = document.getElementById('foo'); for (var child = parentNode.firstChild; child; child = child.nextSibling) { doSomething(child); }

BE CONSISTENT.

If you're editing code, take a few minutes to look at the code around you and determine its style. If they use spaces around all their arithmetic operators, you should too. If their comments have little boxes of hash marks around them, make your comments have little boxes of hash marks around them too.

The point of having style guidelines is to have a common vocabulary of coding so people can concentrate on what you're saying rather than on how you're saying it. We present global style rules here so people know the vocabulary, but local style is also important. If code you add to a file looks drastically different from the existing code around it, it throws readers out of their rhythm when they go to read it. Avoid this.

Revision 2.93

Aaron Whyte
Bob Jervis
Dan Pupius
Erik Arvidsson
Fritz Schneider
Robby Walker
================================================ FILE: jsguide.html ================================================ Google JavaScript Style Guide

Google JavaScript Style Guide

Please note: This guide is no longer being updated. Google recommends migrating to TypeScript, and following the TypeScript guide.

1 Introduction

This document serves as the complete definition of Google’s coding standards for source code in the JavaScript programming language. A JavaScript source file is described as being in Google Style if and only if it adheres to the rules herein.

Like other programming style guides, the issues covered span not only aesthetic issues of formatting, but other types of conventions or coding standards as well. However, this document focuses primarily on the hard-and-fast rules that we follow universally, and avoids giving advice that isn't clearly enforceable (whether by human or tool).

1.1 Terminology notes

In this document, unless otherwise clarified:

  1. The term comment always refers to implementation comments. We do not use the phrase documentation comments, instead using the common term “JSDoc” for both human-readable text and machine-readable annotations within /** … */.

  2. This Style Guide uses RFC 2119 terminology when using the phrases must, must not, should, should not, and may. The terms prefer and avoid correspond to should and should not, respectively. Imperative and declarative statements are prescriptive and correspond to must.

Other terminology notes will appear occasionally throughout the document.

1.2 Guide notes

Example code in this document is non-normative. That is, while the examples are in Google Style, they may not illustrate the only stylish way to represent the code. Optional formatting choices made in examples must not be enforced as rules.

2 Source file basics

2.1 File name

File names must be all lowercase and may include underscores (_) or dashes (-), but no additional punctuation. Follow the convention that your project uses. Filenames’ extension must be .js.

2.2 File encoding: UTF-8

Source files are encoded in UTF-8.

2.3 Special characters

2.3.1 Whitespace characters

Aside from the line terminator sequence, the ASCII horizontal space character (0x20) is the only whitespace character that appears anywhere in a source file. This implies that

  1. All other whitespace characters in string literals are escaped, and

  2. Tab characters are not used for indentation.

2.3.2 Special escape sequences

For any character that has a special escape sequence (\', \", \\, \b, \f, \n, \r, \t, \v), that sequence is used rather than the corresponding numeric escape (e.g \x0a, \u000a, or \u{a}). Legacy octal escapes are never used.

2.3.3 Non-ASCII characters

For the remaining non-ASCII characters, either the actual Unicode character (e.g. ) or the equivalent hex or Unicode escape (e.g. \u221e) is used, depending only on which makes the code easier to read and understand.

Tip: In the Unicode escape case, and occasionally even when actual Unicode characters are used, an explanatory comment can be very helpful.

/* Best: perfectly clear even without a comment. */
const units = 'μs';

/* Allowed: but unnecessary as μ is a printable character. */
const units = '\u03bcs'; // 'μs'

/* Good: use escapes for non-printable characters with a comment for clarity. */
return '\ufeff' + content;  // Prepend a byte order mark.
/* Poor: the reader has no idea what character this is. */
const units = '\u03bcs';

Tip: Never make your code less readable simply out of fear that some programs might not handle non-ASCII characters properly. If that happens, those programs are broken and they must be fixed.

3 Source file structure

All new source files should either be a goog.module file (a file containing a goog.module call) or an ECMAScript (ES) module (uses import and export statements).

Files consist of the following, in order:

  1. License or copyright information, if present
  2. @fileoverview JSDoc, if present
  3. goog.module statement, if a goog.module file
  4. ES import statements, if an ES module
  5. goog.require and goog.requireType statements
  6. The file’s implementation

Exactly one blank line separates each section that is present, except the file's implementation, which may be preceded by 1 or 2 blank lines.

If license or copyright information belongs in a file, it belongs here.

3.2 @fileoverview JSDoc, if present

See ?? for formatting rules.

3.3 goog.module statement

All goog.module files must declare exactly one goog.module name on a single line: lines containing a goog.module declaration must not be wrapped, and are therefore an exception to the 80-column limit.

The entire argument to goog.module is what defines a namespace. It is the package name (an identifier that reflects the fragment of the directory structure where the code lives) plus, optionally, the main class/enum/interface that it defines concatenated to the end in lowerCamelCase.

Example:

goog.module('search.urlHistory.urlHistoryService');

3.3.1 Hierarchy

Module namespaces may never be named as a direct child of another module's namespace.

Disallowed:

goog.module('foo.bar');   // 'foo.bar.qux' would be fine, though
goog.module('foo.bar.baz');

The directory hierarchy reflects the namespace hierarchy, so that deeper-nested children are subdirectories of higher-level parent directories. Note that this implies that owners of “parent” namespace groups are necessarily aware of all child namespaces, since they exist in the same directory.

3.3.2 goog.module.declareLegacyNamespace

The single goog.module statement may optionally be followed by a call to goog.module.declareLegacyNamespace();. Avoid goog.module.declareLegacyNamespace() when possible.

Example:

goog.module('my.test.helpers');
goog.module.declareLegacyNamespace();
goog.setTestOnly();

goog.module.declareLegacyNamespace exists to ease the transition from traditional object hierarchy-based namespaces but comes with some naming restrictions. As the child module name must be created after the parent namespace, this name must not be a child or parent of any other goog.module (for example, goog.module('parent'); and goog.module('parent.child'); cannot both exist safely, nor can goog.module('parent'); and goog.module('parent.child.grandchild');).

3.3.3 goog.module Exports

Classes, enums, functions, constants, and other symbols are exported using the exports object. Exported symbols may be defined directly on the exports object, or else declared locally and exported separately. Symbols are only exported if they are meant to be used outside the module. Non-exported module-local symbols are not declared @private. There is no prescribed ordering for exported and module-local symbols.

Examples:

const /** !Array<number> */ exportedArray = [1, 2, 3];

const /** !Array<number> */ moduleLocalArray = [4, 5, 6];

/** @return {number} */
function moduleLocalFunction() {
  return moduleLocalArray.length;
}

/** @return {number} */
function exportedFunction() {
  return moduleLocalFunction() * 2;
}

exports = {exportedArray, exportedFunction};
/** @const {number} */
exports.CONSTANT_ONE = 1;

/** @const {string} */
exports.CONSTANT_TWO = 'Another constant';

Do not annotate the exports object as @const as it is already treated as a constant by the compiler.

/** @const */
exports = {exportedFunction};

Do not use default exports as they don't translate easily to ES module semantics.

exports = FancyClass;

3.4 ES modules

ES modules are files that use the import and export keywords.

3.4.1 Imports

Import statements must not be line wrapped and are therefore an exception to the 80-column limit.

3.4.1.1 Import paths

ES module files must use the import statement to import other ES module files. Do not goog.require another ES module.

import './sideeffects.js';

import * as goog from '../closure/goog/goog.js';
import * as parent from '../parent.js';

import {name} from './sibling.js';

3.4.1.1.1 File extensions in import paths

The .js file extension is not optional in import paths and must always be included.

import '../directory/file';
import '../directory/file.js';
3.4.1.2 Importing the same file multiple times

Do not import the same file multiple times. This can make it hard to determine the aggregate imports of a file.

// Imports have the same path, but since it doesn't align it can be hard to see.
import {short} from './long/path/to/a/file.js';
import {aLongNameThatBreaksAlignment} from './long/path/to/a/file.js';

3.4.1.3 Naming imports
3.4.1.3.1 Naming module imports

Module import names (import * as name) are lowerCamelCase names that are derived from the imported file name.

import * as fileOne from '../file-one.js';
import * as fileTwo from '../file_two.js';
import * as fileThree from '../filethree.js';
import * as libString from './lib/string.js';
import * as math from './math/math.js';
import * as vectorMath from './vector/math.js';

Some libraries might commonly use a namespace import prefix that violates this naming scheme, but overbearingly common open source use makes the violating style more readable. The only library that currently falls under this exception is threejs, using the THREE prefix.

3.4.1.3.2 Naming default imports

Default import names are derived from the imported file name and follow the rules in ??.

import MyClass from '../my-class.js';
import myFunction from '../my_function.js';
import SOME_CONSTANT from '../someconstant.js';

Note: In general this should not happen as default exports are banned by this style guide, see ??. Default imports are only used to import modules that do not conform to this style guide.

3.4.1.3.3 Naming named imports

In general symbols imported via the named import (import {name}) should keep the same name. Avoid aliasing imports (import {SomeThing as SomeOtherThing}). Prefer fixing name collisions by using a module import (import *) or renaming the exports themselves.

import * as bigAnimals from './biganimals.js';
import * as domesticatedAnimals from './domesticatedanimals.js';

new bigAnimals.Cat();
new domesticatedAnimals.Cat();

If renaming a named import is needed then use components of the imported module's file name or path in the resulting alias.

import {Cat as BigCat} from './biganimals.js';
import {Cat as DomesticatedCat} from './domesticatedanimals.js';

new BigCat();
new DomesticatedCat();

3.4.2 Exports

Symbols are only exported if they are meant to be used outside the module. Non-exported module-local symbols are not declared @private. There is no prescribed ordering for exported and module-local symbols.

3.4.2.1 Named vs default exports

Use named exports in all code. You can apply the export keyword to a declaration, or use the export {name}; syntax.

Do not use default exports. Importing modules must give a name to these values, which can lead to inconsistencies in naming across modules.

// Do not use default exports:
export default class Foo { ... } // BAD!
// Use named exports:
export class Foo { ... }
// Alternate style named exports:
class Foo { ... }

export {Foo};

3.4.2.2 Mutability of exports

Exported variables must not be mutated outside of module initialization.

There are alternatives if mutation is needed, including exporting a constant reference to an object that has mutable fields or exporting accessor functions for mutable data.

// Bad: both foo and mutateFoo are exported and mutated.
export let /** number */ foo = 0;

/**
 * Mutates foo.
 */
export function mutateFoo() {
  ++foo;
}

/**
 * @param {function(number): number} newMutateFoo
 */
export function setMutateFoo(newMutateFoo) {
  // Exported classes and functions can be mutated!
  mutateFoo = () => {
    foo = newMutateFoo(foo);
  };
}
// Good: Rather than export the mutable variables foo and mutateFoo directly,
// instead make them module scoped and export a getter for foo and a wrapper for
// mutateFooFunc.
let /** number */ foo = 0;
let /** function(number): number */ mutateFooFunc = (foo) => foo + 1;

/** @return {number} */
export function getFoo() {
  return foo;
}

export function mutateFoo() {
  foo = mutateFooFunc(foo);
}

/** @param {function(number): number} mutateFoo */
export function setMutateFoo(mutateFoo) {
  mutateFooFunc = mutateFoo;
}

3.4.2.3 export from

export from statements must not be line wrapped and are therefore an exception to the 80-column limit. This applies to both export from flavors.

export {specificName} from './other.js';
export * from './another.js';

3.4.3 Circular Dependencies in ES modules

Do not create cycles between ES modules, even though the ECMAScript specification allows this. Note that it is possible to create cycles with both the import and export statements.

// a.js
import './b.js';
// b.js
import './a.js';

// `export from` can cause circular dependencies too!
export {x} from './c.js';
// c.js
import './b.js';

export let x;

3.4.4 Interoperating with Closure

3.4.4.1 Referencing goog

To reference the Closure goog namespace, import Closure's goog.js.

import * as goog from '../closure/goog/goog.js';

const {compute} = goog.require('a.name');

export const CONSTANT = compute();

goog.js exports only a subset of properties from the global goog that can be used in ES modules.

3.4.4.2 goog.require in ES modules

goog.require in ES modules works as it does in goog.module files. You can require any Closure namespace symbol (i.e., symbols created by goog.provide or goog.module) and goog.require will return the value.

import * as goog from '../closure/goog/goog.js';
import * as anEsModule from './anEsModule.js';

const GoogPromise = goog.require('goog.Promise');
const myNamespace = goog.require('my.namespace');

3.4.4.3 Declaring Closure Module IDs in ES modules

goog.declareModuleId can be used within ES modules to declare a goog.module-like module ID. This means that this module ID can be goog.required, goog.module.getd etc. as if it were a goog.module that did not call goog.module.declareLegacyNamespace. It does not create the module ID as a globally available JavaScript symbol.

A goog.require (or goog.module.get) for a module ID from goog.declareModuleId will always return the module object (as if it was import *'d). As a result, the argument to goog.declareModuleId should always end with a lowerCamelCaseName.

Note: It is an error to call goog.module.declareLegacyNamespace in an ES module, it can only be called from goog.module files. There is no direct way to associate a legacy namespace with an ES module.

goog.declareModuleId should only be used to upgrade Closure files to ES modules in place, where named exports are used.

import * as goog from '../closure/goog.js';

goog.declareModuleId('my.esm');

export class Class {};

3.5 goog.setTestOnly

In a goog.module file the goog.module statement and, if present, goog.module.declareLegacyNamespace() statement may optionally be followed by a call to goog.setTestOnly().

In an ES module the import statements may optionally be followed by a call to goog.setTestOnly().

3.6 goog.require and goog.requireType statements

Imports are done with goog.require and goog.requireType statements. The names imported by a goog.require statement may be used both in code and in type annotations, while those imported by a goog.requireType may be used in type annotations only.

The goog.require and goog.requireType statements form a contiguous block with no empty lines. This block follows the goog.module declaration separated by a single empty line. The entire argument to goog.require or goog.requireType is a namespace defined by a goog.module in a separate file. goog.require and goog.requireType statements may not appear anywhere else in the file.

Each goog.require or goog.requireType is assigned to a single constant alias, or else destructured into several constant aliases. These aliases are the only acceptable way to refer to dependencies in type annotations or code. Fully qualified namespaces must not be used anywhere, except as an argument to goog.require or goog.requireType.

Exception: Types, variables, and functions declared in externs files have to use their fully qualified name in type annotations and code.

When goog.require is assigned to a single constant alias, it must match the final dot-separated component of the imported module's namespace.

Exception: In certain cases, additional components of the namespace can be used to form a longer alias. The resulting alias must retain the original identifier's casing such that it still correctly identifies its type. Longer aliases may be used to disambiguate otherwise identical aliases, or if it significantly improves readability. In addition, a longer alias must be used to prevent masking native types such as Element, Event, Error, Map, and Promise (for a more complete list, see Standard Built-in Objects and Web APIs at MDN).

When renaming destructured aliases, a space must follow the colon as required in ??.

A file should not contain both a goog.require and a goog.requireType statement for the same namespace. If the imported name is used both in code and in type annotations, it should be imported by a single goog.require statement.

If a module is imported only for its side effects, the call must be a goog.require (not a goog.requireType) and assignment may be omitted. A comment is required to explain why this is needed and suppress a compiler warning.

The lines are sorted according to the following rules: All requires with a name on the left hand side come first, sorted alphabetically by those names. Then destructuring requires, again sorted by the names on the left hand side. Finally, any require calls that are standalone (generally these are for modules imported just for their side effects).

Tip: There’s no need to memorize this order and enforce it manually. You can rely on your IDE to report requires that are not sorted correctly.

If a long alias or module name would cause a line to exceed the 80-column limit, it must not be wrapped: require lines are an exception to the 80-column limit.

Example:

// Standard alias style.
const asserts = goog.require('goog.asserts');
// Namespace-based alias used to disambiguate.
const testingAsserts = goog.require('goog.testing.asserts');
// Standard destructuring into aliases.
const {MyClass} = goog.require('some.package');
const {MyType} = goog.requireType('other.package');
const {clear, clone} = goog.require('goog.array');
const {Rgb} = goog.require('goog.color');
// Namespace-based destructuring into aliases used to disambiguate.
const {MyClass: NsMyClass} = goog.require('other.ns');
const {SomeType: FooSomeType} = goog.requireType('foo.types');
const {clear: objectClear, clone: objectClone} = goog.require('goog.object');
// Namespace-based destructuring into aliases used to prevent masking native type.
const {Element: RendererElement} = goog.require('web.renderer');
// Out of sequence namespace-based aliases used to improve readability.
// Also, require lines longer than 80 columns must not be wrapped.
const {SomeDataStructure: SomeDataStructureModel} = goog.requireType('identical.package.identifiers.models');
const {SomeDataStructure: SomeDataStructureProto} = goog.require('proto.identical.package.identifiers');
// goog.require without an alias in order to trigger side effects.
/** @suppress {extraRequire} Initializes MyFramework. */
goog.require('my.framework.initialization');

Discouraged:

// Some legacy code uses a "default export" style to export a single class, enum,
// record type, etc. Do not use this pattern in new JS.
// When using a "default export", prefer destructuring into aliases.
const MyClass = goog.require('some.package.MyClass');
const MyType = goog.requireType('some.package.MyType');
// If necessary to disambiguate, prefer PackageClass over SomeClass as it is
// closer to the format of the module name.
const SomeClass = goog.require('some.package.Class');

Disallowed:

// Extra terms must come from the namespace.
const MyClassForBizzing = goog.require('some.package.MyClass');
// Alias must include the entire final namespace component.
const MyClass = goog.require('some.package.MyClassForBizzing');
// Alias must not mask native type (should be `const JspbMap` here).
const Map = goog.require('jspb.Map');
// Don't break goog.require lines over 80 columns.
const SomeDataStructure =
    goog.require('proto.identical.package.identifiers.SomeDataStructure');
// Alias must be based on the namespace.
const randomName = goog.require('something.else');
// Missing a space after the colon.
const {Foo:FooProto} = goog.require('some.package.proto.Foo');
// goog.requireType without an alias.
goog.requireType('some.package.with.a.Type');


/**
 * @param {!some.unimported.Dependency} param All external types used in JSDoc
 *     annotations must be goog.require'd, unless declared in externs.
 */
function someFunction(param) {
  // goog.require lines must be at the top level before any other code.
  const alias = goog.require('my.long.name.alias');
  // ...
}

3.7 The file’s implementation

The actual implementation follows after all dependency information is declared (separated by at least one blank line).

This may consist of any module-local declarations (constants, variables, classes, functions, etc), as well as any exported symbols.

4 Formatting

Terminology Note: block-like construct refers to the body of a class, function, method, or brace-delimited block of code. Note that, by ?? and ??, any array or object literal may optionally be treated as if it were a block-like construct.

Tip: Use clang-format. The JavaScript community has invested effort to make sure clang-format does the right thing on JavaScript files. clang-format has integration with several popular editors.

4.1 Braces

4.1.1 Braces are used for all control structures

Braces are required for all control structures (i.e. if, else, for, do, while, as well as any others), even if the body contains only a single statement. The first statement of a non-empty block must begin on its own line.

Disallowed:

if (someVeryLongCondition())
  doSomething();

for (let i = 0; i < foo.length; i++) bar(foo[i]);

Exception: A simple if statement that can fit entirely on a single line with no wrapping (and that doesn’t have an else) may be kept on a single line with no braces when it improves readability. This is the only case in which a control structure may omit braces and newlines.

if (shortCondition()) foo();

4.1.2 Nonempty blocks: K&R style

Braces follow the Kernighan and Ritchie style (Egyptian brackets) for nonempty blocks and block-like constructs:

  • No line break before the opening brace.
  • Line break after the opening brace.
  • Line break before the closing brace.
  • Line break after the closing brace if that brace terminates a statement or the body of a function or class statement, or a class method. Specifically, there is no line break after the brace if it is followed by else, catch, while, or a comma, semicolon, or right-parenthesis.

Example:

class InnerClass {
  constructor() {}

  /** @param {number} foo */
  method(foo) {
    if (condition(foo)) {
      try {
        // Note: this might fail.
        something();
      } catch (err) {
        recover();
      }
    }
  }
}

4.1.3 Empty blocks: may be concise

An empty block or block-like construct may be closed immediately after it is opened, with no characters, space, or line break in between (i.e. {}), unless it is a part of a multi-block statement (one that directly contains multiple blocks: if/else or try/catch/finally).

Example:

function doNothing() {}

Disallowed:

if (condition) {
  // …
} else if (otherCondition) {} else {
  // …
}

try {
  // …
} catch (e) {}

4.2 Block indentation: +2 spaces

Each time a new block or block-like construct is opened, the indent increases by two spaces. When the block ends, the indent returns to the previous indent level. The indent level applies to both code and comments throughout the block. (See the example in ??).

4.2.1 Array literals: optionally block-like

Any array literal may optionally be formatted as if it were a “block-like construct.” For example, the following are all valid (not an exhaustive list):

const a = [
  0,
  1,
  2,
];

const b =
    [0, 1, 2];

const c = [0, 1, 2];

someMethod(foo, [
  0, 1, 2,
], bar);

Other combinations are allowed, particularly when emphasizing semantic groupings between elements, but should not be used only to reduce the vertical size of larger arrays.

4.2.2 Object literals: optionally block-like

Any object literal may optionally be formatted as if it were a “block-like construct.” The same examples apply as ??. For example, the following are all valid (not an exhaustive list):

const a = {
  a: 0,
  b: 1,
};

const b =
    {a: 0, b: 1};
const c = {a: 0, b: 1};

someMethod(foo, {
  a: 0, b: 1,
}, bar);

4.2.3 Class literals

Class literals (whether declarations or expressions) are indented as blocks. Do not add semicolons after methods, or after the closing brace of a class declaration (statements—such as assignments—that contain class expressions are still terminated with a semicolon). For inheritance, the extends keyword is sufficient unless the superclass is templatized. Subclasses of templatized types must explicitly specify the template type in an @extends JSDoc annotation, even if it is just passing along the same template name.

Example:

/** @template T */
class Foo {
  /** @param {T} x */
  constructor(x) {
    /** @type {T} */
    this.x = x;
  }
}

/** @extends {Foo<number>} */
class Bar extends Foo {
  constructor() {
    super(42);
  }
}

exports.Baz = class extends Bar {
  /** @return {number} */
  method() {
    return this.x;
  }
};
/** @extends {Bar} */ // <-- unnecessary @extends
exports.Baz = class extends Bar {
  /** @return {number} */
  method() {
    return this.x;
  }
};

4.2.4 Function expressions

When declaring an anonymous function in the list of arguments for a function call, the body of the function is indented two spaces more than the preceding indentation depth.

Example:

prefix.something.reallyLongFunctionName('whatever', (a1, a2) => {
  // Indent the function body +2 relative to indentation depth
  // of the 'prefix' statement one line above.
  if (a1.equals(a2)) {
    someOtherLongFunctionName(a1);
  } else {
    andNowForSomethingCompletelyDifferent(a2.parrot);
  }
});

some.reallyLongFunctionCall(arg1, arg2, arg3)
    .thatsWrapped()
    .then((result) => {
      // Indent the function body +2 relative to the indentation depth
      // of the '.then()' call.
      if (result) {
        result.use();
      }
    });

4.2.5 Switch statements

As with any other block, the contents of a switch block are indented +2.

After a switch label, a newline appears, and the indentation level is increased +2, exactly as if a block were being opened. An explicit block may be used if required by lexical scoping. The following switch label returns to the previous indentation level, as if a block had been closed.

A blank line is optional between a break and the following case.

Example:

switch (animal) {
  case Animal.BANDERSNATCH:
    handleBandersnatch();
    break;

  case Animal.JABBERWOCK:
    handleJabberwock();
    break;

  default:
    throw new Error('Unknown animal');
}

4.3 Statements

4.3.1 One statement per line

Each statement is followed by a line-break.

4.3.2 Semicolons are required

Every statement must be terminated with a semicolon. Relying on automatic semicolon insertion is forbidden.

4.4 Column limit: 80

JavaScript code has a column limit of 80 characters. Except as noted below, any line that would exceed this limit must be line-wrapped, as explained in ??.

Exceptions:

  1. goog.module, goog.require and goog.requireType statements (see ?? and ??).
  2. ES module import and export from statements (see ?? and ??).
  3. Lines where obeying the column limit is not possible or would hinder discoverability. Examples include:
    • A long URL which should be clickable in source.
    • A shell command intended to be copied-and-pasted.
    • A long string literal which may need to be copied or searched for wholly (e.g., a long file path).

4.5 Line-wrapping

Terminology Note: Line wrapping is breaking a chunk of code into multiple lines to obey column limit, where the chunk could otherwise legally fit in a single line.

There is no comprehensive, deterministic formula showing exactly how to line-wrap in every situation. Very often there are several valid ways to line-wrap the same piece of code.

Note: While the typical reason for line-wrapping is to avoid overflowing the column limit, even code that would in fact fit within the column limit may be line-wrapped at the author's discretion.

Tip: Extracting a method or local variable may solve the problem without the need to line-wrap.

4.5.1 Where to break

The prime directive of line-wrapping is: prefer to break at a higher syntactic level.

Preferred:

currentEstimate =
    calc(currentEstimate + x * currentEstimate) /
        2.0;

Discouraged:

currentEstimate = calc(currentEstimate + x *
    currentEstimate) / 2.0;

In the preceding example, the syntactic levels from highest to lowest are as follows: assignment, division, function call, parameters, number constant.

Operators are wrapped as follows:

  1. When a line is broken at an operator the break comes after the symbol. (Note that this is not the same practice used in Google style for Java.)
    1. This does not apply to the dot (.), which is not actually an operator.
  2. A method or constructor name stays attached to the open parenthesis (() that follows it.
  3. A comma (,) stays attached to the token that precedes it.
  4. A line break is never added between a return and the return value as this would change the meaning of the code.
  5. JSDoc annotations with type names break after {. This is necessary as annotations with optional types (@const, @private, @param, etc) do not scan the next line.

Note: The primary goal for line wrapping is to have clear code, not necessarily code that fits in the smallest number of lines.

4.5.2 Indent continuation lines at least +4 spaces

When line-wrapping, each line after the first (each continuation line) is indented at least +4 from the original line, unless it falls under the rules of block indentation.

When there are multiple continuation lines, indentation may be varied beyond +4 as appropriate. In general, continuation lines at a deeper syntactic level are indented by larger multiples of 4, and two lines use the same indentation level if and only if they begin with syntactically parallel elements.

?? addresses the discouraged practice of using a variable number of spaces to align certain tokens with previous lines.

4.6 Whitespace

4.6.1 Vertical whitespace

A single blank line appears:

  1. Between consecutive methods in a class or object literal
    1. Exception: A blank line between two consecutive properties definitions in an object literal (with no other code between them) is optional. Such blank lines are used as needed to create logical groupings of fields.
  2. Within method bodies, sparingly to create logical groupings of statements. Blank lines at the start or end of a function body are not allowed.
  3. Optionally before the first or after the last method in a class or object literal (neither encouraged nor discouraged).
  4. As required by other sections of this document (e.g. ??).

Multiple consecutive blank lines are permitted, but never required (nor encouraged).

4.6.2 Horizontal whitespace

Use of horizontal whitespace depends on location, and falls into three broad categories: leading (at the start of a line), trailing (at the end of a line), and internal. Leading whitespace (i.e., indentation) is addressed elsewhere. Trailing whitespace is forbidden.

Beyond where required by the language or other style rules, and apart from literals, comments, and JSDoc, a single internal ASCII space also appears in the following places only.

  1. Separating any reserved word (such as if, for, or catch) except for function and super, from an open parenthesis (() that follows it on that line.
  2. Separating any reserved word (such as else or catch) from a closing curly brace (}) that precedes it on that line.
  3. Before any open curly brace ({), with two exceptions:
    1. Before an object literal that is the first argument of a function or the first element in an array literal (e.g. foo({a: [{c: d}]})).
    2. In a template expansion, as it is forbidden by the language (e.g. valid: `ab${1 + 2}cd`, invalid: `xy$ {3}z`).
  4. On both sides of any binary or ternary operator.
  5. After a comma (,) or semicolon (;). Note that spaces are never allowed before these characters.
  6. After the colon (:) in an object literal.
  7. On both sides of the double slash (//) that begins an end-of-line comment. Here, multiple spaces are allowed, but not required.
  8. After an open-block comment character and on both sides of close characters (e.g. for short-form type declarations, casts, and parameter name comments: this.foo = /** @type {number} */ (bar); or function(/** string */ foo) {; or baz(/* buzz= */ true)).

4.6.3 Horizontal alignment: discouraged

Terminology Note: Horizontal alignment is the practice of adding a variable number of additional spaces in your code with the goal of making certain tokens appear directly below certain other tokens on previous lines.

This practice is permitted, but it is generally discouraged by Google Style. It is not even required to maintain horizontal alignment in places where it was already used.

Here is an example without alignment, followed by one with alignment. Both are allowed, but the latter is discouraged:

{
  tiny: 42, // this is great
  longer: 435, // this too
};

{
  tiny:   42,  // permitted, but future edits
  longer: 435, // may leave it unaligned
};

Tip: Alignment can aid readability, but it creates problems for future maintenance. Consider a future change that needs to touch just one line. This change may leave the formerly-pleasing formatting mangled, and that is allowed. More often it prompts the coder (perhaps you) to adjust whitespace on nearby lines as well, possibly triggering a cascading series of reformattings. That one-line change now has a blast radius. This can at worst result in pointless busywork, but at best it still corrupts version history information, slows down reviewers and exacerbates merge conflicts.

4.6.4 Function arguments

Prefer to put all function arguments on the same line as the function name. If doing so would exceed the 80-column limit, the arguments must be line-wrapped in a readable way. To save space, you may wrap as close to 80 as possible, or put each argument on its own line to enhance readability. Indentation should be four spaces. Aligning to the parenthesis is allowed, but discouraged. Below are the most common patterns for argument wrapping:

// Arguments start on a new line, indented four spaces. Preferred when the
// arguments don't fit on the same line with the function name (or the keyword
// "function") but fit entirely on the second line. Works with very long
// function names, survives renaming without reindenting, low on space.
doSomething(
    descriptiveArgumentOne, descriptiveArgumentTwo, descriptiveArgumentThree) {
  // …
}

// If the argument list is longer, wrap at 80. Uses less vertical space,
// but violates the rectangle rule and is thus not recommended.
doSomething(veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
    tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
  // …
}

// Four-space, one argument per line.  Works with long function names,
// survives renaming, and emphasizes each argument.
doSomething(
    veryDescriptiveArgumentNumberOne,
    veryDescriptiveArgumentTwo,
    tableModelEventHandlerProxy,
    artichokeDescriptorAdapterIterator) {
  // …
}

4.7 Grouping parentheses: recommended

Optional grouping parentheses are omitted only when the author and reviewer agree that there is no reasonable chance that the code will be misinterpreted without them, nor would they have made the code easier to read. It is not reasonable to assume that every reader has the entire operator precedence table memorized.

Do not use unnecessary parentheses around the entire expression following delete, typeof, void, return, throw, case, in, of, or yield.

Parentheses are required for type casts: /** @type {!Foo} */ (foo).

4.8 Comments

This section addresses implementation comments. JSDoc is addressed separately in ??.

4.8.1 Block comment style

Block comments are indented at the same level as the surrounding code. They may be in /* … */ or //-style. For multi-line /* … */ comments, subsequent lines must start with * aligned with the * on the previous line, to make comments obvious with no extra context.

/*
 * This is
 * okay.
 */

// And so
// is this.

/* This is fine, too. */

Comments are not enclosed in boxes drawn with asterisks or other characters.

Do not use JSDoc (/** … */) for implementation comments.

4.8.2 Parameter Name Comments

“Parameter name” comments should be used whenever the value and method name do not sufficiently convey the meaning, and refactoring the method to be clearer is infeasible . Their preferred format is before the value with =:

someFunction(obviousParam, /* shouldRender= */ true, /* name= */ 'hello');

For consistency with surrounding code you may put them after the value without =:

someFunction(obviousParam, true /* shouldRender */, 'hello' /* name */);

5 Language features

JavaScript includes many dubious (and even dangerous) features. This section delineates which features may or may not be used, and any additional constraints on their use.

Language features which are not discussed in this style guide may be used with no recommendations of their usage.

5.1 Local variable declarations

5.1.1 Use const and let

Declare all local variables with either const or let. Use const by default, unless a variable needs to be reassigned. The var keyword must not be used.

5.1.2 One variable per declaration

Every local variable declaration declares only one variable: declarations such as let a = 1, b = 2; are not used.

5.1.3 Declared when needed, initialized as soon as possible

Local variables are not habitually declared at the start of their containing block or block-like construct. Instead, local variables are declared close to the point they are first used (within reason), to minimize their scope, and initialized as soon as possible.

5.1.4 Declare types as needed

JSDoc type annotations may be added either on the line above the declaration, or else inline before the variable name if no other JSDoc is present.

Example:

const /** !Array<number> */ data = [];

/**
 * Some description.
 * @type {!Array<number>}
 */
const data = [];

Mixing inline and JSDoc styles is not allowed: the compiler will only process the first JsDoc and the inline annotations will be lost.

/** Some description. */
const /** !Array<number> */ data = [];

Tip: There are many cases where the compiler can infer a templatized type but not its parameters. This is particularly the case when the initializing literal or constructor call does not include any values of the template parameter type (e.g., empty arrays, objects, Maps, or Sets), or if the variable is modified in a closure. Local variable type annotations are particularly helpful in these cases since otherwise the compiler will infer the template parameter as unknown.

5.2 Array literals

5.2.1 Use trailing commas

Include a trailing comma whenever there is a line break between the final element and the closing bracket.

Example:

const values = [
  'first value',
  'second value',
];

5.2.2 Do not use the variadic Array constructor

The constructor is error-prone if arguments are added or removed. Use a literal instead.

Disallowed:

const a1 = new Array(x1, x2, x3);
const a2 = new Array(x1, x2);
const a3 = new Array(x1);
const a4 = new Array();

This works as expected except for the third case: if x1 is a whole number then a3 is an array of size x1 where all elements are undefined. If x1 is any other number, then an exception will be thrown, and if it is anything else then it will be a single-element array.

Instead, write

const a1 = [x1, x2, x3];
const a2 = [x1, x2];
const a3 = [x1];
const a4 = [];

Explicitly allocating an array of a given length using new Array(length) is allowed when appropriate.

5.2.3 Non-numeric properties

Do not define or use non-numeric properties on an array (other than length). Use a Map (or Object) instead.

5.2.4 Destructuring

Array literals may be used on the left-hand side of an assignment to perform destructuring (such as when unpacking multiple values from a single array or iterable). A final rest element may be included (with no space between the ... and the variable name). Elements should be omitted if they are unused.

const [a, b, c, ...rest] = generateResults();
let [, b,, d] = someArray;

Destructuring may also be used for function parameters (note that a parameter name is required but ignored). Always specify [] as the default value if a destructured array parameter is optional, and provide default values on the left hand side:

/** @param {!Array<number>=} param1 */
function optionalDestructuring([a = 4, b = 2] = []) { … };

Disallowed:

function badDestructuring([a, b] = [4, 2]) { … };

Tip: For (un)packing multiple values into a function’s parameter or return, prefer object destructuring to array destructuring when possible, as it allows naming the individual elements and specifying a different type for each.

5.2.5 Spread operator

Array literals may include the spread operator (...) to flatten elements out of one or more other iterables. The spread operator should be used instead of more awkward constructs with Array.prototype. There is no space after the ....

Example:

[...foo]   // preferred over Array.prototype.slice.call(foo)
[...foo, ...bar]   // preferred over foo.concat(bar)

5.3 Object literals

5.3.1 Use trailing commas

Include a trailing comma whenever there is a line break between the final property and the closing brace.

5.3.2 Do not use the Object constructor

While Object does not have the same problems as Array, it is still disallowed for consistency. Use an object literal ({} or {a: 0, b: 1, c: 2}) instead.

5.3.3 Do not mix quoted and unquoted keys

Object literals may represent either structs (with unquoted keys and/or symbols) or dicts (with quoted and/or computed keys). Do not mix these key types in a single object literal.

Disallowed:

{
  width: 42, // struct-style unquoted key
  'maxWidth': 43, // dict-style quoted key
}

This also extends to passing the property name to functions, like hasOwnProperty. In particular, doing so will break in compiled code because the compiler cannot rename/obfuscate the string literal.

Disallowed:

/** @type {{width: number, maxWidth: (number|undefined)}} */
const o = {width: 42};
if (o.hasOwnProperty('maxWidth')) {
  ...
}

This is best implemented as:

/** @type {{width: number, maxWidth: (number|undefined)}} */
const o = {width: 42};
if (o.maxWidth != null) {
  ...
}

5.3.4 Computed property names

Computed property names (e.g., {['key' + foo()]: 42}) are allowed, and are considered dict-style (quoted) keys (i.e., must not be mixed with non-quoted keys) unless the computed property is a symbol (e.g., [Symbol.iterator]). Enum values may also be used for computed keys, but should not be mixed with non-enum keys in the same literal.

5.3.5 Method shorthand

Methods can be defined on object literals using the method shorthand ({method() {… }}) in place of a colon immediately followed by a function or arrow function literal.

Example:

return {
  stuff: 'candy',
  method() {
    return this.stuff;  // Returns 'candy'
  },
};

Note that this in a method shorthand or function refers to the object literal itself whereas this in an arrow function refers to the scope outside the object literal.

Example:

class {
  getObjectLiteral() {
    this.stuff = 'fruit';
    return {
      stuff: 'candy',
      method: () => this.stuff,  // Returns 'fruit'
    };
  }
}

5.3.6 Shorthand properties

Shorthand properties are allowed on object literals.

Example:

const foo = 1;
const bar = 2;
const obj = {
  foo,
  bar,
  method() { return this.foo + this.bar; },
};
assertEquals(3, obj.method());

5.3.7 Destructuring

Object destructuring patterns may be used on the left-hand side of an assignment to perform destructuring and unpack multiple values from a single object.

Destructured objects may also be used as function parameters, but should be kept as simple as possible: a single level of unquoted shorthand properties. Deeper levels of nesting and computed properties may not be used in parameter destructuring. Specify any default values in the left-hand-side of the destructured parameter ({str = 'some default'} = {}, rather than {str} = {str: 'some default'}), and if a destructured object is itself optional, it must default to {}. The JSDoc for the destructured parameter may be given any name (the name is unused but is required by the compiler).

Example:

/**
 * @param {string} ordinary
 * @param {{num: (number|undefined), str: (string|undefined)}=} param1
 *     num: The number of times to do something.
 *     str: A string to do stuff to.
 */
function destructured(ordinary, {num, str = 'some default'} = {}) {}

Disallowed:

/** @param {{x: {num: (number|undefined), str: (string|undefined)}}} param1 */
function nestedTooDeeply({x: {num, str}}) {};
/** @param {{num: (number|undefined), str: (string|undefined)}=} param1 */
function nonShorthandProperty({num: a, str: b} = {}) {};
/** @param {{a: number, b: number}} param1 */
function computedKey({a, b, [a + b]: c}) {};
/** @param {{a: number, b: string}=} param1 */
function nontrivialDefault({a, b} = {a: 2, b: 4}) {};

Destructuring may also be used for goog.require statements, and in this case must not be wrapped: the entire statement occupies one line, regardless of how long it is (see ??).

5.3.8 Enums

Enumerations are defined by adding the @enum annotation to an object literal. Enums must be module-local or assigned directly on exports, not nested under a type or object.

Additional properties may not be added to an enum after it is defined. Enums must be constant. All enum values must be either a string literal or a number.

/**
 * Supported temperature scales.
 * @enum {string}
 */
const TemperatureScale = {
  CELSIUS: 'celsius',
  FAHRENHEIT: 'fahrenheit',
};

/**
 * An enum with two values.
 * @enum {number}
 */
const Value = {
  /** The value used shall have been the first. */
  FIRST_VALUE: 1,
  /** The second among two values. */
  SECOND_VALUE: 2,
};

For string enums, all values must be statically initialized and not computed using arithmetic operators, template literal substitution, function calls or even a variable reference.

const ABSOLUTE_ZERO = '-273°F';

/**
 * Not supported computed values in string enum.
 * @enum {string}
 */
const TemperatureInFahrenheit = {
  MIN_POSSIBLE: ABSOLUTE_ZERO,
  ZERO_FAHRENHEIT: 0 + '°F',
  ONE_FAHRENHEIT: `${Values.FIRST_VALUE}°F`,
  TWO_FAHRENHEIT: Values.SECOND_VALUE + '°F',
  SOME_FAHRENHEIT: getTemperatureInFahrenheit() + '°F',
};

Note: Although TypeScript supports a few more patterns for enum values (e.g A: 'a'+'b', etc), the restriction of only allowing string literals and numbers for enum values is to aid migration to TypeScript. For complex values consider using a const object without @enum.

5.4 Classes

5.4.1 Constructors

Constructors are optional. Subclass constructors must call super() before setting any fields or otherwise accessing this. Interfaces should declare non-method properties in the constructor.

5.4.2 Fields

Define all of a concrete object’s fields (i.e. all properties other than methods) in the constructor. Annotate fields that are never reassigned with @const (these need not be deeply immutable). Annotate non-public fields with the proper visibility annotation (@private, @protected, @package). @private fields' names may optionally end with an underscore. Fields must not be defined within a nested scope in the constructor nor on a concrete class's prototype.

Example:

class Foo {
  constructor() {
    /** @private @const {!Bar} */
    this.bar_ = computeBar();

    /** @protected @const {!Baz} */
    this.baz = computeBaz();
  }
}

Tip: Properties should never be added to or removed from an instance after the constructor is finished, since it significantly hinders VMs’ ability to optimize. If necessary, fields that are initialized later should be explicitly set to undefined in the constructor to prevent later shape changes. Adding @struct to an object will check that undeclared properties are not added/accessed. Classes have this added by default.

5.4.3 Computed properties

Computed properties may only be used in classes when the property is a symbol. Dict-style properties (that is, quoted or computed non-symbol keys, as defined in ??) are not allowed. A [Symbol.iterator] method should be defined for any classes that are logically iterable. Beyond this, Symbol should be used sparingly.

Tip: be careful of using any other built-in symbols (e.g., Symbol.isConcatSpreadable) as they are not polyfilled by the compiler and will therefore not work in older browsers.

5.4.4 Static methods

Where it does not interfere with readability, prefer module-local functions over private static methods.

Code should not rely on dynamic dispatch of static methods, because it interferes with Closure Compiler optimizations. Static methods should only be called on the base class itself. Static methods should not be called on variables containing a dynamic instance that may be either the constructor or a subclass constructor (and must be defined with @nocollapse if this is done), and must not be called directly on a subclass that doesn’t define the method itself. Do not access this in static methods.

Disallowed:

// Context for the examples below; by itself this code is allowed.
class Base {
  /** @nocollapse */ static foo() {}
}
class Sub extends Base {}

// discouraged: don't call static methods dynamically
function callFoo(cls) { cls.foo(); }

// Disallowed: don't call static methods on subclasses that don't define it themselves
Sub.foo();

// Disallowed: don't access this in static methods.
class Clazz {
  static foo() {
    return this.staticField;
  }
}
Class.staticField = 1;

5.4.5 Old-style class declarations

While ES6 classes are preferred, there are cases where ES6 classes may not be feasible. For example:

  1. If there exist or will exist subclasses, including frameworks that create subclasses, that cannot be immediately changed to use ES6 class syntax. If such a class were to use ES6 syntax, all downstream subclasses not using ES6 class syntax would need to be modified.

  2. Frameworks that require a known this value before calling the superclass constructor, since constructors with ES6 super classes do not have access to the instance this value until the call to super returns.

In all other ways the style guide still applies to this code: let, const, default parameters, rest, and arrow functions should all be used when appropriate.

goog.defineClass allows for a class-like definition similar to ES6 class syntax:

let C = goog.defineClass(S, {
  /**
   * @param {string} value
   */
  constructor(value) {
    S.call(this, 2);
    /** @const */
    this.prop = value;
  },

  /**
   * @param {string} param
   * @return {number}
   */
  method(param) {
    return 0;
  },
});

Alternatively, while goog.defineClass should be preferred for all new code, more traditional syntax is also allowed.

/**
  * @constructor @extends {S}
  * @param {string} value
  */
function C(value) {
  S.call(this, 2);
  /** @const */
  this.prop = value;
}
goog.inherits(C, S);

/**
 * @param {string} param
 * @return {number}
 */
C.prototype.method = function(param) {
  return 0;
};

Per-instance properties should be defined in the constructor after the call to the super class constructor, if there is a super class. Methods should be defined on the prototype of the constructor.

Defining constructor prototype hierarchies correctly is harder than it first appears! For that reason, it is best to use goog.inherits from the Closure Library .

5.4.6 Do not manipulate prototypes directly

The class keyword allows clearer and more readable class definitions than defining prototype properties. Ordinary implementation code has no business manipulating these objects, though they are still useful for defining classes as defined in ??. Mixins and modifying the prototypes of builtin objects are explicitly forbidden.

Exception: Framework code (such as Polymer, or Angular) may need to use prototypes, and should not resort to even-worse workarounds to avoid doing so.

5.4.7 Getters and Setters

Do not use JavaScript getter and setter properties. They are potentially surprising and difficult to reason about, and have limited support in the compiler. Provide ordinary methods instead.

Exception: there are situations where defining a getter or setter is unavoidable (e.g. data binding frameworks such as Angular and Polymer, or for compatibility with external APIs that cannot be adjusted). In these cases only, getters and setters may be used with caution, provided they are defined with the get and set shorthand method keywords or Object.defineProperties (not Object.defineProperty, which interferes with property renaming). Getters must not change observable state.

Disallowed:

class Foo {
  get next() { return this.nextId++; }
}

5.4.8 Overriding toString

The toString method may be overridden, but must always succeed and never have visible side effects.

Tip: Beware, in particular, of calling other methods from toString, since exceptional conditions could lead to infinite loops.

5.4.9 Interfaces

Interfaces may be declared with @interface or @record. Interfaces declared with @record can be explicitly (i.e. via @implements) or implicitly implemented by a class or object literal.

All methods on an interface must be non-static and method bodies must be empty blocks. Fields must be declared as uninitialized members in the class constructor.

Example:

/**
 * Something that can frobnicate.
 * @record
 */
class Frobnicator {
  constructor() {
    /** @type {number} The number of attempts before giving up. */
    this.attempts;
  }

  /**
   * Performs the frobnication according to the given strategy.
   * @param {!FrobnicationStrategy} strategy
   */
  frobnicate(strategy) {}
}

5.4.10 Abstract Classes

Use abstract classes when appropriate. Abstract classes and methods must be annotated with @abstract. Do not use goog.abstractMethod. See abstract classes and methods.

5.4.11 Do not create static container classes

Do not use container classes with only static methods or properties for the sake of namespacing.

// container.js
// Bad: Container is an exported class that has only static methods and fields.
class Container {
  /** @return {number} */
  static bar() {
    return 1;
  }
}

/** @const {number} */
Container.FOO = 1;

exports = {Container};

Instead, export individual constants and functions:

/** @return {number} */
exports.bar = () => {
  return 1;
}

/** @const {number} */
exports.FOO = 1;

5.4.12 Do not define nested namespaces

Do not define a nested type (e.g. class, typedef, enum, interface) on another module-local name.

// foo.js
goog.module('my.namespace');

class Foo {...}

Foo.Bar = class {...};

/** @enum {number} */
Foo.Baz = {...};

/** @typedef {{value: number}} */
Foo.Qux;

/** @interface */
Foo.Quuz = class {...}

exports.Foo = Foo;

These values should be top-level exports. Choose clear names for these values (e.g. FooConverter for a Converter that could have been nested on Foo). However, when the module name is redundant with part of the class name, consider omitting the redundancy: foo.Foo and foo.Converter rather than foo.Foo and foo.FooConverter. Importers can add the prefix when necessary for clarity (e.g. import {Converter as FooConverter} from './foo';) but cannot easily remove the redundancy when importing the entire module as a namespace.

// foo.js
goog.module('my.namespace');

class Foo {...}

class FooBar {...}

/** @enum {string} */
let FooBaz = {...};

/** @typedef {{value: number}} */
let FooQux;

/** @interface */
class FooQuuz {...};

export = {
  Foo,
  FooBar,
  FooBaz,
  FooQux,
  FooQuuz,
};

5.5 Functions

5.5.1 Top-level functions

Top-level functions may be defined directly on the exports object, or else declared locally and optionally exported. See ?? for more on exports.

Examples:

/** @param {string} str */
exports.processString = (str) => {
  // Process the string.
};
/** @param {string} str */
const processString = (str) => {
  // Process the string.
};

exports = {processString};

5.5.2 Nested functions and closures

Functions may contain nested function definitions. If it is useful to give the function a name, it should be assigned to a local const.

5.5.3 Arrow functions

Arrow functions provide a concise function syntax and simplify scoping this for nested functions. Prefer arrow functions over the function keyword for nested functions (but see ??).

Prefer arrow functions over other this scoping approaches such as f.bind(this), goog.bind(f, this), and const self = this. Arrow functions are particularly useful for calling into callbacks as they permit explicitly specifying which parameters to pass to the callback whereas binding will blindly pass along all parameters.

The left-hand side of the arrow contains zero or more parameters. Parentheses around the parameters are optional if there is only a single non-destructured parameter. When parentheses are used, inline parameter types may be specified (see ??).

Tip: Always using parentheses even for single-parameter arrow functions can avoid situations where adding parameters, but forgetting to add parentheses, may result in parseable code which no longer works as intended.

The right-hand side of the arrow contains the body of the function. By default the body is a block statement (zero or more statements surrounded by curly braces). The body may also be an implicitly returned single expression if either: the program logic requires returning a value, or the void operator precedes a single function or method call (using void ensures undefined is returned, prevents leaking values, and communicates intent). The single expression form is preferred if it improves readability (e.g., for short or simple expressions).

Examples:

/**
 * Arrow functions can be documented just like normal functions.
 * @param {number} numParam A number to add.
 * @param {string} strParam Another number to add that happens to be a string.
 * @return {number} The sum of the two parameters.
 */
const moduleLocalFunc = (numParam, strParam) => numParam + Number(strParam);

// Uses the single expression syntax with `void` because the program logic does
// not require returning a value.
getValue((result) => void alert(`Got ${result}`));

class CallbackExample {
  constructor() {
    /** @private {number} */
    this.cachedValue_ = 0;

    // For inline callbacks, you can use inline typing for parameters.
    // Uses a block statement because the value of the single expression should
    // not be returned and the expression is not a single function call.
    getNullableValue((/** ?number */ result) => {
      this.cachedValue_ = result == null ? 0 : result;
    });
  }
}

Disallowed:

/**
 * A function with no params and no returned value.
 * This single expression body usage is illegal because the program logic does
 * not require returning a value and we're missing the `void` operator.
 */
const moduleLocalFunc = () => anotherFunction();

5.5.4 Generators

Generators enable a number of useful abstractions and may be used as needed.

When defining generator functions, attach the * to the function keyword when present, and separate it with a space from the name of the function. When using delegating yields, attach the * to the yield keyword.

Example:

/** @return {!Iterator<number>} */
function* gen1() {
  yield 42;
}

/** @return {!Iterator<number>} */
const gen2 = function*() {
  yield* gen1();
}

class SomeClass {
  /** @return {!Iterator<number>} */
  * gen() {
    yield 42;
  }
}

5.5.5 Parameter and return types

Function parameters and return types should usually be documented with JSDoc annotations. See ?? for more information.

5.5.5.1 Default parameters

Optional parameters are permitted using the equals operator in the parameter list. Optional parameters must include spaces on both sides of the equals operator, be named exactly like required parameters (i.e., not prefixed with opt_), use the = suffix in their JSDoc type, come after required parameters, and not use initializers that produce observable side effects. All optional parameters for concrete functions must have default values, even if that value is undefined. In contrast to concrete functions, abstract and interface methods must omit default parameter values.

Example:

/**
 * @param {string} required This parameter is always needed.
 * @param {string=} optional This parameter can be omitted.
 * @param {!Node=} node Another optional parameter.
 */
function maybeDoSomething(required, optional = '', node = undefined) {}

/** @interface */
class MyInterface {
  /**
   * Interface and abstract methods must omit default parameter values.
   * @param {string=} optional
   */
  someMethod(optional) {}
}

Use default parameters sparingly. Prefer destructuring (as in ??) to create readable APIs when there are more than a small handful of optional parameters that do not have a natural order.

Note: Unlike Python's default parameters, it is okay to use initializers that return new mutable objects (such as {} or []) because the initializer is evaluated each time the default value is used, so a single object won't be shared across invocations.

Tip: While arbitrary expressions including function calls may be used as initializers, these should be kept as simple as possible. Avoid initializers that expose shared mutable state, as that can easily introduce unintended coupling between function calls.

5.5.5.2 Rest parameters

Use a rest parameter instead of accessing arguments. Rest parameters are typed with a ... prefix in their JSDoc. The rest parameter must be the last parameter in the list. There is no space between the ... and the parameter name. Do not name the rest parameter var_args. Never name a local variable or parameter arguments, which confusingly shadows the built-in name.

Example:

/**
 * @param {!Array<string>} array This is an ordinary parameter.
 * @param {...number} numbers The remainder of arguments are all numbers.
 */
function variadic(array, ...numbers) {}

5.5.6 Generics

Declare generic functions and methods when necessary with @template TYPE in the JSDoc above the function or method definition.

5.5.7 Spread operator

Function calls may use the spread operator (...). Prefer the spread operator to Function.prototype.apply when an array or iterable is unpacked into multiple parameters of a variadic function. There is no space after the ....

Example:

function myFunction(...elements) {}
myFunction(...array, ...iterable, ...generator());

5.6 String literals

5.6.1 Use single quotes

Ordinary string literals are delimited with single quotes ('), rather than double quotes (").

Tip: if a string contains a single quote character, consider using a template string to avoid having to escape the quote.

Ordinary string literals may not span multiple lines.

5.6.2 Template literals

Use template literals (delimited with `) over complex string concatenation, particularly if multiple string literals are involved. Template literals may span multiple lines.

If a template literal spans multiple lines, it does not need to follow the indentation of the enclosing block, though it may if the added whitespace does not matter.

Example:

function arithmetic(a, b) {
  return `Here is a table of arithmetic operations:
${a} + ${b} = ${a + b}
${a} - ${b} = ${a - b}
${a} * ${b} = ${a * b}
${a} / ${b} = ${a / b}`;
}

5.6.3 No line continuations

Do not use line continuations (that is, ending a line inside a string literal with a backslash) in either ordinary or template string literals. Even though ES5 allows this, it can lead to tricky errors if any trailing whitespace comes after the slash, and is less obvious to readers.

Disallowed:

const longString = 'This is a very long string that far exceeds the 80 \
    column limit. It unfortunately contains long stretches of spaces due \
    to how the continued lines are indented.';

Instead, write

const longString = 'This is a very long string that far exceeds the 80 ' +
    'column limit. It does not contain long stretches of spaces since ' +
    'the concatenated strings are cleaner.';

5.7 Number literals

Numbers may be specified in decimal, hex, octal, or binary. Use exactly 0x, 0o, and 0b prefixes, with lowercase letters, for hex, octal, and binary, respectively. Never include a leading zero unless it is immediately followed by x, o, or b.

5.8 Control structures

5.8.1 For loops

With ES6, the language now has three different kinds of for loops. All may be used, though for-of loops should be preferred when possible.

for-in loops may only be used on dict-style objects (see ??), and should not be used to iterate over an array. Object.prototype.hasOwnProperty should be used in for-in loops to exclude unwanted prototype properties. Prefer for-of and Object.keys over for-in when possible.

5.8.2 Exceptions

Exceptions are an important part of the language and should be used whenever exceptional cases occur. Always throw Errors or subclasses of Error: never throw string literals or other objects. Always use new when constructing an Error.

This treatment extends to Promise rejection values as Promise.reject(obj) is equivalent to throw obj; in async functions.

Custom exceptions provide a great way to convey additional error information from functions. They should be defined and used wherever the native Error type is insufficient.

Prefer throwing exceptions over ad-hoc error-handling approaches (such as passing an error container reference type, or returning an object with an error property).

5.8.2.1 Empty catch blocks

It is very rarely correct to do nothing in response to a caught exception. When it truly is appropriate to take no action whatsoever in a catch block, the reason this is justified is explained in a comment.

try {
  return handleNumericResponse(response);
} catch (ok) {
  // it's not numeric; that's fine, just continue
}
return handleTextResponse(response);

Disallowed:

  try {
    shouldFail();
    fail('expected an error');
  } catch (expected) {
  }

Tip: Unlike in some other languages, patterns like the above simply don’t work since this will catch the error thrown by fail. Use assertThrows() instead.

5.8.3 Switch statements

Terminology Note: Inside the braces of a switch block are one or more statement groups. Each statement group consists of one or more switch labels (either case FOO: or default:), followed by one or more statements.

5.8.3.1 Fall-through: commented

Within a switch block, each statement group either terminates abruptly (with a break, return or thrown exception), or is marked with a comment to indicate that execution will or might continue into the next statement group. Any comment that communicates the idea of fall-through is sufficient (typically // fall through). This special comment is not required in the last statement group of the switch block.

Example:

switch (input) {
  case 1:
  case 2:
    prepareOneOrTwo();
  // fall through
  case 3:
    handleOneTwoOrThree();
    break;
  default:
    handleLargeNumber(input);
}
5.8.3.2 The default case is present

Each switch statement includes a default statement group, even if it contains no code. The default statement group must be last.

5.9 this

Only use this in class constructors and methods, in arrow functions defined within class constructors and methods, or in functions that have an explicit @this declared in the immediately-enclosing function’s JSDoc.

Never use this to refer to the global object, the context of an eval, the target of an event, or unnecessarily call()ed or apply()ed functions.

5.10 Equality Checks

Use identity operators (===/!==) except in the cases documented below.

5.10.1 Exceptions Where Coercion is Desirable

Catching both null and undefined values:

if (someObjectOrPrimitive == null) {
  // Checking for null catches both null and undefined for objects and
  // primitives, but does not catch other falsy values like 0 or the empty
  // string.
}

5.11 Disallowed features

5.11.1 with

Do not use the with keyword. It makes your code harder to understand and has been banned in strict mode since ES5.

5.11.2 Dynamic code evaluation

Do not use eval or the Function(...string) constructor (except for code loaders). These features are potentially dangerous and simply do not work in CSP environments.

5.11.3 Automatic semicolon insertion

Always terminate statements with semicolons (except function and class declarations, as noted above).

5.11.4 Non-standard features

Do not use non-standard features. This includes old features that have been removed (e.g., WeakMap.clear), new features that are not yet standardized (e.g., the current TC39 working draft, proposals at any stage, or proposed but not-yet-complete web standards), or proprietary features that are only implemented in some browsers. Use only features defined in the current ECMA-262 or WHATWG standards. (Note that projects writing against specific APIs, such as Chrome extensions or Node.js, can obviously use those APIs). Non-standard language “extensions” (such as those provided by some external transpilers) are forbidden.

5.11.5 Wrapper objects for primitive types

Never use new on the primitive object wrappers (Boolean, Number, String, Symbol), nor include them in type annotations.

Disallowed:

const /** Boolean */ x = new Boolean(false);
if (x) alert(typeof x);  // alerts 'object' - WAT?

The wrappers may be called as functions for coercing (which is preferred over using + or concatenating the empty string) or creating symbols.

Example:

const /** boolean */ x = Boolean(0);
if (!x) alert(typeof x);  // alerts 'boolean', as expected

5.11.6 Modifying builtin objects

Never modify builtin types, either by adding methods to their constructors or to their prototypes. Avoid depending on libraries that do this. Note that the JSCompiler’s runtime library will provide standards-compliant polyfills where possible; nothing else may modify builtin objects.

Do not add symbols to the global object unless absolutely necessary (e.g. required by a third-party API).

5.11.7 Omitting () when invoking a constructor

Never invoke a constructor in a new statement without using parentheses ().

Disallowed:

new Foo;

Use instead:

new Foo();

Omitting parentheses can lead to subtle mistakes. These two lines are not equivalent:

new Foo().Bar();
new Foo.Bar();

6 Naming

6.1 Rules common to all identifiers

Identifiers use only ASCII letters and digits, and, in a small number of cases noted below, underscores and very rarely (when required by frameworks like Angular) dollar signs.

Give as descriptive a name as possible, within reason. Do not worry about saving horizontal space as it is far more important to make your code immediately understandable by a new reader. Do not use abbreviations that are ambiguous or unfamiliar to readers outside your project, and do not abbreviate by deleting letters within a word.

errorCount          // No abbreviation.
dnsConnectionIndex  // Most people know what "DNS" stands for.
referrerUrl         // Ditto for "URL".
customerId          // "Id" is both ubiquitous and unlikely to be misunderstood.

Disallowed:

n                   // Meaningless.
nErr                // Ambiguous abbreviation.
nCompConns          // Ambiguous abbreviation.
wgcConnections      // Only your group knows what this stands for.
pcReader            // Lots of things can be abbreviated "pc".
cstmrId             // Deletes internal letters.
kSecondsPerDay      // Do not use Hungarian notation.

Exception: Variables that are in scope for 10 lines or fewer, including arguments that are not part of an exported API, may use short (e.g. single letter) variable names.

6.2 Rules by identifier type

6.2.1 Package names

Package names are all lowerCamelCase. For example, my.exampleCode.deepSpace, but not my.examplecode.deepspace or my.example_code.deep_space.

Exception: The package name may conform to TypeScript's path-based pattern. This is typically all lower case with underscores where present in filenames.

6.2.2 Class names

Class, interface, record, and typedef names are written in UpperCamelCase. Unexported classes are simply locals: they are not marked @private.

Type names are typically nouns or noun phrases. For example, Request, ImmutableView, or VisibilityMode. Additionally, interface names may sometimes be adjectives or adjective phrases instead (for example, Readable).

6.2.3 Method names

Method names are written in lowerCamelCase. Names for @private methods may optionally end with a trailing underscore.

Method names are typically verbs or verb phrases. For example, sendMessage or stop_. Getter and setter methods for properties are never required, but if they are used they should be named getFoo (or optionally isFoo or hasFoo for booleans), or setFoo(value) for setters.

Underscores may also appear in JsUnit test method names to separate logical components of the name. One typical pattern is test<MethodUnderTest>_<state>_<expectedOutcome>, for example testPop_emptyStack_throws. There is no One Correct Way to name test methods.

6.2.4 Enum names

Enum names are written in UpperCamelCase, similar to classes, and should generally be singular nouns. Individual items within the enum are named in CONSTANT_CASE.

6.2.5 Constant names

Constant names use CONSTANT_CASE: all uppercase letters, with words separated by underscores. There is no reason for a constant to be named with a trailing underscore, since private static properties can be replaced by (implicitly private) module locals.

6.2.5.1 Definition of “constant”

Every constant is a @const static property or a module-local const declaration, but not all @const static properties and module-local consts are constants. Before choosing constant case, consider whether the field really feels like a deeply immutable constant. For example, if any of that instance's observable state can change, it is almost certainly not a constant. Merely intending to never mutate the object is generally not enough.

Examples:

// Constants
const NUMBER = 5;
/** @const */ exports.NAMES = goog.debug.freeze(['Ed', 'Ann']);
/** @enum */ exports.SomeEnum = { ENUM_CONSTANT: 'value' };

// Not constants
let letVariable = 'non-const';

class MyClass {
  constructor() { /** @const {string} */ this.nonStatic = 'non-static'; }
};
/** @type {string} */
MyClass.staticButMutable = 'not @const, can be reassigned';

const /** Set<string> */ mutableCollection = new Set();

const /** MyImmutableContainer<SomeMutableType> */ stillMutable =
    new MyImmutableContainer(mutableInner);

const {Foo} = goog.require('my.foo');  // mirrors imported name

const logger = log.getLogger('loggers.are.not.immutable');

Constants’ names are typically nouns or noun phrases.

6.2.5.2 Local aliases

Local aliases should be used whenever they improve readability over fully-qualified names. Follow the same rules as goog.requires (??), maintaining the last part of the aliased name. Aliases may also be used within functions. Aliases must be const.

Examples:

const staticHelper = importedNamespace.staticHelper;
const CONSTANT_NAME = ImportedClass.CONSTANT_NAME;
const {assert, assertInstanceof} = asserts;

6.2.6 Non-constant field names

Non-constant field names (static or otherwise) are written in lowerCamelCase, with an optional trailing underscore for private fields.

These names are typically nouns or noun phrases. For example, computedValues or index_.

6.2.7 Parameter names

Parameter names are written in lowerCamelCase. Note that this applies even if the parameter expects a constructor.

One-character parameter names should not be used in public methods.

Exception: When required by a third-party framework, parameter names may begin with a $. This exception does not apply to any other identifiers (e.g. local variables or properties).

6.2.8 Local variable names

Local variable names are written in lowerCamelCase, except for module-local (top-level) constants, as described above. Constants in function scopes are still named in lowerCamelCase. Note that lowerCamelCase is used even if the variable holds a constructor.

6.2.9 Template parameter names

Template parameter names should be concise, single-word or single-letter identifiers, and must be all-caps, such as TYPE or THIS.

6.2.10 Module-local names

Module-local names that are not exported are implicitly private. They are not marked @private. This applies to classes, functions, variables, constants, enums, and other module-local identifiers.

6.3 Camel case: defined

Sometimes there is more than one reasonable way to convert an English phrase into camel case, such as when acronyms or unusual constructs like IPv6 or iOS are present. To improve predictability, Google Style specifies the following (nearly) deterministic scheme.

Beginning with the prose form of the name:

  1. Convert the phrase to plain ASCII and remove any apostrophes. For example, Müller's algorithm might become Muellers algorithm.
  2. Divide this result into words, splitting on spaces and any remaining punctuation (typically hyphens).
    1. Recommended: if any word already has a conventional camel case appearance in common usage, split this into its constituent parts (e.g., AdWords becomes ad words). Note that a word such as iOS is not really in camel case per se; it defies any convention, so this recommendation does not apply.
  3. Now lowercase everything (including acronyms), then uppercase only the first character of:
    1. … each word, to yield UpperCamelCase, or
    2. … each word except the first, to yield lowerCamelCase
  4. Finally, join all the words into a single identifier.

Note that the casing of the original words is almost entirely disregarded.

Examples of lowerCamelCase:

Prose form Correct Incorrect
XML HTTP request xmlHttpRequest XMLHTTPRequest
new customer ID newCustomerId newCustomerID
inner stopwatch innerStopwatch innerStopWatch
supports IPv6 on iOS? supportsIpv6OnIos supportsIPv6OnIOS
YouTube importer youTubeImporter youtubeImporter*

*Acceptable, but not recommended.

For examples of UpperCamelCase, uppercase the first letter of each correct lowerCamelCase example.

Note: Some words are ambiguously hyphenated in the English language: for example nonempty and non-empty are both correct, so the method names checkNonempty and checkNonEmpty are likewise both correct.

7 JSDoc

JSDoc is used on all classes, fields, and methods.

7.1 General form

The basic formatting of JSDoc blocks is as seen in this example:

/**
 * Multiple lines of JSDoc text are written here,
 * wrapped normally.
 * @param {number} arg A number to do something to.
 */
function doSomething(arg) { … }

or in this single-line example:

/** @const @private {!Foo} A short bit of JSDoc. */
this.foo_ = foo;

If a single-line comment overflows into multiple lines, it must use the multi-line style with /** and */ on their own lines.

Many tools extract metadata from JSDoc comments to perform code validation and optimization. As such, these comments must be well-formed.

7.2 Markdown

JSDoc is written in Markdown, though it may include HTML when necessary.

Note that tools that automatically extract JSDoc (e.g. JsDossier) will often ignore plain text formatting, so if you did this:

/**
 * Computes weight based on three factors:
 *   items sent
 *   items received
 *   last timestamp
 */

it would come out like this:

Computes weight based on three factors: items sent items received last timestamp

Instead, write a Markdown list:

/**
 * Computes weight based on three factors:
 *
 *  - items sent
 *  - items received
 *  - last timestamp
 */

7.3 JSDoc tags

Google style allows a subset of JSDoc tags. See ?? for the complete list. Most tags must occupy their own line, with the tag at the beginning of the line.

Disallowed:

/**
 * The "param" tag must occupy its own line and may not be combined.
 * @param {number} left @param {number} right
 */
function add(left, right) { ... }

Simple tags that do not require any additional data (such as @private, @const, @final, @export) may be combined onto the same line, along with an optional type when appropriate.

/**
 * Place more complex annotations (like "implements" and "template")
 * on their own lines. Multiple simple tags (like "export" and "final")
 * may be combined in one line.
 * @export @final
 * @implements {Iterable<TYPE>}
 * @template TYPE
 */
class MyClass {
  /**
   * @param {!ObjType} obj Some object.
   * @param {number=} num An optional number.
   */
  constructor(obj, num = 42) {
    /** @private @const {!Array<!ObjType|number>} */
    this.data_ = [obj, num];
  }
}

There is no hard rule for when to combine tags, or in which order, but be consistent.

For general information about annotating types in JavaScript see Annotating JavaScript for the Closure Compiler and Types in the Closure Type System.

7.4 Line wrapping

Line-wrapped block tags are indented four spaces. Wrapped description text may be lined up with the description on previous lines, but this horizontal alignment is discouraged.

/**
 * Illustrates line wrapping for long param/return descriptions.
 * @param {string} foo This is a param with a description too long to fit in
 *     one line.
 * @return {number} This returns something that has a description too long to
 *     fit in one line.
 */
exports.method = function(foo) {
  return 5;
};

Do not indent when wrapping a @desc or @fileoverview description.

7.5 Top/file-level comments

A file may have a top-level file overview. A copyright notice, author information, and default visibility level are optional. File overviews are generally recommended whenever a file consists of more than a single class definition. The top level comment is designed to orient readers unfamiliar with the code to what is in this file. If present, it may provide a description of the file's contents and any dependencies or compatibility information. Wrapped lines are not indented.

Example:

/**
 * @fileoverview Description of file, its uses and information
 * about its dependencies.
 * @package
 */

7.6 Class comments

Classes, interfaces and records must be documented with a description and any template parameters, implemented interfaces, visibility, or other appropriate tags. The class description should provide the reader with enough information to know how and when to use the class, as well as any additional considerations necessary to correctly use the class. Textual descriptions may be omitted on the constructor. When defining a class @constructor and @extends annotations are not used with the class keyword unless it extends a generic class. When defining an @interface or a @record, the @extends annotation is used when defining a subclass and the extends keyword is never used.

/**
 * A fancier event target that does cool things.
 * @implements {Iterable<string>}
 */
class MyFancyTarget extends EventTarget {
  /**
   * @param {string} arg1 An argument that makes this more interesting.
   * @param {!Array<number>} arg2 List of numbers to be processed.
   */
  constructor(arg1, arg2) {
    // ...
  }
};

/**
 * Records are also helpful.
 * @extends {Iterator<TYPE>}
 * @record
 * @template TYPE
 */
class Listable {
  /** @return {TYPE} The next item in line to be returned. */
  next() {}
}

7.7 Enum and typedef comments

All enums and typedefs must be documented with appropriate JSDoc tags (@typedef or @enum) on the preceding line. Public enums and typedefs must also have a description. Individual enum items may be documented with a JSDoc comment on the preceding line.

/**
 * A useful type union, which is reused often.
 * @typedef {!FruitType|!FruitTypeEnum}
 */
let CoolUnionType;
 
/**
 * Types of fruits.
 * @enum {string}
 */
const FruitTypeEnum = {
  /** This kind is very sour. */
  SOUR: 'sour',
  /** The less-sour kind. */
  SWEET: 'sweet',
};

Typedefs are useful for defining short record types, or aliases for unions, complex functions, or generic types. Typedefs should be avoided for record types with many fields, since they do not allow documenting individual fields, nor using templates or recursive references. For large record types, prefer @record.

7.8 Method and function comments

In methods and named functions, parameter and return types must be documented, even in the case of same-signature @overrides. The this type should be documented when necessary. Return type may be omitted if the function has no non-empty return statements.

Method, parameter, and return descriptions (but not types) may be omitted if they are obvious from the rest of the method’s JSDoc or from its signature.

Method descriptions begin with a verb phrase that describes what the method does. This phrase is not an imperative sentence, but instead is written in the third person, as if there is an implied This method ... before it.

If a method overrides a superclass method, it must include an @override annotation. For overridden methods, all @param and @return annotations must be specified explicitly even if no type from the superclass method is refined. This is to align with TypeScript.

/** A class that does something. */
class SomeClass extends SomeBaseClass {
  /**
   * Operates on an instance of MyClass and returns something.
   * @param {!MyClass} obj An object that for some reason needs detailed
   *     explanation that spans multiple lines.
   * @param {!OtherClass} obviousOtherClass
   * @return {boolean} Whether something occurred.
   */
  someMethod(obj, obviousOtherClass) { ... }

  /**
   * @param {string} param
   * @return {string}
   * @override
   */
  overriddenMethod(param) { ... }
}

/**
 * Demonstrates how top-level functions follow the same rules.  This one
 * makes an array.
 * @param {TYPE} arg
 * @return {!Array<TYPE>}
 * @template TYPE
 */
function makeArray(arg) { ... }

If you only need to document the param and return types of a function, you may optionally use inline JSDocs in the function's signature. These inline JSDocs specify the return and param types without tags.

function /** string */ foo(/** number */ arg) {...}

If you need descriptions or tags, use a single JSDoc comment above the method. For example, methods which return values need a @return tag.

class MyClass {
  /**
   * @param {number} arg
   * @return {string}
   */
  bar(arg) {...}
}
// Illegal inline JSDocs.

class MyClass {
  /** @return {string} */ foo() {...}
}

/** No function description allowed inline here. */ function bar() {...}

function /** Function description is also illegal here. */ baz() {...}

In anonymous functions annotations are generally optional. If the automatic type inference is insufficient or explicit annotation improves readability, then annotate param and return types like this:

promise.then(
    /** @return {string} */
    (/** !Array<string> */ items) => {
      doSomethingWith(items);
      return items[0];
    });

For function type expressions, see ??.

7.9 Property comments

Property types must be documented. The description may be omitted for private properties, if name and type provide enough documentation for understanding the code.

Publicly exported constants are commented the same way as properties.

/** My class. */
class MyClass {
  /** @param {string=} someString */
  constructor(someString = 'default string') {
    /** @private @const {string} */
    this.someString_ = someString;

    /** @private @const {!OtherType} */
    this.someOtherThing_ = functionThatReturnsAThing();

    /**
     * Maximum number of things per pane.
     * @type {number}
     */
    this.someProperty = 4;
  }
}

/**
 * The number of times we'll try before giving up.
 * @const {number}
 */
MyClass.RETRY_COUNT = 33;

7.10 Type annotations

Type annotations are found on @param, @return, @this, and @type tags, and optionally on @const, @export, and any visibility tags. Type annotations attached to JSDoc tags must always be enclosed in braces.

7.10.1 Nullability

The type system defines modifiers ! and ? for non-null and nullable, respectively. These modifiers must precede the type.

Nullability modifiers have different requirements for different types, which fall into two broad categories:

  1. Type annotations for primitives (string, number, boolean, symbol, undefined, null) and literals ({function(...): ...} and {{foo: string...}}) are always non-nullable by default. Use the ? modifier to make it nullable, but omit the redundant !.
  2. Reference types (generally, anything in UpperCamelCase, including some.namespace.ReferenceType) refer to a class, enum, record, or typedef defined elsewhere. Since these types may or may not be nullable, it is impossible to tell from the name alone whether it is nullable or not. Always use explicit ? and ! modifiers for these types to prevent ambiguity at use sites.

Bad:

const /** MyObject */ myObject = null; // Non-primitive types must be annotated.
const /** !number */ someNum = 5; // Primitives are non-nullable by default.
const /** number? */ someNullableNum = null; // ? should precede the type.
const /** !{foo: string, bar: number} */ record = ...; // Already non-nullable.
const /** MyTypeDef */ def = ...; // Not sure if MyTypeDef is nullable.

// Not sure if object (nullable), enum (non-nullable, unless otherwise
// specified), or typedef (depends on definition).
const /** SomeCamelCaseName */ n = ...;

Good:

const /** ?MyObject */ myObject = null;
const /** number */ someNum = 5;
const /** ?number */ someNullableNum = null;
const /** {foo: string, bar: number} */ record = ...;
const /** !MyTypeDef */ def = ...;
const /** ?SomeCamelCaseName */ n = ...;

7.10.2 Type Casts

In cases where the compiler doesn't accurately infer the type of an expression, and the assertion functions in goog.asserts cannot remedy it, it is possible to tighten the type by adding a type annotation comment and enclosing the expression in parentheses. Note that the parentheses are required.

/** @type {number} */ (x)

7.10.3 Template Parameter Types

Always specify template parameters. This way compiler can do a better job and it makes it easier for readers to understand what code does.

Bad:

const /** !Object */ users = {};
const /** !Array */ books = [];
const /** !Promise */ response = ...;

Good:

const /** !Object<string, !User> */ users = {};
const /** !Array<string> */ books = [];
const /** !Promise<!Response> */ response = ...;

const /** !Promise<undefined> */ thisPromiseReturnsNothingButParameterIsStillUseful = ...;
const /** !Object<string, *> */ mapOfEverything = {};

Cases when template parameters should not be used:

  • Object is used for type hierarchy and not as map-like structure.

7.10.4 Function type expressions

Terminology Note: function type expression refers to a type annotation for function types with the keyword function in the annotation (see examples below).

Where the function definition is given, do not use a function type expression. Specify parameter and return types with @param and @return, or with inline annotations (see ??). This includes anonymous functions and functions defined and assigned to a const (where the function jsdoc appears above the whole assignment expression).

Function type expressions are needed, for example, inside @typedef, @param or @return. Use it also for variables or properties of function type, if they are not immediately initialized with the function definition.

  /** @private {function(string): string} */
  this.idGenerator_ = googFunctions.identity;

When using a function type expression, always specify the return type explicitly. Otherwise the default return type is unknown (?), which leads to strange and unexpected behavior, and is rarely what is actually desired.

Bad - type error, but no warning given:

/** @param {function()} generateNumber */
function foo(generateNumber) {
  const /** number */ x = generateNumber();  // No compile-time type error here.
}

foo(() => 'clearly not a number');

Good:

/**
 * @param {function(): *} inputFunction1 Can return any type.
 * @param {function(): undefined} inputFunction2 Definitely doesn't return
 *      anything.
 * NOTE: the return type of `foo` itself is safely implied to be {undefined}.
 */
function foo(inputFunction1, inputFunction2) {...}

7.10.5 Whitespace

Within a type annotation, a single space or line break is required after each comma or colon. Additional line breaks may be inserted to improve readability or avoid exceeding the column limit. These breaks should be chosen and indented following the applicable guidelines (e.g. ?? and ??). No other whitespace is allowed in type annotations.

Good:

/** @type {function(string): number} */

/** @type {{foo: number, bar: number}} */

/** @type {number|string} */

/** @type {!Object<string, string>} */

/** @type {function(this: Object<string, string>, number): string} */

/**
 * @type {function(
 *     !SuperDuperReallyReallyLongTypedefThatForcesTheLineBreak,
 *     !OtherVeryLongTypedef): string}
 */

/**
 * @type {!SuperDuperReallyReallyLongTypedefThatForcesTheLineBreak|
 *     !OtherVeryLongTypedef}
 */

Bad:

// Only put a space after the colon
/** @type {function(string) : number} */

// Put spaces after colons and commas
/** @type {{foo:number,bar:number}} */

// No space in union types
/** @type {number | string} */

7.11 Visibility annotations

Visibility annotations (@private, @package, @protected) may be specified in a @fileoverview block, or on any exported symbol or property. Do not specify visibility for local variables, whether within a function or at the top level of a module. @private names may optionally end with an underscore.

8 Policies

8.1 Issues unspecified by Google Style: Be Consistent!

For any style question that isn't settled definitively by this specification, prefer to do what the other code in the same file is already doing. If that doesn't resolve the question, consider emulating the other files in the same package.

8.2 Compiler warnings

8.2.1 Use a standard warning set

As far as possible projects should use --warning_level=VERBOSE.

8.2.2 How to handle a warning

Before doing anything, make sure you understand exactly what the warning is telling you. If you're not positive why a warning is appearing, ask for help .

Once you understand the warning, attempt the following solutions in order:

  1. First, fix it or work around it. Make a strong attempt to actually address the warning, or find another way to accomplish the task that avoids the situation entirely.
  2. Otherwise, determine if it's a false alarm. If you are convinced that the warning is invalid and that the code is actually safe and correct, add a comment to convince the reader of this fact and apply the @suppress annotation.
  3. Otherwise, leave a TODO comment. This is a last resort. If you do this, do not suppress the warning. The warning should be visible until it can be taken care of properly.

8.2.3 Suppress a warning at the narrowest reasonable scope

Warnings are suppressed at the narrowest reasonable scope, usually that of a single local variable or very small method. Often a variable or method is extracted for that reason alone.

Example

/** @suppress {uselessCode} Unrecognized 'use asm' declaration */
function fn() {
  'use asm';
  return 0;
}

Even a large number of suppressions in a class is still better than blinding the entire class to this type of warning.

8.3 Deprecation

Mark deprecated methods, classes or interfaces with @deprecated annotations. A deprecation comment must include simple, clear directions for people to fix their call sites.

8.4 Code not in Google Style

You will occasionally encounter files in your codebase that are not in proper Google Style. These may have come from an acquisition, or may have been written before Google Style took a position on some issue, or may be in non-Google Style for any other reason.

8.4.1 Reformatting existing code

When updating the style of existing code, follow these guidelines.

  1. It is not required to change all existing code to meet current style guidelines. Reformatting existing code is a trade-off between code churn and consistency. Style rules evolve over time and these kinds of tweaks to maintain compliance would create unnecessary churn. However, if significant changes are being made to a file it is expected that the file will be in Google Style.
  2. Be careful not to allow opportunistic style fixes to muddle the focus of a CL. If you find yourself making a lot of style changes that aren’t critical to the central focus of a CL, promote those changes to a separate CL.

8.4.2 Newly added code: use Google Style

Brand new files use Google Style, regardless of the style choices of other files in the same package.

When adding new code to a file that is not in Google Style, reformatting the existing code first is recommended, subject to the advice in ??.

If this reformatting is not done, then new code should be as consistent as possible with existing code in the same file, but must not violate the style guide.

8.5 Local style rules

Teams and projects may adopt additional style rules beyond those in this document, but must accept that cleanup changes may not abide by these additional rules, and must not block such cleanup changes due to violating any additional rules. Beware of excessive rules which serve no purpose. The style guide does not seek to define style in every possible scenario and neither should you.

8.6 Generated code: mostly exempt

Source code generated by the build process is not required to be in Google Style. However, any generated identifiers that will be referenced from hand-written source code must follow the naming requirements. As a special exception, such identifiers are allowed to contain underscores, which may help to avoid conflicts with hand-written identifiers.

9 Appendices

9.1 JSDoc tag reference

JSDoc serves multiple purposes in JavaScript. In addition to being used to generate documentation it is also used to control tooling. The best known are the Closure Compiler type annotations.

9.1.1 Type annotations and other Closure Compiler annotations

Documentation for JSDoc used by the Closure Compiler is described in Annotating JavaScript for the Closure Compiler and Types in the Closure Type System.

9.1.2 Documentation annotations

In addition to the JSDoc described in Annotating JavaScript for the Closure Compiler the following tags are common and well supported by various documentation generation tools (such as JsDossier) for purely documentation purposes.

9.1.2.1 @author or @owner - Not recommended.

Not recommended.

Syntax: @author username@google.com (First Last)

/**
 * @fileoverview Utilities for handling textareas.
 * @author kuth@google.com (Uthur Pendragon)
 */

Documents the author of a file or the owner of a test, generally only used in the @fileoverview comment. The @owner tag is used by the unit test dashboard to determine who owns the test results.

9.1.2.2 @bug

Syntax: @bug bugnumber

/** @bug 1234567 */
function testSomething() {
  // …
}

/**
 * @bug 1234568
 * @bug 1234569
 */
function testTwoBugs() {
  // …
}

Indicates what bugs the given test function regression tests.

Multiple bugs should each have their own @bug line, to make searching for regression tests as easy as possible.

9.1.2.3 @code - Deprecated. Do not use.

Deprecated. Do not use. Use Markdown backticks instead.

Syntax: {@code ...}

Historically, `BatchItem` was written as {@code BatchItem}.

/** Processes pending `BatchItem` instances. */
function processBatchItems() {}

Indicates that a term in a JSDoc description is code so it may be correctly formatted in generated documentation.

9.1.2.4 @desc

Syntax: @desc Message description

/** @desc Notifying a user that their account has been created. */
exports.MSG_ACCOUNT_CREATED = goog.getMsg(
    'Your account has been successfully created.');
9.1.2.5 @link

Syntax: {@link ...}

This tag is used to generate cross-reference links within generated documentation.

/** Processes pending {@link BatchItem} instances. */
function processBatchItems() {}

Historical note: @link tags have also been used to create external links in generated documentation. For external links, always use Markdown's link syntax instead:

/**
 * This class implements a useful subset of the
 * [native Event interface](https://dom.spec.whatwg.org/#event).
 */
class ApplicationEvent {}
9.1.2.6 @see

Syntax: @see Link

/**
 * Adds a single item, recklessly.
 * @see #addSafely
 * @see goog.Collect
 * @see goog.RecklessAdder#add
 */

Reference a lookup to another class function or method.

9.1.2.7 @supported

Syntax: @supported Description

/**
 * @fileoverview Event Manager
 * Provides an abstracted interface to the browsers' event systems.
 * @supported IE10+, Chrome, Safari
 */

Used in a fileoverview to indicate what browsers are supported by the file.

You may also see other types of JSDoc annotations in third-party code. These annotations appear in the JSDoc Toolkit Tag Reference but are not considered part of valid Google style.

9.1.3 Framework specific annotations

The following annotations are specific to a particular framework.

9.1.3.1 @ngInject for Angular 1
9.1.3.2 @polymerBehavior for Polymer

https://github.com/google/closure-compiler/wiki/Polymer-Pass

9.1.4 Notes about standard Closure Compiler annotations

The following tags used to be standard but are now deprecated.

9.1.4.1 @expose - Deprecated. Do not use.

Deprecated. Do not use. Use @export and/or @nocollapse instead.

9.1.4.2 @inheritDoc - Deprecated. Do not use.

Deprecated. Do not use. Use @override instead.

9.2 Commonly misunderstood style rules

Here is a collection of lesser-known or commonly misunderstood facts about Google Style for JavaScript. (The following are true statements; this is not a list of myths.)

  • Neither a copyright statement nor @author credit is required in a source file. (Neither is explicitly recommended, either.)
  • There is no hard and fast rule governing how to order the members of a class (??).
  • Empty blocks can usually be represented concisely as {}, as detailed in (??).
  • The prime directive of line-wrapping is: prefer to break at a higher syntactic level (??).
  • Non-ASCII characters are allowed in string literals, comments and JSDoc, and in fact are recommended when they make the code easier to read than the equivalent Unicode escape would (??).

The following tools exist to support various aspects of Google Style.

9.3.1 Closure Compiler

This program performs type checking and other checks, optimizations and other transformations (such as lowering code to ECMAScript 5).

9.3.2 clang-format

This program reformats JavaScript source code into Google Style, and also follows a number of non-required but frequently readability-enhancing formatting practices. The output produced by clang-format is compliant with the style guide.

clang-format is not required. Authors are allowed to change its output, and reviewers are allowed to ask for such changes; disputes are worked out in the usual way. However, subtrees may choose to opt in to such enforcement locally.

9.3.3 Closure compiler linter

This program checks for a variety of missteps and anti-patterns.

9.3.4 Conformance framework

The JS Conformance Framework is a tool that is part of the Closure Compiler that provides developers a simple means to specify a set of additional checks to be run against their code base above the standard checks. Conformance checks can, for example, forbid access to a certain property, or calls to a certain function, or missing type information (unknowns).

These rules are commonly used to enforce critical restrictions (such as defining globals, which could break the codebase) and security patterns (such as using eval or assigning to innerHTML), or more loosely to improve code quality.

For additional information see the official documentation for the JS Conformance Framework.

9.4 Exceptions for legacy platforms

9.4.1 Overview

This section describes exceptions and additional rules to be followed when modern ECMAScript syntax is not available to the code authors. Exceptions to the recommended style are required when modern ECMAScript syntax is not possible and are outlined here:

  • Use of var declarations is allowed
  • Use of arguments is allowed
  • Optional parameters without default values are allowed

9.4.2 Use var

9.4.2.1 var declarations are NOT block-scoped

var declarations are scoped to the beginning of the nearest enclosing function, script or module, which can cause unexpected behavior, especially with function closures that reference var declarations inside of loops. The following code gives an example:

for (var i = 0; i < 3; ++i) {
  var iteration = i;
  setTimeout(function() { console.log(iteration); }, i*1000);
}

// logs 2, 2, 2 -- NOT 0, 1, 2
// because `iteration` is function-scoped, not local to the loop.

9.4.2.2 Declare variables as close as possible to first use

Even though var declarations are scoped to the beginning of the enclosing function, var declarations should be as close as possible to their first use, for readability purposes. However, do not put a var declaration inside a block if that variable is referenced outside the block. For example:

function sillyFunction() {
  var count = 0;
  for (var x in y) {
    // "count" could be declared here, but don't do that.
    count++;
  }
  console.log(count + ' items in y');
}
9.4.2.3 Use @const for constants variables

For global declarations where the const keyword would be used, if it were available, annotate the var declaration with @const instead (this is optional for local variables).

9.4.3 Do not use block scoped functions declarations

Do not do this:

if (x) {
  function foo() {}
}

While most JavaScript VMs implemented before ECMAScript 6 support function declarations within blocks it was not standardized. Implementations were inconsistent with each other and with the now-standard ECMAScript behavior for block scoped function declaration. The ECMAScript 5 standard and prior only allow for function declarations in the root statement list of a script or function and explicitly ban them in block scopes in strict mode.

To get consistent behavior, instead use a var initialized with a function expression to define a function within a block:

if (x) {
  var foo = function() {};
}

9.4.4 Dependency management with goog.provide/goog.require

9.4.4.1 Summary

WARNING: goog.provide dependency management is deprecated. All new files, even in projects using goog.provide for older files, should use goog.module. The following rules are for pre-existing goog.provide files only.

  • Place all goog.provides first, goog.requires second. Separate provides from requires with an empty line.
  • Sort the entries alphabetically (uppercase first).
  • Don't wrap goog.provide and goog.require statements. Exceed 80 columns if necessary.
  • Only provide top-level symbols.

goog.provide statements should be grouped together and placed first. All goog.require statements should follow. The two lists should be separated with an empty line.

Similar to import statements in other languages, goog.provide and goog.require statements should be written in a single line, even if they exceed the 80 column line length limit.

The lines should be sorted alphabetically, with uppercase letters coming first:

goog.provide('namespace.MyClass');
goog.provide('namespace.helperFoo');

goog.require('an.extremelyLongNamespace.thatSomeoneThought.wouldBeNice.andNowItIsLonger.Than80Columns');
goog.require('goog.dom');
goog.require('goog.dom.TagName');
goog.require('goog.dom.classes');
goog.require('goog.dominoes');

All members defined on a class should be in the same file. Only top-level classes should be provided in a file that contains multiple members defined on the same class (e.g. enums, inner classes, etc).

Do this:

goog.provide('namespace.MyClass');

Not this:

goog.provide('namespace.MyClass');
goog.provide('namespace.MyClass.CONSTANT');
goog.provide('namespace.MyClass.Enum');
goog.provide('namespace.MyClass.InnerClass');
goog.provide('namespace.MyClass.TypeDef');
goog.provide('namespace.MyClass.staticMethod');

Members on namespaces may also be provided:

goog.provide('foo.bar');
goog.provide('foo.bar.CONSTANT');
goog.provide('foo.bar.method');
9.4.4.2 Aliasing with goog.scope

WARNING: goog.scope is deprecated. New files should not use goog.scope even in projects with existing goog.scope usage.

goog.scope may be used to shorten references to namespaced symbols in code using goog.provide/goog.require dependency management.

Only one goog.scope invocation may be added per file. Always place it in the global scope.

The opening goog.scope(function() { invocation must be preceded by exactly one blank line and follow any goog.provide statements, goog.require statements, or top-level comments. The invocation must be closed on the last line in the file. Append // goog.scope to the closing statement of the scope. Separate the comment from the semicolon by two spaces.

Similar to C++ namespaces, do not indent under goog.scope declarations. Instead, continue from the 0 column.

Only make aliases for names that will not be re-assigned to another object (e.g., most constructors, enums, and namespaces). Do not do this (see below for how to alias a constructor):

goog.scope(function() {
var Button = goog.ui.Button;

Button = function() { ... };
...

Names must be the same as the last property of the global that they are aliasing.

goog.provide('my.module.SomeType');

goog.require('goog.dom');
goog.require('goog.ui.Button');

goog.scope(function() {
var Button = goog.ui.Button;
var dom = goog.dom;

// Alias new types after the constructor declaration.
my.module.SomeType = function() { ... };
var SomeType = my.module.SomeType;

// Declare methods on the prototype as usual:
SomeType.prototype.findButton = function() {
  // Button as aliased above.
  this.button = new Button(dom.getElement('my-button'));
};
...
});  // goog.scope
9.4.4.3 goog.forwardDeclare

Prefer to use goog.requireType instead of goog.forwardDeclare to break circular dependencies between files in the same library. Unlike goog.require, a goog.requireType statement is allowed to import a namespace before it is defined.

goog.forwardDeclare statements must follow the same style rules as goog.require and goog.requireType. The entire block of goog.forwardDeclare, goog.require and goog.requireType statements is sorted alphabetically.

goog.forwardDeclare is used in legacy code to break circular references spanning across library boundaries. This pattern however is poorly supported by build tools and should not be used. Code should be organized to avoid circular dependencies across libraries (by splitting/merging libraries).

9.4.4.4 goog.module.get(name)

If a goog.provide file depends on a goog.module file, the goog.provide file can not normally refer to the module's exports via a global name. Instead, in addition to goog.require()ing the module, the goog.provide file must fetch the module's export object by calling goog.module.get('module.name').

Note: Only calling goog.module.get('module.name') does not create a build-time dependency of your code on the module. The goog.require is needed for the build dependency.

9.4.4.5 goog.module.declareLegacyNamespace()

WARNING: goog.module.declareLegacyNamespace is only for transitional use.

goog.module.declareLegacyNamespace is only for use while migrating a JavaScript file and its consumers from goog.provide to goog.module . Update consumers of your goog.module to use goog.module themselves. Remove calls to goog.module.declareLegacyNamespace whenever possible.

If you can't update consumers of a legacy namespace from goog.provide to goog.module soon, please wrap the contents of your file in a call to goog.scope, use goog.module.get to import the legacy namespace--and then delete the call to goog.module.declareLegacyNamespace in your goog.module.

Calling goog.module.declareLegacyNamespace() inside a goog.module(name) will declare the module's namespace as a global name just like a goog.provide() call does. This allows a non goog.module namespace to access the module's exports without calling goog.module.get(name).

================================================ FILE: jsoncstyleguide.html ================================================ Redirecting Redirecting you to jsoncstyleguide.xml. ================================================ FILE: jsoncstyleguide.xml ================================================

Revision 0.9

This style guide contains many details that are initially hidden from view. They are marked by the triangle icon, which you see here on your left. Click it now. You should see "Hooray" appear below.

Hooray! Now you know you can expand points to get more details. Alternatively, there's an "expand all" at the top of this document.

This style guide documents guidelines and recommendations for building JSON APIs at Google. In general, JSON APIs should follow the spec found at JSON.org. This style guide clarifies and standardizes specific cases so that JSON APIs from Google have a standard look and feel. These guidelines are applicable to JSON requests and responses in both RPC-based and REST-based APIs.

For the purposes of this style guide, we define the following terms:

  • property - a name/value pair inside a JSON object.
  • property name - the name (or key) portion of the property.
  • property value - the value portion of the property.
{ // The name/value pair together is a "property". "propertyName": "propertyValue" }

Javascript's number type encompasses all floating-point numbers, which is a broad designation. In this guide, number will refer to JavaScript's number type, while integer will refer to integers.

No comments in JSON objects.

Comments should not be included in JSON objects. Some of the examples in this style guide include comments. However this is only to clarify the examples.

{ // You may see comments in the examples below, // But don't include comments in your JSON. "propertyName": "propertyValue" }
Use double quotes.

If a property requires quotes, double quotes must be used. All property names must be surrounded by double quotes. Property values of type string must be surrounded by double quotes. Other value types (like boolean or number) should not be surrounded by double quotes.

Data should not be arbitrarily grouped for convenience.

Data elements should be "flattened" in the JSON representation. Data should not be arbitrarily grouped for convenience.

In some cases, such as a collection of properties that represents a single structure, it may make sense to keep the structured hierarchy. These cases should be carefully considered, and only used if it makes semantic sense. For example, an address could be represented two ways, but the structured way probably makes more sense for developers:

Flattened Address:

{ "company": "Google", "website": "https://www.google.com/", "addressLine1": "111 8th Ave", "addressLine2": "4th Floor", "state": "NY", "city": "New York", "zip": "10011" }

Structured Address:

{ "company": "Google", "website": "https://www.google.com/", "address": { "line1": "111 8th Ave", "line2": "4th Floor", "state": "NY", "city": "New York", "zip": "10011" } }
Choose meaningful property names.

Property names must conform to the following guidelines:

  • Property names should be meaningful names with defined semantics.
  • Property names must be camel-cased, ascii strings.
  • The first character must be a letter, an underscore (_) or a dollar sign ($).
  • Subsequent characters can be a letter, a digit, an underscore, or a dollar sign.
  • Reserved JavaScript keywords should be avoided (A list of reserved JavaScript keywords can be found below).

These guidelines mirror the guidelines for naming JavaScript identifiers. This allows JavaScript clients to access properties using dot notation. (for example, result.thisIsAnInstanceVariable). Here's an example of an object with one property:

{ "thisPropertyIsAnIdentifier": "identifier value" }
JSON maps can use any Unicode character in key names.

The property name naming rules do not apply when a JSON object is used as a map. A map (also referred to as an associative array) is a data type with arbitrary key/value pairs that use the keys to access the corresponding values. JSON objects and JSON maps look the same at runtime; this distinction is relevant to the design of the API. The API documentation should indicate when JSON objects are used as maps.

The keys of a map do not have to obey the naming guidelines for property names. Map keys may contain any Unicode characters. Clients can access these properties using the square bracket notation familiar for maps (for example, result.thumbnails["72"]).

{ // The "address" property is a sub-object // holding the parts of an address. "address": { "addressLine1": "123 Anystreet", "city": "Anytown", "state": "XX", "zip": "00000" }, // The "thumbnails" property is a map that maps // a pixel size to the thumbnail url of that size. "thumbnails": { "72": "https://url.to.72px.thumbnail", "144": "https://url.to.144px.thumbnail" } }
Certain property names are reserved for consistent use across services.

Details about reserved property names, along with the full list, can be found later on in this guide. Services should avoid using these property names for anything other than their defined semantics.

Array types should have plural property names. All other property names should be singular.

Arrays usually contain multiple items, and a plural property name reflects this. An example of this can be seen in the reserved names below. The items property name is plural because it represents an array of item objects. Most of the other fields are singular.

There may be exceptions to this, especially when referring to numeric property values. For example, in the reserved names, totalItems makes more sense than totalItem. However, technically, this is not violating the style guide, since totalItems can be viewed as totalOfItems, where total is singular (as per the style guide), and OfItems serves to qualify the total. The field name could also be changed to itemCount to look singular.

{ // Singular "author": "lisa", // An array of siblings, plural "siblings": [ "bart", "maggie"], // "totalItem" doesn't sound right "totalItems": 10, // But maybe "itemCount" is better "itemCount": 10, }
Avoid naming conflicts by choosing a new property name or versioning the API.

New properties may be added to the reserved list in the future. There is no concept of JSON namespacing. If there is a naming conflict, these can usually be resolved by choosing a new property name or by versioning. For example, suppose we start with the following JSON object:

{ "apiVersion": "1.0", "data": { "recipeName": "pizza", "ingredients": ["tomatoes", "cheese", "sausage"] } }

If in the future we wish to make ingredients a reserved word, we can do one of two things:

1) Choose a different name:

{ "apiVersion": "1.0", "data": { "recipeName": "pizza", "ingredientsData": "Some new property", "ingredients": ["tomatoes", "cheese", "sausage"] } }

2) Rename the property on a major version boundary:

{ "apiVersion": "2.0", "data": { "recipeName": "pizza", "ingredients": "Some new property", "recipeIngredients": ["tomatos", "cheese", "sausage"] } }
Property values must be booleans, numbers, Unicode strings, objects, arrays, or null.

The spec at JSON.org specifies exactly what type of data is allowed in a property value. This includes booleans, numbers, Unicode strings, objects, arrays, and null. JavaScript expressions are not allowed. APIs should support that spec for all values, and should choose the data type most appropriate for a particular property (numbers to represent numbers, etc.).

Good:

{ "canPigsFly": null, // null "areWeThereYet": false, // boolean "answerToLife": 42, // number "name": "Bart", // string "moreData": {}, // object "things": [] // array }

Bad:

{ "aVariableName": aVariableName, // Bad - JavaScript identifier "functionFoo": function() { return 1; } // Bad - JavaScript function }
Consider removing empty or null values.

If a property is optional or has an empty or null value, consider dropping the property from the JSON, unless there's a strong semantic reason for its existence.

{ "volume": 10, // Even though the "balance" property's value is zero, it should be left in, // since "0" signifies "even balance" (the value could be "-1" for left // balance and "+1" for right balance. "balance": 0, // The "currentlyPlaying" property can be left out since it is null. // "currentlyPlaying": null }
Enum values should be represented as strings.

As APIs grow, enum values may be added, removed or changed. Using strings as enum values ensures that downstream clients can gracefully handle changes to enum values.

Java code:

public enum Color { WHITE, BLACK, RED, YELLOW, BLUE }

JSON object:

{ "color": "WHITE" }

As mentioned above, property value types must be booleans, numbers, strings, objects, arrays, or null. However, it is useful define a set of standard data types when dealing with certain values. These data types will always be strings, but they will be formatted in a specific manner so that they can be easily parsed.

Dates should be formatted as recommended by RFC 3339.

Dates should be strings formatted as recommended by RFC 3339

{ "lastUpdate": "2007-11-06T16:34:41.000Z" }
Time durations should be formatted as recommended by ISO 8601.

Time duration values should be strings formatted as recommended by ISO 8601.

{ // three years, six months, four days, twelve hours, // thirty minutes, and five seconds "duration": "P3Y6M4DT12H30M5S" }
Latitudes/Longitudes should be formatted as recommended by ISO 6709.

Latitude/Longitude should be strings formatted as recommended by ISO 6709. Furthermore, they should favor the ±DD.DDDD±DDD.DDDD degrees format.

{ // The latitude/longitude location of the statue of liberty. "statueOfLiberty": "+40.6894-074.0447" }

In order to maintain a consistent interface across APIs, JSON objects should follow the structure outlined below. This structure applies to both requests and responses made with JSON. Within this structure, there are certain property names that are reserved for specific uses. These properties are NOT required; in other words, each reserved property may appear zero or one times. But if a service needs these properties, this naming convention is recommended. Here is a schema of the JSON structure, represented in Orderly format (which in turn can be compiled into a JSONSchema). You can few examples of the JSON structure at the end of this guide.

object { string apiVersion?; string context?; string id?; string method?; object { string id? }* params?; object { string kind?; string fields?; string etag?; string id?; string lang?; string updated?; # date formatted RFC 3339 boolean deleted?; integer currentItemCount?; integer itemsPerPage?; integer startIndex?; integer totalItems?; integer pageIndex?; integer totalPages?; string pageLinkTemplate /^https?:/ ?; object {}* next?; string nextLink?; object {}* previous?; string previousLink?; object {}* self?; string selfLink?; object {}* edit?; string editLink?; array [ object {}*; ] items?; }* data?; object { integer code?; string message?; array [ object { string domain?; string reason?; string message?; string location?; string locationType?; string extendedHelp?; string sendReport?; }*; ] errors?; }* error?; }*;

The JSON object has a few top-level properties, followed by either a data object or an error object, but not both. An explanation of each of these properties can be found below.

The top-level of the JSON object may contain the following properties.

Property Value Type: string
Parent: -

Represents the desired version of the service API in a request, and the version of the service API that's served in the response. apiVersion should always be present. This is not related to the version of the data. Versioning of data should be handled through some other mechanism such as etags.

Example:

{ "apiVersion": "2.1" }
Property Value Type: string
Parent: -

Client sets this value and server echos data in the response. This is useful in JSON-P and batch situations , where the user can use the context to correlate responses with requests. This property is a top-level property because the context should present regardless of whether the response was successful or an error. context differs from id in that context is specified by the user while id is assigned by the service.

Example:

Request #1:

https://www.google.com/myapi?context=bart

Request #2:

https://www.google.com/myapi?context=lisa

Response #1:

{ "context": "bart", "data": { "items": [] } }

Response #2:

{ "context": "lisa", "data": { "items": [] } }

Common JavaScript handler code to process both responses:

function handleResponse(response) { if (response.result.context == "bart") { // Update the "Bart" section of the page. } else if (response.result.context == "lisa") { // Update the "Lisa" section of the page. } }
Property Value Type: string
Parent: -

A server supplied identifier for the response (regardless of whether the response is a success or an error). This is useful for correlating server logs with individual responses received at a client.

Example:

{ "id": "1" }
Property Value Type: string
Parent: -

Represents the operation to perform, or that was performed, on the data. In the case of a JSON request, the method property can be used to indicate which operation to perform on the data. In the case of a JSON response, the method property can indicate the operation performed on the data.

One example of this is in JSON-RPC requests, where method indicates the operation to perform on the params property:

{ "method": "people.get", "params": { "userId": "@me", "groupId": "@self" } }
Property Value Type: object
Parent: -

This object serves as a map of input parameters to send to an RPC request. It can be used in conjunction with the method property to execute an RPC function. If an RPC function does not need parameters, this property can be omitted.

Example:

{ "method": "people.get", "params": { "userId": "@me", "groupId": "@self" } }
Property Value Type: object
Parent: -

Container for all the data from a response. This property itself has many reserved property names, which are described below. Services are free to add their own data to this object. A JSON response should contain either a data object or an error object, but not both. If both data and error are present, the error object takes precedence.

Property Value Type: object
Parent: -

Indicates that an error has occurred, with details about the error. The error format supports either one or more errors returned from the service. A JSON response should contain either a data object or an error object, but not both. If both data and error are present, the error object takes precedence.

Example:

{ "apiVersion": "2.0", "error": { "code": 404, "message": "File Not Found", "errors": [{ "domain": "Calendar", "reason": "ResourceNotFoundException", "message": "File Not Found" }] } }

The data property of the JSON object may contain the following properties.

Property Value Type: string
Parent: data

The kind property serves as a guide to what type of information this particular object stores. It can be present at the data level, or at the items level, or in any object where its helpful to distinguish between various types of objects. If the kind object is present, it should be the first property in the object (See the "Property Ordering" section below for more details).

Example:

// "Kind" indicates an "album" in the Picasa API. {"data": {"kind": "album"}}
Property Value Type: string
Parent: data

Represents the fields present in the response when doing a partial GET, or the fields present in a request when doing a partial PATCH. This property should only exist during a partial GET/PATCH, and should not be empty.

Example:

{ "data": { "kind": "user", "fields": "author,id", "id": "bart", "author": "Bart" } }
Property Value Type: string
Parent: data

Represents the etag for the response. Details about ETags in the GData APIs can be found here: https://code.google.com/apis/gdata/docs/2.0/reference.html#ResourceVersioning

Example:

{"data": {"etag": "W/"C0QBRXcycSp7ImA9WxRVFUk.""}}
Property Value Type: string
Parent: data

A globally unique string used to reference the object. The specific details of the id property are left up to the service.

Example:

{"data": {"id": "12345"}}
Property Value Type: string (formatted as specified in BCP 47)
Parent: data (or any child element)

Indicates the language of the rest of the properties in this object. This property mimics HTML's lang property and XML's xml:lang properties. The value should be a language value as defined in BCP 47. If a single JSON object contains data in multiple languages, the service is responsible for developing and documenting an appropriate location for the lang property.

Example:

{"data": { "items": [ { "lang": "en", "title": "Hello world!" }, { "lang": "fr", "title": "Bonjour monde!" } ]} }
Property Value Type: string (formatted as specified in RFC 3339)
Parent: data

Indicates the last date/time (RFC 3339) the item was updated, as defined by the service.

Example:

{"data": {"updated": "2007-11-06T16:34:41.000Z"}}
Property Value Type: boolean
Parent: data (or any child element)

A marker element, that, when present, indicates the containing entry is deleted. If deleted is present, its value must be true; a value of false can cause confusion and should be avoided.

Example:

{"data": { "items": [ { "title": "A deleted entry", "deleted": true } ]} }
Property Value Type: array
Parent: data

The property name items is reserved to represent an array of items (for example, photos in Picasa, videos in YouTube). This construct is intended to provide a standard location for collections related to the current result. For example, the JSON output could be plugged into a generic pagination system that knows to page on the items array. If items exists, it should be the last property in the data object (See the "Property Ordering" section below for more details).

Example:

{ "data": { "items": [ { /* Object #1 */ }, { /* Object #2 */ }, ... ] } }

The following properties are located in the data object, and help page through a list of items. Some of the language and concepts are borrowed from the OpenSearch specification.

The paging properties below allow for various styles of paging, including:

  • Previous/Next paging - Allows user's to move forward and backward through a list, one page at a time. The nextLink and previousLink properties (described in the "Reserved Property Names for Links" section below) are used for this style of paging.
  • Index-based paging - Allows user's to jump directly to a specific item position within a list of items. For example, to load 10 items starting at item 200, the developer may point the user to a url with the query string ?startIndex=200.
  • Page-based paging - Allows user's to jump directly to a specific page within the items. This is similar to index-based paging, but saves the developer the extra step of having to calculate the item index for a new page of items. For example, rather than jump to item number 200, the developer could jump to page 20. The urls during page-based paging could use the query string ?page=1 or ?page=20. The pageIndex and totalPages properties are used for this style of paging.

An example of how to use these properties to implement paging can be found at the end of this guide.

Property Value Type: integer
Parent: data

The number of items in this result set. Should be equivalent to items.length, and is provided as a convenience property. For example, suppose a developer requests a set of search items, and asks for 10 items per page. The total set of that search has 14 total items. The first page of items will have 10 items in it, so both itemsPerPage and currentItemCount will equal "10". The next page of items will have the remaining 4 items; itemsPerPage will still be "10", but currentItemCount will be "4".

Example:

{ "data": { // "itemsPerPage" does not necessarily match "currentItemCount" "itemsPerPage": 10, "currentItemCount": 4 } }
Property Value Type: integer
Parent: data

The number of items in the result. This is not necessarily the size of the data.items array; if we are viewing the last page of items, the size of data.items may be less than itemsPerPage. However the size of data.items should not exceed itemsPerPage.

Example:

{ "data": { "itemsPerPage": 10 } }
Property Value Type: integer
Parent: data

The index of the first item in data.items. For consistency, startIndex should be 1-based. For example, the first item in the first set of items should have a startIndex of 1. If the user requests the next set of data, the startIndex may be 10.

Example:

{ "data": { "startIndex": 1 } }
Property Value Type: integer
Parent: data

The total number of items available in this set. For example, if a user has 100 blog posts, the response may only contain 10 items, but the totalItems would be 100.

Example:

{ "data": { "totalItems": 100 } }
Property Value Type: string
Parent: data

A URI template indicating how users can calculate subsequent paging links. The URI template also has some reserved variable names: {index} representing the item number to load, and {pageIndex}, representing the page number to load.

Example:

{ "data": { "pagingLinkTemplate": "https://www.google.com/search/hl=en&q=chicago+style+pizza&start={index}&sa=N" } }
Property Value Type: integer
Parent: data

The index of the current page of items. For consistency, pageIndex should be 1-based. For example, the first page of items has a pageIndex of 1. pageIndex can also be calculated from the item-based paging properties: pageIndex = floor(startIndex / itemsPerPage) + 1.

Example:

{ "data": { "pageIndex": 1 } }
Property Value Type: integer
Parent: data

The total number of pages in the result set. totalPages can also be calculated from the item-based paging properties above: totalPages = ceiling(totalItems / itemsPerPage).

Example:

{ "data": { "totalPages": 50 } }

The following properties are located in the data object, and represent references to other resources. There are two forms of link properties: 1) objects, which can contain any sort of reference (such as a JSON-RPC object), and 2) URI strings, which represent URIs to resources (and will always be suffixed with "Link").

Property Value Type: object / string
Parent: data

The self link can be used to retrieve the item's data. For example, in a list of a user's Picasa album, each album object in the items array could contain a selfLink that can be used to retrieve data related to that particular album.

Example:

{ "data": { "self": { }, "selfLink": "https://www.google.com/feeds/album/1234" } }
Property Value Type: object / string
Parent: data

The edit link indicates where a user can send update or delete requests. This is useful for REST-based APIs. This link need only be present if the user can update/delete this item.

Example:

{ "data": { "edit": { }, "editLink": "https://www.google.com/feeds/album/1234/edit" } }
Property Value Type: object / string
Parent: data

The next link indicates how more data can be retrieved. It points to the location to load the next set of data. It can be used in conjunction with the itemsPerPage, startIndex and totalItems properties in order to page through data.

Example:

{ "data": { "next": { }, "nextLink": "https://www.google.com/feeds/album/1234/next" } }
Property Value Type: object / string
Parent: data

The previous link indicates how more data can be retrieved. It points to the location to load the previous set of data. It can be used in conjunction with the itemsPerPage, startIndex and totalItems properties in order to page through data.

Example:

{ "data": { "previous": { }, "previousLink": "https://www.google.com/feeds/album/1234/next" } }

The error property of the JSON object may contain the following properties.

Property Value Type: integer
Parent: error

Represents the code for this error. This property value will usually represent the HTTP response code. If there are multiple errors, code will be the error code for the first error.

Example:

{ "error":{ "code": 404 } }
Property Value Type: string
Parent: error

A human readable message providing more details about the error. If there are multiple errors, message will be the message for the first error.

Example:

{ "error":{ "message": "File Not Found" } }
Property Value Type: array
Parent: error

Container for any additional information regarding the error. If the service returns multiple errors, each element in the errors array represents a different error.

Example:

{ "error": { "errors": [] } }
Property Value Type: string
Parent: error.errors

Unique identifier for the service raising this error. This helps distinguish service-specific errors (i.e. error inserting an event in a calendar) from general protocol errors (i.e. file not found).

Example:

{ "error":{ "errors": [{"domain": "Calendar"}] } }
Property Value Type: string
Parent: error.errors

Unique identifier for this error. Different from the error.code property in that this is not an http response code.

Example:

{ "error":{ "errors": [{"reason": "ResourceNotFoundException"}] } }
Property Value Type: string
Parent: error.errors

A human readable message providing more details about the error. If there is only one error, this field will match error.message.

Example:

{ "error":{ "code": 404, "message": "File Not Found", "errors": [{"message": "File Not Found"}] } }
Property Value Type: string
Parent: error.errors

The location of the error (the interpretation of its value depends on locationType).

Example:

{ "error":{ "errors": [{"location": ""}] } }
Property Value Type: string
Parent: error.errors

Indicates how the location property should be interpreted.

Example:

{ "error":{ "errors": [{"locationType": ""}] } }
Property Value Type: string
Parent: error.errors

A URI for a help text that might shed some more light on the error.

Example:

{ "error":{ "errors": [{"extendedHelper": "https://url.to.more.details.example.com/"}] } }
Property Value Type: string
Parent: error.errors

A URI for a report form used by the service to collect data about the error condition. This URI should be preloaded with parameters describing the request.

Example:

{ "error":{ "errors": [{"sendReport": "https://report.example.com/"}] } }

Properties can be in any order within the JSON object. However, in some cases the ordering of properties can help parsers quickly interpret data and lead to better performance. One example is a pull parser in a mobile environment, where performance and memory are critical, and unnecessary parsing should be avoided.

kind should be the first property

Suppose a parser is responsible for parsing a raw JSON stream into a specific object. The kind property guides the parser to instantiate the appropriate object. Therefore it should be the first property in the JSON object. This only applies when objects have a kind property (usually found in the data and items properties).

items should be the last property in the data object

This allows all of the collection's properties to be read before reading each individual item. In cases where there are a lot of items, this avoids unnecessarily parsing those items when the developer only needs fields from the data.

// The "kind" property distinguishes between an "album" and a "photo". // "Kind" is always the first property in its parent object. // The "items" property is the last property in the "data" object. { "data": { "kind": "album", "title": "My Photo Album", "description": "An album in the user's account", "items": [ { "kind": "photo", "title": "My First Photo" } ] } }
Here's an example of the YouTube JSON API's response object. You can learn more about YouTube's JSON API here: https://code.google.com/apis/youtube/2.0/developers_guide_jsonc.html. { "apiVersion": "2.0", "data": { "updated": "2010-02-04T19:29:54.001Z", "totalItems": 6741, "startIndex": 1, "itemsPerPage": 1, "items": [ { "id": "BGODurRfVv4", "uploaded": "2009-11-17T20:10:06.000Z", "updated": "2010-02-04T06:25:57.000Z", "uploader": "docchat", "category": "Animals", "title": "From service dog to SURFice dog", "description": "Surf dog Ricochets inspirational video ...", "tags": [ "Surf dog", "dog surfing", "dog", "golden retriever", ], "thumbnail": { "default": "https://i.ytimg.com/vi/BGODurRfVv4/default.jpg", "hqDefault": "https://i.ytimg.com/vi/BGODurRfVv4/hqdefault.jpg" }, "player": { "default": "https://www.youtube.com/watch?v=BGODurRfVv4&feature=youtube_gdata", "mobile": "https://m.youtube.com/details?v=BGODurRfVv4" }, "content": { "1": "rtsp://v5.cache6.c.youtube.com/CiILENy73wIaGQn-Vl-0uoNjBBMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp", "5": "https://www.youtube.com/v/BGODurRfVv4?f=videos&app=youtube_gdata", "6": "rtsp://v7.cache7.c.youtube.com/CiILENy73wIaGQn-Vl-0uoNjBBMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp" }, "duration": 315, "rating": 4.96, "ratingCount": 2043, "viewCount": 1781691, "favoriteCount": 3363, "commentCount": 1007, "commentsAllowed": true } ] } } This example demonstrates how the Google search items could be represented as a JSON object, with special attention to the paging variables.

This sample is for illustrative purposes only. The API below does not actually exist.

Here's a sample Google search results page:

Here's a sample JSON representation of this page:

{ "apiVersion": "2.1", "id": "1", "data": { "query": "chicago style pizza", "time": "0.1", "currentItemCount": 10, "itemsPerPage": 10, "startIndex": 11, "totalItems": 2700000, "nextLink": "https://www.google.com/search?hl=en&q=chicago+style+pizza&start=20&sa=N" "previousLink": "https://www.google.com/search?hl=en&q=chicago+style+pizza&start=0&sa=N", "pagingLinkTemplate": "https://www.google.com/search/hl=en&q=chicago+style+pizza&start={index}&sa=N", "items": [ { "title": "Pizz'a Chicago Home Page" // More fields for the search results } // More search results ] } }

Here's how each of the colored boxes from the screenshot would be represented (the background colors correspond to the colors in the images above):

  • Results 11 - 20 of about 2,700,000 = startIndex
  • Results 11 - 20 of about 2,700,000 = startIndex + currentItemCount - 1
  • Results 11 - 20 of about 2,700,000 = totalItems
  • Search results = items (formatted appropriately)
  • Previous/Next = previousLink / nextLink
  • Numbered links in "Gooooooooooogle" = Derived from "pageLinkTemplate". The developer is responsible for calculating the values for {index} and substituting those values into the "pageLinkTemplate". The pageLinkTemplate's {index} variable is calculated as follows:
    • Index #1 = 0 * itemsPerPage = 0
    • Index #2 = 2 * itemsPerPage = 10
    • Index #3 = 3 * itemsPerPage = 20
    • Index #N = N * itemsPerPage
A list of reserved JavaScript words that should be avoided in property names.

The words below are reserved by the JavaScript language and cannot be referred to using dot notation. The list represents best knowledge of keywords at this time; the list may change or vary based on your specific execution environment.

From the ECMAScript Language Specification 5th Edition

abstract boolean break byte case catch char class const continue debugger default delete do double else enum export extends false final finally float for function goto if implements import in instanceof int interface let long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var volatile void while with yield

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 3.0 License, and code samples are licensed under the Apache 2.0 License.

Revision 0.9

================================================ FILE: lispguide.xml ================================================

Revision 1.28

Robert Brown
François-René Rideau
In memoriam Dan Weinreb

Patterns mean "I have run out of language." — Rich Hickey

This style guide contains many details that are initially hidden from view. They are marked by the triangle icon, which you see here on your left. Click it now. You should see "Hooray" appear below.

Hooray! Now you know you can expand points to get more details. Alternatively, there's an "expand all" at the top of this document.

Common Lisp is a powerful multiparadigm programming language. With great power comes great responsibility.

This guide recommends formatting and stylistic choices designed to make your code easier for other people to understand. For those internal applications and free software libraries that we develop at Google, you should keep within these guidelines when making changes. Note however that each project has its own rules and customs that complement or override these general guidelines; the speed-oriented QPX low fare search engine notably has a very different style and feel from the QRes reservation system.

If you're writing Common Lisp code outside Google, we invite you to consider these guidelines. You may find some of them useful where they don't conflict with other priorities you have. We welcome remarks and constructive feedback on how to improve our guide, and on what alternate styles work for you and why.

This guide is not a Common Lisp tutorial. For basic information about the language, please consult Practical Common Lisp. For a language reference, please consult the Common Lisp HyperSpec. For more detailed style guidance, take (with a pinch of salt) a look at Peter Norvig and Kent Pitman's style guide.

Each guideline's level of importance is indicated by use of the following keywords and phrases, adapted from RFC 2119.
MUST

This word, or the terms "REQUIRED" or "SHALL", means that the guideline is an absolute requirement. You must ask permission to violate a MUST.

MUST NOT

This phrase, or the phrase "SHALL NOT", means that the guideline is an absolute prohibition. You must ask permission to violate a MUST NOT.

SHOULD

This word, or the adjective "RECOMMENDED", means that there may exist valid reasons in particular circumstances to ignore the demands of the guideline, but the full implications must be understood and carefully weighed before choosing a different course. You must ask forgiveness for violating a SHOULD.

SHOULD NOT

This phrase, or the phrase "NOT RECOMMENDED", means that there may exist valid reasons in particular circumstances to ignore the prohibitions of this guideline, but the full implications should be understood and carefully weighed before choosing a different course. You must ask forgiveness for violating a SHOULD NOT.

MAY

This word, or the adjective "OPTIONAL", means that an item is truly optional.

Unlike RFCs, we don't capitalize every instance of one of the above keywords when it is used.

There are cases where transgression of some of these rules is useful or even necessary. In some cases, you must seek permission or obtain forgiveness from the proper people.

Permission comes from the owners of your project.

Forgiveness is requested in a comment near the point of guideline violation, and is granted by your code reviewer. The original comment should be signed by you, and the reviewer should add a signed approval to the comment at review time.

You MUST follow conventions. They are not optional.

Some of these guidelines are motivated by universal principles of good programming. Some guidelines are motivated by technical peculiarities of Common Lisp. Some guidelines were once motivated by a technical reason, but the guideline remained after the reason subsided. Some guidelines, such those about as comments and indentation, are based purely on convention, rather than on clear technical merit. Whatever the case may be, you must still follow these guidelines, as well as other conventional guidelines that have not been formalized in this document.

You MUST follow conventions. They are important for readability. When conventions are followed by default, violations of the convention are a signal that something notable is happening and deserves attention. When conventions are systematically violated, violations of the convention are a distracting noise that needs to be ignored.

Conventional guidelines are indoctrination. Their purpose is to make you follow the mores of the community, so you can more effectively cooperate with existing members. It is still useful to distinguish the parts that are technically motivated from the parts that are mere conventions, so you know when best to defy conventions for good effect, and when not to fall into the pitfalls that the conventions are there to help avoid.

Fix old code as you go.

A lot of our code was written before these guidelines existed. You should fix violations as you encounter them in the course of your normal coding.

You must not fix violations en masse without warning other developers and coordinating with them, so as not to make the merging of large branches more difficult than it already is.

There are many topics for additional standardization not covered by current version of this document, but deferred to future versions.
  • File and directory structure
  • Packages and modularity
  • Threads and locking
  • How to add configurable components
  • CLOS style: initforms, slot and accessor names, etc.
  • Recommendations on max number of slots per class.
  • More concrete examples of good code:
    • exceptions
    • transactions, with retry
    • XML
    • typing
    • encapsulation / abstraction
    • class and slot names
    • etc.
  • When (not) to use conditional compilation:
    • modifying the product
    • conditional debugging/console output/etc.
    • "temporarily" commenting-out blocks of code
    • etc.
There are some basic principles for team software development that every developer must keep in mind. Whenever the detailed guidelines are inadequate, confusing or contradictory, refer back to these principles for guidance:
  • Every developer's code must be easy for another developer to read, understand, and modify — even if the first developer isn't around to explain it. (This is the "hit by a truck" principle.)
  • Everybody's code should look the same. Ideally, there should be no way to look at lines of code and recognize it as "Fred's code" by its style.
  • Be precise.
  • Be concise.
  • KISS — Keep It Simple, Stupid.
  • Use the smallest hammer for the job.
  • Use common sense.
  • Keep related code together. Minimize the amount of jumping around someone has to do to understand an area of code.

When making decisions about how to write a given piece of code, aim for the following -ilities in this priority order:

  • Usability by the customer
  • Debuggability/Testability
  • Readability/Comprehensibility
  • Extensibility/Modifiability
  • Efficiency (of the Lisp code at runtime)

Most of these are obvious.

Usability by the customer means that the system has to do what the customer requires; it has to handle the customer's transaction volumes, uptime requirements; etc.

For the Lisp efficiency point, given two options of equivalent complexity, pick the one that performs better. (This is often the same as the one that conses less, i.e. allocates less storage from the heap.)

Given two options where one is more complex than the other, pick the simpler option and revisit the decision only if profiling shows it to be a performance bottleneck.

However, avoid premature optimization. Don't add complexity to speed up something that runs rarely, since in the long run, it matters less whether such code is fast.

To build code that is robust and maintainable, it matters a lot how the code is divided into components, how these components communicate, how changes propagate as they evolve, and more importantly how the programmers who develop these components communicate as these components evolve.

If your work affects other groups, might be reusable across groups, adds new components, has an impact on other groups (including QA or Ops), or otherwise isn't purely local, you must write it up using at least a couple of paragraphs, and get a design approval from the other parties involved before starting to write code — or be ready to scratch what you have when they object.

If you don't know or don't care about these issues, ask someone who does.

Often, the smallest hammer is to use an existing library. Or one that doesn't exist yet. In such cases, you are encouraged to use or develop such a library, but you must take appropriate precautions.
  • You MUST NOT start a new library unless you established that none is already available that can be fixed or completed into becoming what you need. That's a rule against the NIH syndrome ("Not Invented Here"), which is particularly strong amongst Lisp hackers.
  • Whichever library, old or new, you pick, you MUST get permission to incorporate third-party code into the code base. You must discuss the use of such library in the appropriate mailing-list, and have your code reviewed by people knowledgeable in the domain and/or the Lisp library ecosystem (if any). Please be ready to argue why this particular solution makes sense as compared to other available libraries.
  • Some libraries are distributed under licenses not compatible with the software you're writing, and must not be considered available for use. Be aware of these issues, or consult with people who are.

If you write a general-purpose library, or modify an existing open-source library, you are encouraged to publish the result separate from your main project and then have your project import it like any other open-source library.

Use your judgment to distinguish general-purpose versus business-specific code, and open-source the general-purpose parts, while keeping the business-specific parts a trade secret.

Open-Sourcing code has many advantages, including being able to leverage third parties for development, letting the development of features be user-directed, and keeping you honest with respect to code quality. Whatever code you write, you will have to maintain anyway, and make sure its quality is high enough to sustain use in production. There should therefore be no additional burden to Open-Sourcing, even of code that (at least initially) is not directly usable by third parties.

Development process is outside the scope of this document. However, developers should remember at least these bits: get reviewed, write tests, eliminate warnings, run tests, avoid mass-changes.

  • All code changes must be reviewed. You should expect that your code will be reviewed by other hackers, and that you will be assigned other hackers' code to review. Part of the review criteria will be that code obeys the coding standards in this document.
  • You must write and check-in tests for new code that you write and old bugs you fix. There must be a unit test for every API function, and any previously failing case. Your work is not truly done until this activity is complete. Estimating tasks must include the time it takes to produce such tests.
  • Your code must compile without any compilation error or warning messages whatsoever. If the compiler issues warnings that should be ignored, muffle those warnings using the UIOP:WITH-MUFFLED-COMPILER-CONDITIONS and UIOP:*UNINTERESTING-COMPILER-CONDITIONS* framework (part of UIOP, part of ASDF 3), either around the entire project, or around individual files (using ASDF's :around-compile hooks).
  • All code should be checked in an appropriate source control system, in a way that allows for complete reproducibility of build, test and execution of the code that is, has been or may be deployed.
  • You must run the "precheckin" tests, and each component must pass its unit tests successfully before you commit any code.
  • You should incorporate code coverage into your testing process. Tests are not sufficient if they do not cover all new and updated code; code that for whatever reason cannot be included in coverage results should be clearly marked as such including the reason.
  • Many people develop on branches. You must get permission to undertake mass-changes (e.g. mass reindentations) so that we can coordinate in advance, and give branch residents time to get back on the mainline

You must use correct spelling in your comments, and most importantly in your identifiers.

When several correct spellings exist (including American vs English), and there isn't a consensus amongst developers as which to use, you should choose the shorter spelling.

You must use only common and domain-specific abbreviations, and must be consistent with these abbreviations. You may abbreviate lexical variables of limited scope in order to avoid overly-long symbol names.

If you're not sure, consult a dictionary, Google for alternative spellings, or ask a local expert.

Here are examples of choosing the correct spelling:

  • Use "complimentary" in the sense of a meal or beverage that is not paid for by the recipient, not "complementary".
  • Use "existent" and "nonexistent", not "existant". Use "existence", not "existance".
  • Use "hierarchy" not "heirarchy".
  • Use "precede" not "preceed".
  • Use "weird", not "wierd".

Here are examples of choosing the shorter spelling:

  • Use "canceled", not "cancelled"
  • Use "queuing", not "queueing".
  • Use "signaled", not "signalled";
  • Use "traveled", not "travelled".
  • Use "aluminum", not "aluminium"
  • Use "oriented", not "orientated"
  • Use "color", not "colour"
  • Use "behavior", not "behaviour"

Make appropriate exceptions for industry standard nomenclature/jargon, including plain misspellings. For instance:

  • Use "referer", not "referrer", in the context of the HTTP protocol.
You should format source code so that no line is longer than 100 characters.

Some line length restriction is better than none at all. While old text terminals used to make 80 columns the standard, these days, allowing 100 columns seems better, since good style encourages the use of descriptive variables and function names.

Indent your code the way a properly configured GNU Emacs does.

Maintain a consistent indentation style throughout a project.

Indent carefully to make the code easier to understand.

Common Lisp indentation in Emacs is provided by the cl-indent library. The latest version of cl-indent is packaged with SLIME (under contrib/slime-cl-indent.el). After installing SLIME, set up Emacs to load SLIME automatically using these instructions, adding slime-indentation to the list of contrib libraries to be loaded in the call to slime-setup.

Ideally, use the default indentation settings provided by slime-indentation. If necessary, customize indentation parameters to maintain a consistent indentation style throughout an existing project. Parameters can be customized using the :variables setting in define-common-lisp-style. Indentation of specific forms can be customized using the :indentation setting of define-common-lisp-style. This is particularly useful when creating forms that behave like macros or special operators that are indented differently than standard function calls (e.g. defun, labels, or let). Add a hook to 'lisp-mode-hook that calls common-lisp-set-style to set the appropriate style automatically.

Use indentation to make complex function applications easier to read. When an application does not fit on one line or the function takes many arguments, consider inserting newlines between the arguments so that each one is on a separate line. However, do not insert newlines in a way that makes it hard to tell how many arguments the function takes or where an argument form starts and ends.

;; Bad (do-something first-argument second-argument (lambda (x) (frob x)) fourth-argument last-argument) ;; Better (do-something first-argument second-argument #'(lambda (x) (frob x)) fourth-argument last-argument)

You should include a description at the top of each source file.

You should include neither authorship nor copyright information in a source file.

Every source file should begin with a brief description of the contents of that file.

After that description, every file should start the code itself with an (in-package #:package-name) form.

After that in-package form, every file should follow with any file-specific (declaim (optimize ...)) declaration that is not covered by an ASDF :around-compile hook.

;;;; Variable length encoding for integers and floating point numbers. (in-package #:varint) (declaim #.*optimize-default*)

You should not include authorship information at the top of a file: better information is available from version control, and such a mention will only cause confusion and grief. Indeed, whoever was the main author at the time such a mention was included might not be who eventually made the most significant contributions to the file, and even less who is responsible for the file at the moment.

You should not include copyright information in individual source code files. An exception is made for files meant to be disseminated as standalone.

Vertical white space: one blank line between top-level forms.

You should include one blank line between top-level forms, such as function definitions. Exceptionally, blank lines can be omitted between simple, closely related defining forms of the same kind, such as a group of related type declarations or constant definitions.

(defconstant +mix32+ #x12b9b0a1 "pi, an arbitrary number") (defconstant +mix64+ #x2b992ddfa23249d6 "more digits of pi") (defconstant +golden-ratio32+ #x9e3779b9 "the golden ratio") (defconstant +golden-ratio64+ #xe08c1d668b756f82 "more digits of the golden ratio") (defmacro incf32 (x y) "Like INCF, but for integers modulo 2**32" `(setf ,x (logand (+ ,x ,y) #xffffffff))) (defmacro incf64 (x y) "Like INCF, but for integers modulo 2**64" `(setf ,x (logand (+ ,x ,y) #xffffffffffffffff)))

Blank lines can be used to separate parts of a complicated function. Generally, however, you should break a large function into smaller ones instead of trying to make it more readable by adding vertical space. If you can't, you should document with a ;; comment what each of the separated parts of the function does.

You should strive to keep top-level forms, including comments but excluding the documentation string, of appropriate length; preferably short. Forms extending beyond a single page should be rare and their use should be justified. This applies to each of the forms in an eval-when, rather than to the eval-when itself. Additionally, defpackage forms may be longer, since they may include long lists of symbols.

Horizontal white space: none around parentheses. No tabs.

You must not include extra horizontal whitespace before or after parentheses or around symbols.

You must not place right parentheses by themselves on a line. A set of consecutive trailing parentheses must appear on the same line.

;; Very Bad ( defun factorial ( limit ) ( let (( product 1 )) ( loop for i from 1 upto limit do (setf product ( * product i ) ) ) product ) ) ;; Better (defun factorial (limit) (let ((product 1)) (loop for i from 1 upto limit do (setf product (* product i))) product))

You should use only one space between forms.

You should not use spaces to vertically align forms in the middle of consecutive lines. An exception is made when the code possesses an important yet otherwise not visible symmetry that you want to emphasize.

;; Bad (let* ((low 1) (high 2) (sum (+ (* low low) (* high high)))) ...) ;; Better (let* ((low 1) (high 2) (sum (+ (* low low) (* high high)))) ...))

You must align nested forms if they occur across more than one line.

;; Bad (defun munge (a b c) (* (+ a b) c)) ;; Better (defun munge (a b c) (* (+ a b) c))

The convention is that the body of a binding form is indented two spaces after the form. Any binding data before the body is usually indented four spaces. Arguments to a function call are aligned with the first argument; if the first argument is on its own line, it is aligned with the function name.

(multiple-value-bind (a b c d) (function-returning-four-values x y) (declare (ignore c)) (something-using a) (also-using b d))

An exception to the rule against lonely parentheses is made for an eval-when form around several definitions; in this case, include a comment ; eval-when after the closing parenthesis.

You must set your editor to avoid inserting tab characters in the files you edit. Tabs cause confusion when editors disagree on how many spaces they represent. In Emacs, do (setq-default indent-tabs-mode nil).

You should use document strings on all visible functions to explain how to use your code.

Unless some bit of code is painfully self-explanatory, document it with a documentation string (also known as docstring).

Documentation strings are destined to be read by the programmers who use your code. They can be extracted from functions, types, classes, variables and macros, and displayed by programming tools, such as IDEs, or by REPL queries such as (describe 'foo); web-based documentation or other reference works can be created based on them. Documentation strings are thus the perfect locus to document your API. They should describe how to use the code (including what pitfalls to avoid), as opposed to how the code works (and where more work is needed), which is what you'll put in comments.

Supply a documentation string when defining top-level functions, types, classes, variables and macros. Generally, add a documentation string wherever the language allows.

For functions, the docstring should describe the function's contract: what the function does, what the arguments mean, what values are returned, what conditions the function can signal. It should be expressed at the appropriate level of abstraction, explaining the intended meaning rather than, say, just the syntax. In documentation strings, capitalize the names of Lisp symbols, such as function arguments. For example, "The value of LENGTH should be an integer."

(defun small-prime-number-p (n) "Return T if N, an integer, is a prime number. Otherwise, return NIL." (cond ((or (< n 2)) nil) ((= n 2) t) ((divisorp 2 n) nil) (t (loop for i from 3 upto (sqrt n) by 2 never (divisorp i n))))) (defgeneric table-clear (table) (:documentation "Like clrhash, empties the TABLE of all associations, and returns the table itself."))

A long docstring may usefully begin with a short, single-sentence summary, followed by the larger body of the docstring.

When the name of a type is used, the symbol may be quoted by surrounding it with a back quote at the beginning and a single quote at the end. Emacs will highlight the type, and the highlighting serves as a cue to the reader that M-. will lead to the symbol's definition.

(defun bag-tag-expected-itinerary (bag-tag) "Return a list of `legacy-pnr-pax-segment' objects representing the expected itinerary of the `bag-tag' object, BAG-TAG." ...)

Every method of a generic function should be independently documented when the specialization affects what the method does, beyond what is described in its generic function's docstring.

When you fix a bug, consider whether what the fixed code does is obviously correct or not; if not, you must add a comment explaining the reason for the code in terms of fixing the bug. Adding the bug number, if any, is also recommended.

You must use the appropriate number of semicolons to introduce comments.

Comments are explanations to the future maintainers of the code. Even if you're the only person who will ever see and touch the code, even if you're either immortal and never going to quit, or unconcerned with what happens after you leave (and have your code self-destruct in such an eventuality), you may find it useful to comment your code. Indeed, by the time you revisit your code, weeks, months or years later, you will find yourself a different person from the one who wrote it, and you will be grateful to that previous self for making the code readable.

You must comment anything complicated so that the next developer can understand what's going on. (Again, the "hit by a truck" principle.)

Also use comments as a way to guide those who read the code, so they know what to find where.

  • File headers and important comments that apply to large sections of code in a source file should begin with four semicolons.
  • You should use three semicolons to begin comments that apply to just one top-level form or small group of top-level forms.
  • Inside a top-level form, you should use two semicolons to begin a comment if it appears between lines.
  • You should use one semicolon if it is a parenthetical remark and occurs at the end of a line. You should use spaces to separate the comment from the code it refers to so the comment stands out. You should try to vertically align consecutive related end-of-line comments.
;;;; project-euler.lisp ;;;; File-level comments or comments for large sections of code. ;;; Problems are described in more detail here: https://projecteuler.net/ ;;; Divisibility ;;; Comments that describe a group of definitions. (defun divisorp (d n) (zerop (mod n d))) (defun proper-divisors (n) ...) (defun divisors (n) (cons n (proper-divisors n))) ;;; Prime numbers (defun small-prime-number-p (n) (cond ((or (< n 2)) nil) ((= n 2) ; parenthetical remark here t) ; continuation of the remark ((divisorp 2 n) nil) ; different remark ;; Comment that applies to a section of code. (t (loop for i from 3 upto (sqrt n) by 2 never (divisorp i n)))))

You should include a space between the semicolon and the text of the comment.

You should punctuate documentation correctly.

When a comment is a full sentence, you should capitalize the initial letter of the first word and end the comment with a period. In general, you should use correct punctuation.

You must follow the convention of using TODO comments for code requiring special attention. For code using unobvious forms, you must include a comment.

For comments requiring special attention, such as incomplete code, todo items, questions, breakage, and danger, include a TODO comment indicating the type of problem, its nature, and any notes on how it may be addressed.

The comments begin with TODO in all capital letters, followed by the name, e-mail address, or other identifier of the person with the best context about the problem referenced by the TODO. The main purpose is to have a consistent TODO that can be searched to find out how to get more details upon request. A TODO is not a commitment that the person referenced will fix the problem. Thus when you create a TODO, it is almost always your name that is given.

When signing comments, you should use your username (for code within the company) or full email address (for code visible outside the company), not just initials.

;;--- TODO(george@gmail.com): Refactor to provide a better API.

Be specific when indicating times or software releases in a TODO comment and use YYYY-MM-DD format for dates to make automated processing of such dates easier, e.g., 2038-01-20 for the end of the 32-bit signed time_t.

;;--- TODO(brown): Remove this code after release 1.7 or before 2012-11-30.

For code that uses unobvious forms to accomplish a task, you must include a comment stating the purpose of the form and the task it accomplishes.

You should document DSLs and any terse program in a DSL.

You should design your Domain Specific Language to be easy to read and understand by people familiar with the domain.

You must properly document all your Domain Specific Language.

Sometimes, your DSL is designed for terseness. In that case, it is important to document what each program does, if it's not painfully obvious from the context.

Notably, when you use regular expressions (e.g. with the CL-PPCRE package), you MUST ALWAYS put in a comment (usually a two-semicolon comment on the previous line) explaining, at least basically, what the regular expression does, or what the purpose of using it is. The comment need not spell out every bit of the syntax, but it should be possible for someone to follow the logic of the code without actually parsing the regular expression.

You should use lower case. You should follow the rules for Spelling and Abbreviations You should follow punctuation conventions.

Use lower case for all symbols. Consistently using lower case makes searching for symbol names easier and is more readable.

Note that Common Lisp is case-converting, and that the symbol-name of your symbols will be upper case. Because of this case-converting, attempts to distinguish symbols by case are defeated, and only result in confusion. While it is possible to escape characters in symbols to force lower case, you should not use this capability unless this is somehow necessary to interoperate with third-party software.

Place hyphens between all the words in a symbol. If you can't easily say an identifier out loud, it is probably badly named.

You must not use "/" or "." instead of "-" unless you have a well-documented overarching reason to, and permission from other hackers who review your proposal.

See the section on Spelling and Abbreviations for guidelines on using abbreviations.

;; Bad (defvar *default-username* "Ann") (defvar *max-widget-cnt* 200) ;; Better (defvar *default-user-name* "Ann") (defvar *maximum-widget-count* 200)

There are conventions in Common Lisp for the use of punctuation in symbols. You should not use punctuation in symbols outside these conventions.

Unless the scope of a variable is very small, do not use overly short names like i and zq.

Name your variables according to their intent, not their content.

You should name a variable according to the high-level concept that it represents, not according to the low-level implementation details of how the concept is represented.

Thus, you should avoid embedding data structure or aggregate type names, such as list, array, or hash-table inside variable names, unless you're writing a generic algorithm that applies to arbitrary lists, arrays, hash-tables, etc. In that case it's perfectly OK to name a variable list or array.

Indeed, you should be introducing new abstract data types with DEFCLASS or DEFTYPE, whenever a new kind of intent appears for objects in your protocols. Functions that manipulate such objects generically may then use variables the name of which reflect that abstract type.

For example, if a variable's value is always a row (or is either a row or NIL), it's good to call it row or first-row or something like that. It is alright is row has been DEFTYPE'd to STRING — precisely because you have abstracted the detail away, and the remaining salient point is that it is a row. You should not name the variable STRING in this context, except possibly in low-level functions that specifically manipulate the innards of rows to provide the suitable abstraction.

Be consistent. If a variable is named row in one function, and its value is being passed to a second function, then call it row rather than, say, value (this was a real case).

Name globals according to convention.

The names of global constants should start and end with plus characters.

Global variable names should start and end with asterisks (also known in this context as earmuffs).

In some projects, parameters that are not meant to be usually modified or bound under normal circumstances (but may be during experimentation or exceptional situations) should start (but do not end) with a dollar sign. If such a convention exists within your project, you should follow it consistently. Otherwise, you should avoid naming variables like this.

Common Lisp does not have global lexical variables, so a naming convention is used to ensure that globals, which are dynamically bound, never have names that overlap with local variables. It is possible to fake global lexical variables with a differently named global variable and a DEFINE-SYMBOL-MACRO. You should not use this trick, unless you first publish a library that abstracts it away.

(defconstant +hash-results+ #xbd49d10d10cbee50) (defvar *maximum-search-depth* 100)
Names of predicate functions and variables end with a "P".

You should name boolean-valued functions and variables with a trailing "P" or "-P", to indicate they are predicates. Generally, you should use "P" when the rest of the function name is one word and "-P" when it is more than one word.

A rationale for this convention is given in the CLtL2 chapter on predicates.

For uniformity, you should follow the convention above, and not one of the alternatives below.

An alternative rule used in some existing packages is to always use "-P". Another alternative rule used in some existing packages is to always use "?". When you develop such a package, you must be consistent with the rest of the package. When you start a new package, you should not use such an alternative rule without a very good documented reason.

You should not include a library or package name as a prefix within the name of symbols.

When naming a symbol (external or internal) in a package, you should not include the package name as a prefix within the name of the symbol. Naming a symbol this way makes it awkward to use from a client package accessing the symbol by qualifying it with a package prefix, where the package name then appears twice (once as a package prefix, another time as a prefix within the symbol name).

;; Bad (in-package #:varint) (defun varint-length64 () ... ) (in-package #:client-code) (defconst +padding+ (varint:varint-length64 +end-token+)) ;; Better (in-package #:varint) (defun length64 () ... ) (in-package #:client-code) (defconst +padding+ (varint:length64 +end-token+))

An exception to the above rule would be to include a prefix for the names of variables that would otherwise be expected to clash with variables in packages that use the current one. For instance, ASDF exports a variable *ASDF-VERBOSE* that controls the verbosity of ASDF only, rather than of the entire Lisp program.

Use packages appropriately.

Lisp packages are used to demarcate namespaces. Usually, each system has its own namespace. A package has a set of external symbols, which are intended to be used from outside the package, in order to allow other modules to use this module's facilities.

The internal symbols of a package should never be referred to from other packages. That is, you should never have to use the double-colon :: construct. (e.g. QUAKE::HIDDEN-FUNCTION). If you need to use double-colons to write real production code, something is wrong and needs to be fixed.

As an exception, unit tests may use the internals of the package being tested. So when you refactor, watch out for internals used by the package's unit tests.

The :: construct is also useful for very temporary hacks, and at the REPL. But if the symbol really is part of the externally-visible definition of the package, export it.

You may find that some internal symbols represent concepts you usually want to abstract away and hide under the hood, yet at times are necessary to expose for various extensions. For the former reason, you do not want to export them, yet for the latter reason, you have to export them. The solution is to have two different packages, one for your normal users to use, and another for the implementation and its extenders to use.

Each package is one of two types:

  • Intended to be included in the :use specification of other packages. If package A "uses" package B, then the external symbols of package B can be referenced from within package A without a package prefix. We mainly use this for low-level modules that provide widely-used facilities.
  • Not intended to be "used". To reference a facility provided by package B, code in package A must use an explicit package prefix, e.g. B:DO-THIS.

If you add a new package, it should always be of the second type, unless you have a special reason and get permission. Usually a package is designed to be one or the other, by virtue of the names of the functions. For example, if you have an abstraction called FIFO, and it were in a package of the first type you'd have functions named things like FIFO-ADD-TO and FIFO-CLEAR-ALL. If you used a package of the second type, you'd have names like ADD-TO and CLEAR-ALL, because the callers would be saying FIFO:ADD-TO and FIFO:CLEAR-ALL. (FIFO:FIFO-CLEAR-ALL is redundant and ugly.)

Another good thing about packages is that your symbol names won't "collide" with the names of other packages, except the ones your packages "uses". So you have to stay away from symbols that are part of the Lisp implementation (since you always "use" that) and that are part of any other packages you "use", but otherwise you are free to make up your own names, even short ones, and not worry about some else having used the same name. You're isolated from each other.

Your package must not shadow (and thus effectively redefine) symbols that are part of the Common Lisp language. There are certain exceptions, but they should be very well-justified and extremely rare:

  • If you are explicitly replacing a Common Lisp symbol by a safer or more featureful version.
  • If you are defining a package not meant to be "used", and have a good reason to export a symbol that clashes with Common Lisp, such as log:error and log:warn and so on.
You should avoid side-effects when they are not necessary.

Lisp is best used as a "mostly functional" language.

Avoid modifying local variables, try rebinding instead.

Avoid creating objects and the SETFing their slots. It's better to set the slots during initialization.

Make classes as immutable as possible, that is, avoid giving slots setter functions if at all possible.

Using a mostly functional style makes it much easier to write concurrent code that is thread-safe. It also makes it easier to test the code.

You should favor iteration over recursion.

Common Lisp systems are not required to implement function calls from tail positions without leaking stack space — which is known as proper tail calls (PTC), tail call elimination (TCE), or tail call optimization (TCO). This means that indefinite recursion through tail calls may quickly blow out the stack, which hampers functional programming. Still, most serious implementations (including SBCL and CCL) do implement proper tail calls, but with restrictions:

  • The (DECLARE (OPTIMIZE ...)) settings must favor SPEED enough and not favor DEBUG too much, for some compiler-dependent meanings of "enough" and "too much". (For instance, in SBCL, you should avoid (SPEED 0) and (DEBUG 3) to achieve proper tail calls.)
  • There should not be dynamic bindings around the call (even though some Scheme compilers are able to properly treat such dynamic bindings, called parameters in Scheme parlance).

For compatibility with all compilers and optimization settings, and to avoid stack overflow when debugging, you should prefer iteration or the built in mapping functions to relying on proper tail calls.

If you do rely on proper tail calls, you must prominently document the fact, and take appropriate measures to ensure an appropriate compiler is used with appropriate optimization settings. For fully portable code, you may have to use trampolines instead.

Use special variables sparingly.

Using Lisp "special" (dynamically bound) variables as implicit arguments to functions should be used sparingly, and only in cases where it won't surprise the person reading the code, and where it offers significant benefits.

Indeed, each special variable constitutes state. Developers have to mentally track the state of all relevant variables when trying to understand what the code does and how it does it; tests have to be written and run with all relevant combinations; to isolate some activity, care has to be taken to locally bind all relevant variables, including those of indirectly used modules. They can hide precious information from being printed in a backtrace. Not only is there overhead associated to each new variable, but interactions between variables can make the code exponentially more complex as the number of such variables increases. The benefits have to match the costs.

Note though that a Lisp special variable is not a global variable in the sense of a global variable in, say, BASIC or C. As special variables can be dynamically bound to a local value, they are much more powerful than global value cells where all users necessarily interfere with each other.

Good candidates for such special variables are items for which "the current" can be naturally used as prefix, such as "the current database connection" or "the current business data source". They are singletons as far as the rest of the code is concerned, and often passing them as an explicit argument does not add anything to the readability or maintainability of the source code in question.

They can make it easier to write code that can be refactored. If you have a request processing chain, with a number of layers that all operate upon a "current" request, passing the request object explicitly to every function requires that every function in the chain have a request argument. Factoring out code into new functions often requires that these functions also have this argument, which clutters the code with boilerplate.

You should treat special variables as though they are per-thread variables. By default, you should leave a special variable with no top-level binding at all, and each thread of control that needs the variable should bind it explicitly. This will mean that any incorrect use of the variable will result in an "unbound variable" error, and each thread will see its own value for the variable. Variables with a default global value should usually be locally bound at thread creation time. You should use suitable infrastructure to automate the appropriate declaration of such variables.

Be consistent in assignment forms.

There are several styles for dealing with assignment and side-effects; whichever a given package is using, keep using the same consistently when hacking said package. Pick a style that makes sense when starting a new package.

Regarding multiple assignment in a same form, there are two schools: the first style groups as many assignments as possible into a single SETF or PSETF form thus minimizing the number of forms with side-effects; the second style splits assignments into as many individual SETF (or SETQ, see below) forms as possible, to maximize the chances of locating forms that modify a kind of place by grepping for (setf (foo .... A grep pattern must actually contain as many place-modifying forms as you may use in your programs, which may make this rationale either convincing or moot depending on the rest of the style of your code. You should follow the convention used in the package you are hacking. We recommend the first convention for new packages.

Regarding SETF and SETQ, there are two schools: this first regards SETQ as an archaic implementation detail, and avoids it entirely in favor of SETF; the second regards SETF as an additional layer of complexity, and avoids it in favor of SETQ whenever possible (i.e. whenever the assigned place is a variable or symbol-macro). You should follow the convention used in the package you are hacking. We recommend the first convention for new packages.

In the spirit of a mostly pure functional style, which makes testing and maintenance easier, we invite you to consider how to do things with the fewest assignments required.

You must make proper usage of assertions and conditions.
  • ASSERT should be used ONLY to detect internal bugs. Code should ASSERT invariants whose failure indicates that the software is itself broken. Incorrect input should be handled properly at runtime, and must not cause an assertion violation. The audience for an ASSERT failure is a developer. Do not use the data-form and argument-form in ASSERT to specify a condition to signal. It's fine to use them to print out a message for debugging purposes (and since it's only for debugging, there's no issue of internationalization).
  • CHECK-TYPE, ETYPECASE are also forms of assertion. When one of these fails, that's a detected bug. You should prefer to use CHECK-TYPE over (DECLARE (TYPE ...)) for the inputs of functions.
  • Your code should use assertions and type checks liberally. The sooner a bug is discovered, the better! Only code in the critical path for performance and internal helpers should eschew explicit assertions and type checks.
  • Invalid input, such as files that are read but do not conform to the expected format, should not be treated as assertion violations. Always check to make sure that input is valid, and take appropriate action if it is not, such as signalling a real error.
  • ERROR should be used to detect problems with user data, requests, permissions, etc., or to report "unusual outcomes" to the caller.
  • ERROR should always be called with an explicit condition type; it should never simply be called with a string. This enables internationalization.
  • Functions that report unusual outcomes by signaling a condition should say so explicitly in their contracts (their textual descriptions, in documentation and docstrings etc.). When a function signals a condition that is not specified by its contract, that's a bug. The contract should specify the condition class(es) clearly. The function may then signal any condition that is a type-of any of those conditions. That is, signaling instances of subclasses of the documented condition classes is fine.
  • Complex bug-checks may need to use ERROR instead of ASSERT.
  • When writing a server, you must not call WARN. Instead, you should use the appropriate logging framework.
  • Code must not call SIGNAL. Instead, use ERROR or ASSERT.
  • Code should not use THROW and CATCH; instead use the restart facility.
  • Code should not generically handle all conditions, e.g. type T, or use IGNORE-ERRORS. Instead, let unknown conditions propagate to the standard ultimate handler for processing.
  • There are a few places where handling all conditions is appropriate, but they are rare. The problem is that handling all conditions can mask program bugs. If you do need to handle "all conditions", you MUST handle only ERROR, not T and not SERIOUS-CONDITION. (This is notably because CCL's process shutdown depends on being able to signal process-reset and have it handled by CCL's handler, so we must not interpose our own handler.)
  • (error (make-condition 'foo-error ...)) is equivalent to (error 'foo-error ...) — code must use the shorter form.
  • Code should not signal conditions from inside the cleanup form of UNWIND-PROTECT (unless they are always handled inside the cleanup form), or otherwise do non-local exits from cleanup handlers outside of the handler e.g. INVOKE-RESTART.
  • Do not clean up by resignaling. If you do that, and the condition is not handled, the stack trace will halt at the point of the resignal, hiding the rest. And the rest is the part we really care about! ;; Bad (handler-case (catch 'ticket-at (etd-process-blocks)) (error (c) (reset-parser-values) (error c))) ;; Better (unwind-protect (catch 'ticket-at (etd-process-blocks)) (reset-parser-values))
If you know the type of something, you should make it explicit in order to enable compile-time and run-time sanity-checking.

If your function is using a special variable as an implicit argument, it's good to put in a CHECK-TYPE for the special variable, for two reasons: to clue in the person reading the code that this variable is being used implicitly as an argument, and also to help detect bugs.

Using (declare (type ...)) is the least-desirable mechanism to use because, as Scott McKay puts it:

The fact is, (declare (type ...)) does different things depending on the compiler settings of speed, safety, etc. In some compilers, when speed is greater than safety, (declare (type ...)) will tell the compiler "please assume that these variables have these types" without generating any type-checks. That is, if some variable has the value 1432 in it, and you declare it to be of type string, the compiler might just go ahead and use it as though it's a string.

Moral: don't use (declare (type ...)) to declare the contract of any API functions, it's not the right thing. Sure, use it for "helper" functions, but not API functions.

You should, of course, use appropriate declarations in internal low-level functions where these declarations are used for optimization. When you do, however, see our recommendations for Unsafe Operations.

Use CLOS appropriately.

When a generic function is intended to be called from other modules (other parts of the code), there should be an explicit DEFGENERIC form, with a :DOCUMENTATION string explaining the generic contract of the function (as opposed to its behavior for some specific class). It's generally good to do explicit DEFGENERIC forms, but for module entry points it is mandatory.

When the argument list of a generic function includes &KEY, the DEFGENERIC should always explicitly list all of the keyword arguments that are acceptable, and explain what they mean. (Common Lisp does not require this, but it is good form, and it may avoid spurious warnings on SBCL.)

You should avoid SLOT-VALUE and WITH-SLOTS, unless you absolutely intend to circumvent any sort of method combination that might be in effect for the slot. Rare exceptions include INITIALIZE-INSTANCE and PRINT-OBJECT methods and accessing normally hidden slots in the low-level implementation of methods that provide user-visible abstractions. Otherwise, you should use accessors, WITH-ACCESSORS

Accessor names generally follow a convention of <protocol-name>-<slot-name>, where a "protocol" in this case loosely indicates a set of functions with well-defined behavior.

No implication of a formal "protocol" concept is necessarily intended, much less first-class "protocol" objects. However, there may indeed be an abstract CLOS class or an Interface-Passing Style interface that embodies the protocol. Further (sub)classes or (sub)interfaces may then implement all or part of a protocol by defining some methods for (generic) functions in the protocol, including readers and writers.

For example, if there were a notional protocol called is pnr with accessors pnr-segments and pnr-passengers, then the classes air-pnr, hotel-pnr and car-pnr could each reasonably implement methods for pnr-segments and pnr-passengers as accessors.

By default, an abstract base class name is used as the notional protocol name, so accessor names default to <class-name>-<slot-name>; while such names are thus quite prevalent, this form is neither required nor even preferred. In general, it contributes to "symbol bloat", and in many cases has led to a proliferation of "trampoline" methods.

Accessors named <slot-name>-of should not be used.

Explicit DEFGENERIC forms should be used when there are (or it is anticipated that there will be) more than one DEFMETHOD for that generic function. The reason is that the documentation for the generic function explains the abstract contract for the function, as opposed to explaining what an individual method does for some specific class(es).

You must not use generic functions where there is no notional protocol. To put it more concretely, if you have more than one generic function that specializes its Nth argument, the specializing classes should all be descendants of a single class. Generic functions must not be used for "overloading", i.e. simply to use the same name for two entirely unrelated types.

More precisely, it's not really whether they descend from a common superclass, but whether they obey the same "protocol". That is, the two classes should handle the same set of generic functions, as if there were an explicit DEFGENERIC for each method.

Here's another way to put it. Suppose you have two classes, A and B, and a generic function F. There are two methods for F, which dispatch on an argument being of types A and B. Is it plausible that there might be a function call somewhere in the program that calls F, in which the argument might sometimes, at runtime, be of class A and other times be of class B? If not, you probably are overloading and should not be using a single generic function.

We allow one exception to this rule: it's OK to do overloading if the corresponding argument "means" the same thing. Typically one overloading allows an X object, and the other allows the name of an X object, which might be a symbol or something.

You must not use MOP "intercessory" operations at runtime. You should not use MOP "intercessory" operations at compile-time. At runtime, they are at worst a danger, at best a performance issue. At compile-time, it is usually cleaner that macros should set things up the right way in one pass than have to require a second pass of fixups through intercession; but sometimes, fixups are necessary to resolve forward references, and intercession is allowed then. MOP intercession is a great tool for interactive development, and you may enjoy it while developping and debugging; but you should not use it in normal applications.

If a class definition creates a method as a :READER, :WRITER, or :ACCESSOR, do not redefine that method. It's OK to add :BEFORE, :AFTER, and :AROUND methods, but don't override the primary method.

In methods with keyword arguments, you must always use &KEY, even if the method does not care about the values of any keys, and you should never use &ALLOW-OTHER-KEYS. As long as a keyword is accepted by any method of a generic function, it's OK to use it in the generic function, even if the other methods of the same generic function don't mention it explicitly. This is particularly important for INITIALIZE-INSTANCE methods, since if you did use &ALLOW-OTHER-KEYS, it would disable error checking for misspelled or wrong keywords in MAKE-INSTANCE calls!

A typical PRINT-OBJECT method might look like this:

(defmethod print-object ((p person) stream) (print-unreadable-object (p stream :type t :identity t) (with-slots (first-name last-name) p (safe-format stream "~a ~a" first-name last-name))))
Use macros when appropriate, which is often. Define macros when appropriate, which is seldom.

Macros bring syntactic abstraction, which is a wonderful thing. It helps make your code clearer, by describing your intent without getting bogged in implementation details (indeed abstracting those details away). It helps make your code more concise and more readable, by eliminating both redundancy and irrelevant details. But it comes at a cost to the reader, which is learning a new syntactic concept for each macro. And so it should not be abused.

The general conclusion is that there shouldn't be any recognizable design pattern in a good Common Lisp program. The one and only pattern is: use the language, which includes defining and using syntactic abstractions.

Existing macros must be used whenever they make code clearer by conveying intent in a more concise way, which is often. When a macro is available in your project that expresses the concept you're using, you must not write the expansion rather than use the macro.

New macros should be defined as appropriate, which should be seldom, for common macros have already been provided by the language and its various libraries, and your program typically only needs few new ones relative to its size.

You should follow the OAOOM rule of thumb for deciding when to create a new abstraction, whether syntactic or not: if a particular pattern is used more than twice, it should probably be abstracted away. A more refined rule to decide when to use abstraction should take into account the benefit in term of number of uses and gain at each use, to the costs in term of having to get used to reading the code. For syntactic abstractions, costs and benefits to the reader is usually more important than costs and benefits to the writer, because good code is usually written once and read many times by many people (including the same programmer who has to maintain the program after having forgotten it). Yet the cost to the writer of the macro should also be taken into account; however, in doing so it should rather be compared to the cost of the programmer writing other code instead that may have higher benefits.

Using Lisp macros properly requires taste. Avoid writing complicated macros unless the benefit clearly outweighs the cost. It takes more effort for your fellow developers to learn your macro, so you should only use a macro if the gain in expressiveness is big enough to justify that cost. As usual, feel free to consult your colleagues if you're not sure, since without a lot of Lisp experience, it can be hard to make this judgment.

You must never use a macro where a function will do. That is, if the semantics of what you are writing conforms to the semantics of a function, then you must write it as a function rather than a macro.

You must not transform a function into a macro for performance reasons. If profiling shows that you have a performance problem with a specific function FOO, document the need and profiling-results appropriately, and (declaim (inline foo)).

You can also use a compiler-macro as a way to speed up function execution by specifying a source-to-source transformation. Beware that it interferes with tracing the optimized function.

When you write a macro-defining macro (a macro that generates macros), document and comment it particularly clearly, since these are harder to understand.

You must not install new reader macros without a consensus among the developers of your system. Reader macros must not leak out of the system that uses them to clients of that system or other systems used in the same project. You must use software such as cl-syntax or named-readtables to control how reader macros are used. This clients who desire it may use the same reader macros as you do. In any case, your system must be usable even to clients who do not use these reader macros.

If your macro has a parameter that is a Lisp form that will be evaluated when the expanded code is run, you should name the parameter with the suffix -form. This convention helps make it clearer to the macro's user which parameters are Lisp forms to be evaluated, and which are not. The common names body and end are exceptions to this rule.

You should follow the so-called CALL-WITH style when it applies. This style is explained at length in http://random-state.net/log/3390120648.html. The general principle is that the macro is strictly limited to processing the syntax, and as much of the semantics as possible is kept in normal functions. Therefore, a macro WITH-FOO is often limited to generating a call to an auxiliary function CALL-WITH-FOO with arguments deduced from the macro arguments. Macro &body arguments are typically wrapped into a lambda expression of which they become the body, which is passed as one of the arguments of the auxiliary function.

The separation of syntactic and semantic concerns is a general principle of style that applies beyond the case of WITH- macros. Its advantages are many. By keeping semantics outside the macro, the macro is made simpler, easier to get right, and less subject to change, which makes it easier to develop and maintain. The semantics is written in a simpler language — one without staging — which also makes it easier to develop and maintain. It becomes possible to debug and update the semantic function without having to recompile all clients of the macro. The semantic function appears in the stack trace which also helps debug client functions. The macro expansion is made shorter and each expansion shares more code with other expansions, which reduces memory pressure which in turn usually makes things faster. It also makes sense to write the semantic functions first, and write the macros last as syntactic sugar on top. You should use this style unless the macro is used in tight loops where performance matters; and even then, see our rules regarding optimization.

Any functions (closures) created by the macro should be named, which can be done using FLET. This also allows you to declare the function to be of dynamic extent (if it is — and often it is; yet see below regarding DYNAMIC-EXTENT).

If a macro call contains a form, and the macro expansion includes more than one copy of that form, the form can be evaluated more than once, and code it contains macro-expanded and compiled more than once. If someone uses the macro and calls it with a form that has side effects or that takes a long time to compute, the behavior will be undesirable (unless you're intentionally writing a control structure such as a loop). A convenient way to avoid this problem is to evaluate the form only once, and bind a (generated) variable to the result. There is a very useful macro called ALEXANDRIA:ONCE-ONLY that generates code to do this. See also ALEXANDRIA:WITH-GENSYMS, to make some temporary variables in the generated code. Note that if you follow our CALL-WITH style, you typically expand the code only once, as either an argument to the auxiliary function, or the body of a lambda passed as argument to it; you therefore avoid the above complexity.

When you write a macro with a body, such as a WITH-xxx macro, even if there aren't any parameters, you should leave space for them anyway. For example, if you invent WITH-LIGHTS-ON, do not make the call to it look like (defmacro with-lights-on (&body b) ...). Instead, do (defmacro with-lights-on (() &body b) ...). That way, if parameters are needed in the future, you can add them without necessarily having to change all the uses of the macro.

When using EVAL-WHEN, you should almost always use all of (:compile-toplevel :load-toplevel :execute).

Lisp evaluation happens at several times, some of them interleaved. Be aware of them when writing macros. EVAL-WHEN considered harmful to your mental health.

In summary of the article linked above, unless you're doing truly advanced macrology, the only valid combination in an EVAL-WHEN is to include all of (eval-when (:compile-toplevel :load-toplevel :execute) ...)

You must use (eval-when (:compile-toplevel :load-toplevel :execute) ...) whenever you define functions, types, classes, constants, variables, etc., that are going to be used in macros.

It is usually an error to omit the :execute, because it prevents LOADing the source rather than the fasl. It is usually an error to omit the :load-toplevel (except to modify e.g. readtables and compile-time settings), because it prevents LOADing future files or interactively compiling code that depends on the effects that happen at compile-time, unless the current file was COMPILE-FILEd within the same Lisp session.

Regarding variables, note that because macros may or may not be expanded in the same process that runs the expanded code, you must not depend on compile-time and runtime effects being either visible or invisible at the other time. There are still valid uses of variables in macros:

  • Some variables may hold dictionaries for some new kind of definition and other meta-data. If such meta-data is to be visible at runtime and/or in other files, you must make sure that the macro expands into code that will register the definitions to those meta-data structures at load-time, in addition to effecting the registration at compile-time. Typically, your top-level definitions expand to code that does the registration. if your code doesn't expand at the top-level, you can sometimes use LOAD-TIME-VALUE for good effect. In extreme cases, you may have to use ASDF-FINALIZERS:EVAL-AT-TOPLEVEL.
  • Some variables may hold temporary data that is only used at compile-time in the same file, and can be cleaned up at the end of the file's compilation. Predefined such variables would include *readtable* or compiler-internal variables holding the current optimization settings. You can often manage existing and new such variables using the :AROUND-COMPILE hooks of ASDF.
You should use #. sparingly, and you must avoid read-time side-effects.

The #. standard read-macro will read one object, evaluate the object, and have the reader return the resulting value.

You must not use it where other idioms will do, such as using EVAL-WHEN to evaluate side-effects at compile-time, using a regular macro to return an expression computed at compile-time, using LOAD-TIME-VALUE to compute it at load-time.

Read-time evaluation is often used as a quick way to get something evaluated at compile time (actually "read time" but it amounts to the same thing). If you use this, the evaluation MUST NOT have any side effects and MUST NOT depend on any variable global state. The #. should be treated as a way to force "constant-folding" that a sufficiently-clever compiler could have figure out all by itself, when the compiler isn't sufficiently-clever and the difference matters.

Another use of #. is to expand the equivalent of macros in places that are neither expressions nor (quasi)quotations, such as lambda-lists. However, if you find yourself using it a lot, it might be time to instead define macros to replace your consumers of lambda-lists with something that recognizes an extension.

Whenever you are going to use #., you should consider using DEFCONSTANT and its variants, possibly in an EVAL-WHEN, to give the value a name explaining what it means.

You must not use EVAL at runtime.

Places where it is actually appropriate to use EVAL are so few and far between that you must consult with your reviewers; it's easily misused.

If your code manipulates symbols at runtime and needs to get the value of a symbol, use SYMBOL-VALUE, not EVAL.

Often, what you really need is to write a macro, not to use EVAL.

You may be tempted to use EVAL as a shortcut to evaluating expressions in a safe subset of the language. But it often requires more scrutiny to properly check and sanitize all possible inputs to such use of EVAL than to build a special-purpose evaluator. You must not use EVAL in this way at runtime.

Places where it is OK to use EVAL are:

  • The implementation of an interactive development tool.
  • The build infrastructure.
  • Backdoors that are part of testing frameworks. (You MUST NOT have such backdoors in production code.)
  • Macros that fold constants at compile-time.
  • Macros that register definitions to meta-data structures; the registration form is sometimes evaluated at compile-time as well as included in the macro-expansion, so it is immediately available to other macros.

Note that in the latter case, if the macro isn't going to be used at the top-level, it might not be possible to make these definitions available as part of the expansion. The same phenomenon may happen in a DEFTYPE expansion, or in helper functions used by macros. In these cases, you may actually have to use ASDF-FINALIZERS:EVAL-AT-TOPLEVEL in your macro. It will not only EVAL your definitions at macro-expansion time for immediate availability, it will also save the form aside, for inclusion in a (ASDF-FINALIZERS:FINAL-FORMS) that you need to include at the end of the file being compiled (or before the form is needed). This way, the side-effects are present when loading the fasl without having compiled it as well as while compiling it; in either case, the form is made available at load-time. ASDF-FINALIZERS ensures that the form is present, by throwing an error if you omit it.

You must not use INTERN or UNINTERN at runtime.

You must not use INTERN at runtime. Not only does it cons, it either creates a permanent symbol that won't be collected or gives access to internal symbols. This creates opportunities for memory leaks, denial of service attacks, unauthorized access to internals, clashes with other symbols.

You must not INTERN a string just to compare it to a keyword; use STRING= or STRING-EQUAL.

(member (intern str :keyword) $keys) ; Bad (member str $keys :test #'string-equal) ; Better

You must not use UNINTERN at runtime. It can break code that relies on dynamic binding. It makes things harder to debug. You must not dynamically intern any new symbol, and therefore you need not dynamically unintern anything.

You may of course use INTERN at compile-time, in the implementation of some macros. Even so, it is usually more appropriate to use abstractions on top of it, such as ALEXANDRIA:SYMBOLICATE or ALEXANDRIA:FORMAT-SYMBOL to create the symbols you need.

Appropriately use or avoid using NIL.

NIL can have several different interpretations:

  • "False." In this case, use NIL. You should test for false NIL using the operator NOT or using the predicate function NULL.
  • "Empty-list." In this case, use '(). (Be careful about quoting the empty-list when calling macros.) You should use ENDP to test for the empty list when the argument is known to be a proper list, or with NULL otherwise.
  • A statement about some value being unspecified. In this case, you may use NIL if there is no risk of ambiguity anywhere in your code; otherwise you should use an explicit, descriptive symbol.
  • A statement about some value being known not to exist. In this case, you should use an explicit, descriptive symbol instead of NIL.

You must not introduce ambiguity in your data representations that will cause headaches for whoever has to debug code. If there is any risk of ambiguity, you should use an explicit, descriptive symbol or keyword for each case, instead of using NIL for either. If you do use NIL, you must make sure that the distinction is well documented.

In many contexts, instead of representing "I don't know" as a particular value, you should instead use multiple values, one for the value that is known if any, and one to denote whether the value was known or found.

When working with database classes, keep in mind that NIL need not always map to 'NULL' (and vice-versa)! The needs of the database may differ from the needs of the Lisp.

You must select proper data representation. You must not abuse the LIST data structure.

Even though back in 1958, LISP was short for "LISt Processing", its successor Common Lisp has been a modern programming language with modern data structures since the 1980s. You must use the proper data structures in your programs.

You must not abuse the builtin (single-linked) LIST data structure where it is not appropriate, even though Common Lisp makes it especially easy to use it.

You must only use lists when their performance characteristics is appropriate for the algorithm at hand: sequential iteration over the entire contents of the list.

An exception where it is appropriate to use lists is when it is known in advance that the size of the list will remain very short (say, less than 16 elements).

List data structures are often (but not always) appropriate for macros and functions used by macros at compile-time: indeed, not only is source code passed as lists in Common Lisp, but the macro-expansion and compilation processes will typically walk over the entire source code, sequentially, once. (Note that advanced macro systems don't directly use lists, but instead use abstract syntax objects that track source code location and scope; however there is no such advanced macro system in Common Lisp at this time.)

Another exception where it is appropriate to use lists is for introducing literal constants that will be transformed into more appropriate data structures at compile-time or load-time. It is a good to have a function with a relatively short name to build your program's data structures from such literals.

In the many cases when lists are not the appropriate data structure, various libraries such as cl-containers or lisp-interface-library provide plenty of different data structures that should fulfill all the basic needs of your programs. If the existing libraries are not satisfactory, see above about Using Libraries and Open-Sourcing Code.

You should use the appropriate representation for product types.

You should avoid using a list as anything besides a container of elements of like type. You must not use a list as method of passing multiple separate values of different types in and out of function calls. Sometimes it is convenient to use a list as a little ad hoc structure, i.e. "the first element of the list is a FOO, and the second is a BAR", but this should be used minimally since it gets harder to remember the little convention. You must only use a list that way when destructuring the list of arguments from a function, or creating a list of arguments to which to APPLY a function.

The proper way to pass around an object comprising several values of heterogeneous types is to use a structure as defined by DEFSTRUCT or DEFCLASS.

You should use multiple values only when function returns a small number of values that are meant to be destructured immediately by the caller, rather than passed together as arguments to further functions.

You should not return a condition object as one of a set of multiple values. Instead, you should signal the condition to denote an unusual outcome.

You should signal a condition to denote an unusual outcome, rather than relying on a special return type.

Use the appropriate functions when manipulating lists.

Use FIRST to access the first element of a list, SECOND to access the second element, etc. Use REST to access the tail of a list. Use ENDP to test for the end of the list.

Use CAR and CDR when the cons cell is not being used to implement a proper list and is instead being treated as a pair of more general objects. Use NULL to test for NIL in this context.

The latter case should be rare outside of alists, since you should be using structures and classes where they apply, and data structure libraries when you want trees.

Exceptionally, you may use CDADR and other variants on lists when manually destructuring them, instead of using a combination of several list accessor functions. In this context, using CAR and CDR instead of FIRST and REST also makes sense. However, keep in mind that it might be more appropriate in such cases to use higher-level constructs such as DESTRUCTURING-BIND or OPTIMA:MATCH.

You should use arrays rather than lists where random access matters.

ELT has O(n) behavior when used on lists. If you are to use random element access on an object, use arrays and AREF instead.

The exception is for code outside the critical path where the list is known to be small anyway.

You should only use lists as sets for very small lists.

Using lists as representations of sets is a bad idea unless you know the lists will be small, for accessors are O(n) instead of O(log n). For arbitrary big sets, use balanced binary trees, for instance using lisp-interface-library.

If you still use lists as sets, you should not UNION lists just to search them.

(member foo (union list-1 list-2)) ; Bad (or (member foo list-1) (member foo list-2)) ; Better

Indeed, UNION not only conses unnecessarily, but it can be O(n^2) on some implementations, and is rather slow even when it's O(n).

You must follow the proper usage regarding well-known functions, macros and special forms.

You must use proper defining forms for constant values.

The Lisp system we primarily use, SBCL, is very picky and signals a condition whenever a constant is redefined to a value not EQL to its previous setting. You must not use DEFCONSTANT when defining variables that are not numbers, characters, or symbols (including booleans and keywords). Instead, consistently use whichever alternative is recommended for your project.

;; Bad (defconstant +google-url+ "https://www.google.com/") (defconstant +valid-colors+ '(red green blue))

Open-Source libraries may use ALEXANDRIA:DEFINE-CONSTANT for constants other than numbers, characters and symbols (including booleans and keywords). You may use the :TEST keyword argument to specify an equality predicate.

;; Better, for Open-Source code: (define-constant +google-url+ "https://www.google.com/" :test #'string=) (define-constant +valid-colors+ '(red green blue))

Note that with optimizing implementations, such as SBCL or CMUCL, defining constants this way precludes any later redefinition short of UNINTERNing the symbol and recompiling all its clients. This may make it "interesting" to debug things at the REPL or to deploy live code upgrades. If there is a chance that your "constants" are not going to be constant over the lifetime of your server processes after taking into consideration scheduled and unscheduled code patches, you should consider using DEFPARAMETER or DEFVAR instead, or possibly a variant of DEFINE-CONSTANT that builds upon some future library implementing global lexicals rather than DEFCONSTANT. You may keep the +plus+ convention in these cases to document the intent of the parameter as a constant.

Also note that LOAD-TIME-VALUE may help you avoid the need for defined constants.

You should make proper use of &OPTIONAL and &KEY arguments. You should not use &AUX arguments.

You should avoid using &ALLOW-OTHER-KEYS, since it blurs the contract of a function. Almost any real function (generic or not) allows a certain fixed set of keywords, as far as its caller is concerned, and those are part of its contract. If you are implementing a method of a generic function, and it does not need to know the values of some of the keyword arguments, you should explicitly (DECLARE (IGNORE ...)) all the arguments that you are not using. You must not use &ALLOW-OTHER-KEYS unless you explicitly want to disable checking of allowed keys for all methods when invoking the generic function on arguments that match this particular method. Note that the contract of a generic function belongs in the DEFGENERIC, not in the DEFMETHOD which is basically an "implementation detail" of the generic function as far as the caller of the generic is concerned.

A case where &ALLOW-OTHER-KEYS is appropriate is when you write a wrapper function to other some other functions that may vary (within the computation or during development), and pass around a plist as a &REST argument.

You should avoid using &AUX arguments.

You should avoid having both &OPTIONAL and &KEY arguments, unless it never makes sense to specify keyword arguments when the optional arguments are not all specified. You must not have non-NIL defaults to your &OPTIONAL arguments when your function has both &OPTIONAL and &KEY arguments.

For maximum portability of a library, it is good form that DEFMETHOD definitions should (DECLARE (IGNORABLE ...)) all the required arguments that they are not using. Indeed, some implementations will issue a warning if you (DECLARE (IGNORE ...)) those arguments, whereas other implementations will issue a warning if you fail to (DECLARE (IGNORE ...)) them. (DECLARE (IGNORABLE ...)) works on all implementations.

You should avoid excessive nesting of binding forms inside a function. If your function ends up with massive nesting, you should probably break it up into several functions or macros. If it is really a single conceptual unit, consider using a macro such as FARE-UTILS:NEST to at least reduce the amount of indentation required. It is bad form to use NEST in typical short functions with 4 or fewer levels of nesting, but also bad form not to use it in the exceptional long functions with 10 or more levels of nesting. Use your judgment and consult your reviewers.

Use the appropriate conditional form.

Use WHEN and UNLESS when there is only one alternative. Use IF when there are two alternatives and COND when there are several.

However, don't use PROGN for an IF clause — use COND, WHEN, or UNLESS.

Note that in Common Lisp, WHEN and UNLESS return NIL when the condition is not met. You may take advantage of it. Nevertheless, you may use an IF to explicitly return NIL if you have a specific reason to insist on the return value. You may similarly include a fall-through clause (t nil) as the last in your COND, or (otherwise nil) as the last in your CASE, to insist on the fact that the value returned by the conditional matters and that such a case is going to be used. You should omit the fall-through clause when the conditional is used for side-effects.

You should prefer AND and OR when it leads to more concise code than using IF, COND, WHEN or UNLESS, and there are no side-effects involved. You may also use an ERROR as a side-effect in the final clause of an OR.

You should only use CASE and ECASE to compare numbers, characters or symbols (including booleans and keywords). Indeed, CASE uses EQL for comparisons, so strings, pathnames and structures may not compare the way you expect, and 1 will differ from 1.0.

You should use ECASE and ETYPECASE in preference to CASE and TYPECASE. It is better to catch erroneous values early.

You should not use CCASE or CTYPECASE at all. At least, you should not use them in server processes, unless you have quite robust error handling infrastructure and make sure not to leak sensitive data this way. These are meant for interactive use, and can cause interesting damage if they cause data or control to leak to attackers.

You must not use gratuitous single quotes in CASE forms. This is a common error:

(case x ; Bad: silently returns NIL on mismatch ('bar :bar) ; Bad: catches QUOTE ('baz :baz)) ; Bad: also would catch QUOTE (ecase x ; Better: will error on mismatch ((bar) :bar) ; Better: won't match QUOTE ((baz) :baz)) ; Better: same reason

'BAR there is (QUOTE BAR), meaning this leg of the case will be executed if X is QUOTE... and ditto for the second leg (though QUOTE will be caught by the first clause). This is unlikely to be what you really want.

In CASE forms, you must use otherwise instead of t when you mean "execute this clause if the others fail". You must use ((t) ...) when you mean "match the symbol T" rather than "match anything". You must also use ((nil) ...) when you mean "match the symbol NIL" rather than "match nothing".

Therefore, if you want to map booleans NIL and T to respective symbols :BAR and :QUUX, you should avoid the former way and do it the latter way:

(ecase x ; Bad: has no actual error case! (nil :bar)) ; Bad: matches nothing (t :quux)) ; Bad: matches anything (ecase x ; Better: will actually catch non-booleans ((nil) :bar)) ; Better: matches NIL ((t) :quux)) ; Better: matches T
You should use the appropriate predicates when comparing objects.

Lisp provides four general equality predicates: EQ, EQL, EQUAL, and EQUALP, which subtly vary in semantics. Additionally, Lisp provides the type-specific predicates =, CHAR=, CHAR-EQUAL, STRING=, and STRING-EQUAL. Know the distinction!

You should use EQL to compare objects and symbols for identity.

You must not use EQ to compare numbers or characters. Two numbers or characters that are EQL are not required by Common Lisp to be EQ.

When choosing between EQ and EQL, you should use EQL unless you are writing performance-critical low-level code. EQL reduces the opportunity for a class of embarrassing errors (i.e. if numbers or characters are ever compared). There may a tiny performance cost relative to EQ, although under SBCL, it often compiles away entirely. EQ is equivalent to EQL and type declarations, and use of it for optimization should be treated just like any such unsafe operations.

You should use CHAR= for case-dependent character comparisons, and CHAR-EQUAL for case-ignoring character comparisons.

You should use STRING= for case-dependent string comparisons, and STRING-EQUAL for case-ignoring string comparisons.

A common mistake when using SEARCH on strings is to provide STRING= or STRING-EQUAL as the :TEST function. The :TEST function is given two sequence elements to compare. If the sequences are strings, the :TEST function is called on two characters, so the correct tests are CHAR= or CHAR-EQUAL. If you use STRING= or STRING-EQUAL, the result is what you expect, but in some Lisp implementations it's much slower. CCL (at least as of 8/2008) creates a one-character string upon each comparison, for example, which is very expensive.

Also, you should use :START and :END arguments to STRING= or STRING-EQUAL instead of using SUBSEQ; e.g. (string-equal (subseq s1 2 6) s2) should instead be (string-equal s1 s2 :start1 2 :end1 6) This is preferable because it does not cons.

You should use ZEROP, PLUSP, or MINUSP, instead of comparing a value to 0 or 0.0.

You must not use exact comparison on floating point numbers, since the vague nature of floating point arithmetic can produce little "errors" in numeric value. You should compare absolute values to a threshold.

You must use = to compare numbers, unless you really mean for 0, 0.0 and -0.0 to compare unequal, in which case you should use EQL. Then again, you must not usually use exact comparison on floating point numbers.

Monetary amounts should be using decimal (rational) numbers to avoid the complexities and rounding errors of floating-point arithmetic. Libraries such as wu-decimal may help you; once again, if this library is not satisfactory, see above about Using Libraries and Open-Sourcing Code.

Use the appropriate form for iteration.

You should use simpler forms such as DOLIST or DOTIMES instead of LOOP in simple cases when you're not going to use any of the LOOP facilities such as bindings, collection or block return.

Use the WITH clause of LOOP when it will avoid a level of nesting with LET. You may use LET if it makes it clearer to return one of bound variables after the LOOP, rather than use a clumsy FINALLY (RETURN ...) form.

In the body of a DOTIMES, do not set the iteration variable. (CCL will issue a compiler warning if you do.)

Most systems use unadorned symbols in the current package as LOOP keywords. Other systems use actual :keywords from the KEYWORD package as LOOP keywords. You must be consistent with the convention used in your system.

Use the appropriate I/O functions.

When writing a server, code must not send output to the standard streams such as *STANDARD-OUTPUT* or *ERROR-OUTPUT*. Instead, code must use the proper logging framework to output messages for debugging. We are running as a server, so there is no console!

Code must not use PRINT-OBJECT to communicate with a user — PRINT-OBJECT is for debugging purposes only. Modifying any PRINT-OBJECT method must not break any public interfaces.

You should not use a sequence of WRITE-XXX where a single FORMAT string could be used. Using format allows you to parameterize the format control string in the future if the need arises.

You should use WRITE-CHAR to emit a character rather than WRITE-STRING to emit a single-character string.

You should not use (format nil "~A" value); you should use PRINC-TO-STRING instead.

You should use ~<Newline> or ~@<Newline> in format strings to keep them from wrapping in 100-column editor windows, or to indent sections or clauses to make them more readable.

You should not use STRING-UPCASE or STRING-DOWNCASE on format control parameters; instead, it should use "~:@(~A~)" or "~(~A~)".

Be careful when using the FORMAT conditional directive. The parameters are easy to forget.

No parameters, e.g. "~[Siamese~;Manx~;Persian~] Cat"
Take one format argument, which should be an integer. Use it to choose a clause. Clause numbers are zero-based. If the number is out of range, just print nothing. You can provide a default value by putting a ":" in front of the last ";". E.g. in "~[Siamese~;Manx~;Persian~:;Alley~] Cat", an out-of-range arg prints "Alley".
: parameter, e.g. "~:[Siamese~;Manx~]"
Take one format argument. If it's NIL, use the first clause, otherwise use the second clause.
@ parameter, e.g. "~@[Siamese ~a~]"
If the next format argument is true, use the choice, but do NOT take the argument. If it's false, take one format argument and print nothing. (Normally the clause uses the format argument.)
# parameter, e.g. "~#[ none~; ~s~; ~s and ~s~]"
Use the number of arguments to format as the number to choose a clause. The same as no parameters in all other ways. Here's the full hairy example: "Items: ~#[ none~; ~S~; ~S and ~S~:;~@{~S~^~#[~; and ~:;, ~]~}~]."
You should avoid unnecessary allocation of memory.

In a language with automatic storage management (such as Lisp or Java), the colloquial phrase "memory leak" refers to situation where storage that is not actually needed nevertheless does not get deallocated, because it is still reachable.

You should be careful that when you create objects, you don't leave them reachable after they are no longer needed!

Here's a particular trap-for-the-unwary in Common Lisp. If you make an array with a fill pointer, and put objects in it, and then set the fill pointer back to zero, those objects are still reachable as far as Lisp goes (the Common Lisp spec says that it's still OK to refer to the array entries past the end of the fill pointer).

Don't cons (i.e., allocate) unnecessarily. Garbage collection is not magic. Excessive allocation is usually a performance problem.

You must only use faster unsafe operations when there is a clear performance need and you can document why it's correct.

Common Lisp implementations often provide backdoors to compute some operations faster in an unsafe way. For instance, some libraries provide arithmetic operations that are designed to be used with fixnums only, and yield the correct result faster if provided proper arguments. The downside is that the result of such operations is incorrect in case of overflow, and can have undefined behavior when called with anything but fixnums.

More generally, unsafe operations will yield the correct result faster than would the equivalent safe operation if the arguments satisfy some invariant such as being of the correct type and small enough; however if the arguments fail to satisfy the required invariants, then the operation may have undefined behavior, such as crashing the software, or, which is sometimes worse, silently giving wrong answers. Depending on whether the software is piloting an aircraft or other life-critical device, or whether it is accounting for large amounts money, such undefined behavior can kill or bankrupt people. Yet proper speed can sometimes make the difference between software that's unusably slow and software that does its job, or between software that is a net loss and software that can yield a profit.

You must not define or use unsafe operations without both profiling results indicating the need for this optimization, and careful documentation explaining why it is safe to use them. Unsafe operations should be restricted to internal functions; you should carefully documented how unsafe it is to use these functions with the wrong arguments. You should only use unsafe operations inside functions internal to a package and you should document the use of the declarations, since calling the functions with arguments of the wrong type can lead to undefined behavior. Use check-type in functions exported from a package to sanitize input arguments, so that internal functions are never passed illegal values.

On some compilers, new unsafe operations can usually be defined by combining type declarations with an OPTIMIZE declaration that has sufficiently high SPEED and low SAFETY. In addition to providing more speed for production code, such declarations may more helpful than check-type assertions for finding bugs at compile-time, on compilers that have type inference. These compilers may interpret those declarations as assertions if you switch to safer and slower optimize settings; this is good to locate a dynamic error in your code during development, but is not to be used for production code since it defeats the purpose of declarations as a performance trick.

You should only use DYNAMIC-EXTENT where it matters for performance, and you can document why it is correct.

DYNAMIC-EXTENT declarations are a particular case of unsafe operations.

The purpose of a DYNAMIC-EXTENT declaration is to improve performance by reducing garbage collection in cases where it appears to be obvious that an object's lifetime is within the "dynamic extent" of a function. That means the object is created at some point after the function is called, and the object is always inaccessible after the function exits by any means.

By declaring a variable or a local function DYNAMIC-EXTENT, the programmer asserts to Lisp that any object that is ever a value of that variable or the closure that is the definition of the function has a lifetime within the dynamic extent of the (innermost) function that declares the variable.

The Lisp implementation is then free to use that information to make the program faster. Typically, Lisp implementations can take advantage of this knowledge to stack-allocate:

  • The lists created to store &REST parameters.
  • Lists, vectors and structures allocated within a function.
  • Closures.

If the assertion is wrong, i.e. if the programmer's claim is not true, the results can be catastrophic: Lisp can terminate any time after the function returns, or it can hang forever, or — worst of all — it can produce incorrect results without any runtime error!

Even if the assertion is correct, future changes to the function might introduce a violation of the assertion. This increases the danger.

In most cases, such objects are ephemeral. Modern Lisp implementations use generational garbage collectors, which are quite efficient under these circumstances.

Therefore, DYNAMIC-EXTENT declarations should be used sparingly. You must only use them if:

  1. There is some good reason to think that the overall effect on performance is noticeable, and
  2. It is absolutely clear that the assertion is true.
  3. It is quite unlikely that the code will be changed in ways that cause the declaration to become false.

Point (1) is a special case of the principle of avoiding premature optimization. An optimization like this only matters if such objects are allocated at a very high rate, e.g. "inside an inner loop".

Note that is relatively easy to ascertain that a function will not escape the dynamic extent of the current call frame by analyzing where the function is called and what other functions it is passed to; therefore, you should somewhat wary of declaring a function DYNAMIC-EXTENT, but this is not a high-stress declaration. On the other hand, it is much harder to ascertain that none of the objects ever bound or assigned to that variable and none of their sub-objects will escape the dynamic extent of the current call frame, and that they still won't in any future modification of a function. Therefore, you should be extremely wary of declaring a variable DYNAMIC-EXTENT.

It's usually hard to predict the effect of such optimization on performance. When writing a function or macro that is part of a library of reusable code, there's no a priori way to know how often the code will run. Ideally, tools would be available to discover the availability and suitability of using such an optimization based on running simulations and test cases, but in practice this isn't as easy as it ought to be. It's a tradeoff. If you're very, very sure that the assertion is true (that any object bound to the variable and any of its sub-objects are only used within the dynamic extent of the specified scope), and it's not obvious how much time will be saved and it's not easy to measure, then it may be better to put in the declaration than to leave it out. (Ideally it would be easier to make such measurements than it actually is.)

You should use REDUCE instead of APPLY where appropriate.

You should use REDUCE instead of APPLY and a consed-up list, where the semantics of the first operator argument otherwise guarantees the same semantics. Of course, you must use APPLY if it does what you want and REDUCE doesn't. For instance:

;; Bad (apply #'+ (mapcar #'acc frobs)) ;; Better (reduce #'+ frobs :key #'acc :initial-value 0)

This is preferable because it does not do extra consing, and does not risk going beyond CALL-ARGUMENTS-LIMIT on implementations where that limit is small, which could blow away the stack on long lists (we want to avoid gratuitous non-portability in our code).

However, you must be careful not to use REDUCE in ways that needlessly increase the complexity class of the computation. For instance, (REDUCE 'STRCAT ...) is O(n^2) when an appropriate implementation is only O(n). Moreover, (REDUCE 'APPEND ...) is also O(n^2) unless you specify :FROM-END T. In such cases, you MUST NOT use REDUCE, and you MUST NOT use (APPLY 'STRCAT ...) or (APPLY 'APPEND ...) either. Instead you MUST use proper abstractions from a suitable library (that you may have to contribute to) that properly handles those cases without burdening users with implementation details. See for instance UIOP:REDUCE/STRCAT.

You should not use NCONC; you should use APPEND instead, or better data structures.

You should almost never use NCONC. You should use APPEND when you don't depend on any side-effect. You should use ALEXANDRIA:APPENDF when you need to update a variable. You should probably not depend on games being played with the CDR of the current CONS cell (which some might argue is suggested but not guaranteed by the specification); if you do, you must include a prominent comment explaining the use of NCONC; and you should probably reconsider your data representation strategy.

By extension, you should avoid MAPCAN or the NCONC feature of LOOP. You should instead respectively use ALEXANDRIA:MAPPEND and the APPEND feature of LOOP.

NCONC is very seldom a good idea, since its time complexity class is no better than APPEND, its space complexity class also is no better than APPEND in the common case where no one else is sharing the side-effected list, and its bug complexity class is way higher than APPEND.

If the small performance hit due to APPEND vs. NCONC is a limiting factor in your program, you have a big problem and are probably using the wrong data structure: you should be using sequences with constant-time append (see Okasaki's book, and add them to lisp-interface-library), or more simply you should be accumulating data in a tree that will get flattened once in linear time after the accumulation phase is complete.

You may only use NCONC, MAPCAN or the NCONC feature of LOOP in low-level functions where performance matters, where the use of lists as a data structure has been vetted because these lists are known to be short, and when the function or expression the result of which are accumulated explicitly promises in its contract that it only returns fresh lists (in particular, it can't be a constant quote or backquote expression). Even then, the use of such primitives must be rare, and accompanied by justifying documentation.

You should usually refer to a function as #'FUN rather than 'FUN.

The former, which reads as (FUNCTION FUN), refers to the function object, and is lexically scoped. The latter, which reads as (QUOTE FUN), refers to the symbol, which when called uses the global FDEFINITION of the symbol.

When using functions that take a functional argument (e.g., MAPCAR, APPLY, :TEST and :KEY arguments), you should use the #' to refer to the function, not just single quote.

An exception is when you explicitly want dynamic linking, because you anticipate that the global function binding will be updated.

Another exception is when you explicitly want to access a global function binding, and avoid a possible shadowing lexical binding. This shouldn't happen often, as it is usually a bad idea to shadow a function when you will want to use the shadowed function; just use a different name for the lexical function.

You must consistently use either #'(lambda ...) or (lambda ...) without #' everywhere. Unlike the case of #'symbol vs 'symbol, it is only a syntactic difference with no semantic impact, except that the former works on Genera and the latter doesn't. You must use the former style if your code is intended as a library with maximal compatibility to all Common Lisp implementations; otherwise, it is optional which style you use. #' may be seen as a hint that you're introducing a function in expression context; but the lambda itself is usually sufficient hint, and concision is good. Choose wisely, but above all, consistently with yourself and other developers, within a same file, package, system, project, etc.

Note that if you start writing a new system in a heavily functional style, you may consider using lambda-reader, a system that lets you use the unicode character λ instead of LAMBDA. But you must not start using such a syntactic extension in an existing system without getting permission from other developers.

Common Lisp pathnames are tricky. Be aware of pitfalls. Use UIOP.

It is surprisingly hard to properly deal with pathnames in Common Lisp.

ASDF 3 comes with a portability library UIOP that makes it much easier to deal with pathnames portably — and correctly — in Common Lisp. You should use it when appropriate.

First, be aware of the discrepancies between the syntax of Common Lisp pathnames, which depends on which implementation and operating system you are using, and the native syntax of pathnames on your operating system. The Lisp syntax may involves quoting of special characters such as #\. and #\*, etc., in addition to the quoting of #\\ and #\" within strings. By contrast, your operating system's other system programming languages (shell, C, scripting languages) may only have one layer of quoting, into strings.

Second, when using MERGE-PATHNAMES, be wary of the treatment of the HOST component, which matters a lot on non-Unix platforms (and even on some Unix implementations). You probably should be using UIOP:MERGE-PATHNAMES* or UIOP:SUBPATHNAME instead of MERGE-PATHNAMES, especially if your expectations for relative pathnames are informed by the way they work in Unix or Windows; otherwise you might hit weird bugs whereby on some implementations, merging a relative pathnames with an absolute pathname results in overriding the absolute pathname's host and replace it with the host from the value of *DEFAULT-PATHNAME-DEFAULTS* at the time the relative pathname was created.

Third, be aware that DIRECTORY is not portable across implementations in how it handles wildcards, sub-directories, symlinks, etc. There again, UIOP provides several common abstractions to deal with pathnames, but only does so good a job. For a complete portable solution, use IOLib — though its Windows support lags behind.

LOGICAL-PATHNAMEs are not a portable abstraction, and should not be used in portable code. Many implementations have bugs in them, when they are supported at all. SBCL implements them very well, but strictly enforces the limitations on characters allowed by the standard, which restricts their applicability. Other implementations allow arbitrary characters in such pathnames, but in doing so are not being conformant, and are still incompatible with each other in many ways. You should use other pathname abstractions, such as ASDF:SYSTEM-RELATIVE-PATHNAME or the underlying UIOP:SUBPATHNAME and UIOP:PARSE-UNIX-NAMESTRING.

Finally, be aware that paths may change between the time you build the Lisp image for your application, and the time you run the application from its image. You should be careful to reset your image to forget irrelevant build-time paths and reinitialize any search path from current environment variables. ASDF for instance requires you to reset its paths with UIOP:CLEAR-CONFIGURATION. UIOP provides hooks to call functions before an image is dumped, from which to reset or makunbound relevant variables.

You must be careful when using a SATISFIES clause in a type specifier.

Most Common Lisp implementations can't optimize based on a SATISFIES type, but many of them offer simple optimizations based on a type of the form (AND FOO (SATISFIES BAR-P)) where the first term of the AND clause describes the structure of the object without any SATISFIES and the second term is the SATISFIES.

(deftype prime-number () (satisfies prime-number-p)) ; Bad (deftype prime-number () (and integer (satisfies prime-number-p)) ; Better

However, AND in the DEFTYPE language isn't a left-to-right short-circuit operator as in the expression language; it is a symmetrical connector that allows for reordering subterms and doesn't guarantee short-circuiting. Therefore, in the above example, you cannot rely on the test for INTEGERness to protect the function PRIME-NUMBER-P from being supplied non-integer arguments to test for being of instances of the type. Implementations may, and some will, invoke SATISFIES-specified function at compile-time to test various relevant objects.

That is why any function specified in a SATISFIES clause MUST accept objects of any type as argument to the function, and MUST be defined within an EVAL-WHEN (as well as any variable it uses or function it calls):

(defun prime-number-p (n) ; Doubly bad! (let ((m (abs n))) (if (<= m *prime-number-cutoff*) (small-prime-number-p m) (big-prime-number-p m)))) (eval-when (:compile-toplevel :load-toplevel :execute) ; Better (defun prime-number-p (n) (when (integerp n) ; Better (let ((m (abs n))) (if (<= m *prime-number-cutoff*) (small-prime-number-p m) (big-prime-number-p m))))))

In particular, the above means that the example used in the Common Lisp Standard is erroneous: (and integer (satisfies evenp)) is not a safe, conformant type specifier to use, because EVENP will throw an error rather than return NIL when passed a non-integer as an argument.

Finally, there is a catch when your DEFTYPE code expands to a SATISFIES with a dynamically generated function:

  • You cannot control when implementations will or will not expand a DEFTYPE.
  • The expansion itself cannot contain a function definition or any code in the expression language.
  • You cannot control when the expansion is used, it may happen in a different process that didn't expand the definition.

Therefore, you cannot merely create the function as a side-effect of expansion using EVAL at type-expansion time. The solution is to use ASDF-FINALIZERS:EVAL-AT-TOPLEVEL instead. See the very last point in the discussion about EVAL.

Common Lisp is hard to satisfy.


Credits: Adam Worrall, Dan Pierson, Matt Marjanovic, Matt Reklaitis, Paul Weiss, Scott McKay, Sundar Narasimhan, and several other people contributed. Special thanks to Steve Hain, and to the previous editors, in reverse chronological order Dan Weinreb and Jeremy Brown.

Revision 1.28

Robert Brown
François-René Rideau
================================================ FILE: objcguide.md ================================================ # Google Objective-C Style Guide > Objective-C is a dynamic, object-oriented extension of C. It's designed to be > easy to use and read, while enabling sophisticated object-oriented design. It > is one of the primary development languages for applications on Apple > platforms. > > Apple has already written a very good, and widely accepted, [Cocoa Coding > Guidelines](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html) > for Objective-C. Please read it in addition to this guide. > > The purpose of this document is to describe the Objective-C (and > Objective-C++) coding guidelines and practices. These guidelines have evolved > and been proven over time on other projects and teams. > Open-source projects developed by Google conform to the requirements in this guide. > > Note that this guide is not an Objective-C tutorial. We assume that the reader > is familiar with the language. If you are new to Objective-C or need a > refresher, please read [Programming with > Objective-C](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html). ## Principles ### Optimize for the reader, not the writer Codebases often have extended lifetimes and more time is spent reading the code than writing it. We explicitly choose to optimize for the experience of our average software engineer reading, maintaining, and debugging code in our codebase rather than the ease of writing said code. For example, when something surprising or unusual is happening in a snippet of code, leaving textual hints for the reader is valuable. ### Be consistent When the style guide allows multiple options it is preferable to pick one option over mixed usage of multiple options. Using one style consistently throughout a codebase lets engineers focus on other (more important) issues. Consistency also enables better automation because consistent code allows more efficient development and operation of tools that format or refactor code. In many cases, rules that are attributed to "Be Consistent" boil down to "Just pick one and stop worrying about it"; the potential value of allowing flexibility on these points is outweighed by the cost of having people argue over them. ### Be consistent with Apple SDKs Consistency with the way Apple SDKs use Objective-C has value for the same reasons as consistency within our code base. If an Objective-C feature solves a problem that's an argument for using it. However, sometimes language features and idioms are flawed, or were just designed with assumptions that are not universal. In those cases it is appropriate to constrain or ban language features or idioms. ### Style rules should pull their weight The benefit of a style rule must be large enough to justify asking engineers to remember it. The benefit is measured relative to the codebase we would get without the rule, so a rule against a very harmful practice may still have a small benefit if people are unlikely to do it anyway. This principle mostly explains the rules we don’t have, rather than the rules we do: for example, goto contravenes many of the following principles, but is not discussed due to its extreme rarity. ## Example They say an example is worth a thousand words, so let's start off with an example that should give you a feel for the style, spacing, naming, and so on. Here is an example header file, demonstrating the correct commenting and spacing for an `@interface` declaration. ```objectivec // GOOD: #import @class Bar; /** * A sample class demonstrating good Objective-C style. All interfaces, * categories, and protocols (read: all non-trivial top-level declarations * in a header) MUST be commented. Comments must also be adjacent to the * object they're documenting. */ @interface Foo : NSObject /** The retained Bar. */ @property(nonatomic) Bar *bar; /** The current drawing attributes. */ @property(nonatomic, copy) NSDictionary *attributes; /** * Convenience creation method. * See -initWithBar: for details about @c bar. * * @param bar The string for fooing. * @return An instance of Foo. */ + (instancetype)fooWithBar:(Bar *)bar; /** * Initializes and returns a Foo object using the provided Bar instance. * * @param bar A string that represents a thing that does a thing. */ - (instancetype)initWithBar:(Bar *)bar NS_DESIGNATED_INITIALIZER; /** * Does some work with @c blah. * * @param blah * @return YES if the work was completed; NO otherwise. */ - (BOOL)doWorkWithBlah:(NSString *)blah; @end ``` An example source file, demonstrating the correct commenting and spacing for the `@implementation` of an interface. ```objectivec // GOOD: #import "Shared/Util/Foo.h" @implementation Foo { /** The string used for displaying "hi". */ NSString *_string; } + (instancetype)fooWithBar:(Bar *)bar { return [[self alloc] initWithBar:bar]; } - (instancetype)init { // Classes with a custom designated initializer should always override // the superclass's designated initializer. return [self initWithBar:nil]; } - (instancetype)initWithBar:(Bar *)bar { self = [super init]; if (self) { _bar = [bar copy]; _string = [[NSString alloc] initWithFormat:@"hi %d", 3]; _attributes = @{ @"color" : UIColor.blueColor, @"hidden" : @NO }; } return self; } - (BOOL)doWorkWithBlah:(NSString *)blah { // Work should be done here. return NO; } @end ``` ## Naming Names should be as descriptive as possible, within reason. Follow standard [Objective-C naming rules](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html). Avoid non-standard abbreviations (including non-standard acronyms and initialisms). Don't worry about saving horizontal space as it is far more important to make your code immediately understandable by a new reader. For example: ```objectivec // GOOD: // Good names. int numberOfErrors = 0; int completedConnectionsCount = 0; tickets = [[NSMutableArray alloc] init]; userInfo = [someObject object]; port = [network port]; NSDate *gAppLaunchDate; ``` ```objectivec // AVOID: // Names to avoid. int w; int nerr; int nCompConns; tix = [[NSMutableArray alloc] init]; obj = [someObject object]; p = [network port]; ``` Any class, category, method, function, or variable name should use all capitals for acronyms and [initialisms](https://en.wikipedia.org/wiki/Initialism) within (including at the beginning of) the name. This follows Apple's standard of using all capitals within a name for acronyms such as URL, ID, TIFF, and EXIF. Names of C functions and typedefs should be capitalized and use camel case as appropriate for the surrounding code. ### Inclusive Language In all code, including naming and comments, use inclusive language and avoid terms that other programmers might find disrespectful or offensive (such as "master" and "slave", "blacklist" and "whitelist", or "redline"), even if the terms also have an ostensibly neutral meaning. Similarly, use gender-neutral language unless you're referring to a specific person (and using their pronouns). For example, use "they"/"them"/"their" for people of unspecified gender (even when singular), and "it"/"its" for non-people. ### File Names File names should reflect the name of the class implementation that they contain—including case. Follow the convention that your project uses. File extensions should be as follows: Extension | Type --------- | --------------------------------- .h | C/C++/Objective-C header file .m | Objective-C implementation file .mm | Objective-C++ implementation file .cc | Pure C++ implementation file .c | C implementation file Files containing code that may be shared across projects or used in a large project should have a clearly unique name, typically including the project or class [prefix](#prefixes). File names for categories should include the name of the class being extended, like GTMNSString+Utils.h or NSTextView+GTMAutocomplete.h ### Prefixes Prefixes are commonly required in Objective-C to avoid naming collisions in a global namespace. Classes, protocols, global functions, and global constants should generally be named with a prefix that begins with a capital letter followed by one or more capital letters or numbers. WARNING: Apple reserves two-letter prefixes—see [Conventions in Programming with Objective-C](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Conventions/Conventions.html)—so prefixes with a minimum of three characters are considered best practice. ```objectivec // GOOD: /** An example error domain. */ GTM_EXTERN NSString *GTMExampleErrorDomain; /** Gets the default time zone. */ GTM_EXTERN NSTimeZone *GTMGetDefaultTimeZone(void); /** An example delegate. */ @protocol GTMExampleDelegate @end /** An example class. */ @interface GTMExample : NSObject @end ``` ### Class Names Class names (along with category and protocol names) should start as uppercase and use mixed case to delimit words. Classes and protocols in code shared across multiple applications must have an appropriate [prefix](#prefixes) (e.g. GTMSendMessage). Prefixes are recommended, but not required, for other classes and protocols. ### Category Naming Category names should start with an appropriate [prefix](#prefixes) identifying the category as part of a project or open for general use. Category source file names should begin with the class being extended followed by a plus sign and the name of the category, e.g., `NSString+GTMParsing.h`. Methods in a category should be prefixed with a lowercase version of the prefix used for the category name followed by an underscore (e.g., `gtm_myCategoryMethodOnAString:`) in order to prevent collisions in Objective-C's global namespace. There should be a single space between the class name and the opening parenthesis of the category. ```objectivec // GOOD: // UIViewController+GTMCrashReporting.h /** A category that adds metadata to include in crash reports to UIViewController. */ @interface UIViewController (GTMCrashReporting) /** A unique identifier to represent the view controller in crash reports. */ @property(nonatomic, setter=gtm_setUniqueIdentifier:) int gtm_uniqueIdentifier; /** Returns an encoded representation of the view controller's current state. */ - (nullable NSData *)gtm_encodedState; @end ``` If a class is not shared with other projects, categories extending it may omit name prefixes and method name prefixes. ```objectivec // GOOD: /** This category extends a class that is not shared with other projects. */ @interface XYZDataObject (Storage) - (NSString *)storageIdentifier; @end ``` ### Objective-C Method Names Method and parameter names typically start as lowercase and then use mixed case. Proper capitalization should be respected, including at the beginning of names. ```objectivec // GOOD: + (NSURL *)URLWithString:(NSString *)URLString; ``` The method name should read like a sentence if possible, meaning you should choose parameter names that flow with the method name. Objective-C method names tend to be very long, but this has the benefit that a block of code can almost read like prose, thus rendering many implementation comments unnecessary. Use prepositions and conjunctions like "with", "from", and "to" in the second and later parameter names only where necessary to clarify the meaning or behavior of the method. ```objectivec // GOOD: - (void)addTarget:(id)target action:(SEL)action; // GOOD; no conjunction needed - (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view; // GOOD; conjunction clarifies parameter - (void)replaceCharactersInRange:(NSRange)aRange withAttributedString:(NSAttributedString *)attributedString; // GOOD. ``` If the method returns an attribute of the receiver, name the method after the attribute. ```objectivec // GOOD: /** Returns this instance's sandwich. */ - (Sandwich *)sandwich; // GOOD. - (CGFloat)height; // GOOD. // GOOD; Returned value is not an attribute. - (UIBackgroundTaskIdentifier)beginBackgroundTask; ``` ```objectivec // AVOID: - (CGFloat)calculateHeight; // AVOID. - (id)theDelegate; // AVOID. ``` An accessor method should be named the same as the object it's getting, but it should not be prefixed with the word `get`. For example: ```objectivec // GOOD: - (id)delegate; // GOOD. ``` ```objectivec // AVOID: - (id)getDelegate; // AVOID. ``` Accessors that return the value of boolean adjectives have method names beginning with `is`, but property names for those methods omit the `is`. Dot notation is used only with property names, not with method names. ```objectivec // GOOD: @property(nonatomic, getter=isGlorious) BOOL glorious; // The method for the getter of the property above is: // - (BOOL)isGlorious; BOOL isGood = object.glorious; // GOOD. BOOL isGood = [object isGlorious]; // GOOD. ``` ```objectivec // AVOID: BOOL isGood = object.isGlorious; // AVOID. ``` ```objectivec // GOOD: NSArray *frogs = [NSArray arrayWithObject:frog]; NSEnumerator *enumerator = [frogs reverseObjectEnumerator]; // GOOD. ``` ```objectivec // AVOID: NSEnumerator *enumerator = frogs.reverseObjectEnumerator; // AVOID. ``` See [Apple's Guide to Naming Methods](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html#//apple_ref/doc/uid/20001282-BCIGIJJF) for more details on Objective-C naming. These guidelines are for Objective-C methods only. C++ method names continue to follow the rules set in the C++ style guide. ### Function Names Function names should start with a capital letter and have a capital letter for each new word (a.k.a. "[camel case](https://en.wikipedia.org/wiki/Camel_case)" or "Pascal case"). ```objectivec // GOOD: static void AddTableEntry(NSString *tableEntry); static BOOL DeleteFile(const char *filename); ``` Because Objective-C does not provide namespacing, non-static functions should have a [prefix](#prefixes) that minimizes the chance of a name collision. ```objectivec // GOOD: GTM_EXTERN NSTimeZone *GTMGetDefaultTimeZone(void); GTM_EXTERN NSString *GTMGetURLScheme(NSURL *URL); ``` ### Variable Names Variable names typically start with a lowercase and use mixed case to delimit words. Instance variables have leading underscores. File scope or global variables have a prefix `g`. For example: `myLocalVariable`, `_myInstanceVariable`, `gMyGlobalVariable`. #### Common Variable Names Readers should be able to infer the variable type from the name, but do not use Hungarian notation for syntactic attributes, such as the static type of a variable (int or pointer). File scope or global variables (as opposed to constants) declared outside the scope of a method or function should be rare, and should have the prefix `g`. ```objectivec // GOOD: static int gGlobalCounter; ``` #### Instance Variables Instance variable names are mixed case and should be prefixed with an underscore, like `_usernameTextField`. NOTE: Google's previous convention for Objective-C ivars was a trailing underscore. Existing projects may opt to continue using trailing underscores in new code in order to maintain consistency within the project codebase. Consistency of prefix or suffix underscores should be maintained within each class. #### Constants Constant symbols (const global and static variables and constants created with #define) should use mixed case to delimit words. Global and file scope constants should have an appropriate [prefix](#prefixes). ```objectivec // GOOD: /** The domain for GTL service errors. */ GTL_EXTERN NSString *const GTLServiceErrorDomain; /** An enumeration of GTL service error codes. */ typedef NS_ENUM(int32_t, GTLServiceError) { /** An error code indicating that a query result was missing. */ GTLServiceErrorQueryResultMissing = -3000, /** An error code indicating that the query timed out. */ GTLServiceErrorQueryTimedOut = -3001, }; ``` Because Objective-C does not provide namespacing, constants with external linkage should have a prefix that minimizes the chance of a name collision, typically like `ClassNameConstantName` or `ClassNameEnumName`. For interoperability with Swift code, enumerated values should have names that extend the typedef name: ```objectivec // GOOD: /** An enumeration of supported display tinges. */ typedef NS_ENUM(int32_t, DisplayTinge) { DisplayTingeGreen = 1, DisplayTingeBlue = 2, }; ``` A lowercase k can be used as a standalone prefix for constants of static storage duration declared within implementation files: ```objectivec // GOOD: static const int kFileCount = 12; static NSString *const kUserKey = @"kUserKey"; ``` NOTE: Previous convention was for public constant names to begin with a lowercase k followed by a project-specific [prefix](#prefixes). This practice is no longer recommended. ## Types and Declarations ### Method Declarations As shown in the [example](#Example), the recommended order for declarations in an `@interface` declaration are: properties, class methods, initializers, and then finally instance methods. The class methods section should begin with any convenience constructors. ### Local Variables Declare variables in the narrowest practical scopes, and close to their use. Initialize variables in their declarations. ```objectivec // GOOD: CLLocation *location = [self lastKnownLocation]; for (int meters = 1; meters < 10; meters++) { reportFrogsWithinRadius(location, meters); } ``` Occasionally, efficiency will make it more appropriate to declare a variable outside the scope of its use. This example declares meters separate from initialization, and needlessly sends the lastKnownLocation message each time through the loop: ```objectivec // AVOID: int meters; // AVOID. for (meters = 1; meters < 10; meters++) { CLLocation *location = [self lastKnownLocation]; // AVOID. reportFrogsWithinRadius(location, meters); } ``` Under Automatic Reference Counting, strong and weak pointers to Objective-C objects are automatically initialized to `nil`, so explicit initialization to `nil` is not required for those common cases. However, automatic initialization does *not* occur for many Objective-C pointer types, including object pointers declared with the `__unsafe_unretained` ownership qualifier and CoreFoundation object pointer types. When in doubt, prefer to initialize all Objective-C local variables. ### Static Variables When file scope variable/constant declarations in an implementation file do not need to be referenced outside that file, declare them static (or in an anonymous namespace in Objective-C++). Do not declare file scope variables or constants with static storage duration (or in anonymous namespaces in Objective-C++) in .h files. ```objectivec // GOOD: // file: Foo.m static const int FOORequestLimit = 5; ``` ```objectivec // AVOID: // file: Foo.h static const int FOORequestLimit = 5; // AVOID. ``` ### Unsigned Integers Avoid unsigned integers except when matching types used by system interfaces. Subtle errors crop up when doing math or counting down to zero using unsigned integers. Rely only on signed integers in math expressions except when matching NSUInteger in system interfaces. ```objectivec // GOOD: NSUInteger numberOfObjects = array.count; for (NSInteger counter = numberOfObjects - 1; counter >= 0; --counter) ``` ```objectivec // AVOID: for (NSUInteger counter = numberOfObjects - 1; counter >= 0; --counter) // AVOID. ``` Unsigned integers may be used for flags and bitmasks, though often NS_OPTIONS or NS_ENUM will be more appropriate. ### Types with Inconsistent Sizes Be aware that types long, NSInteger, NSUInteger and CGFloat have sizes that differ in 32- and 64-bit builds. Their use is appropriate when matching system interfaces but should be avoided when dealing with APIs that require exact sizing, e.g., proto APIs. ```objectivec // GOOD: int32_t scalar1 = proto.intValue; int64_t scalar2 = proto.longValue; NSUInteger numberOfObjects = array.count; CGFloat offset = view.bounds.origin.x; ``` ```objectivec // AVOID: NSInteger scalar2 = proto.longValue; // AVOID. ``` File and buffer sizes often exceed 32-bit limits, so they should be declared using `int64_t`, not with `long`, `NSInteger`, or `NSUInteger`. #### Floating Point Constants When defining `CGFloat` constants, please keep in mind the following. Previously for projects targeting 32-bit platforms, using `float` literals (numbers with the `f` suffix) could be necessary to avoid type-conversion warnings. Since all Google iOS projects are now targeting only 64-bit runtime, `CGFloat` constants may omit the suffix (use `double` values). However, teams may choose to continue using `float` numbers for legacy code consistency, until they eventually migrate to `double` values everywhere. Avoid a mixture of `float` and `double` values in the same code. ```objectivec // GOOD: // Good since CGFloat is double static const CGFloat kHorizontalMargin = 8.0; static const CGFloat kVerticalMargin = 12.0; // This is OK as long as all values for CGFloat constants in your project are float static const CGFloat kHorizontalMargin = 8.0f; static const CGFloat kVerticalMargin = 12.0f; ``` ```objectivec // AVOID: // Avoid a mixture of float and double constants static const CGFloat kHorizontalMargin = 8.0f; static const CGFloat kVerticalMargin = 12.0; ``` ## Comments Comments are absolutely vital to keeping our code readable. The following rules describe what you should comment and where. But remember: while comments are important, the best code is self-documenting. Giving sensible names to types and variables is much better than using obscure names and then trying to explain them through comments. Pay attention to punctuation, spelling, and grammar; it is easier to read well-written comments than badly written ones. Comments should be as readable as narrative text, with proper capitalization and punctuation. In many cases, complete sentences are more readable than sentence fragments. Shorter comments, such as comments at the end of a line of code, can sometimes be less formal, but use a consistent style. When writing your comments, write for your audience: the next contributor who will need to understand your code. Be generous—the next one may be you! ### File Comments A file may optionally start with a description of its contents. Every file may contain the following items, in order * License boilerplate if necessary. Choose the appropriate boilerplate for the license used by the project. * A basic description of the contents of the file if necessary. If you make significant changes to a file with an author line, consider deleting the author line since revision history already provides a more detailed and accurate record of authorship. ### Declaration Comments Every non-trivial interface, public and private, should have an accompanying comment describing its purpose and how it fits into the larger picture. Comments should be used to document classes, properties, ivars, functions, categories, protocol declarations, and enums. ```objectivec // GOOD: /** * A delegate for NSApplication to handle notifications about app * launch and shutdown. Owned by the main app controller. */ @interface MyAppDelegate : NSObject { /** * The background task in progress, if any. This is initialized * to the value UIBackgroundTaskInvalid. */ UIBackgroundTaskIdentifier _backgroundTaskID; } /** The factory that creates and manages fetchers for the app. */ @property(nonatomic) GTMSessionFetcherService *fetcherService; @end ``` [Doxygen](https://doxygen.nl)-style comments are encouraged for interfaces as they are parsed by Xcode to display formatted documentation. There is a wide variety of [Doxygen commands](https://www.doxygen.nl/manual/commands.html); use them consistently within a project. If you have already described an interface in detail in the comments at the top of your file, feel free to simply state, "See comment at top of file for a complete description", but be sure to have some sort of comment. Additionally, each method should have a comment explaining its function, arguments, return value, thread or queue assumptions, and any side effects. Documentation comments should be in the header for public methods, or immediately preceding the method for non-trivial private methods. Use descriptive form ("Opens the file") rather than imperative form ("Open the file") for method and function comments. The comment describes the function; it does not tell the function what to do. Document the thread usage assumptions the class, properties, or methods make, if any. If an instance of the class can be accessed by multiple threads, take extra care to document the rules and invariants surrounding multithreaded use. Any sentinel values for properties and ivars, such as `NULL` or `-1`, should be documented in comments. Declaration comments explain how a method or function is used. Comments explaining how a method or function is implemented should be with the implementation rather than with the declaration. Declaration comments may be omitted on test case classes and test methods if comments would communicate no additional information beyond the method's name. Utility methods in tests or test-specific classes (such as helpers) should be commented. ### Implementation Comments Provide comments explaining tricky, subtle, or complicated sections of code. ```objectivec // GOOD: // Set the property to nil before invoking the completion handler to // avoid the risk of reentrancy leading to the callback being // invoked again. CompletionHandler handler = self.completionHandler; self.completionHandler = nil; handler(); ``` When useful, also provide comments about implementation approaches that were considered or abandoned. End-of-line comments should be separated from the code by at least 2 spaces. If you have several comments on subsequent lines, it can often be more readable to line them up. ```objectivec // GOOD: [self doSomethingWithALongName]; // Two spaces before the comment. [self doSomethingShort]; // More spacing to align the comment. ``` ### Disambiguating Symbols Where needed to avoid ambiguity, use backticks or vertical bars to quote variable names and symbols in comments in preference to using quotation marks or naming the symbols inline. In Doxygen-style comments, prefer demarcating symbols with a monospace text command, such as [`@c`](https://www.doxygen.nl/manual/commands.html#cmdc). Demarcation helps provide clarity when a symbol is a common word that might make the sentence read like it was poorly constructed. A common example is the symbol `count`: ```objectivec // GOOD: // Sometimes `count` will be less than zero. ``` or when quoting something which already contains quotes ```objectivec // GOOD: // Remember to call `StringWithoutSpaces("foo bar baz")` ``` Backticks or vertical bars are not needed when a symbol is self-apparent. ```objectivec // GOOD: // This class serves as a delegate to GTMDepthCharge. ``` Doxygen formatting is also suitable for identifying symbols. ```objectivec // GOOD: /** @param maximum The highest value for @c count. */ ``` ### Object Ownership For objects not managed by ARC, make the pointer ownership model as explicit as possible when it falls outside the most common Objective-C usage idioms. #### Manual Reference Counting Instance variables for NSObject-derived objects are presumed to be retained; if they are not retained, they should be either commented as weak or declared with the `__weak` lifetime qualifier. An exception is in Mac software for instance variables labeled as `@IBOutlets`, which are presumed to not be retained. Where instance variables are pointers to Core Foundation, C++, and other non-Objective-C objects, they should always be declared with strong and weak comments to indicate which pointers are and are not retained. Core Foundation and other non-Objective-C object pointers require explicit memory management, even when building for automatic reference counting. Examples of strong and weak declarations: ```objectivec // GOOD: @interface MyDelegate : NSObject @property(nonatomic) NSString *doohickey; @property(nonatomic, weak) NSString *parent; @end @implementation MyDelegate { IBOutlet NSButton *_okButton; // Normal NSControl; implicitly weak on Mac only AnObjcObject *_doohickey; // My doohickey __weak MyObjcParent *_parent; // To send messages back (owns this instance) // non-NSObject pointers... CWackyCPPClass *_wacky; // Strong, some cross-platform object CFDictionaryRef *_dict; // Strong } @end ``` #### Automatic Reference Counting Object ownership and lifetime are explicit when using ARC, so no additional comments are required for automatically retained objects. ## C Language Features ### Macros Avoid macros, especially where `const` variables, enums, Xcode snippets, or C functions may be used instead. Macros make the code you see different from the code the compiler sees. Modern C renders traditional uses of macros for constants and utility functions unnecessary. Macros should only be used when there is no other solution available. Where a macro is needed, use a unique name to avoid the risk of a symbol collision in the compilation unit. If practical, keep the scope limited by `#undefining` the macro after its use. Macro names should use `SHOUTY_SNAKE_CASE`—all uppercase letters with underscores between words. Function-like macros may use C function naming practices. Do not define macros that appear to be C or Objective-C keywords. ```objectivec // GOOD: #define GTM_EXPERIMENTAL_BUILD ... // GOOD // Assert unless X > Y #define GTM_ASSERT_GT(X, Y) ... // GOOD, macro style. // Assert unless X > Y #define GTMAssertGreaterThan(X, Y) ... // GOOD, function style. ``` ```objectivec // AVOID: #define kIsExperimentalBuild ... // AVOID #define unless(X) if(!(X)) // AVOID ``` Avoid macros that expand to unbalanced C or Objective-C constructs. Avoid macros that introduce scope, or may obscure the capturing of values in blocks. Avoid macros that generate class, property, or method definitions in headers to be used as public API. These only make the code hard to understand, and the language already has better ways of doing this. Avoid macros that generate method implementations, or that generate declarations of variables that are later used outside of the macro. Macros shouldn't make code hard to understand by hiding where and how a variable is declared. ```objectivec // AVOID: #define ARRAY_ADDER(CLASS) \ -(void)add ## CLASS ## :(CLASS *)obj toArray:(NSMutableArray *)array ARRAY_ADDER(NSString) { if (array.count > 5) { // AVOID -- where is 'array' defined? ... } } ``` Examples of acceptable macro use include assertion and debug logging macros that are conditionally compiled based on build settings—often, these are not compiled into release builds. ### Nonstandard Extensions Nonstandard extensions to C/Objective-C may not be used unless otherwise specified. Compilers support various extensions that are not part of standard C. Examples include compound statement expressions (e.g. `foo = ({ int x; Bar(&x); x })`). #### The `__typeof__` Keyword The `__typeof__` keyword is allowed in cases where the type doesn't aid in clarity for the reader. The `__typeof__` keyword is encouraged over other similar keywords (e.g., the `typeof` keyword) as it is supported in all language variants. ```objectivec // GOOD: __weak __typeof__(self) weakSelf = self; ``` ```objectivec // AVOID: __typeof__(data) copiedData = [data copy]; // AVOID. __weak typeof(self) weakSelf = self; // AVOID. ``` #### The `__auto_type` Keyword and Type Deduction Type deduction using the `__auto_type` keyword is allowed only for local variables of block and function pointer types. Avoid type deduction if a typedef already exists for the block or pointer type. ```objectivec // GOOD: __auto_type block = ^(NSString *arg1, int arg2) { ... }; __auto_type functionPointer = &MyFunction; typedef void(^SignInCallback)(Identity *, NSError *); SignInCallback signInCallback = ^(Identity *identity, NSError *error) { ... }; ``` ```objectivec // AVOID: __auto_type button = [self createButtonForInfo:info]; __auto_type viewController = [[MyCustomViewControllerClass alloc] initWith...]; typedef void(^SignInCallback)(Identity *, NSError *); __auto_type signInCallback = ^(Identity *identity, NSError *error) { ... }; ``` #### Approved Nonstandard Extensions * The `__attribute__` keyword is approved as it is used in Apple API declarations. * The binary form of the conditional operator, `A ?: B`, is approved. ## Cocoa and Objective-C Features ### Identify Designated Initializers Clearly identify your designated initializer(s). It is important for subclassing that a class clearly identify its designated initializers. This allows a subclass to override a subset of initializers to initialize subclass state or invoke a new designated initializer provided by the subclass. Clearly identified designated initializers also make tracing through and debugging initialization code easier. Prefer identifying designated initializers by annotating them with designated initializer attributes, e.g., `NS_DESIGNATED_INITIALIZER`. Declare designated initializers in comments when designated initializer attributes are not available. Prefer a single designated initializer unless there is a compelling reason or requirement for multiple designated initializers. Support initializers inherited from superclasses by [overriding superclass designated initializers](#Override_Designated_Initializer) to ensure that all inherited initializers are directed through subclass designated initializers. When there is a compelling reason or requirement that an inherited initializer should not be supported, the initializer may be annotated with availability attributes (e.g., `NS_UNAVAILABLE`) to discourage usage; however, note that availability attributes alone do not completely protect against invalid initialization. ### Override Designated Initializers When writing a subclass that requires a new designated initializer, make sure you override any designated initializers of the superclass. When declaring designated initializers on a class, remember that any initializers that were considered designated initializers on the superclass become convenience initializers of the subclass unless declared otherwise. Failure to override superclass designated initializers can result in bugs due to invalid initialization using superclass initializers. To avoid invalid initialization, ensure convenience initializers call through to a designated initializer. ### Overridden NSObject Method Placement Put overridden methods of NSObject at the top of an `@implementation`. This commonly applies to (but is not limited to) the `init...`, `copyWithZone:`, and `dealloc` methods. The `init...` methods should be grouped together, including those `init...` methods that are not `NSObject` overrides, followed by other typical `NSObject` methods such as `description`, `isEqual:`, and `hash`. Convenience class factory methods for creating instances may precede the `NSObject` methods. ### Initialization Don't initialize instance variables to `0` or `nil` in the `init` method; doing so is redundant. All instance variables for a newly allocated object are [initialized to](https://developer.apple.com/library/mac/documentation/General/Conceptual/CocoaEncyclopedia/ObjectAllocation/ObjectAllocation.html) `0` (except for isa), so don't clutter up the init method by re-initializing variables to `0` or `nil`. ### Instance Variables In Headers Should Be @protected or @private Instance variables should typically be declared in implementation files or auto-synthesized by properties. When ivars are declared in a header file, they should be marked `@protected` or `@private`. ```objectivec // GOOD: @interface MyClass : NSObject { @protected id _myInstanceVariable; } @end ``` ### Do Not Use +new Do not invoke the `NSObject` class method `new`, nor override it in a subclass. `+new` is rarely used and contrasts greatly with initializer usage. Instead, use `+alloc` and `-init` methods to instantiate retained objects. ### Keep the Public API Simple Keep your class simple; avoid "kitchen-sink" APIs. If a method doesn't need to be public, keep it out of the public interface. Unlike C++, Objective-C doesn't differentiate between public and private methods; any message may be sent to an object. As a result, avoid placing methods in the public API unless they are actually expected to be used by a consumer of the class. This helps reduce the likelihood they'll be called when you're not expecting it. This includes methods that are being overridden from the parent class. Since internal methods are not really private, it's easy to accidentally override a superclass's "private" method, thus making a very difficult bug to squash. In general, private methods should have a fairly unique name that will prevent subclasses from unintentionally overriding them. ### #import and #include `#import` Objective-C and Objective-C++ headers, and `#include` C/C++ headers. C/C++ headers include other C/C++ headers using `#include`. Using `#import` on C/C++ headers prevents future inclusions using `#include` and could result in unintended compilation behavior. C/C++ headers should provide their own `#define` guard. ### Order of Includes The standard order for header inclusion is the related header, operating system headers, language library headers, and finally groups of headers for other dependencies. The related header precedes others to ensure it has no hidden dependencies. For implementation files the related header is the header file. For test files the related header is the header containing the tested interface. Separate each non-empty group of includes with one blank line. Within each group the includes should be ordered alphabetically. Import headers using their path relative to the project's source directory. ```objectivec // GOOD: #import "ProjectX/BazViewController.h" #import #include #include #include "base/basictypes.h" #include "base/integral_types.h" #import "base/mac/FOOComplexNumberSupport" #include "util/math/mathutil.h" #import "ProjectX/BazModel.h" #import "Shared/Util/Foo.h" ``` ### Use Umbrella Headers for System Frameworks Import umbrella headers for system frameworks and system libraries rather than include individual files. While it may seem tempting to include individual system headers from a framework such as Cocoa or Foundation, in fact it's less work on the compiler if you include the top-level root framework. The root framework is generally pre-compiled and can be loaded much more quickly. In addition, remember to use `@import` or `#import` rather than `#include` for Objective-C frameworks. ```objectivec // GOOD: @import UIKit; // GOOD. #import // GOOD. ``` ```objectivec // AVOID: #import // AVOID. #import ... ``` ### Avoid Messaging the Current Object Within Initializers and `-dealloc` Code in initializers and `-dealloc` should avoid invoking instance methods when possible. Superclass initialization completes before subclass initialization. Until all classes have had a chance to initialize their instance state any method invocation on self may lead to a subclass operating on uninitialized instance state. A similar issue exists for `-dealloc`, where a method invocation may cause a class to operate on state that has been deallocated. One case where this is less obvious is property accessors. These can be overridden just like any other selector. Whenever practical, directly assign to and release ivars in initializers and `-dealloc`, rather than rely on accessors. ```objectivec // GOOD: - (instancetype)init { self = [super init]; if (self) { _bar = 23; // GOOD. } return self; } ``` Beware of factoring common initialization code into helper methods: - Methods can be overridden in subclasses, either deliberately, or accidentally due to naming collisions. - When editing a helper method, it may not be obvious that the code is being run from an initializer. ```objectivec // AVOID: - (instancetype)init { self = [super init]; if (self) { self.bar = 23; // AVOID. [self sharedMethod]; // AVOID. Fragile to subclassing or future extension. } return self; } ``` ```objectivec // GOOD: - (void)dealloc { [_notifier removeObserver:self]; // GOOD. } ``` ```objectivec // AVOID: - (void)dealloc { [self removeNotifications]; // AVOID. } ``` There are common cases where a class may need to use properties and methods provided by a superclass during initialization. This commonly occurs for classes derived from UIKit and AppKit base classes, among other base classes. Use your judgement and knowledge of common practice when deciding whether to make an exception to this rule. ### Avoid redundant property access Code should avoid redundant property access. Prefer to assign a property value to a local variable when the property value is not expected to change and needs to be used multiple times. ```objc // GOOD: UIView *view = self.view; UIScrollView *scrollView = self.scrollView; [scrollView.leadingAnchor constraintEqualToAnchor:view.leadingAnchor].active = YES; [scrollView.trailingAnchor constraintEqualToAnchor:view.trailingAnchor].active = YES; ``` ```objc // AVOID: [self.scrollView.loadingAnchor constraintEqualToAnchor:self.view.loadingAnchor].active = YES; [self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES; ``` When repeatedly referencing chained property invocations, prefer to capture the repeated expression in a local variable: ```objc // AVOID: foo.bar.baz.field1 = 10; foo.bar.baz.field2 = @"Hello"; foo.bar.baz.field3 = 2.71828183; ``` ```objc // GOOD: Baz *baz = foo.bar.baz; baz.field1 = 10; baz.field2 = @"Hello"; baz.field3 = 2.71828183; ``` Redundantly accessing the same properties results in multiple message dispatches to fetch the same value, and under ARC requires retains and releases of any returned objects; the compiler cannot optimize away these extra operations, leading to slower execution and substantial increases in binary size. ### Mutables, Copies and Ownership For [Foundation and other hierarchies containing both immutable and mutable subclasses](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ObjectMutability/ObjectMutability.html) a mutable subclass may be substituted for an immutable so long as the immutable's contract is honored. The most common example of this sort of substitution are ownership transfers, particularly for return values. In these cases an additional copy is not necessary and returning the mutable subclass is more efficient. [Callers are expected to treat return values as their declared type](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ObjectMutability/ObjectMutability.html#//apple_ref/doc/uid/TP40010810-CH5-SW67), and thus the return value will be treated as an immutable going forward. ```objectivec // GOOD: - (NSArray *)listOfThings { NSMutableArray *generatedList = [NSMutableArray array]; for (NSInteger i = 0; i < _someLimit; i++) { [generatedList addObject:[self thingForIndex:i]]; } // Copy not necessary, ownership of generatedList is transferred. return generatedList; } ``` This rule also applies to classes where only a mutable variant exists so long as the ownership transfer is clear. Protos are a common example. ```objectivec // GOOD: - (SomeProtoMessage *)someMessageForValue:(BOOL)value { SomeProtoMessage *message = [SomeProtoMessage message]; message.someValue = value; return message; } ``` It is not necessary to create a local immutable copy of a mutable type to match the method signature of a method being called so long as the mutable argument will not change for the duration of the method call. Called methods are expected to treat arguments as the declared type, and take [defensive copies](#Defensive_Copies) ([referred to by Apple as "snapshots"](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ObjectMutability/ObjectMutability.html#//apple_ref/doc/uid/TP40010810-CH5-SW68)) if they intend to retain those arguments beyond the duration of the call. ```objectivec // AVOID: NSMutableArray *updatedThings = [NSMutableArray array]; [updatedThings addObject:newThing]; [_otherManager updateWithCurrentThings:[updatedThings copy]]; // AVOID ``` ### Copy Potentially Mutable Objects Code receiving and retaining collections or other types with [mutable variants](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ObjectMutability/ObjectMutability.html) should consider that the passed object may be mutable, and thus an immutable or mutable copy should be retained instead of the original object. In particular, initializers and setters [should copy instead of retaining objects whose types have mutable variants](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ObjectMutability/ObjectMutability.html#//apple_ref/doc/uid/TP40010810-CH5-SW68). Synthesized accessors should use the `copy` keyword to ensure the generated code matches these expectations. NOTE: [The `copy` property keyword only affects the synthesized setter and has no effect on getters](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW27). Since property keywords have no effect on direct ivar access custom accessors must implement the same copy semantics. ```objectivec // GOOD: @property(nonatomic, copy) NSString *name; @property(nonatomic, copy) NSSet *filters; - (instancetype)initWithName:(NSString *)name filters:(NSSet *)filters { self = [super init]; if (self) { _name = [name copy]; _filters = [filters copy]; } return self; } - (void)setFilters:(NSSet *)filters { // Ensure that we retain an immutable collection. _filters = [filters copy]; } ``` Similarly, getters must return types that match the contract expectations of the immutable types they return. ```objectivec // GOOD: @implementation Foo { NSMutableArray *_currentContent; } - (NSArray *)currentContent { return [_currentContent copy]; } ``` All Objective-C protos are mutable and typically should be copied rather than retained [except in clear cases of ownership transfer](#Mutables_Copies_Ownership). ```objectivec // GOOD: - (void)setFooMessage:(FooMessage *)fooMessage { // Copy proto to ensure no other retainer can mutate our value. _fooMessage = [fooMessage copy]; } - (FooMessage *)fooMessage { // Copy proto to return so that caller cannot mutate our value. return [_fooMessage copy]; } ``` Asynchronous code should copy potentially mutable objects prior to dispatch. Objects captured by blocks are retained but not copied. ```objectivec // GOOD: - (void)doSomethingWithThings:(NSArray *)things { NSArray *thingsToWorkOn = [things copy]; dispatch_async(_workQueue, ^{ for (id thing in thingsToWorkOn) { ... } }); } ``` NOTE: It is unnecessary to copy objects that do not have mutable variants, e.g. `NSURL`, `NSNumber`, `NSDate`, `UIColor`, etc. ### Use Lightweight Generics to Document Contained Types All projects compiling on Xcode 7 or newer versions should make use of the Objective-C lightweight generics notation to type contained objects. Every `NSArray`, `NSDictionary`, or `NSSet` reference should be declared using lightweight generics for improved type safety and to explicitly document usage. ```objectivec // GOOD: @property(nonatomic, copy) NSArray *locations; @property(nonatomic, copy, readonly) NSSet *identifiers; NSMutableArray *mutableLocations = [otherObject.locations mutableCopy]; ``` If the fully-annotated types become complex, consider using a typedef to preserve readability. ```objectivec // GOOD: typedef NSSet *> TimeZoneMappingSet; TimeZoneMappingSet *timeZoneMappings = [TimeZoneMappingSet setWithObjects:...]; ``` Use the most descriptive common superclass or protocol available. In the most generic case when nothing else is known, declare the collection to be explicitly heterogeneous using id. ```objectivec // GOOD: @property(nonatomic, copy) NSArray *unknowns; ``` ### Avoid Throwing Exceptions Don't `@throw` Objective-C exceptions, but you should be prepared to catch them from third-party or OS calls. This follows the recommendation to use error objects for error delivery in [Apple's Introduction to Exception Programming Topics for Cocoa](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Exceptions/Exceptions.html). We do compile with `-fobjc-exceptions` (mainly so we get `@synchronized`), but we don't `@throw`. Use of `@try`, `@catch`, and `@finally` are allowed when required to properly use 3rd party code or libraries. If you do use them, please document exactly which methods you expect to throw. ### `nil` Checks Avoid `nil` pointer checks that exist only to prevent sending messages to `nil`. Sending a message to `nil` [reliably returns](http://www.sealiesoftware.com/blog/archive/2012/2/29/objc_explain_return_value_of_message_to_nil.html) `nil` as a pointer, zero as an integer or floating-point value, structs initialized to `0`, and `_Complex` values equal to `{0, 0}`. ```objectivec // AVOID: if (dataSource) { // AVOID. [dataSource moveItemAtIndex:1 toIndex:0]; } ``` ```objectivec // GOOD: [dataSource moveItemAtIndex:1 toIndex:0]; // GOOD. ``` Note that this applies to `nil` as a message target, not as a parameter value. Individual methods may or may not safely handle `nil` parameter values. Note too that this is distinct from checking C/C++ pointers and block pointers against `NULL`, which the runtime does not handle and will cause your application to crash. You still need to make sure you do not dereference a `NULL` pointer. ### Nullability Interfaces can be decorated with nullability annotations to describe how the interface should be used and how it behaves. Use of nullability regions (e.g., `NS_ASSUME_NONNULL_BEGIN` and `NS_ASSUME_NONNULL_END`) and explicit nullability annotations are both accepted. Prefer using the `_Nullable` and `_Nonnull` keywords over the `__nullable` and `__nonnull` keywords. For Objective-C methods and properties prefer using the context-sensitive, non-underscored keywords, e.g., `nonnull` and `nullable`. ```objectivec // GOOD: /** A class representing an owned book. */ @interface GTMBook : NSObject /** The title of the book. */ @property(nonatomic, readonly, copy, nonnull) NSString *title; /** The author of the book, if one exists. */ @property(nonatomic, readonly, copy, nullable) NSString *author; /** The owner of the book. Setting nil resets to the default owner. */ @property(nonatomic, copy, null_resettable) NSString *owner; /** Initializes a book with a title and an optional author. */ - (nonnull instancetype)initWithTitle:(nonnull NSString *)title author:(nullable NSString *)author NS_DESIGNATED_INITIALIZER; /** Returns nil because a book is expected to have a title. */ - (nullable instancetype)init; @end /** Loads books from the file specified by the given path. */ NSArray *_Nullable GTMLoadBooksFromFile(NSString *_Nonnull path); ``` ```objectivec // AVOID: NSArray *__nullable GTMLoadBooksFromTitle(NSString *__nonnull path); ``` Do not assume that a pointer is not null based on a nonnull qualifier, because the compiler only checks a subset of such cases, and does not guarantee that the pointer is not null. Avoid intentionally violating nullability semantics of function, method, and property declarations. ### BOOL Pitfalls #### BOOL Expressions and Conversions Be careful when converting general integral values to `BOOL`. Avoid comparing directly with `YES` or comparing multiple `BOOL` values with comparison operators. `BOOL` on some Apple platforms (notably Intel macOS, watchOS, and 32-bit iOS) is defined as a signed `char`, so it may have values other than `YES` (`1`) and `NO` (`0`). Do not cast or convert general integral values directly to `BOOL`. Common mistakes include casting or converting an array's size, a pointer value, or the result of a bitwise logic operation to a `BOOL`. These operations can depend on the value of the last byte of the integer value and result in an unexpected `NO` value. Operations with NS_OPTIONS values and flag masking are especially common errors. When converting a general integral value to a `BOOL`, use conditional operators to return a `YES` or `NO` value. You can safely interchange and convert `BOOL`, `_Bool` and `bool` (see C++ Std 4.7.4, 4.12 and C99 Std 6.3.1.2). Use `BOOL` in Objective-C method signatures. Using logical operators (`&&`, `||` and `!`) with `BOOL` is also valid and will return values that can be safely converted to `BOOL` without the need for a conditional operator. ```objectivec // AVOID: - (BOOL)isBold { return [self fontTraits] & NSFontBoldTrait; // AVOID. } - (BOOL)isValid { return [self stringValue]; // AVOID. } - (BOOL)isLongEnough { return (BOOL)([self stringValue].count); // AVOID. } ``` ```objectivec // GOOD: - (BOOL)isBold { return ([self fontTraits] & NSFontBoldTrait) ? YES : NO; } - (BOOL)isValid { return [self stringValue] != nil; } - (BOOL)isLongEnough { return [self stringValue].count > 0; } - (BOOL)isEnabled { return [self isValid] && [self isBold]; } ``` Don't directly compare `BOOL` variables directly with `YES`. Not only is it harder to read for those well-versed in C, but the first point above demonstrates that return values may not always be what you expect. ```objectivec // AVOID: BOOL great = [foo isGreat]; if (great == YES) { // AVOID. // ...be great! } ``` ```objectivec // GOOD: BOOL great = [foo isGreat]; if (great) { // GOOD. // ...be great! } ``` Don't directly compare `BOOL` values using comparison operators. `BOOL` values that are true may not be equal. Use logical operators in place of bitwise comparisons of `BOOL` values. ```objectivec // AVOID: if (oldBOOLValue != newBOOLValue) { // AVOID. // ... code that should only run when the value changes. } ``` ```objectivec // GOOD: if ((!oldBoolValue && newBoolValue) || (oldBoolValue && !newBoolValue)) { // GOOD. // ... code that should only run when the value changes. } // GOOD, the results of logical operators on BOOLs are safe to compare. if (!oldBoolValue != !newBoolValue) { // ... code that should only run when the value changes. } ``` #### BOOL Literals The [BOOL NSNumber literals](https://clang.llvm.org/docs/ObjectiveCLiterals.html#nsnumber-literals) are `@YES` and `@NO` which are equivalent to `[NSNumber numberWithBool:...]`. Avoid using [boxed expressions](https://clang.llvm.org/docs/ObjectiveCLiterals.html#boxed-expressions) to create BOOL values, including simple expressions like `@(YES)`. Boxed expressions suffer from [the same pitfalls as other BOOL expressions] (#BOOL_Expressions_Conversions) as boxing general integral values can produce true or false `NSNumbers` that are not equal to `@YES` and `@NO`. When converting a general integral value to a BOOL literal, use conditional operators to convert to `@YES` or `@NO`. Do not embed a conditional operator inside a boxed expression as this is equivalent to boxing general integral values even when the result of the operation is a BOOL. ```objectivec // AVOID: [_boolArray addValue:@(YES)]; // AVOID boxing even in simple cases. NSNumber *isBold = @(self.fontTraits & NSFontBoldTrait); // AVOID. NSNumber *hasContent = @([self stringValue].length); // AVOID. NSNumber *isValid = @([self stringValue]); // AVOID. NSNumber *isStringNotNil = @([self stringValue] ? YES : NO); // AVOID. ``` ```objectivec // GOOD: [_boolArray addValue:@YES]; // GOOD. NSNumber *isBold = self.fontTraits & NSFontBoldTrait ? @YES : @NO; // GOOD. NSNumber *hasContent = [self stringValue].length ? @YES : @NO; // GOOD. NSNumber *isValid = [self stringValue] ? @YES : @NO; // GOOD. NSNumber *isStringNotNil = [self stringValue] ? @YES : @NO; // GOOD. ``` ### Containers Without Instance Variables Omit the empty set of braces on interfaces, class extensions, and implementations without any instance variable declarations. ```objectivec // GOOD: @interface MyClass : NSObject // Does a lot of stuff. - (void)fooBarBam; @end @interface MyClass () - (void)classExtensionMethod; @end @implementation MyClass // Actual implementation. @end ``` ```objectivec // AVOID: @interface MyClass : NSObject { } // Does a lot of stuff. - (void)fooBarBam; @end @interface MyClass () { } - (void)classExtensionMethod; @end @implementation MyClass { } // Actual implementation. @end ``` ## Cocoa Patterns ### Delegate Pattern Delegates, target objects, and block pointers should not be retained when doing so would create a retain cycle. To avoid causing a retain cycle, a delegate or target pointer should be released as soon as it is clear there will no longer be a need to message the object. If there is no clear time at which the delegate or target pointer is no longer needed, the pointer should only be retained weakly. Block pointers cannot be retained weakly. To avoid causing retain cycles in the client code, block pointers should be used for callbacks only where they can be explicitly released after they have been called or once they are no longer needed. Otherwise, callbacks should be done via weak delegate or target pointers. ## Objective-C++ ### Style Matches the Language Within an Objective-C++ source file, follow the style for the language of the function or method you're implementing. In order to minimize clashes between the differing naming styles when mixing Cocoa/Objective-C and C++, follow the style of the method being implemented. For code in an `@implementation` block, use the Objective-C naming rules. For code in a method of a C++ class, use the C++ naming rules. For code in an Objective-C++ file outside of a class implementation, be consistent within the file. ```objectivec++ // GOOD: // file: cross_platform_header.h class CrossPlatformAPI { public: ... int DoSomethingPlatformSpecific(); // impl on each platform private: int an_instance_var_; }; // file: mac_implementation.mm #include "cross_platform_header.h" /** A typical Objective-C class, using Objective-C naming. */ @interface MyDelegate : NSObject { @private int _instanceVar; CrossPlatformAPI* _backEndObject; } - (void)respondToSomething:(id)something; @end @implementation MyDelegate - (void)respondToSomething:(id)something { // bridge from Cocoa through our C++ backend _instanceVar = _backEndObject->DoSomethingPlatformSpecific(); NSString* tempString = [NSString stringWithFormat:@"%d", _instanceVar]; NSLog(@"%@", tempString); } @end /** The platform-specific implementation of the C++ class, using C++ naming. */ int CrossPlatformAPI::DoSomethingPlatformSpecific() { NSString* temp_string = [NSString stringWithFormat:@"%d", an_instance_var_]; NSLog(@"%@", temp_string); return [temp_string intValue]; } ``` Projects may opt to use an 80 column line length limit for consistency with Google's C++ style guide. ## Spacing and Formatting ### Spaces vs. Tabs Use only spaces, and indent 2 spaces at a time. We use spaces for indentation. Do not use tabs in your code. You should set your editor to emit spaces when you hit the tab key, and to trim trailing spaces on lines. ### Line Length The maximum line length for Objective-C files is 100 columns. ### Method Declarations and Definitions One space should be used between the `-` or `+` and the return type. In general, there should be no spacing in the parameter list except between parameters. Methods should look like this: ```objectivec // GOOD: - (void)doSomethingWithString:(NSString *)theString { ... } ``` The spacing before the asterisk is optional. When adding new code, be consistent with the surrounding file's style. If a method declaration does not fit on a single line, put each parameter on its own line. All lines except the first should be indented at least four spaces. Colons before parameters should be aligned on all lines. If the colon before the parameter on the first line of a method declaration is positioned such that colon alignment would cause indentation on a subsequent line to be less than four spaces, then colon alignment is only required for all lines except the first. If a parameter declared after the `:` in a method declaration or definition would cause the line limit to be exceeded, wrap the content to the next line indented by at least four spaces. ```objectivec // GOOD: - (void)doSomethingWithFoo:(GTMFoo *)theFoo rect:(NSRect)theRect interval:(float)theInterval { ... } - (void)shortKeyword:(GTMFoo *)theFoo longerKeyword:(NSRect)theRect someEvenLongerKeyword:(float)theInterval error:(NSError **)theError { ... } - (id) adaptivePresentationControllerDelegateForViewController:(UIViewController *)viewController; - (void)presentWithAdaptivePresentationControllerDelegate: (id)delegate; - (void)updateContentHeaderViewForExpansionToContentOffset:(CGPoint)contentOffset withController: (GTMCollectionExpansionController *)controller; ``` ### Function Declarations and Definitions Prefer putting the return type on the same line as the function name and append all parameters on the same line if they will fit. Wrap parameter lists which do not fit on a single line as you would wrap arguments in a [function call](#Function_Calls). ```objectivec // GOOD: NSString *GTMVersionString(int majorVersion, int minorVersion) { ... } void GTMSerializeDictionaryToFileOnDispatchQueue( NSDictionary *dictionary, NSString *filename, dispatch_queue_t queue) { ... } ``` Function declarations and definitions should also satisfy the following conditions: * The opening parenthesis must always be on the same line as the function name. * If you cannot fit the return type and the function name on a single line, break between them and do not indent the function name. * There should never be a space before the opening parenthesis. * There should never be a space between function parentheses and parameters. * The open curly brace is always on the end of the last line of the function declaration, not the start of the next line. * The close curly brace is either on the last line by itself or on the same line as the open curly brace. * There should be a space between the close parenthesis and the open curly brace. * All parameters should be aligned if possible. * Function scopes should be indented 2 spaces. * Wrapped parameters should have a 4 space indent. ### Conditionals Include a space after `if`, `while`, `for`, and `switch`, and around comparison operators. ```objectivec // GOOD: for (int i = 0; i < 5; ++i) { } while (test) {}; ``` Braces may be omitted when a loop body or conditional statement fits on a single line. ```objectivec // GOOD: if (hasSillyName) LaughOutLoud(); for (int i = 0; i < 10; i++) { BlowTheHorn(); } ``` ```objectivec // AVOID: if (hasSillyName) LaughOutLoud(); // AVOID. for (int i = 0; i < 10; i++) BlowTheHorn(); // AVOID. ``` If an `if` clause has an `else` clause, both clauses should use braces. ```objectivec // GOOD: if (hasBaz) { foo(); } else { // The else goes on the same line as the closing brace. bar(); } ``` ```objectivec // AVOID: if (hasBaz) foo(); else bar(); // AVOID. if (hasBaz) { foo(); } else bar(); // AVOID. ``` Intentional fall-through to the next case should be documented with a comment unless the case has no intervening code before the next case. ```objectivec // GOOD: switch (i) { case 1: ... break; case 2: j++; // Falls through. case 3: { int k; ... break; } case 4: case 5: case 6: break; } ``` ### Expressions Use a space around binary operators and assignments. Omit a space for a unary operator. Do not add spaces inside parentheses. ```objectivec // GOOD: x = 0; v = w * x + y / z; v = -y * (x + z); ``` Factors in an expression may omit spaces. ```objectivec // GOOD: v = w*x + y/z; ``` ### Method Invocations Method invocations should be formatted much like method declarations. When there's a choice of formatting styles, follow the convention already used in a given source file. Invocations should have all arguments on one line: ```objectivec // GOOD: [myObject doFooWith:arg1 name:arg2 error:arg3]; ``` or have one argument per line, with colons aligned: ```objectivec // GOOD: [myObject doFooWith:arg1 name:arg2 error:arg3]; ``` Don't use any of these styles: ```objectivec // AVOID: [myObject doFooWith:arg1 name:arg2 // some lines with >1 arg error:arg3]; [myObject doFooWith:arg1 name:arg2 error:arg3]; [myObject doFooWith:arg1 name:arg2 // aligning keywords instead of colons error:arg3]; ``` As with declarations and definitions, when the first keyword is shorter than the others, indent the later lines by at least four spaces, maintaining colon alignment: ```objectivec // GOOD: [myObj short:arg1 longKeyword:arg2 evenLongerKeyword:arg3 error:arg4]; ``` Invocations containing multiple inlined blocks may have their parameter names left-aligned at a four space indent. ### Function Calls Function calls should include as many parameters as fit on each line, except where shorter lines are needed for clarity or documentation of the parameters. Continuation lines for function parameters may be indented to align with the opening parenthesis, or may have a four-space indent. ```objectivec // GOOD: CFArrayRef array = CFArrayCreate(kCFAllocatorDefault, objects, numberOfObjects, &kCFTypeArrayCallBacks); NSString *string = NSLocalizedStringWithDefaultValue(@"FEET", @"DistanceTable", resourceBundle, @"%@ feet", @"Distance for multiple feet"); UpdateTally(scores[x] * y + bases[x], // Score heuristic. x, y, z); TransformImage(image, x1, x2, x3, y1, y2, y3, z1, z2, z3); ``` Use local variables with descriptive names to shorten function calls and reduce nesting of calls. ```objectivec // GOOD: double scoreHeuristic = scores[x] * y + bases[x]; UpdateTally(scoreHeuristic, x, y, z); ``` ### Exceptions Format exceptions with `@catch` and `@finally` labels on the same line as the preceding `}`. Add a space between the `@` label and the opening brace (`{`), as well as between the `@catch` and the caught object declaration. If you must use Objective-C exceptions, format them as follows. However, see [Avoid Throwing Exceptions](#Avoid_Throwing_Exceptions) for reasons why you should not be using exceptions. ```objectivec // GOOD: @try { foo(); } @catch (NSException *ex) { bar(ex); } @finally { baz(); } ``` ### Function Length Prefer small and focused functions. Long functions and methods are occasionally appropriate, so no hard limit is placed on function length. If a function exceeds about 40 lines, think about whether it can be broken up without harming the structure of the program. Even if your long function works perfectly now, someone modifying it in a few months may add new behavior. This could result in bugs that are hard to find. Keeping your functions short and simple makes it easier for other people to read and modify your code. When updating legacy code, consider also breaking long functions into smaller and more manageable pieces. ### Vertical Whitespace Use vertical whitespace sparingly. To allow more code to be easily viewed on a screen, avoid putting blank lines just inside the braces of functions. Limit blank lines to one or two between functions and between logical groups of code. ## Objective-C Style Exceptions ### Indicating style exceptions Lines of code that are not expected to adhere to these style recommendations require `// NOLINT` at the end of the line or `// NOLINTNEXTLINE` at the end of the previous line. Sometimes it is required that parts of Objective-C code must ignore these style recommendations (for example code may be machine generated or code constructs are such that its not possible to style correctly). A `// NOLINT` comment on that line or `// NOLINTNEXTLINE` on the previous line can be used to indicate to the reader that code is intentionally ignoring style guidelines. In addition these annotations can also be picked up by automated tools such as linters and handle code correctly. Note that there is a single space between `//` and `NOLINT*`. ================================================ FILE: objcguide.xml ================================================

The style guide has moved to objcguide.md

================================================ FILE: pyguide.md ================================================ # Google Python Style Guide
Table of Contents - [1 Background](#s1-background) - [2 Python Language Rules](#s2-python-language-rules) * [2.1 Lint](#s2.1-lint) * [2.2 Imports](#s2.2-imports) * [2.3 Packages](#s2.3-packages) * [2.4 Exceptions](#s2.4-exceptions) * [2.5 Mutable Global State](#s2.5-global-variables) * [2.6 Nested/Local/Inner Classes and Functions](#s2.6-nested) * [2.7 Comprehensions & Generator Expressions](#s2.7-comprehensions) * [2.8 Default Iterators and Operators](#s2.8-default-iterators-and-operators) * [2.9 Generators](#s2.9-generators) * [2.10 Lambda Functions](#s2.10-lambda-functions) * [2.11 Conditional Expressions](#s2.11-conditional-expressions) * [2.12 Default Argument Values](#s2.12-default-argument-values) * [2.13 Properties](#s2.13-properties) * [2.14 True/False Evaluations](#s2.14-truefalse-evaluations) * [2.16 Lexical Scoping](#s2.16-lexical-scoping) * [2.17 Function and Method Decorators](#s2.17-function-and-method-decorators) * [2.18 Threading](#s2.18-threading) * [2.19 Power Features](#s2.19-power-features) * [2.20 Modern Python: from \_\_future\_\_ imports](#s2.20-modern-python) * [2.21 Type Annotated Code](#s2.21-type-annotated-code) - [3 Python Style Rules](#s3-python-style-rules) * [3.1 Semicolons](#s3.1-semicolons) * [3.2 Line length](#s3.2-line-length) * [3.3 Parentheses](#s3.3-parentheses) * [3.4 Indentation](#s3.4-indentation) + [3.4.1 Trailing commas in sequences of items?](#s3.4.1-trailing-commas) * [3.5 Blank Lines](#s3.5-blank-lines) * [3.6 Whitespace](#s3.6-whitespace) * [3.7 Shebang Line](#s3.7-shebang-line) * [3.8 Comments and Docstrings](#s3.8-comments-and-docstrings) + [3.8.1 Docstrings](#s3.8.1-comments-in-doc-strings) + [3.8.2 Modules](#s3.8.2-comments-in-modules) + [3.8.2.1 Test modules](#s3.8.2.1-test-modules) + [3.8.3 Functions and Methods](#s3.8.3-functions-and-methods) + [3.8.3.1 Overridden Methods](#s3.8.3.1-overridden-methods) + [3.8.4 Classes](#s3.8.4-comments-in-classes) + [3.8.5 Block and Inline Comments](#s3.8.5-block-and-inline-comments) + [3.8.6 Punctuation, Spelling, and Grammar](#s3.8.6-punctuation-spelling-and-grammar) * [3.10 Strings](#s3.10-strings) + [3.10.1 Logging](#s3.10.1-logging) + [3.10.2 Error Messages](#s3.10.2-error-messages) * [3.11 Files, Sockets, and similar Stateful Resources](#s3.11-files-sockets-closeables) * [3.12 TODO Comments](#s3.12-todo-comments) * [3.13 Imports formatting](#s3.13-imports-formatting) * [3.14 Statements](#s3.14-statements) * [3.15 Accessors](#s3.15-accessors) * [3.16 Naming](#s3.16-naming) + [3.16.1 Names to Avoid](#s3.16.1-names-to-avoid) + [3.16.2 Naming Conventions](#s3.16.2-naming-conventions) + [3.16.3 File Naming](#s3.16.3-file-naming) + [3.16.4 Guidelines derived from Guido's Recommendations](#s3.16.4-guidelines-derived-from-guidos-recommendations) * [3.17 Main](#s3.17-main) * [3.18 Function length](#s3.18-function-length) * [3.19 Type Annotations](#s3.19-type-annotations) + [3.19.1 General Rules](#s3.19.1-general-rules) + [3.19.2 Line Breaking](#s3.19.2-line-breaking) + [3.19.3 Forward Declarations](#s3.19.3-forward-declarations) + [3.19.4 Default Values](#s3.19.4-default-values) + [3.19.5 NoneType](#s3.19.5-nonetype) + [3.19.6 Type Aliases](#s3.19.6-type-aliases) + [3.19.7 Ignoring Types](#s3.19.7-ignoring-types) + [3.19.8 Typing Variables](#s3.19.8-typing-variables) + [3.19.9 Tuples vs Lists](#s3.19.9-tuples-vs-lists) + [3.19.10 Type variables](#s3.19.10-typevars) + [3.19.11 String types](#s3.19.11-string-types) + [3.19.12 Imports For Typing](#s3.19.12-imports-for-typing) + [3.19.13 Conditional Imports](#s3.19.13-conditional-imports) + [3.19.14 Circular Dependencies](#s3.19.14-circular-dependencies) + [3.19.15 Generics](#s3.19.15-generics) + [3.19.16 Build Dependencies](#s3.19.16-build-dependencies) - [4 Parting Words](#4-parting-words)
## 1 Background Python is the main dynamic language used at Google. This style guide is a list of *dos and don'ts* for Python programs. To help you format code correctly, we've created a [settings file for Vim](google_python_style.vim). For Emacs, the default settings should be fine. Many teams use the [Black](https://github.com/psf/black) or [Pyink](https://github.com/google/pyink) auto-formatter to avoid arguing over formatting. ## 2 Python Language Rules ### 2.1 Lint Run `pylint` over your code using this [pylintrc](https://google.github.io/styleguide/pylintrc). #### 2.1.1 Definition `pylint` is a tool for finding bugs and style problems in Python source code. It finds problems that are typically caught by a compiler for less dynamic languages like C and C++. Because of the dynamic nature of Python, some warnings may be incorrect; however, spurious warnings should be fairly infrequent. #### 2.1.2 Pros Catches easy-to-miss errors like typos, using-vars-before-assignment, etc. #### 2.1.3 Cons `pylint` isn't perfect. To take advantage of it, sometimes we'll need to write around it, suppress its warnings or fix it. #### 2.1.4 Decision Make sure you run `pylint` on your code. Suppress warnings if they are inappropriate so that other issues are not hidden. To suppress warnings, you can set a line-level comment: ```python def do_PUT(self): # WSGI name, so pylint: disable=invalid-name ... ``` `pylint` warnings are each identified by symbolic name (`empty-docstring`) Google-specific warnings start with `g-`. If the reason for the suppression is not clear from the symbolic name, add an explanation. Suppressing in this way has the advantage that we can easily search for suppressions and revisit them. You can get a list of `pylint` warnings by doing: ```shell pylint --list-msgs ``` To get more information on a particular message, use: ```shell pylint --help-msg=invalid-name ``` Prefer `pylint: disable` to the deprecated older form `pylint: disable-msg`. Unused argument warnings can be suppressed by deleting the variables at the beginning of the function. Always include a comment explaining why you are deleting it. "Unused." is sufficient. For example: ```python def viking_cafe_order(spam: str, beans: str, eggs: str | None = None) -> str: del beans, eggs # Unused by vikings. return spam + spam + spam ``` Other common forms of suppressing this warning include using '`_`' as the identifier for the unused argument or prefixing the argument name with '`unused_`', or assigning them to '`_`'. These forms are allowed but no longer encouraged. These break callers that pass arguments by name and do not enforce that the arguments are actually unused. ### 2.2 Imports Use `import` statements for packages and modules only, not for individual types, classes, or functions. #### 2.2.1 Definition Reusability mechanism for sharing code from one module to another. #### 2.2.2 Pros The namespace management convention is simple. The source of each identifier is indicated in a consistent way; `x.Obj` says that object `Obj` is defined in module `x`. #### 2.2.3 Cons Module names can still collide. Some module names are inconveniently long. #### 2.2.4 Decision * Use `import x` for importing packages and modules. * Use `from x import y` where `x` is the package prefix and `y` is the module name with no prefix. * Use `from x import y as z` in any of the following circumstances: - Two modules named `y` are to be imported. - `y` conflicts with a top-level name defined in the current module. - `y` conflicts with a common parameter name that is part of the public API (e.g., `features`). - `y` is an inconveniently long name. - `y` is too generic in the context of your code (e.g., `from storage.file_system import options as fs_options`). * Use `import y as z` only when `z` is a standard abbreviation (e.g., `import numpy as np`). For example the module `sound.effects.echo` may be imported as follows: ```python from sound.effects import echo ... echo.EchoFilter(input, output, delay=0.7, atten=4) ``` Do not use relative names in imports. Even if the module is in the same package, use the full package name. This helps prevent unintentionally importing a package twice. ##### 2.2.4.1 Exemptions Exemptions from this rule: * Symbols from the following modules are used to support static analysis and type checking: * [`typing` module](#typing-imports) * [`collections.abc` module](#typing-imports) * [`typing_extensions` module](https://github.com/python/typing_extensions/blob/main/README.md) * Redirects from the [six.moves module](https://six.readthedocs.io/#module-six.moves). ### 2.3 Packages Import each module using the full pathname location of the module. #### 2.3.1 Pros Avoids conflicts in module names or incorrect imports due to the module search path not being what the author expected. Makes it easier to find modules. #### 2.3.2 Cons Makes it harder to deploy code because you have to replicate the package hierarchy. Not really a problem with modern deployment mechanisms. #### 2.3.3 Decision All new code should import each module by its full package name. Imports should be as follows: ```python Yes: # Reference absl.flags in code with the complete name (verbose). import absl.flags from doctor.who import jodie _FOO = absl.flags.DEFINE_string(...) ``` ```python Yes: # Reference flags in code with just the module name (common). from absl import flags from doctor.who import jodie _FOO = flags.DEFINE_string(...) ``` *(assume this file lives in `doctor/who/` where `jodie.py` also exists)* ```python No: # Unclear what module the author wanted and what will be imported. The actual # import behavior depends on external factors controlling sys.path. # Which possible jodie module did the author intend to import? import jodie ``` The directory the main binary is located in should not be assumed to be in `sys.path` despite that happening in some environments. This being the case, code should assume that `import jodie` refers to a third-party or top-level package named `jodie`, not a local `jodie.py`. ### 2.4 Exceptions Exceptions are allowed but must be used carefully. #### 2.4.1 Definition Exceptions are a means of breaking out of normal control flow to handle errors or other exceptional conditions. #### 2.4.2 Pros The control flow of normal operation code is not cluttered by error-handling code. It also allows the control flow to skip multiple frames when a certain condition occurs, e.g., returning from N nested functions in one step instead of having to plumb error codes through. #### 2.4.3 Cons May cause the control flow to be confusing. Easy to miss error cases when making library calls. #### 2.4.4 Decision Exceptions must follow certain conditions: - Make use of built-in exception classes when it makes sense. For example, raise a `ValueError` to indicate a programming mistake like a violated precondition, such as may happen when validating function arguments. - Do not use `assert` statements in place of conditionals or validating preconditions. They must not be critical to the application logic. A litmus test would be that the `assert` could be removed without breaking the code. `assert` conditionals are [not guaranteed](https://docs.python.org/3/reference/simple_stmts.html#the-assert-statement) to be evaluated. For [pytest](https://pytest.org) based tests, `assert` is okay and expected to verify expectations. For example: ```python Yes: def connect_to_next_port(self, minimum: int) -> int: """Connects to the next available port. Args: minimum: A port value greater or equal to 1024. Returns: The new minimum port. Raises: ConnectionError: If no available port is found. """ if minimum < 1024: # Note that this raising of ValueError is not mentioned in the doc # string's "Raises:" section because it is not appropriate to # guarantee this specific behavioral reaction to API misuse. raise ValueError(f'Min. port must be at least 1024, not {minimum}.') port = self._find_next_open_port(minimum) if port is None: raise ConnectionError( f'Could not connect to service on port {minimum} or higher.') # The code does not depend on the result of this assert. assert port >= minimum, ( f'Unexpected port {port} when minimum was {minimum}.') return port ``` ```python No: def connect_to_next_port(self, minimum: int) -> int: """Connects to the next available port. Args: minimum: A port value greater or equal to 1024. Returns: The new minimum port. """ assert minimum >= 1024, 'Minimum port must be at least 1024.' # The following code depends on the previous assert. port = self._find_next_open_port(minimum) assert port is not None # The type checking of the return statement relies on the assert. return port ``` - Libraries or packages may define their own exceptions. When doing so they must inherit from an existing exception class. Exception names should end in `Error` and should not introduce repetition (`foo.FooError`). - Never use catch-all `except:` statements, or catch `Exception` or `StandardError`, unless you are - re-raising the exception, or - creating an isolation point in the program where exceptions are not propagated but are recorded and suppressed instead, such as protecting a thread from crashing by guarding its outermost block. Python is very tolerant in this regard and `except:` will really catch everything including misspelled names, sys.exit() calls, Ctrl+C interrupts, unittest failures and all kinds of other exceptions that you simply don't want to catch. - Minimize the amount of code in a `try`/`except` block. The larger the body of the `try`, the more likely that an exception will be raised by a line of code that you didn't expect to raise an exception. In those cases, the `try`/`except` block hides a real error. - Use the `finally` clause to execute code whether or not an exception is raised in the `try` block. This is often useful for cleanup, i.e., closing a file. ### 2.5 Mutable Global State Avoid mutable global state. #### 2.5.1 Definition Module-level values or class attributes that can get mutated during program execution. #### 2.5.2 Pros Occasionally useful. #### 2.5.3 Cons * Breaks encapsulation: Such design can make it hard to achieve valid objectives. For example, if global state is used to manage a database connection, then connecting to two different databases at the same time (such as for computing differences during a migration) becomes difficult. Similar problems easily arise with global registries. * Has the potential to change module behavior during the import, because assignments to global variables are done when the module is first imported. #### 2.5.4 Decision Avoid mutable global state. In those rare cases where using global state is warranted, mutable global entities should be declared at the module level or as a class attribute and made internal by prepending an `_` to the name. If necessary, external access to mutable global state must be done through public functions or class methods. See [Naming](#s3.16-naming) below. Please explain the design reasons why mutable global state is being used in a comment or a doc linked to from a comment. Module-level constants are permitted and encouraged. For example: `_MAX_HOLY_HANDGRENADE_COUNT = 3` for an internal use constant or `SIR_LANCELOTS_FAVORITE_COLOR = "blue"` for a public API constant. Constants must be named using all caps with underscores. See [Naming](#s3.16-naming) below. ### 2.6 Nested/Local/Inner Classes and Functions Nested local functions or classes are fine when used to close over a local variable. Inner classes are fine. #### 2.6.1 Definition A class can be defined inside of a method, function, or class. A function can be defined inside a method or function. Nested functions have read-only access to variables defined in enclosing scopes. #### 2.6.2 Pros Allows definition of utility classes and functions that are only used inside of a very limited scope. Very [ADT](https://en.wikipedia.org/wiki/Abstract_data_type)-y. Commonly used for implementing decorators. #### 2.6.3 Cons Nested functions and classes cannot be directly tested. Nesting can make the outer function longer and less readable. #### 2.6.4 Decision They are fine with some caveats. Avoid nested functions or classes except when closing over a local value other than `self` or `cls`. Do not nest a function just to hide it from users of a module. Instead, prefix its name with an \_ at the module level so that it can still be accessed by tests. ### 2.7 Comprehensions & Generator Expressions Okay to use for simple cases. #### 2.7.1 Definition List, Dict, and Set comprehensions as well as generator expressions provide a concise and efficient way to create container types and iterators without resorting to the use of traditional loops, `map()`, `filter()`, or `lambda`. #### 2.7.2 Pros Simple comprehensions can be clearer and simpler than other dict, list, or set creation techniques. Generator expressions can be very efficient, since they avoid the creation of a list entirely. #### 2.7.3 Cons Complicated comprehensions or generator expressions can be hard to read. #### 2.7.4 Decision Comprehensions are allowed, however multiple `for` clauses or filter expressions are not permitted. Optimize for readability, not conciseness. ```python Yes: result = [mapping_expr for value in iterable if filter_expr] result = [ is_valid(metric={'key': value}) for value in interesting_iterable if a_longer_filter_expression(value) ] descriptive_name = [ transform({'key': key, 'value': value}, color='black') for key, value in generate_iterable(some_input) if complicated_condition_is_met(key, value) ] result = [] for x in range(10): for y in range(5): if x * y > 10: result.append((x, y)) return { x: complicated_transform(x) for x in long_generator_function(parameter) if x is not None } return (x**2 for x in range(10)) unique_names = {user.name for user in users if user is not None} ``` ```python No: result = [(x, y) for x in range(10) for y in range(5) if x * y > 10] return ( (x, y, z) for x in range(5) for y in range(5) if x != y for z in range(5) if y != z ) ``` ### 2.8 Default Iterators and Operators Use default iterators and operators for types that support them, like lists, dictionaries, and files. #### 2.8.1 Definition Container types, like dictionaries and lists, define default iterators and membership test operators ("in" and "not in"). #### 2.8.2 Pros The default iterators and operators are simple and efficient. They express the operation directly, without extra method calls. A function that uses default operators is generic. It can be used with any type that supports the operation. #### 2.8.3 Cons You can't tell the type of objects by reading the method names (unless the variable has type annotations). This is also an advantage. #### 2.8.4 Decision Use default iterators and operators for types that support them, like lists, dictionaries, and files. The built-in types define iterator methods, too. Prefer these methods to methods that return lists, except that you should not mutate a container while iterating over it. ```python Yes: for key in adict: ... if obj in alist: ... for line in afile: ... for k, v in adict.items(): ... ``` ```python No: for key in adict.keys(): ... for line in afile.readlines(): ... ``` ### 2.9 Generators Use generators as needed. #### 2.9.1 Definition A generator function returns an iterator that yields a value each time it executes a yield statement. After it yields a value, the runtime state of the generator function is suspended until the next value is needed. #### 2.9.2 Pros Simpler code, because the state of local variables and control flow are preserved for each call. A generator uses less memory than a function that creates an entire list of values at once. #### 2.9.3 Cons Local variables in the generator will not be garbage collected until the generator is either consumed to exhaustion or itself garbage collected. #### 2.9.4 Decision Fine. Use "Yields:" rather than "Returns:" in the docstring for generator functions. If the generator manages an expensive resource, make sure to force the clean up. A good way to do the clean up is by wrapping the generator with a context manager [PEP-0533](https://peps.python.org/pep-0533/). ### 2.10 Lambda Functions Okay for one-liners. Prefer generator expressions over `map()` or `filter()` with a `lambda`. #### 2.10.1 Definition Lambdas define anonymous functions in an expression, as opposed to a statement. #### 2.10.2 Pros Convenient. #### 2.10.3 Cons Harder to read and debug than local functions. The lack of names means stack traces are more difficult to understand. Expressiveness is limited because the function may only contain an expression. #### 2.10.4 Decision Lambdas are allowed. If the code inside the lambda function spans multiple lines or is longer than 60-80 chars, it might be better to define it as a regular [nested function](#lexical-scoping). For common operations like multiplication, use the functions from the `operator` module instead of lambda functions. For example, prefer `operator.mul` to `lambda x, y: x * y`. ### 2.11 Conditional Expressions Okay for simple cases. #### 2.11.1 Definition Conditional expressions (sometimes called a “ternary operator”) are mechanisms that provide a shorter syntax for if statements. For example: `x = 1 if cond else 2`. #### 2.11.2 Pros Shorter and more convenient than an if statement. #### 2.11.3 Cons May be harder to read than an if statement. The condition may be difficult to locate if the expression is long. #### 2.11.4 Decision Okay to use for simple cases. Each portion must fit on one line: true-expression, if-expression, else-expression. Use a complete if statement when things get more complicated. ```python Yes: one_line = 'yes' if predicate(value) else 'no' slightly_split = ('yes' if predicate(value) else 'no, nein, nyet') the_longest_ternary_style_that_can_be_done = ( 'yes, true, affirmative, confirmed, correct' if predicate(value) else 'no, false, negative, nay') ``` ```python No: bad_line_breaking = ('yes' if predicate(value) else 'no') portion_too_long = ('yes' if some_long_module.some_long_predicate_function( really_long_variable_name) else 'no, false, negative, nay') ``` ### 2.12 Default Argument Values Okay in most cases. #### 2.12.1 Definition You can specify values for variables at the end of a function's parameter list, e.g., `def foo(a, b=0):`. If `foo` is called with only one argument, `b` is set to 0. If it is called with two arguments, `b` has the value of the second argument. #### 2.12.2 Pros Often you have a function that uses lots of default values, but on rare occasions you want to override the defaults. Default argument values provide an easy way to do this, without having to define lots of functions for the rare exceptions. As Python does not support overloaded methods/functions, default arguments are an easy way of "faking" the overloading behavior. #### 2.12.3 Cons Default arguments are evaluated once at module load time. This may cause problems if the argument is a mutable object such as a list or a dictionary. If the function modifies the object (e.g., by appending an item to a list), the default value is modified. #### 2.12.4 Decision Okay to use with the following caveat: Do not use mutable objects as default values in the function or method definition. ```python Yes: def foo(a, b=None): if b is None: b = [] Yes: def foo(a, b: Sequence | None = None): if b is None: b = [] Yes: def foo(a, b: Sequence = ()): # Empty tuple OK since tuples are immutable. ... ``` ```python from absl import flags _FOO = flags.DEFINE_string(...) No: def foo(a, b=[]): ... No: def foo(a, b=time.time()): # Is `b` supposed to represent when this module was loaded? ... No: def foo(a, b=_FOO.value): # sys.argv has not yet been parsed... ... No: def foo(a, b: Mapping = {}): # Could still get passed to unchecked code. ... ``` ### 2.13 Properties Properties may be used to control getting or setting attributes that require trivial computations or logic. Property implementations must match the general expectations of regular attribute access: that they are cheap, straightforward, and unsurprising. #### 2.13.1 Definition A way to wrap method calls for getting and setting an attribute as a standard attribute access. #### 2.13.2 Pros * Allows for an attribute access and assignment API rather than [getter and setter](#getters-and-setters) method calls. * Can be used to make an attribute read-only. * Allows calculations to be lazy. * Provides a way to maintain the public interface of a class when the internals evolve independently of class users. #### 2.13.3 Cons * Can hide side-effects much like operator overloading. * Can be confusing for subclasses. #### 2.13.4 Decision Properties are allowed, but, like operator overloading, should only be used when necessary and match the expectations of typical attribute access; follow the [getters and setters](#getters-and-setters) rules otherwise. For example, using a property to simply both get and set an internal attribute isn't allowed: there is no computation occurring, so the property is unnecessary ([make the attribute public instead](#getters-and-setters)). In comparison, using a property to control attribute access or to calculate a *trivially* derived value is allowed: the logic is simple and unsurprising. Properties should be created with the `@property` [decorator](#s2.17-function-and-method-decorators). Manually implementing a property descriptor is considered a [power feature](#power-features). Inheritance with properties can be non-obvious. Do not use properties to implement computations a subclass may ever want to override and extend. ### 2.14 True/False Evaluations Use the "implicit" false if at all possible (with a few caveats). #### 2.14.1 Definition Python evaluates certain values as `False` when in a boolean context. A quick "rule of thumb" is that all "empty" values are considered false, so `0, None, [], {}, ''` all evaluate as false in a boolean context. #### 2.14.2 Pros Conditions using Python booleans are easier to read and less error-prone. In most cases, they're also faster. #### 2.14.3 Cons May look strange to C/C++ developers. #### 2.14.4 Decision Use the "implicit" false if possible, e.g., `if foo:` rather than `if foo != []:`. There are a few caveats that you should keep in mind though: - Always use `if foo is None:` (or `is not None`) to check for a `None` value. E.g., when testing whether a variable or argument that defaults to `None` was set to some other value. The other value might be a value that's false in a boolean context! - Never compare a boolean variable to `False` using `==`. Use `if not x:` instead. If you need to distinguish `False` from `None` then chain the expressions, such as `if not x and x is not None:`. - For sequences (strings, lists, tuples), use the fact that empty sequences are false, so `if seq:` and `if not seq:` are preferable to `if len(seq):` and `if not len(seq):` respectively. - When handling integers, implicit false may involve more risk than benefit (i.e., accidentally handling `None` as 0). You may compare a value which is known to be an integer (and is not the result of `len()`) against the integer 0. ```python Yes: if not users: print('no users') if i % 10 == 0: self.handle_multiple_of_ten() def f(x=None): if x is None: x = [] ``` ```python No: if len(users) == 0: print('no users') if not i % 10: self.handle_multiple_of_ten() def f(x=None): x = x or [] ``` - Note that `'0'` (i.e., `0` as string) evaluates to true. - Note that Numpy arrays may raise an exception in an implicit boolean context. Prefer the `.size` attribute when testing emptiness of a `np.array` (e.g. `if not users.size`). ### 2.16 Lexical Scoping Okay to use. #### 2.16.1 Definition A nested Python function can refer to variables defined in enclosing functions, but cannot assign to them. Variable bindings are resolved using lexical scoping, that is, based on the static program text. Any assignment to a name in a block will cause Python to treat all references to that name as a local variable, even if the use precedes the assignment. If a global declaration occurs, the name is treated as a global variable. An example of the use of this feature is: ```python def get_adder(summand1: float) -> Callable[[float], float]: """Returns a function that adds numbers to a given number.""" def adder(summand2: float) -> float: return summand1 + summand2 return adder ``` #### 2.16.2 Pros Often results in clearer, more elegant code. Especially comforting to experienced Lisp and Scheme (and Haskell and ML and ...) programmers. #### 2.16.3 Cons Can lead to confusing bugs, such as this example based on [PEP-0227](https://peps.python.org/pep-0227/): ```python i = 4 def foo(x: Iterable[int]): def bar(): print(i, end='') # ... # A bunch of code here # ... for i in x: # Ah, i *is* local to foo, so this is what bar sees print(i, end='') bar() ``` So `foo([1, 2, 3])` will print `1 2 3 3`, not `1 2 3 4`. #### 2.16.4 Decision Okay to use. ### 2.17 Function and Method Decorators Use decorators judiciously when there is a clear advantage. Avoid `staticmethod` and limit use of `classmethod`. #### 2.17.1 Definition [Decorators for Functions and Methods](https://docs.python.org/3/glossary.html#term-decorator) (a.k.a "the `@` notation"). One common decorator is `@property`, used for converting ordinary methods into dynamically computed attributes. However, the decorator syntax allows for user-defined decorators as well. Specifically, for some function `my_decorator`, this: ```python class C: @my_decorator def method(self): # method body ... ``` is equivalent to: ```python class C: def method(self): # method body ... method = my_decorator(method) ``` #### 2.17.2 Pros Elegantly specifies some transformation on a method; the transformation might eliminate some repetitive code, enforce invariants, etc. #### 2.17.3 Cons Decorators can perform arbitrary operations on a function's arguments or return values, resulting in surprising implicit behavior. Additionally, decorators execute at object definition time. For module-level objects (classes, module functions, ...) this happens at import time. Failures in decorator code are pretty much impossible to recover from. #### 2.17.4 Decision Use decorators judiciously when there is a clear advantage. Decorators should follow the same import and naming guidelines as functions. A decorator docstring should clearly state that the function is a decorator. Write unit tests for decorators. Avoid external dependencies in the decorator itself (e.g. don't rely on files, sockets, database connections, etc.), since they might not be available when the decorator runs (at import time, perhaps from `pydoc` or other tools). A decorator that is called with valid parameters should (as much as possible) be guaranteed to succeed in all cases. Decorators are a special case of "top-level code" - see [main](#s3.17-main) for more discussion. Never use `staticmethod` unless forced to in order to integrate with an API defined in an existing library. Write a module-level function instead. Use `classmethod` only when writing a named constructor, or a class-specific routine that modifies necessary global state such as a process-wide cache. ### 2.18 Threading Do not rely on the atomicity of built-in types. While Python's built-in data types such as dictionaries appear to have atomic operations, there are corner cases where they aren't atomic (e.g. if `__hash__` or `__eq__` are implemented as Python methods) and their atomicity should not be relied upon. Neither should you rely on atomic variable assignment (since this in turn depends on dictionaries). Use the `queue` module's `Queue` data type as the preferred way to communicate data between threads. Otherwise, use the `threading` module and its locking primitives. Prefer condition variables and `threading.Condition` instead of using lower-level locks. ### 2.19 Power Features Avoid these features. #### 2.19.1 Definition Python is an extremely flexible language and gives you many fancy features such as custom metaclasses, access to bytecode, on-the-fly compilation, dynamic inheritance, object reparenting, import hacks, reflection (e.g. some uses of `getattr()`), modification of system internals, `__del__` methods implementing customized cleanup, etc. #### 2.19.2 Pros These are powerful language features. They can make your code more compact. #### 2.19.3 Cons It's very tempting to use these "cool" features when they're not absolutely necessary. It's harder to read, understand, and debug code that's using unusual features underneath. It doesn't seem that way at first (to the original author), but when revisiting the code, it tends to be more difficult than code that is longer but is straightforward. #### 2.19.4 Decision Avoid these features in your code. Standard library modules and classes that internally use these features are okay to use (for example, `abc.ABCMeta`, `dataclasses`, and `enum`). ### 2.20 Modern Python: from \_\_future\_\_ imports New language version semantic changes may be gated behind a special future import to enable them on a per-file basis within earlier runtimes. #### 2.20.1 Definition Being able to turn on some of the more modern features via `from __future__ import` statements allows early use of features from expected future Python versions. #### 2.20.2 Pros This has proven to make runtime version upgrades smoother as changes can be made on a per-file basis while declaring compatibility and preventing regressions within those files. Modern code is more maintainable as it is less likely to accumulate technical debt that will be problematic during future runtime upgrades. #### 2.20.3 Cons Such code may not work on very old interpreter versions prior to the introduction of the needed future statement. The need for this is more common in projects supporting an extremely wide variety of environments. #### 2.20.4 Decision ##### from \_\_future\_\_ imports Use of `from __future__ import` statements is encouraged. It allows a given source file to start using more modern Python syntax features today. Once you no longer need to run on a version where the features are hidden behind a `__future__` import, feel free to remove those lines. In code that may execute on versions as old as 3.5 rather than >= 3.7, import: ```python from __future__ import generator_stop ``` For more information read the [Python future statement definitions](https://docs.python.org/3/library/__future__.html) documentation. Please don't remove these imports until you are confident the code is only ever used in a sufficiently modern environment. Even if you do not currently use the feature a specific future import enables in your code today, keeping it in place in the file prevents later modifications of the code from inadvertently depending on the older behavior. Use other `from __future__` import statements as you see fit. ### 2.21 Type Annotated Code You can annotate Python code with [type hints](https://docs.python.org/3/library/typing.html). Type-check the code at build time with a type checking tool like [pytype](https://github.com/google/pytype). In most cases, when feasible, type annotations are in source files. For third-party or extension modules, annotations can be in [stub `.pyi` files](https://peps.python.org/pep-0484/#stub-files). #### 2.21.1 Definition Type annotations (or "type hints") are for function or method arguments and return values: ```python def func(a: int) -> list[int]: ``` You can also declare the type of a variable using similar syntax: ```python a: SomeType = some_func() ``` #### 2.21.2 Pros Type annotations improve the readability and maintainability of your code. The type checker will convert many runtime errors to build-time errors, and reduce your ability to use [Power Features](#power-features). #### 2.21.3 Cons You will have to keep the type declarations up to date. You might see type errors that you think are valid code. Use of a [type checker](https://github.com/google/pytype) may reduce your ability to use [Power Features](#power-features). #### 2.21.4 Decision You are strongly encouraged to enable Python type analysis when updating code. When adding or modifying public APIs, include type annotations and enable checking via pytype in the build system. As static analysis is relatively new to Python, we acknowledge that undesired side-effects (such as wrongly inferred types) may prevent adoption by some projects. In those situations, authors are encouraged to add a comment with a TODO or link to a bug describing the issue(s) currently preventing type annotation adoption in the BUILD file or in the code itself as appropriate. ## 3 Python Style Rules ### 3.1 Semicolons Do not terminate your lines with semicolons, and do not use semicolons to put two statements on the same line. ### 3.2 Line length Maximum line length is *80 characters*. Explicit exceptions to the 80 character limit: - Long import statements. - URLs, pathnames, or long flags in comments. - Long string module-level constants not containing whitespace that would be inconvenient to split across lines such as URLs or pathnames. - Pylint disable comments. (e.g.: `# pylint: disable=invalid-name`) Do not use a backslash for [explicit line continuation](https://docs.python.org/3/reference/lexical_analysis.html#explicit-line-joining). Instead, make use of Python's [implicit line joining inside parentheses, brackets and braces](http://docs.python.org/reference/lexical_analysis.html#implicit-line-joining). If necessary, you can add an extra pair of parentheses around an expression. Note that this rule doesn't prohibit backslash-escaped newlines within strings (see [below](#strings)). ```python Yes: foo_bar(self, width, height, color='black', design=None, x='foo', emphasis=None, highlight=0) ``` ```python Yes: if (width == 0 and height == 0 and color == 'red' and emphasis == 'strong'): (bridge_questions.clarification_on .average_airspeed_of.unladen_swallow) = 'African or European?' with ( very_long_first_expression_function() as spam, very_long_second_expression_function() as beans, third_thing() as eggs, ): place_order(eggs, beans, spam, beans) ``` ```python No: if width == 0 and height == 0 and \ color == 'red' and emphasis == 'strong': bridge_questions.clarification_on \ .average_airspeed_of.unladen_swallow = 'African or European?' with very_long_first_expression_function() as spam, \ very_long_second_expression_function() as beans, \ third_thing() as eggs: place_order(eggs, beans, spam, beans) ``` When a literal string won't fit on a single line, use parentheses for implicit line joining. ```python x = ('This will build a very long long ' 'long long long long long long string') ``` Prefer to break lines at the highest possible syntactic level. If you must break a line twice, break it at the same syntactic level both times. ```python Yes: bridgekeeper.answer( name="Arthur", quest=questlib.find(owner="Arthur", perilous=True)) answer = (a_long_line().of_chained_methods() .that_eventually_provides().an_answer()) if ( config is None or 'editor.language' not in config or config['editor.language'].use_spaces is False ): use_tabs() ``` ```python No: bridgekeeper.answer(name="Arthur", quest=questlib.find( owner="Arthur", perilous=True)) answer = a_long_line().of_chained_methods().that_eventually_provides( ).an_answer() if (config is None or 'editor.language' not in config or config[ 'editor.language'].use_spaces is False): use_tabs() ``` Within comments, put long URLs on their own line if necessary. ```python Yes: # See details at # http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html ``` ```python No: # See details at # http://www.example.com/us/developer/documentation/api/content/\ # v2.0/csv_file_name_extension_full_specification.html ``` Make note of the indentation of the elements in the line continuation examples above; see the [indentation](#s3.4-indentation) section for explanation. [Docstring](#docstrings) summary lines must remain within the 80 character limit. In all other cases where a line exceeds 80 characters, and the [Black](https://github.com/psf/black) or [Pyink](https://github.com/google/pyink) auto-formatter does not help bring the line below the limit, the line is allowed to exceed this maximum. Authors are encouraged to manually break the line up per the notes above when it is sensible. ### 3.3 Parentheses Use parentheses sparingly. It is fine, though not required, to use parentheses around tuples. Do not use them in return statements or conditional statements unless using parentheses for implied line continuation or to indicate a tuple. ```python Yes: if foo: bar() while x: x = bar() if x and y: bar() if not x: bar() # For a 1 item tuple the ()s are more visually obvious than the comma. onesie = (foo,) return foo return spam, beans return (spam, beans) for (x, y) in dict.items(): ... ``` ```python No: if (x): bar() if not(x): bar() return (foo) ``` ### 3.4 Indentation Indent your code blocks with *4 spaces*. Never use tabs. Implied line continuation should align wrapped elements vertically (see [line length examples](#s3.2-line-length)), or use a hanging 4-space indent. Closing (round, square or curly) brackets can be placed at the end of the expression, or on separate lines, but then should be indented the same as the line with the corresponding opening bracket. ```python Yes: # Aligned with opening delimiter. foo = long_function_name(var_one, var_two, var_three, var_four) meal = (spam, beans) # Aligned with opening delimiter in a dictionary. foo = { 'long_dictionary_key': value1 + value2, ... } # 4-space hanging indent; nothing on first line. foo = long_function_name( var_one, var_two, var_three, var_four) meal = ( spam, beans) # 4-space hanging indent; nothing on first line, # closing parenthesis on a new line. foo = long_function_name( var_one, var_two, var_three, var_four ) meal = ( spam, beans, ) # 4-space hanging indent in a dictionary. foo = { 'long_dictionary_key': long_dictionary_value, ... } ``` ```python No: # Stuff on first line forbidden. foo = long_function_name(var_one, var_two, var_three, var_four) meal = (spam, beans) # 2-space hanging indent forbidden. foo = long_function_name( var_one, var_two, var_three, var_four) # No hanging indent in a dictionary. foo = { 'long_dictionary_key': long_dictionary_value, ... } ``` #### 3.4.1 Trailing commas in sequences of items? Trailing commas in sequences of items are recommended only when the closing container token `]`, `)`, or `}` does not appear on the same line as the final element, as well as for tuples with a single element. The presence of a trailing comma is also used as a hint to our Python code auto-formatter [Black](https://github.com/psf/black) or [Pyink](https://github.com/google/pyink) to direct it to auto-format the container of items to one item per line when the `,` after the final element is present. ```python Yes: golomb3 = [0, 1, 3] golomb4 = [ 0, 1, 4, 6, ] ``` ```python No: golomb4 = [ 0, 1, 4, 6,] ``` ### 3.5 Blank Lines Two blank lines between top-level definitions, be they function or class definitions. One blank line between method definitions and between the docstring of a `class` and the first method. No blank line following a `def` line. Use single blank lines as you judge appropriate within functions or methods. Blank lines need not be anchored to the definition. For example, related comments immediately preceding function, class, and method definitions can make sense. Consider if your comment might be more useful as part of the docstring. ### 3.6 Whitespace Follow standard typographic rules for the use of spaces around punctuation. No whitespace inside parentheses, brackets or braces. ```python Yes: spam(ham[1], {'eggs': 2}, []) ``` ```python No: spam( ham[ 1 ], { 'eggs': 2 }, [ ] ) ``` No whitespace before a comma, semicolon, or colon. Do use whitespace after a comma, semicolon, or colon, except at the end of the line. ```python Yes: if x == 4: print(x, y) x, y = y, x ``` ```python No: if x == 4 : print(x , y) x , y = y , x ``` No whitespace before the open paren/bracket that starts an argument list, indexing or slicing. ```python Yes: spam(1) ``` ```python No: spam (1) ``` ```python Yes: dict['key'] = list[index] ``` ```python No: dict ['key'] = list [index] ``` No trailing whitespace. Surround binary operators with a single space on either side for assignment (`=`), comparisons (`==, <, >, !=, <>, <=, >=, in, not in, is, is not`), and Booleans (`and, or, not`). Use your better judgment for the insertion of spaces around arithmetic operators (`+`, `-`, `*`, `/`, `//`, `%`, `**`, `@`). ```python Yes: x == 1 ``` ```python No: x<1 ``` Never use spaces around `=` when passing keyword arguments or defining a default parameter value, with one exception: [when a type annotation is present](#typing-default-values), *do* use spaces around the `=` for the default parameter value. ```python Yes: def complex(real, imag=0.0): return Magic(r=real, i=imag) Yes: def complex(real, imag: float = 0.0): return Magic(r=real, i=imag) ``` ```python No: def complex(real, imag = 0.0): return Magic(r = real, i = imag) No: def complex(real, imag: float=0.0): return Magic(r = real, i = imag) ``` Don't use spaces to vertically align tokens on consecutive lines, since it becomes a maintenance burden (applies to `:`, `#`, `=`, etc.): ```python Yes: foo = 1000 # comment long_name = 2 # comment that should not be aligned dictionary = { 'foo': 1, 'long_name': 2, } ``` ```python No: foo = 1000 # comment long_name = 2 # comment that should not be aligned dictionary = { 'foo' : 1, 'long_name': 2, } ``` ### 3.7 Shebang Line Most `.py` files do not need to start with a `#!` line. Start the main file of a program with `#!/usr/bin/env python3` (to support virtualenvs) or `#!/usr/bin/python3` per [PEP-394](https://peps.python.org/pep-0394/). This line is used by the kernel to find the Python interpreter, but is ignored by Python when importing modules. It is only necessary on a file intended to be executed directly. ### 3.8 Comments and Docstrings Be sure to use the right style for module, function, method docstrings and inline comments. #### 3.8.1 Docstrings Python uses *docstrings* to document code. A docstring is a string that is the first statement in a package, module, class or function. These strings can be extracted automatically through the `__doc__` member of the object and are used by `pydoc`. (Try running `pydoc` on your module to see how it looks.) Always use the three-double-quote `"""` format for docstrings (per [PEP 257](https://peps.python.org/pep-0257/)). A docstring should be organized as a summary line (one physical line not exceeding 80 characters) terminated by a period, question mark, or exclamation point. When writing more (encouraged), this must be followed by a blank line, followed by the rest of the docstring starting at the same cursor position as the first quote of the first line. There are more formatting guidelines for docstrings below. #### 3.8.2 Modules Every file should contain license boilerplate. Choose the appropriate boilerplate for the license used by the project (for example, Apache 2.0, BSD, LGPL, GPL). Files should start with a docstring describing the contents and usage of the module. ```python """A one-line summary of the module or program, terminated by a period. Leave one blank line. The rest of this docstring should contain an overall description of the module or program. Optionally, it may also contain a brief description of exported classes and functions and/or usage examples. Typical usage example: foo = ClassFoo() bar = foo.function_bar() """ ``` ##### 3.8.2.1 Test modules Module-level docstrings for test files are not required. They should be included only when there is additional information that can be provided. Examples include some specifics on how the test should be run, an explanation of an unusual setup pattern, dependency on the external environment, and so on. ```python """This blaze test uses golden files. You can update those files by running `blaze run //foo/bar:foo_test -- --update_golden_files` from the `google3` directory. """ ``` Docstrings that do not provide any new information should not be used. ```python """Tests for foo.bar.""" ``` #### 3.8.3 Functions and Methods In this section, "function" means a method, function, generator, or property. A docstring is mandatory for every function that has one or more of the following properties: - being part of the public API - nontrivial size - non-obvious logic A docstring should give enough information to write a call to the function without reading the function's code. The docstring should describe the function's calling syntax and its semantics, but generally not its implementation details, unless those details are relevant to how the function is to be used. For example, a function that mutates one of its arguments as a side effect should note that in its docstring. Otherwise, subtle but important details of a function's implementation that are not relevant to the caller are better expressed as comments alongside the code than within the function's docstring. The docstring may be descriptive-style (`"""Fetches rows from a Bigtable."""`) or imperative-style (`"""Fetch rows from a Bigtable."""`), but the style should be consistent within a file. The docstring for a `@property` data descriptor should use the same style as the docstring for an attribute or a function argument (`"""The Bigtable path."""`, rather than `"""Returns the Bigtable path."""`). Certain aspects of a function should be documented in special sections, listed below. Each section begins with a heading line, which ends with a colon. All sections other than the heading should maintain a hanging indent of two or four spaces (be consistent within a file). These sections can be omitted in cases where the function's name and signature are informative enough that it can be aptly described using a one-line docstring. [*Args:*](#doc-function-args) : List each parameter by name. A description should follow the name, and be separated by a colon followed by either a space or newline. If the description is too long to fit on a single 80-character line, use a hanging indent of 2 or 4 spaces more than the parameter name (be consistent with the rest of the docstrings in the file). The description should include required type(s) if the code does not contain a corresponding type annotation. If a function accepts `*foo` (variable length argument lists) and/or `**bar` (arbitrary keyword arguments), they should be listed as `*foo` and `**bar`. [*Returns:* (or *Yields:* for generators)](#doc-function-returns) : Describe the semantics of the return value, including any type information that the type annotation does not provide. If the function only returns None, this section is not required. It may also be omitted if the docstring starts with "Return", "Returns", "Yield", or "Yields" (e.g. `"""Returns row from Bigtable as a tuple of strings."""`) *and* the opening sentence is sufficient to describe the return value. Do not imitate older 'NumPy style' ([example](https://numpy.org/doc/1.24/reference/generated/numpy.linalg.qr.html)), which frequently documented a tuple return value as if it were multiple return values with individual names (never mentioning the tuple). Instead, describe such a return value as: "Returns: A tuple (mat_a, mat_b), where mat_a is ..., and ...". The auxiliary names in the docstring need not necessarily correspond to any internal names used in the function body (as those are not part of the API). If the function uses `yield` (is a generator), the `Yields:` section should document the object returned by `next()`, instead of the generator object itself that the call evaluates to. [*Raises:*](#doc-function-raises) : List all exceptions that are relevant to the interface followed by a description. Use a similar exception name + colon + space or newline and hanging indent style as described in *Args:*. You should not document exceptions that get raised if the API specified in the docstring is violated (because this would paradoxically make behavior under violation of the API part of the API). ```python def fetch_smalltable_rows( table_handle: smalltable.Table, keys: Sequence[bytes | str], require_all_keys: bool = False, ) -> Mapping[bytes, tuple[str, ...]]: """Fetches rows from a Smalltable. Retrieves rows pertaining to the given keys from the Table instance represented by table_handle. String keys will be UTF-8 encoded. Args: table_handle: An open smalltable.Table instance. keys: A sequence of strings representing the key of each table row to fetch. String keys will be UTF-8 encoded. require_all_keys: If True only rows with values set for all keys will be returned. Returns: A dict mapping keys to the corresponding table row data fetched. Each row is represented as a tuple of strings. For example: {b'Serak': ('Rigel VII', 'Preparer'), b'Zim': ('Irk', 'Invader'), b'Lrrr': ('Omicron Persei 8', 'Emperor')} Returned keys are always bytes. If a key from the keys argument is missing from the dictionary, then that row was not found in the table (and require_all_keys must have been False). Raises: IOError: An error occurred accessing the smalltable. """ ``` Similarly, this variation on `Args:` with a line break is also allowed: ```python def fetch_smalltable_rows( table_handle: smalltable.Table, keys: Sequence[bytes | str], require_all_keys: bool = False, ) -> Mapping[bytes, tuple[str, ...]]: """Fetches rows from a Smalltable. Retrieves rows pertaining to the given keys from the Table instance represented by table_handle. String keys will be UTF-8 encoded. Args: table_handle: An open smalltable.Table instance. keys: A sequence of strings representing the key of each table row to fetch. String keys will be UTF-8 encoded. require_all_keys: If True only rows with values set for all keys will be returned. Returns: A dict mapping keys to the corresponding table row data fetched. Each row is represented as a tuple of strings. For example: {b'Serak': ('Rigel VII', 'Preparer'), b'Zim': ('Irk', 'Invader'), b'Lrrr': ('Omicron Persei 8', 'Emperor')} Returned keys are always bytes. If a key from the keys argument is missing from the dictionary, then that row was not found in the table (and require_all_keys must have been False). Raises: IOError: An error occurred accessing the smalltable. """ ``` ##### 3.8.3.1 Overridden Methods A method that overrides a method from a base class does not need a docstring if it is explicitly decorated with [`@override`](https://typing-extensions.readthedocs.io/en/latest/#override) (from `typing_extensions` or `typing` modules), unless the overriding method's behavior materially refines the base method's contract, or details need to be provided (e.g., documenting additional side effects), in which case a docstring with at least those differences is required on the overriding method. ```python from typing_extensions import override class Parent: def do_something(self): """Parent method, includes docstring.""" # Child class, method annotated with override. class Child(Parent): @override def do_something(self): pass ``` ```python # Child class, but without @override decorator, a docstring is required. class Child(Parent): def do_something(self): pass # Docstring is trivial, @override is sufficient to indicate that docs can be # found in the base class. class Child(Parent): @override def do_something(self): """See base class.""" ``` #### 3.8.4 Classes Classes should have a docstring below the class definition describing the class. Public attributes, excluding [properties](#properties), should be documented here in an `Attributes` section and follow the same formatting as a [function's `Args`](#doc-function-args) section. ```python class SampleClass: """Summary of class here. Longer class information... Longer class information... Attributes: likes_spam: A boolean indicating if we like SPAM or not. eggs: An integer count of the eggs we have laid. """ def __init__(self, likes_spam: bool = False): """Initializes the instance based on spam preference. Args: likes_spam: Defines if instance exhibits this preference. """ self.likes_spam = likes_spam self.eggs = 0 @property def butter_sticks(self) -> int: """The number of butter sticks we have.""" ``` All class docstrings should start with a one-line summary that describes what the class instance represents. This implies that subclasses of `Exception` should also describe what the exception represents, and not the context in which it might occur. The class docstring should not repeat unnecessary information, such as that the class is a class. ```python # Yes: class CheeseShopAddress: """The address of a cheese shop. ... """ class OutOfCheeseError(Exception): """No more cheese is available.""" ``` ```python # No: class CheeseShopAddress: """Class that describes the address of a cheese shop. ... """ class OutOfCheeseError(Exception): """Raised when no more cheese is available.""" ``` #### 3.8.5 Block and Inline Comments The final place to have comments is in tricky parts of the code. If you're going to have to explain it at the next [code review](http://en.wikipedia.org/wiki/Code_review), you should comment it now. Complicated operations get a few lines of comments before the operations commence. Non-obvious ones get comments at the end of the line. ```python # We use a weighted dictionary search to find out where i is in # the array. We extrapolate position based on the largest num # in the array and the array size and then do binary search to # get the exact number. if i & (i-1) == 0: # True if i is 0 or a power of 2. ``` To improve legibility, these comments should start at least 2 spaces away from the code with the comment character `#`, followed by at least one space before the text of the comment itself. On the other hand, never describe the code. Assume the person reading the code knows Python (though not what you're trying to do) better than you do. ```python # BAD COMMENT: Now go through the b array and make sure whenever i occurs # the next element is i+1 ``` #### 3.8.6 Punctuation, Spelling, and Grammar Pay attention to punctuation, spelling, and grammar; it is easier to read well-written comments than badly written ones. Comments should be as readable as narrative text, with proper capitalization and punctuation. In many cases, complete sentences are more readable than sentence fragments. Shorter comments, such as comments at the end of a line of code, can sometimes be less formal, but you should be consistent with your style. Although it can be frustrating to have a code reviewer point out that you are using a comma when you should be using a semicolon, it is very important that source code maintain a high level of clarity and readability. Proper punctuation, spelling, and grammar help with that goal. ### 3.10 Strings Use an [f-string](https://docs.python.org/3/reference/lexical_analysis.html#f-strings), the `%` operator, or the `format` method for formatting strings, even when the parameters are all strings. Use your best judgment to decide between string formatting options. A single join with `+` is okay but do not format with `+`. ```python Yes: x = f'name: {name}; score: {n}' x = '%s, %s!' % (imperative, expletive) x = '{}, {}'.format(first, second) x = 'name: %s; score: %d' % (name, n) x = 'name: %(name)s; score: %(score)d' % {'name':name, 'score':n} x = 'name: {}; score: {}'.format(name, n) x = a + b ``` ```python No: x = first + ', ' + second x = 'name: ' + name + '; score: ' + str(n) ``` Avoid using the `+` and `+=` operators to accumulate a string within a loop. In some conditions, accumulating a string with addition can lead to quadratic rather than linear running time. Although common accumulations of this sort may be optimized on CPython, that is an implementation detail. The conditions under which an optimization applies are not easy to predict and may change. Instead, add each substring to a list and `''.join` the list after the loop terminates, or write each substring to an `io.StringIO` buffer. These techniques consistently have amortized-linear run-time complexity. ```python Yes: items = [''] for last_name, first_name in employee_list: items.append('' % (last_name, first_name)) items.append('
%s, %s
') employee_table = ''.join(items) ``` ```python No: employee_table = '' for last_name, first_name in employee_list: employee_table += '' % (last_name, first_name) employee_table += '
%s, %s
' ``` Be consistent with your choice of string quote character within a file. Pick `'` or `"` and stick with it. It is okay to use the other quote character on a string to avoid the need to backslash-escape quote characters within the string. ```python Yes: Python('Why are you hiding your eyes?') Gollum("I'm scared of lint errors.") Narrator('"Good!" thought a happy Python reviewer.') ``` ```python No: Python("Why are you hiding your eyes?") Gollum('The lint. It burns. It burns us.') Gollum("Always the great lint. Watching. Watching.") ``` Prefer `"""` for multi-line strings rather than `'''`. Projects may choose to use `'''` for all non-docstring multi-line strings if and only if they also use `'` for regular strings. Docstrings must use `"""` regardless. Multi-line strings do not flow with the indentation of the rest of the program. If you need to avoid embedding extra space in the string, use either concatenated single-line strings or a multi-line string with [`textwrap.dedent()`](https://docs.python.org/3/library/textwrap.html#textwrap.dedent) to remove the initial space on each line: ```python No: long_string = """This is pretty ugly. Don't do this. """ ``` ```python Yes: long_string = """This is fine if your use case can accept extraneous leading spaces.""" ``` ```python Yes: long_string = ("And this is fine if you cannot accept\n" + "extraneous leading spaces.") ``` ```python Yes: long_string = ("And this too is fine if you cannot accept\n" "extraneous leading spaces.") ``` ```python Yes: import textwrap long_string = textwrap.dedent("""\ This is also fine, because textwrap.dedent() will collapse common leading spaces in each line.""") ``` Note that using a backslash here does not violate the prohibition against [explicit line continuation](#line-length); in this case, the backslash is [escaping a newline](https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals) in a string literal. #### 3.10.1 Logging For logging functions that expect a pattern-string (with %-placeholders) as their first argument: Always call them with a string literal (not an f-string!) as their first argument with pattern-parameters as subsequent arguments. Some logging implementations collect the unexpanded pattern-string as a queryable field. It also prevents spending time rendering a message that no logger is configured to output. ```python Yes: import tensorflow as tf logger = tf.get_logger() logger.info('TensorFlow Version is: %s', tf.__version__) ``` ```python Yes: import os from absl import logging logging.info('Current $PAGER is: %s', os.getenv('PAGER', default='')) homedir = os.getenv('HOME') if homedir is None or not os.access(homedir, os.W_OK): logging.error('Cannot write to home directory, $HOME=%r', homedir) ``` ```python No: import os from absl import logging logging.info('Current $PAGER is:') logging.info(os.getenv('PAGER', default='')) homedir = os.getenv('HOME') if homedir is None or not os.access(homedir, os.W_OK): logging.error(f'Cannot write to home directory, $HOME={homedir!r}') ``` #### 3.10.2 Error Messages Error messages (such as: message strings on exceptions like `ValueError`, or messages shown to the user) should follow three guidelines: 1. The message needs to precisely match the actual error condition. 2. Interpolated pieces need to always be clearly identifiable as such. 3. They should allow simple automated processing (e.g. grepping). ```python Yes: if not 0 <= p <= 1: raise ValueError(f'Not a probability: {p=}') try: os.rmdir(workdir) except OSError as error: logging.warning('Could not remove directory (reason: %r): %r', error, workdir) ``` ```python No: if p < 0 or p > 1: # PROBLEM: also false for float('nan')! raise ValueError(f'Not a probability: {p=}') try: os.rmdir(workdir) except OSError: # PROBLEM: Message makes an assumption that might not be true: # Deletion might have failed for some other reason, misleading # whoever has to debug this. logging.warning('Directory already was deleted: %s', workdir) try: os.rmdir(workdir) except OSError: # PROBLEM: The message is harder to grep for than necessary, and # not universally non-confusing for all possible values of `workdir`. # Imagine someone calling a library function with such code # using a name such as workdir = 'deleted'. The warning would read: # "The deleted directory could not be deleted." logging.warning('The %s directory could not be deleted.', workdir) ``` ### 3.11 Files, Sockets, and similar Stateful Resources Explicitly close files and sockets when done with them. This rule naturally extends to closeable resources that internally use sockets, such as database connections, and also other resources that need to be closed down in a similar fashion. To name only a few examples, this also includes [mmap](https://docs.python.org/3/library/mmap.html) mappings, [h5py File objects](https://docs.h5py.org/en/stable/high/file.html), and [matplotlib.pyplot figure windows](https://matplotlib.org/2.1.0/api/_as_gen/matplotlib.pyplot.close.html). Leaving files, sockets or other such stateful objects open unnecessarily has many downsides: - They may consume limited system resources, such as file descriptors. Code that deals with many such objects may exhaust those resources unnecessarily if they're not returned to the system promptly after use. - Holding files open may prevent other actions such as moving or deleting them, or unmounting a filesystem. - Files and sockets that are shared throughout a program may inadvertently be read from or written to after logically being closed. If they are actually closed, attempts to read or write from them will raise exceptions, making the problem known sooner. Furthermore, while files and sockets (and some similarly behaving resources) are automatically closed when the object is destructed, coupling the lifetime of the object to the state of the resource is poor practice: - There are no guarantees as to when the runtime will actually invoke the `__del__` method. Different Python implementations use different memory management techniques, such as delayed garbage collection, which may increase the object's lifetime arbitrarily and indefinitely. - Unexpected references to the file, e.g. in globals or exception tracebacks, may keep it around longer than intended. Relying on finalizers to do automatic cleanup that has observable side effects has been rediscovered over and over again to lead to major problems, across many decades and multiple languages (see e.g. [this article](https://wiki.sei.cmu.edu/confluence/display/java/MET12-J.+Do+not+use+finalizers) for Java). The preferred way to manage files and similar resources is using the [`with` statement](http://docs.python.org/reference/compound_stmts.html#the-with-statement): ```python with open("hello.txt") as hello_file: for line in hello_file: print(line) ``` For file-like objects that do not support the `with` statement, use `contextlib.closing()`: ```python import contextlib with contextlib.closing(urllib.urlopen("http://www.python.org/")) as front_page: for line in front_page: print(line) ``` In rare cases where context-based resource management is infeasible, code documentation must explain clearly how resource lifetime is managed. ### 3.12 TODO Comments Use `TODO` comments for code that is temporary, a short-term solution, or good-enough but not perfect. A `TODO` comment begins with the word `TODO` in all caps, a following colon, and a link to a resource that contains the context, ideally a bug reference. A bug reference is preferable because bugs are tracked and have follow-up comments. Follow this piece of context with an explanatory string introduced with a hyphen `-`. The purpose is to have a consistent `TODO` format that can be searched to find out how to get more details. ```python # TODO: crbug.com/192795 - Investigate cpufreq optimizations. ``` Old style, formerly recommended, but discouraged for use in new code: ```python # TODO(crbug.com/192795): Investigate cpufreq optimizations. # TODO(yourusername): Use a "\*" here for concatenation operator. ``` Avoid adding TODOs that refer to an individual or team as the context: ```python # TODO: @yourusername - File an issue and use a '*' for repetition. ``` If your `TODO` is of the form "At a future date do something" make sure that you either include a very specific date ("Fix by November 2009") or a very specific event ("Remove this code when all clients can handle XML responses.") that future code maintainers will comprehend. Issues are ideal for tracking this. ### 3.13 Imports formatting Imports should be on separate lines; there are [exceptions for `typing` and `collections.abc` imports](#typing-imports). E.g.: ```python Yes: from collections.abc import Mapping, Sequence import os import sys from typing import Any, NewType ``` ```python No: import os, sys ``` Imports are always put at the top of the file, just after any module comments and docstrings and before module globals and constants. Imports should be grouped from most generic to least generic: 1. Python future import statements. For example: ```python from __future__ import annotations ``` See [above](#from-future-imports) for more information about those. 2. Python standard library imports. For example: ```python import sys ``` 3. [third-party](https://pypi.org/) module or package imports. For example: ```python import tensorflow as tf ``` 4. Code repository sub-package imports. For example: ```python from otherproject.ai import mind ``` 5. **Deprecated:** application-specific imports that are part of the same top-level sub-package as this file. For example: ```python from myproject.backend.hgwells import time_machine ``` You may find older Google Python Style code doing this, but it is no longer required. **New code is encouraged not to bother with this.** Simply treat application-specific sub-package imports the same as other sub-package imports. Within each grouping, imports should be sorted lexicographically, ignoring case, according to each module's full package path (the `path` in `from path import ...`). Code may optionally place a blank line between import sections. ```python import collections import queue import sys from absl import app from absl import flags import bs4 import cryptography import tensorflow as tf from book.genres import scifi from myproject.backend import huxley from myproject.backend.hgwells import time_machine from myproject.backend.state_machine import main_loop from otherproject.ai import body from otherproject.ai import mind from otherproject.ai import soul # Older style code may have these imports down here instead: #from myproject.backend.hgwells import time_machine #from myproject.backend.state_machine import main_loop ``` ### 3.14 Statements Generally only one statement per line. However, you may put the result of a test on the same line as the test only if the entire statement fits on one line. In particular, you can never do so with `try`/`except` since the `try` and `except` can't both fit on the same line, and you can only do so with an `if` if there is no `else`. ```python Yes: if foo: bar(foo) ``` ```python No: if foo: bar(foo) else: baz(foo) try: bar(foo) except ValueError: baz(foo) try: bar(foo) except ValueError: baz(foo) ``` ### 3.15 Getters and Setters Getter and setter functions (also called accessors and mutators) should be used when they provide a meaningful role or behavior for getting or setting a variable's value. In particular, they should be used when getting or setting the variable is complex or the cost is significant, either currently or in a reasonable future. If, for example, a pair of getters/setters simply read and write an internal attribute, the internal attribute should be made public instead. By comparison, if setting a variable means some state is invalidated or rebuilt, it should be a setter function. The function invocation hints that a potentially non-trivial operation is occurring. Alternatively, [properties](#properties) may be an option when simple logic is needed, or refactoring to no longer need getters and setters. Getters and setters should follow the [Naming](#s3.16-naming) guidelines, such as `get_foo()` and `set_foo()`. If the past behavior allowed access through a property, do not bind the new getter/setter functions to the property. Any code still attempting to access the variable by the old method should break visibly so they are made aware of the change in complexity. ### 3.16 Naming `module_name`, `package_name`, `ClassName`, `method_name`, `ExceptionName`, `function_name`, `GLOBAL_CONSTANT_NAME`, `global_var_name`, `instance_var_name`, `function_parameter_name`, `local_var_name`, `query_proper_noun_for_thing`, `send_acronym_via_https`. Names should be descriptive. This includes functions, classes, variables, attributes, files and any other type of named entities. Avoid abbreviation. In particular, do not use abbreviations that are ambiguous or unfamiliar to readers outside your project, and do not abbreviate by deleting letters within a word. Always use a `.py` filename extension. Never use dashes. #### 3.16.1 Names to Avoid - single character names, except for specifically allowed cases: - counters or iterators (e.g. `i`, `j`, `k`, `v`, et al.) - `e` as an exception identifier in `try/except` statements. - `f` as a file handle in `with` statements - private [type variables](#typing-type-var) with no constraints (e.g. `_T = TypeVar("_T")`, `_P = ParamSpec("_P")`) - names that match established notation in a reference paper or algorithm (see [Mathematical Notation](#math-notation)) Please be mindful not to abuse single-character naming. Generally speaking, descriptiveness should be proportional to the name's scope of visibility. For example, `i` might be a fine name for 5-line code block but within multiple nested scopes, it is likely too vague. - dashes (`-`) in any package/module name - `__double_leading_and_trailing_underscore__` names (reserved by Python) - offensive terms - names that needlessly include the type of the variable (for example: `id_to_name_dict`) #### 3.16.2 Naming Conventions - "Internal" means internal to a module, or protected or private within a class. - Prepending a single underscore (`_`) has some support for protecting module variables and functions (linters will flag protected member access). Note that it is okay for unit tests to access protected constants from the modules under test. - Prepending a double underscore (`__` aka "dunder") to an instance variable or method effectively makes the variable or method private to its class (using name mangling); we discourage its use as it impacts readability and testability, and isn't *really* private. Prefer a single underscore. - Place related classes and top-level functions together in a module. Unlike Java, there is no need to limit yourself to one class per module. - Use CapWords for class names, but lower\_with\_under.py for module names. Although there are some old modules named CapWords.py, this is now discouraged because it's confusing when the module happens to be named after a class. ("wait -- did I write `import StringIO` or `from StringIO import StringIO`?") - New *unit test* files follow PEP 8 compliant lower\_with\_under method names, for example, `test__`. For consistency(\*) with legacy modules that follow CapWords function names, underscores may appear in method names starting with `test` to separate logical components of the name. One possible pattern is `test_`. #### 3.16.3 File Naming Python filenames must have a `.py` extension and must not contain dashes (`-`). This allows them to be imported and unittested. If you want an executable to be accessible without the extension, use a symbolic link or a simple bash wrapper containing `exec "$0.py" "$@"`. #### 3.16.4 Guidelines derived from [Guido](https://en.wikipedia.org/wiki/Guido_van_Rossum)'s Recommendations
Type Public Internal
Packages lower_with_under
Modules lower_with_under _lower_with_under
Classes CapWords _CapWords
Exceptions CapWords
Functions lower_with_under() _lower_with_under()
Global/Class Constants CAPS_WITH_UNDER _CAPS_WITH_UNDER
Global/Class Variables lower_with_under _lower_with_under
Instance Variables lower_with_under _lower_with_under (protected)
Method Names lower_with_under() _lower_with_under() (protected)
Function/Method Parameters lower_with_under
Local Variables lower_with_under
#### 3.16.5 Mathematical Notation For mathematically-heavy code, short variable names that would otherwise violate the style guide are preferred when they match established notation in a reference paper or algorithm. When using names based on established notation: 1. Cite the source of all naming conventions, preferably with a hyperlink to academic resource itself, in a comment or docstring. If the source is not accessible, clearly document the naming conventions. 2. Prefer PEP8-compliant `descriptive_names` for public APIs, which are much more likely to be encountered out of context. 3. Use a narrowly-scoped `pylint: disable=invalid-name` directive to silence warnings. For just a few variables, use the directive as an endline comment for each one; for more, apply the directive at the beginning of a block. ### 3.17 Main In Python, `pydoc` as well as unit tests require modules to be importable. If a file is meant to be used as an executable, its main functionality should be in a `main()` function, and your code should always check `if __name__ == '__main__'` before executing your main program, so that it is not executed when the module is imported. When using [absl](https://github.com/abseil/abseil-py), use `app.run`: ```python from absl import app ... def main(argv: Sequence[str]): # process non-flag arguments ... if __name__ == '__main__': app.run(main) ``` Otherwise, use: ```python def main(): ... if __name__ == '__main__': main() ``` All code at the top level will be executed when the module is imported. Be careful not to call functions, create objects, or perform other operations that should not be executed when the file is being `pydoc`ed. ### 3.18 Function length Prefer small and focused functions. We recognize that long functions are sometimes appropriate, so no hard limit is placed on function length. If a function exceeds about 40 lines, think about whether it can be broken up without harming the structure of the program. Even if your long function works perfectly now, someone modifying it in a few months may add new behavior. This could result in bugs that are hard to find. Keeping your functions short and simple makes it easier for other people to read and modify your code. You could find long and complicated functions when working with some code. Do not be intimidated by modifying existing code: if working with such a function proves to be difficult, you find that errors are hard to debug, or you want to use a piece of it in several different contexts, consider breaking up the function into smaller and more manageable pieces. ### 3.19 Type Annotations #### 3.19.1 General Rules * Familiarize yourself with [type hints](https://docs.python.org/3/library/typing.html). * Annotating `self` or `cls` is generally not necessary. [`Self`](https://docs.python.org/3/library/typing.html#typing.Self) can be used if it is necessary for proper type information, e.g. ```python from typing import Self class BaseClass: @classmethod def create(cls) -> Self: ... def difference(self, other: Self) -> float: ... ``` * Similarly, don't feel compelled to annotate the return value of `__init__` (where `None` is the only valid option). * If any other variable or a returned type should not be expressed, use `Any`. * You are not required to annotate all the functions in a module. - At least annotate your public APIs. - Use judgment to get to a good balance between safety and clarity on the one hand, and flexibility on the other. - Annotate code that is prone to type-related errors (previous bugs or complexity). - Annotate code that is hard to understand. - Annotate code as it becomes stable from a types perspective. In many cases, you can annotate all the functions in mature code without losing too much flexibility. #### 3.19.2 Line Breaking Try to follow the existing [indentation](#indentation) rules. After annotating, many function signatures will become "one parameter per line". To ensure the return type is also given its own line, a comma can be placed after the last parameter. ```python def my_method( self, first_var: int, second_var: Foo, third_var: Bar | None, ) -> int: ... ``` Always prefer breaking between variables, and not, for example, between variable names and type annotations. However, if everything fits on the same line, go for it. ```python def my_method(self, first_var: int) -> int: ... ``` If the combination of the function name, the last parameter, and the return type is too long, indent by 4 in a new line. When using line breaks, prefer putting each parameter and the return type on their own lines and aligning the closing parenthesis with the `def`: ```python Yes: def my_method( self, other_arg: MyLongType | None, ) -> tuple[MyLongType1, MyLongType1]: ... ``` Optionally, the return type may be put on the same line as the last parameter: ```python Okay: def my_method( self, first_var: int, second_var: int) -> dict[OtherLongType, MyLongType]: ... ``` `pylint` allows you to move the closing parenthesis to a new line and align with the opening one, but this is less readable. ```python No: def my_method(self, other_arg: MyLongType | None, ) -> dict[OtherLongType, MyLongType]: ... ``` As in the examples above, prefer not to break types. However, sometimes they are too long to be on a single line (try to keep sub-types unbroken). ```python def my_method( self, first_var: tuple[list[MyLongType1], list[MyLongType2]], second_var: list[dict[ MyLongType3, MyLongType4]], ) -> None: ... ``` If a single name and type is too long, consider using an [alias](#typing-aliases) for the type. The last resort is to break after the colon and indent by 4. ```python Yes: def my_function( long_variable_name: long_module_name.LongTypeName, ) -> None: ... ``` ```python No: def my_function( long_variable_name: long_module_name. LongTypeName, ) -> None: ... ``` #### 3.19.3 Forward Declarations If you need to use a class name (from the same module) that is not yet defined -- for example, if you need the class name inside the declaration of that class, or if you use a class that is defined later in the code -- either use `from __future__ import annotations` or use a string for the class name. ```python Yes: from __future__ import annotations class MyClass: def __init__(self, stack: Sequence[MyClass], item: OtherClass) -> None: class OtherClass: ... ``` ```python Yes: class MyClass: def __init__(self, stack: Sequence['MyClass'], item: 'OtherClass') -> None: class OtherClass: ... ``` #### 3.19.4 Default Values As per [PEP-008](https://peps.python.org/pep-0008/#other-recommendations), use spaces around the `=` *only* for arguments that have both a type annotation and a default value. ```python Yes: def func(a: int = 0) -> int: ... ``` ```python No: def func(a:int=0) -> int: ... ``` #### 3.19.5 NoneType In the Python type system, `NoneType` is a "first class" type, and for typing purposes, `None` is an alias for `NoneType`. If an argument can be `None`, it has to be declared! You can use `|` union type expressions (recommended in new Python 3.10+ code), or the older `Optional` and `Union` syntaxes. Use explicit `X | None` instead of implicit. Earlier versions of type checkers allowed `a: str = None` to be interpreted as `a: str | None = None`, but that is no longer the preferred behavior. ```python Yes: def modern_or_union(a: str | int | None, b: str | None = None) -> str: ... def union_optional(a: Union[str, int, None], b: Optional[str] = None) -> str: ... ``` ```python No: def nullable_union(a: Union[None, str]) -> str: ... def implicit_optional(a: str = None) -> str: ... ``` #### 3.19.6 Type Aliases You can declare aliases of complex types. The name of an alias should be CapWorded. If the alias is used only in this module, it should be \_Private. Note that the `: TypeAlias` annotation is only supported in versions 3.10+. ```python from typing import TypeAlias _LossAndGradient: TypeAlias = tuple[tf.Tensor, tf.Tensor] ComplexTFMap: TypeAlias = Mapping[str, _LossAndGradient] ``` #### 3.19.7 Ignoring Types You can disable type checking on a line with the special comment `# type: ignore`. `pytype` has a disable option for specific errors (similar to lint): ```python # pytype: disable=attribute-error ``` #### 3.19.8 Typing Variables [*Annotated Assignments*](#annotated-assignments) : If an internal variable has a type that is hard or impossible to infer, specify its type with an annotated assignment - use a colon and type between the variable name and value (the same as is done with function arguments that have a default value): ```python a: Foo = SomeUndecoratedFunction() ``` [*Type Comments*](#type-comments) : Though you may see them remaining in the codebase (they were necessary before Python 3.6), do not add any more uses of a `# type: ` comment on the end of the line: ```python a = SomeUndecoratedFunction() # type: Foo ``` #### 3.19.9 Tuples vs Lists Typed lists can only contain objects of a single type. Typed tuples can either have a single repeated type or a set number of elements with different types. The latter is commonly used as the return type from a function. ```python a: list[int] = [1, 2, 3] b: tuple[int, ...] = (1, 2, 3) c: tuple[int, str, float] = (1, "2", 3.5) ``` #### 3.19.10 Type variables The Python type system has [generics](https://docs.python.org/3/library/typing.html#generics). A type variable, such as `TypeVar` and `ParamSpec`, is a common way to use them. Example: ```python from collections.abc import Callable from typing import ParamSpec, TypeVar _P = ParamSpec("_P") _T = TypeVar("_T") ... def next(l: list[_T]) -> _T: return l.pop() def print_when_called(f: Callable[_P, _T]) -> Callable[_P, _T]: def inner(*args: _P.args, **kwargs: _P.kwargs) -> _T: print("Function was called") return f(*args, **kwargs) return inner ``` A `TypeVar` can be constrained: ```python AddableType = TypeVar("AddableType", int, float, str) def add(a: AddableType, b: AddableType) -> AddableType: return a + b ``` A common predefined type variable in the `typing` module is `AnyStr`. Use it for multiple annotations that can be `bytes` or `str` and must all be the same type. ```python from typing import AnyStr def check_length(x: AnyStr) -> AnyStr: if len(x) <= 42: return x raise ValueError() ``` A type variable must have a descriptive name, unless it meets all of the following criteria: * not externally visible * not constrained ```python Yes: _T = TypeVar("_T") _P = ParamSpec("_P") AddableType = TypeVar("AddableType", int, float, str) AnyFunction = TypeVar("AnyFunction", bound=Callable) ``` ```python No: T = TypeVar("T") P = ParamSpec("P") _T = TypeVar("_T", int, float, str) _F = TypeVar("_F", bound=Callable) ``` #### 3.19.11 String types > Do not use `typing.Text` in new code. It's only for Python 2/3 compatibility. Use `str` for string/text data. For code that deals with binary data, use `bytes`. ```python def deals_with_text_data(x: str) -> str: ... def deals_with_binary_data(x: bytes) -> bytes: ... ``` If all the string types of a function are always the same, for example if the return type is the same as the argument type in the code above, use [AnyStr](#typing-type-var). #### 3.19.12 Imports For Typing For symbols (including types, functions, and constants) from the `typing` or `collections.abc` modules used to support static analysis and type checking, always import the symbol itself. This keeps common annotations more concise and matches typing practices used around the world. You are explicitly allowed to import multiple specific symbols on one line from the `typing` and `collections.abc` modules. For example: ```python from collections.abc import Mapping, Sequence from typing import Any, Generic, cast, TYPE_CHECKING ``` Given that this way of importing adds items to the local namespace, names in `typing` or `collections.abc` should be treated similarly to keywords, and not be defined in your Python code, typed or not. If there is a collision between a type and an existing name in a module, import it using `import x as y`. ```python from typing import Any as AnyType ``` When annotating function signatures, prefer abstract container types like `collections.abc.Sequence` over concrete types like `list`. If you need to use a concrete type (for example, a `tuple` of typed elements), prefer built-in types like `tuple` over the parametric type aliases from the `typing` module (e.g., `typing.Tuple`). ```python from typing import List, Tuple def transform_coordinates(original: List[Tuple[float, float]]) -> List[Tuple[float, float]]: ... ``` ```python from collections.abc import Sequence def transform_coordinates(original: Sequence[tuple[float, float]]) -> Sequence[tuple[float, float]]: ... ``` #### 3.19.13 Conditional Imports Use conditional imports only in exceptional cases where the additional imports needed for type checking must be avoided at runtime. This pattern is discouraged; alternatives such as refactoring the code to allow top-level imports should be preferred. Imports that are needed only for type annotations can be placed within an `if TYPE_CHECKING:` block. - Conditionally imported types need to be referenced as strings, to be forward compatible with Python 3.6 where the annotation expressions are actually evaluated. - Only entities that are used solely for typing should be defined here; this includes aliases. Otherwise it will be a runtime error, as the module will not be imported at runtime. - The block should be right after all the normal imports. - There should be no empty lines in the typing imports list. - Sort this list as if it were a regular imports list. ```python import typing if typing.TYPE_CHECKING: import sketch def f(x: "sketch.Sketch"): ... ``` #### 3.19.14 Circular Dependencies Circular dependencies that are caused by typing are code smells. Such code is a good candidate for refactoring. Although technically it is possible to keep circular dependencies, various build systems will not let you do so because each module has to depend on the other. Replace modules that create circular dependency imports with `Any`. Set an [alias](#typing-aliases) with a meaningful name, and use the real type name from this module (any attribute of `Any` is `Any`). Alias definitions should be separated from the last import by one line. ```python from typing import Any some_mod = Any # some_mod.py imports this module. ... def my_method(self, var: "some_mod.SomeType") -> None: ... ``` #### 3.19.15 Generics When annotating, prefer to specify type parameters for [generic](https://docs.python.org/3/library/typing.html#generics) types in a parameter list; otherwise, the generics' parameters will be assumed to be [`Any`](https://docs.python.org/3/library/typing.html#the-any-type). ```python # Yes: def get_names(employee_ids: Sequence[int]) -> Mapping[int, str]: ... ``` ```python # No: # This is interpreted as get_names(employee_ids: Sequence[Any]) -> Mapping[Any, Any] def get_names(employee_ids: Sequence) -> Mapping: ... ``` If the best type parameter for a generic is `Any`, make it explicit, but remember that in many cases [`TypeVar`](#typing-type-var) might be more appropriate: ```python # No: def get_names(employee_ids: Sequence[Any]) -> Mapping[Any, str]: """Returns a mapping from employee ID to employee name for given IDs.""" ``` ```python # Yes: _T = TypeVar('_T') def get_names(employee_ids: Sequence[_T]) -> Mapping[_T, str]: """Returns a mapping from employee ID to employee name for given IDs.""" ``` ## 4 Parting Words *BE CONSISTENT*. If you're editing code, take a few minutes to look at the code around you and determine its style. If they use `_idx` suffixes in index variable names, you should too. If their comments have little boxes of hash marks around them, make your comments have little boxes of hash marks around them too. The point of having style guidelines is to have a common vocabulary of coding so people can concentrate on what you're saying rather than on how you're saying it. We present global style rules here so people know the vocabulary, but local style is also important. If code you add to a file looks drastically different from the existing code around it, it throws readers out of their rhythm when they go to read it. However, there are limits to consistency. It applies more heavily locally and on choices unspecified by the global style. Consistency should not generally be used as a justification to do things in an old style without considering the benefits of the new style, or the tendency of the codebase to converge on newer styles over time. ================================================ FILE: pylintrc ================================================ # This Pylint rcfile contains a best-effort configuration to uphold the # best-practices and style described in the Google Python style guide: # https://google.github.io/styleguide/pyguide.html # # Its canonical open-source location is: # https://google.github.io/styleguide/pylintrc # Copyright 2018 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. [MAIN] # Files or directories to be skipped. They should be base names, not paths. ignore=third_party # Files or directories matching the regex patterns are skipped. The regex # matches against base names, not paths. ignore-patterns= # Pickle collected data for later comparisons. persistent=no # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. load-plugins= # Use multiple processes to speed up Pylint. jobs=4 # Allow loading of arbitrary C extensions. Extensions are imported into the # active Python interpreter and may run arbitrary code. unsafe-load-any-extension=no [MESSAGES CONTROL] # Only show warnings with the listed confidence levels. Leave empty to show # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED confidence= # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time (only on the command line, not in the configuration file where # it should appear only once). See also the "--disable" option for examples. #enable= # Disable the message, report, category or checker with the given id(s). You # can either give multiple identifiers separated by comma (,) or put this # option multiple times (only on the command line, not in the configuration # file where it should appear only once).You can also use "--disable=all" to # disable everything first and then reenable specific checks. For example, if # you want to run only the similarities checker, you can use "--disable=all # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" disable=R, abstract-method, apply-builtin, arguments-differ, attribute-defined-outside-init, backtick, bad-option-value, basestring-builtin, buffer-builtin, c-extension-no-member, consider-using-enumerate, cmp-builtin, cmp-method, coerce-builtin, coerce-method, delslice-method, div-method, eq-without-hash, execfile-builtin, file-builtin, filter-builtin-not-iterating, fixme, getslice-method, global-statement, hex-method, idiv-method, implicit-str-concat, import-error, import-self, import-star-module-level, input-builtin, intern-builtin, invalid-str-codec, locally-disabled, long-builtin, long-suffix, map-builtin-not-iterating, misplaced-comparison-constant, missing-function-docstring, metaclass-assignment, next-method-called, next-method-defined, no-absolute-import, no-init, # added no-member, no-name-in-module, no-self-use, nonzero-method, oct-method, old-division, old-ne-operator, old-octal-literal, old-raise-syntax, parameter-unpacking, print-statement, raising-string, range-builtin-not-iterating, raw_input-builtin, rdiv-method, reduce-builtin, relative-import, reload-builtin, round-builtin, setslice-method, signature-differs, standarderror-builtin, suppressed-message, sys-max-int, trailing-newlines, unichr-builtin, unicode-builtin, unnecessary-pass, unpacking-in-except, useless-else-on-loop, useless-suppression, using-cmp-argument, wrong-import-order, xrange-builtin, zip-builtin-not-iterating, [REPORTS] # Set the output format. Available formats are text, parseable, colorized, msvs # (visual studio) and html. You can also give a reporter class, eg # mypackage.mymodule.MyReporterClass. output-format=text # Tells whether to display a full report or only the messages reports=no # Activate the evaluation score. score=no # Python expression which should return a note less than 10 (10 is the highest # note). You have access to the variables errors warning, statement which # respectively contain the number of errors / warnings messages and the total # number of statements analyzed. This is used by the global evaluation report # (RP0004). evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) # Template used to display messages. This is a python new-style format string # used to format the message information. See doc for all details #msg-template= [BASIC] # Good variable names which should always be accepted, separated by a comma good-names=main,_ # Bad variable names which should always be refused, separated by a comma bad-names= # Colon-delimited sets of names that determine each other's naming style when # the name regexes allow several styles. name-group= # Include a hint for the correct naming format with invalid-name include-naming-hint=no # List of decorators that produce properties, such as abc.abstractproperty. Add # to this list to register other decorators that produce valid properties. property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl # Regular expression matching correct function names function-rgx=^(?:(?PsetUp|tearDown|setUpModule|tearDownModule)|(?P_?[A-Z][a-zA-Z0-9]*)|(?P_?[a-z][a-z0-9_]*))$ # Regular expression matching correct variable names variable-rgx=^[a-z][a-z0-9_]*$ # Regular expression matching correct constant names const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ # Regular expression matching correct attribute names attr-rgx=^_{0,2}[a-z][a-z0-9_]*$ # Regular expression matching correct argument names argument-rgx=^[a-z][a-z0-9_]*$ # Regular expression matching correct class attribute names class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$ # Regular expression matching correct inline iteration names inlinevar-rgx=^[a-z][a-z0-9_]*$ # Regular expression matching correct class names class-rgx=^_?[A-Z][a-zA-Z0-9]*$ # Regular expression matching correct module names module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$ # Regular expression matching correct method names method-rgx=(?x)^(?:(?P_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P_{0,2}[a-z][a-z0-9_]*))$ # Regular expression which should only match function or class names that do # not require a docstring. no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$ # Minimum line length for functions/classes that require docstrings, shorter # ones are exempt. docstring-min-length=12 [TYPECHECK] # List of decorators that produce context managers, such as # contextlib.contextmanager. Add to this list to register other decorators that # produce valid context managers. contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager # List of module names for which member attributes should not be checked # (useful for modules/projects where namespaces are manipulated during runtime # and thus existing member attributes cannot be deduced by static analysis. It # supports qualified module names, as well as Unix pattern matching. ignored-modules= # List of class names for which member attributes should not be checked (useful # for classes with dynamically set attributes). This supports the use of # qualified names. ignored-classes=optparse.Values,thread._local,_thread._local # List of members which are set dynamically and missed by pylint inference # system, and so shouldn't trigger E1101 when accessed. Python regular # expressions are accepted. generated-members= [FORMAT] # Maximum number of characters on a single line. max-line-length=80 # TODO(https://github.com/pylint-dev/pylint/issues/3352): Direct pylint to exempt # lines made too long by directives to pytype. # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=(?x)( ^\s*(\#\ )??$| ^\s*(from\s+\S+\s+)?import\s+.+$) # Allow the body of an if to be on the same line as the test if there is no # else. single-line-if-stmt=yes # Maximum number of lines in a module max-module-lines=99999 # String used as indentation unit. The internal Google style guide mandates 2 # spaces. Google's externaly-published style guide says 4, consistent with # PEP 8. indent-string=' ' # Number of spaces of indent required inside a hanging or continued line. indent-after-paren=4 # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. expected-line-ending-format= [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. notes=TODO [STRING] # This flag controls whether inconsistent-quotes generates a warning when the # character used as a quote delimiter is used inconsistently within a module. check-quote-consistency=yes [VARIABLES] # Tells whether we should check for unused import in __init__ files. init-import=no # A regular expression matching the name of dummy variables (i.e. expectedly # not used). dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_) # List of additional names supposed to be defined in builtins. Remember that # you should avoid to define new builtins when possible. additional-builtins= # List of strings which can identify a callback function by name. A callback # name must start or end with one of those strings. callbacks=cb_,_cb # List of qualified module names which can have objects that can redefine # builtins. redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools [LOGGING] # Logging modules to check that the string format arguments are in logging # function parameter format logging-modules=logging,absl.logging,tensorflow.io.logging [SIMILARITIES] # Minimum lines number of a similarity. min-similarity-lines=4 # Ignore comments when computing similarities. ignore-comments=yes # Ignore docstrings when computing similarities. ignore-docstrings=yes # Ignore imports when computing similarities. ignore-imports=no [SPELLING] # Spelling dictionary name. Available dictionaries: none. To make it working # install python-enchant package. spelling-dict= # List of comma separated words that should not be checked. spelling-ignore-words= # A path to a file that contains private dictionary; one word per line. spelling-private-dict-file= # Tells whether to store unknown words to indicated private dictionary in # --spelling-private-dict-file option instead of raising a message. spelling-store-unknown-words=no [IMPORTS] # Deprecated modules which should not be used, separated by a comma deprecated-modules=regsub, TERMIOS, Bastion, rexec, sets # Create a graph of every (i.e. internal and external) dependencies in the # given file (report RP0402 must not be disabled) import-graph= # Create a graph of external dependencies in the given file (report RP0402 must # not be disabled) ext-import-graph= # Create a graph of internal dependencies in the given file (report RP0402 must # not be disabled) int-import-graph= # Force import order to recognize a module as part of the standard # compatibility libraries. known-standard-library= # Force import order to recognize a module as part of a third party library. known-third-party=enchant, absl # Analyse import fallback blocks. This can be used to support both Python 2 and # 3 compatible code, which means that the block might have code that exists # only in one or another interpreter, leading to false positives when analysed. analyse-fallback-blocks=no [CLASSES] # List of method names used to declare (i.e. assign) instance attributes. defining-attr-methods=__init__, __new__, setUp # List of member names, which should be excluded from the protected access # warning. exclude-protected=_asdict, _fields, _replace, _source, _make # List of valid names for the first argument in a class method. valid-classmethod-first-arg=cls, class_ # List of valid names for the first argument in a metaclass class method. valid-metaclass-classmethod-first-arg=mcs ================================================ FILE: shell.xml ================================================ The guide has been moved to shellguide.html. ================================================ FILE: shell.xsl ================================================ <xsl:value-of select="@title"/>

================================================ FILE: shellguide.md ================================================ # Shell Style Guide Authored, revised and maintained by many Googlers. ## Table of Contents Section | Contents ------------------------------------------------------------------------------------ | -------- [Background](#s1-background) | [Which Shell to Use](#s1.1-which-shell-to-use) - [When to use Shell](#s1.2-when-to-use-shell) [Shell Files and Interpreter Invocation](#s2-shell-files-and-interpreter-invocation) | [File Extensions](#s2.1-file-extensions) - [SUID/SGID](#s2.2-suid-sgid) [Environment](#s3-environment) | [STDOUT vs STDERR](#s3.1-stdout-vs-stderr) [Comments](#s4-comments) | [File Header](#s4.1-file-header) - [Function Comments](#s4.2-function-comments) - [Implementation Comments](#s4.3-implementation-comments) - [TODO Comments](#s4.4-todo-comments) [Formatting](#s5-formatting) | [Indentation](#s5.1-indentation) - [Line Length and Long Strings](#s5.2-line-length-and-long-strings) - [Pipelines](#s5.3-pipelines) - [Control Flow](#s5.4-control-flow) - [Case statement](#s5.5-case-statement) - [Variable expansion](#s5.6-variable-expansion) - [Quoting](#s5.7-quoting) [Features and Bugs](#s6-features-and-bugs) | [ShellCheck](#s6.1-shellcheck) - [Command Substitution](#s6.2-command-substitution) - [Test, `[… ]`, and `[[… ]]`](#s6.3-tests) - [Testing Strings](#s6.4-testing-strings) - [Wildcard Expansion of Filenames](#s6.5-wildcard-expansion-of-filenames) - [Eval](#s6.6-eval) - [Arrays](#s6.7-arrays) - [Pipes to While](#s6.8-pipes-to-while) - [Arithmetic](#s6.9-arithmetic) - [Aliases](#s6.10-aliases) [Naming Conventions](#s7-naming-conventions) | [Function Names](#s7.1-function-names) - [Variable Names](#s7.2-variable-names) - [Constants and Environment Variable Names](#s7.3-constants-and-environment-variable-names) - [Source Filenames](#s7.4-source-filenames) - [Use Local Variables](#s7.5-use-local-variables) - [Function Location](#s7.6-function-location) - [main](#s7.7-main) [Calling Commands](#s8-calling-commands) | [Checking Return Values](#s8.1-checking-return-values) - [Builtin Commands vs. External Commands](#s8.2-builtin-commands-vs-external-commands) [When in Doubt: Be Consistent](#s9-conclusion) | ## Background ### Which Shell to Use Bash is the only shell scripting language permitted for executables. Executables must start with `#!/bin/bash` and minimal flags. Use `set` to set shell options so that calling your script as `bash script_name` does not break its functionality. Restricting all executable shell scripts to *bash* gives us a consistent shell language that's installed on all our machines. In particular, this means there is generally no need to strive for POSIX-compatibility or otherwise avoid "bashisms". The only exception to the above is where you're forced to by whatever you're coding for. For example some legacy operating systems or constrained execution environments may require plain Bourne shell for certain scripts. ### When to use Shell Shell should only be used for small utilities or simple wrapper scripts. While shell scripting isn't a development language, it is used for writing various utility scripts throughout Google. This style guide is more a recognition of its use rather than a suggestion that it be used for widespread deployment. Some guidelines: * If you're mostly calling other utilities and are doing relatively little data manipulation, shell is an acceptable choice for the task. * If performance matters, use something other than shell. * If you are writing a script that is more than 100 lines long, or that uses non-straightforward control flow logic, you should rewrite it in a more structured language *now*. Bear in mind that scripts grow. Rewrite your script early to avoid a more time-consuming rewrite at a later date. * When assessing the complexity of your code (e.g. to decide whether to switch languages) consider whether the code is easily maintainable by people other than its author. ## Shell Files and Interpreter Invocation ### File Extensions Executables should have a `.sh` extension or no extension. - If the executable will have a build rule that renames the source file then prefer to use a `.sh` extension. This enables you to use the recommended naming convention, with a source file like `foo.sh` and a build rule named `foo`. - If the executable will be added directly to the user's `PATH`, then prefer to use no extension. It is not necessary to know what language a program is written in when executing it and shell doesn't require an extension so we prefer not to use one for executables that will be directly invoked by users. At the same time, consider whether it is preferable to deploy the output of a build rule rather than deploying the source file directly. - If neither of the above apply, then either choice is acceptable. Libraries must have a `.sh` extension and should not be executable. ### SUID/SGID SUID and SGID are *forbidden* on shell scripts. There are too many security issues with shell that make it nearly impossible to secure sufficiently to allow SUID/SGID. While bash does make it difficult to run SUID, it's still possible on some platforms which is why we're being explicit about banning it. Use `sudo` to provide elevated access if you need it. ## Environment ### STDOUT vs STDERR All error messages should go to `STDERR`. This makes it easier to separate normal status from actual issues. A function to print out error messages along with other status information is recommended. ```shell err() { echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2 } if ! do_something; then err "Unable to do_something" exit 1 fi ``` ## Comments ### File Header Start each file with a description of its contents. Every file must have a top-level comment including a brief overview of its contents. A copyright notice and author information are optional. Example: ```shell #!/bin/bash # # Perform hot backups of Oracle databases. ``` ### Function Comments Any function that is not both obvious and short must have a function header comment. Any function in a library must have a function header comment regardless of length or complexity. It should be possible for someone else to learn how to use your program or to use a function in your library by reading the comments (and self-help, if provided) without reading the code. All function header comments should describe the intended API behaviour using: * Description of the function. * Globals: List of global variables used and modified. * Arguments: Arguments taken. * Outputs: Output to STDOUT or STDERR. * Returns: Returned values other than the default exit status of the last command run. Example: ```shell ####################################### # Cleanup files from the backup directory. # Globals: # BACKUP_DIR # ORACLE_SID # Arguments: # None ####################################### function cleanup() { … } ####################################### # Get configuration directory. # Globals: # SOMEDIR # Arguments: # None # Outputs: # Writes location to stdout ####################################### function get_dir() { echo "${SOMEDIR}" } ####################################### # Delete a file in a sophisticated manner. # Arguments: # File to delete, a path. # Returns: # 0 if thing was deleted, non-zero on error. ####################################### function del_thing() { rm "$1" } ``` ### Implementation Comments Comment tricky, non-obvious, interesting or important parts of your code. This follows general Google coding comment practice. Don't comment everything. If there's a complex algorithm or you're doing something out of the ordinary, put a short comment in. ### TODO Comments Use TODO comments for code that is temporary, a short-term solution, or good-enough but not perfect. This matches the convention in the [C++ Guide](https://google.github.io/styleguide/cppguide.html#TODO_Comments). `TODO`s should include the string `TODO` in all caps, followed by the name, e-mail address, or other identifier of the person with the best context about the problem referenced by the `TODO`. The main purpose is to have a consistent `TODO` that can be searched to find out how to get more details upon request. A `TODO` is not a commitment that the person referenced will fix the problem. Thus when you create a `TODO`, it is almost always your name that is given. Examples: ```shell # TODO(mrmonkey): Handle the unlikely edge cases (bug ####) ``` ## Formatting While you should follow the style that's already there for files that you're modifying, the following are required for any new code. ### Indentation Indent 2 spaces. No tabs. Use blank lines between blocks to improve readability. Indentation is two spaces. Whatever you do, don't use tabs. For existing files, stay faithful to the existing indentation. **Exception:** The only exception for using tabs is for the body of `<<-` tab-indented [here-document](https://www.gnu.org/software/bash/manual/html_node/Redirections.html#Here-Documents). ### Line Length and Long Strings Maximum line length is 80 characters. If you have to write literal strings that are longer than 80 characters, this should be done with a [here document](https://www.gnu.org/software/bash/manual/html_node/Redirections.html#Here-Documents) or an embedded newline if possible. Words that are longer than 80 chars and can't sensibly be split are ok, but where possible these items should be on a line of their own, or factored into a variable. Examples include file paths and URLs, particularly where string-matching them (such as `grep`) is valuable for maintenance. ```shell # DO use 'here document's cat < ### Pipelines Pipelines should be split one per line if they don't all fit on one line. If a pipeline all fits on one line, it should be on one line. If not, it should be split at one pipe segment per line with the pipe on the newline and a 2 space indent for the next section of the pipe. `\ ` should be consistently used to indicate line continuation. This applies to a chain of commands combined using `|` as well as to logical compounds using `||` and `&&`. ```shell # All fits on one line command1 | command2 # Long commands command1 \ | command2 \ | command3 \ | command4 ``` This helps readability when distinguishing a pipeline from a regular long command continuation, particularly if the line is using both. Comments will need to precede the whole pipeline. If the comment and pipeline are large and complex, then it is worth considering moving low level details of them aside by using a helper function. ### Control Flow Put `; then` and `; do` on the same line as the `if`, `for`, or `while`. Control flow statements in shell are a bit different, but we follow the same principles as with braces when declaring functions. That is: `; then` and `; do` should be on the same line as the `if`/`for`/`while`/`until`/`select`. `else` should be on its own line and closing statements (`fi` and `done`) should be on their own line vertically aligned with the opening statement. Example: ```shell # If inside a function remember to declare the loop variable as # a local to avoid it leaking into the global environment: local dir for dir in "${dirs_to_cleanup[@]}"; do if [[ -d "${dir}/${SESSION_ID}" ]]; then log_date "Cleaning up old files in ${dir}/${SESSION_ID}" rm "${dir}/${SESSION_ID}/"* || error_message else mkdir -p "${dir}/${SESSION_ID}" || error_message fi done ``` Although it is possible to [omit `in "$@"`](https://www.gnu.org/software/bash/manual/html_node/Looping-Constructs.html#index-for) in for loops we recommend consistently including it for clarity. ```shell for arg in "$@"; do echo "argument: ${arg}" done ``` ### Case statement * Indent alternatives by 2 spaces. * A one-line alternative needs a space after the close parenthesis of the pattern and before the `;;`. * Long or multi-command alternatives should be split over multiple lines with the pattern, actions, and `;;` on separate lines. The matching expressions are indented one level from the `case` and `esac`. Multiline actions are indented another level. In general, there is no need to quote match expressions. Pattern expressions should not be preceded by an open parenthesis. Avoid the `;&` and `;;&` notations. ```shell case "${expression}" in a) variable="…" some_command "${variable}" "${other_expr}" … ;; absolute) actions="relative" another_command "${actions}" "${other_expr}" … ;; *) error "Unexpected expression '${expression}'" ;; esac ``` Simple commands may be put on the same line as the pattern and `;;` as long as the expression remains readable. This is often appropriate for single-letter option processing. When the actions don't fit on a single line, put the pattern on a line on its own, then the actions, then `;;` also on a line of its own. When on the same line as the actions, use a space after the close parenthesis of the pattern and another before the `;;`. ```shell verbose='false' aflag='' bflag='' files='' while getopts 'abf:v' flag; do case "${flag}" in a) aflag='true' ;; b) bflag='true' ;; f) files="${OPTARG}" ;; v) verbose='true' ;; *) error "Unexpected option ${flag}" ;; esac done ``` ### Variable expansion In order of precedence: Stay consistent with what you find; quote your variables; prefer `"${var}"` over `"$var"`. These are strongly recommended guidelines but not mandatory regulation. Nonetheless, the fact that it's a recommendation and not mandatory doesn't mean it should be taken lightly or downplayed. They are listed in order of precedence. * Stay consistent with what you find for existing code. * Quote variables, see [Quoting section below](#quoting). * Don't brace-delimit single character shell specials / positional parameters, unless strictly necessary or avoiding deep confusion. Prefer brace-delimiting all other variables. ```shell # Section of *recommended* cases. # Preferred style for 'special' variables: echo "Positional: $1" "$5" "$3" echo "Specials: !=$!, -=$-, _=$_. ?=$?, #=$# *=$* @=$@ \$=$$ …" # Braces necessary: echo "many parameters: ${10}" # Braces avoiding confusion: # Output is "a0b0c0" set -- a b c echo "${1}0${2}0${3}0" # Preferred style for other variables: echo "PATH=${PATH}, PWD=${PWD}, mine=${some_var}" while read -r f; do echo "file=${f}" done < <(find /tmp) ``` ```shell # Section of *discouraged* cases # Unquoted vars, unbraced vars, brace-delimited single letter # shell specials. echo a=$avar "b=$bvar" "PID=${$}" "${1}" # Confusing use: this is expanded as "${1}0${2}0${3}0", # not "${10}${20}${30} set -- a b c echo "$10$20$30" ``` NOTE: Using braces in `${var}` is *not* a form of quoting. "Double quotes" must be used *as well*. ### Quoting * Always quote strings containing variables, command substitutions, spaces or shell meta characters, unless careful unquoted expansion is required or it's a shell-internal integer (see next point). * Use arrays for safe quoting of lists of elements, especially command-line flags. See [Arrays](#arrays) below. * Optionally quote shell-internal, readonly [special variables](https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html) that are defined to be integers: `$?`, `$#`, `$$`, `$!`. Prefer quoting of "named" internal integer variables, e.g. PPID etc for consistency. * Prefer quoting strings that are "words" (as opposed to command options or path names). * Be aware of the quoting rules for pattern matches in `[[ … ]]`. See the [Test, `[ … ]`, and `[[ … ]]`](#tests) section below. * Use `"$@"` unless you have a specific reason to use `$*`, such as simply appending the arguments to a string in a message or log. ```shell # 'Single' quotes indicate that no substitution is desired. # "Double" quotes indicate that substitution is required/tolerated. # Simple examples # "quote command substitutions" # Note that quotes nested inside "$()" don't need escaping. flag="$(some_command and its args "$@" 'quoted separately')" # "quote variables" echo "${flag}" # Use arrays with quoted expansion for lists. declare -a FLAGS FLAGS=( --foo --bar='baz' ) readonly FLAGS mybinary "${FLAGS[@]}" # It's ok to not quote internal integer variables. if (( $# > 3 )); then echo "ppid=${PPID}" fi # "never quote literal integers" value=32 # "quote command substitutions", even when you expect integers number="$(generate_number)" # "prefer quoting words", not compulsory readonly USE_INTEGER='true' # "quote shell meta characters" echo 'Hello stranger, and well met. Earn lots of $$$' echo "Process $$: Done making \$\$\$." # "command options or path names" # ($1 is assumed to contain a value here) grep -li Hugo /dev/null "$1" # Less simple examples # "quote variables, unless proven false": ccs might be empty git send-email --to "${reviewers}" ${ccs:+"--cc" "${ccs}"} # Positional parameter precautions: $1 might be unset # Single quotes leave regex as-is. grep -cP '([Ss]pecial|\|?characters*)$' ${1:+"$1"} # For passing on arguments, # "$@" is right almost every time, and # $* is wrong almost every time: # # * $* and $@ will split on spaces, clobbering up arguments # that contain spaces and dropping empty strings; # * "$@" will retain arguments as-is, so no args # provided will result in no args being passed on; # This is in most cases what you want to use for passing # on arguments. # * "$*" expands to one argument, with all args joined # by (usually) spaces, # so no args provided will result in one empty string # being passed on. # # Consult # https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html and # https://mywiki.wooledge.org/BashGuide/Arrays for more (set -- 1 "2 two" "3 three tres"; echo $#; set -- "$*"; echo "$#, $@") (set -- 1 "2 two" "3 three tres"; echo $#; set -- "$@"; echo "$#, $@") ``` ## Features and Bugs ### ShellCheck The [ShellCheck project](https://www.shellcheck.net/) identifies common bugs and warnings for your shell scripts. It is recommended for all scripts, large or small. ### Command Substitution Use `$(command)` instead of backticks. Nested backticks require escaping the inner ones with `\ `. The `$(command)` format doesn't change when nested and is easier to read. Example: ```shell # This is preferred: var="$(command "$(command1)")" ``` ```shell # This is not: var="`command \`command1\``" ``` ### Test, `[ … ]`, and `[[ … ]]` `[[ … ]]` is preferred over `[ … ]`, `test` and `/usr/bin/[`. `[[ … ]]` reduces errors as no pathname expansion or word splitting takes place between `[[` and `]]`. In addition, `[[ … ]]` allows for pattern and regular expression matching, while `[ … ]` does not. ```shell # This ensures the string on the left is made up of characters in # the alnum character class followed by the string name. # Note that the RHS should not be quoted here. if [[ "filename" =~ ^[[:alnum:]]+name ]]; then echo "Match" fi # This matches the exact pattern "f*" (Does not match in this case) if [[ "filename" == "f*" ]]; then echo "Match" fi ``` ```shell # This gives a "too many arguments" error as f* is expanded to the # contents of the current directory. It might also trigger the # "unexpected operator" error because `[` does not support `==`, only `=`. if [ "filename" == f* ]; then echo "Match" fi ``` For the gory details, see E14 in the [Bash FAQ](http://tiswww.case.edu/php/chet/bash/FAQ) ### Testing Strings Use quotes rather than filler characters where possible. Bash is smart enough to deal with an empty string in a test. So, given that the code is much easier to read, use tests for empty/non-empty strings or empty strings rather than filler characters. ```shell # Do this: if [[ "${my_var}" == "some_string" ]]; then do_something fi # -z (string length is zero) and -n (string length is not zero) are # preferred over testing for an empty string if [[ -z "${my_var}" ]]; then do_something fi # This is OK (ensure quotes on the empty side), but not preferred: if [[ "${my_var}" == "" ]]; then do_something fi ``` ```shell # Not this: if [[ "${my_var}X" == "some_stringX" ]]; then do_something fi ``` To avoid confusion about what you're testing for, explicitly use `-z` or `-n`. ```shell # Use this if [[ -n "${my_var}" ]]; then do_something fi ``` ```shell # Instead of this if [[ "${my_var}" ]]; then do_something fi ``` For clarity, use `==` for equality rather than `=` even though both work. The former encourages the use of `[[` and the latter can be confused with an assignment. However, be careful when using `<` and `>` in `[[ … ]]` which performs a lexicographical comparison. Use `(( … ))` or `-lt` and `-gt` for numerical comparison. ```shell # Use this if [[ "${my_var}" == "val" ]]; then do_something fi if (( my_var > 3 )); then do_something fi if [[ "${my_var}" -gt 3 ]]; then do_something fi ``` ```shell # Instead of this if [[ "${my_var}" = "val" ]]; then do_something fi # Probably unintended lexicographical comparison. if [[ "${my_var}" > 3 ]]; then # True for 4, false for 22. do_something fi ``` ### Wildcard Expansion of Filenames Use an explicit path when doing wildcard expansion of filenames. As filenames can begin with a `-`, it's a lot safer to expand wildcards with `./*` instead of `*`. ```shell # Here's the contents of the directory: # -f -r somedir somefile # Incorrectly deletes almost everything in the directory by force psa@bilby$ rm -v * removed directory: `somedir' removed `somefile' ``` ```shell # As opposed to: psa@bilby$ rm -v ./* removed `./-f' removed `./-r' rm: cannot remove `./somedir': Is a directory removed `./somefile' ``` ### Eval `eval` should be avoided. Eval munges the input when used for assignment to variables and can set variables without making it possible to check what those variables were. ```shell # What does this set? # Did it succeed? In part or whole? eval $(set_my_variables) # What happens if one of the returned values has a space in it? variable="$(eval some_function)" ``` ### Arrays Bash arrays should be used to store lists of elements, to avoid quoting complications. This particularly applies to argument lists. Arrays should not be used to facilitate more complex data structures (see [When to use Shell](#when-to-use-shell) above). Arrays store an ordered collection of strings, and can be safely expanded into individual elements for a command or loop. Using a single string for multiple command arguments should be avoided, as it inevitably leads to authors using `eval` or trying to nest quotes inside the string, which does not give reliable or readable results and leads to needless complexity. ```shell # An array is assigned using parentheses, and can be appended to # with +=( … ). declare -a flags flags=(--foo --bar='baz') flags+=(--greeting="Hello ${name}") mybinary "${flags[@]}" ``` ```shell # Don’t use strings for sequences. flags='--foo --bar=baz' flags+=' --greeting="Hello world"' # This won’t work as intended. mybinary ${flags} ``` ```shell # Command expansions return single strings, not arrays. Avoid # unquoted expansion in array assignments because it won’t # work correctly if the command output contains special # characters or whitespace. # This expands the listing output into a string, then does special keyword # expansion, and then whitespace splitting. Only then is it turned into a # list of words. The ls command may also change behavior based on the user's # active environment! declare -a files=($(ls /directory)) # The get_arguments writes everything to STDOUT, but then goes through the # same expansion process above before turning into a list of arguments. mybinary $(get_arguments) ``` #### Arrays Pros * Using Arrays allows lists of things without confusing quoting semantics. Conversely, not using arrays leads to misguided attempts to nest quoting inside a string. * Arrays make it possible to safely store sequences/lists of arbitrary strings, including strings containing whitespace. #### Arrays Cons Using arrays can risk a script’s complexity growing. #### Arrays Decision Arrays should be used to safely create and pass around lists. In particular, when building a set of command arguments, use arrays to avoid confusing quoting issues. Use quoted expansion – `"${array[@]}"` – to access arrays. However, if more advanced data manipulation is required, shell scripting should be avoided altogether; see [above](#when-to-use-shell). ### Pipes to While Use process substitution or the `readarray` builtin (bash4+) in preference to piping to `while`. Pipes create a subshell, so any variables modified within a pipeline do not propagate to the parent shell. The implicit subshell in a pipe to `while` can introduce subtle bugs that are hard to track down. ```shell last_line='NULL' your_command | while read -r line; do if [[ -n "${line}" ]]; then last_line="${line}" fi done # This will always output 'NULL'! echo "${last_line}" ``` Using process substitution also creates a subshell. However, it allows redirecting from a subshell to a `while` without putting the `while` (or any other command) in a subshell. ```shell last_line='NULL' while read line; do if [[ -n "${line}" ]]; then last_line="${line}" fi done < <(your_command) # This will output the last non-empty line from your_command echo "${last_line}" ``` Alternatively, use the `readarray` builtin to read the file into an array, then loop over the array's contents. Notice that (for the same reason as above) you need to use a process substitution with `readarray` rather than a pipe, but with the advantage that the input generation for the loop is located before it, rather than after. ```shell last_line='NULL' readarray -t lines < <(your_command) for line in "${lines[@]}"; do if [[ -n "${line}" ]]; then last_line="${line}" fi done echo "${last_line}" ``` > Note: Be cautious using a for-loop to iterate over output, as in `for var in > $(...)`, as the output is split by whitespace, not by line. Sometimes you will > know this is safe because the output can't contain any unexpected whitespace, > but where this isn't obvious or doesn't improve readability (such as a long > command inside `$(...)`), a `while read` loop or `readarray` is often safer > and clearer. ### Arithmetic Always use `(( … ))` or `$(( … ))` rather than `let` or `$[ … ]` or `expr`. Never use the `$[ … ]` syntax, the `expr` command, or the `let` built-in. `<` and `>` don't perform numerical comparison inside `[[ … ]]` expressions (they perform lexicographical comparisons instead; see [Testing Strings](#testing-strings)). For preference, don't use `[[ … ]]` *at all* for numeric comparisons, use `(( … ))` instead. It is recommended to avoid using `(( … ))` as a standalone statement, and otherwise be wary of its expression evaluating to zero - particularly with `set -e` enabled. For example, `set -e; i=0; (( i++ ))` will cause the shell to exit. ```shell # Simple calculation used as text - note the use of $(( … )) within # a string. echo "$(( 2 + 2 )) is 4" # When performing arithmetic comparisons for testing if (( a < b )); then … fi # Some calculation assigned to a variable. (( i = 10 * j + 400 )) ``` ```shell # This form is non-portable and deprecated i=$[2 * 10] # Despite appearances, 'let' isn't one of the declarative keywords, # so unquoted assignments are subject to globbing wordsplitting. # For the sake of simplicity, avoid 'let' and use (( … )) let i="2 + 2" # The expr utility is an external program and not a shell builtin. i=$( expr 4 + 4 ) # Quoting can be error prone when using expr too. i=$( expr 4 '*' 4 ) ``` Stylistic considerations aside, the shell's built-in arithmetic is many times faster than `expr`. When using variables, the `${var}` (and `$var`) forms are not required within `$(( … ))`. The shell knows to look up `var` for you, and omitting the `${…}` leads to cleaner code. This is slightly contrary to the previous rule about always using braces, so this is a recommendation only. ```shell # N.B.: Remember to declare your variables as integers when # possible, and to prefer local variables over globals. local -i hundred="$(( 10 * 10 ))" declare -i five="$(( 10 / 2 ))" # Increment the variable "i" by three. # Note that: # - We do not write ${i} or $i. # - We put a space after the (( and before the )). (( i += 3 )) # To decrement the variable "i" by five: (( i -= 5 )) # Do some complicated computations. # Note that normal arithmetic operator precedence is observed. hr=2 min=5 sec=30 echo "$(( hr * 3600 + min * 60 + sec ))" # prints 7530 as expected ``` ## Aliases Although commonly seen in `.bashrc` files, aliases should be avoided in scripts. As the [Bash manual](https://www.gnu.org/software/bash/manual/html_node/Aliases.html) notes: > For almost every purpose, shell functions are preferred over aliases. Aliases are cumbersome to work with because they require carefully quoting and escaping their contents, and mistakes can be hard to notice. ```shell # this evaluates $RANDOM once when the alias is defined, # so the echo'ed string will be the same on each invocation alias random_name="echo some_prefix_${RANDOM}" ``` Functions provide a superset of alias' functionality and should always be preferred. . ```shell random_name() { echo "some_prefix_${RANDOM}" } # Note that unlike aliases function's arguments are accessed via $@ fancy_ls() { ls -lh "$@" } ``` ## Naming Conventions ### Function Names Lower-case, with underscores to separate words. Separate libraries with `::`. Parentheses are required after the function name. The keyword `function` is optional, but must be used consistently throughout a project. If you're writing single functions, use lowercase and separate words with underscore. If you're writing a package, separate package names with `::`. However, functions intended for interactive use may choose to avoid colons as it can confuse bash auto-completion. Braces must be on the same line as the function name (as with other languages at Google) and no space between the function name and the parenthesis. ```shell # Single function my_func() { … } # Part of a package mypackage::my_func() { … } ``` The `function` keyword is extraneous when "()" is present after the function name, but enhances quick identification of functions. ### Variable Names Same as for function names. Variables names for loops should be similarly named for any variable you're looping through. ```shell for zone in "${zones[@]}"; do something_with "${zone}" done ``` ### Constants, Environment Variables, and readonly Variables Constants and anything exported to the environment should be capitalized, separated with underscores, and declared at the top of the file. ```shell # Constant readonly PATH_TO_FILES='/some/path' # Both constant and exported to the environment declare -xr ORACLE_SID='PROD' ``` For the sake of clarity `readonly` or `export` is recommended vs. the equivalent `declare` commands. You can do one after the other, like: ```shell # Constant readonly PATH_TO_FILES='/some/path' export PATH_TO_FILES ``` It's OK to set a constant at runtime or in a conditional, but it should be made readonly immediately afterwards. ```shell ZIP_VERSION="$(dpkg --status zip | sed -n 's/^Version: //p')" if [[ -z "${ZIP_VERSION}" ]]; then ZIP_VERSION="$(pacman -Q --info zip | sed -n 's/^Version *: //p')" fi if [[ -z "${ZIP_VERSION}" ]]; then handle_error_and_quit fi readonly ZIP_VERSION ``` ### Source Filenames Lowercase, with underscores to separate words if desired. This is for consistency with other code styles in Google: `maketemplate` or `make_template` but not `make-template`. ### Use Local Variables Declare function-specific variables with `local`. Ensure that local variables are only seen inside a function and its children by using `local` when declaring them. This avoids polluting the global namespace and inadvertently setting variables that may have significance outside the function. Declaration and assignment must be separate statements when the assignment value is provided by a command substitution; as the `local` builtin does not propagate the exit code from the command substitution. ```shell my_func2() { local name="$1" # Separate lines for declaration and assignment: local my_var my_var="$(my_func)" (( $? == 0 )) || return … } ``` ```shell my_func2() { # DO NOT do this: # $? will always be zero, as it contains the exit code of 'local', not my_func local my_var="$(my_func)" (( $? == 0 )) || return … } ``` ### Function Location Put all functions together in the file just below constants. Don't hide executable code between functions. Doing so makes the code difficult to follow and results in nasty surprises when debugging. If you've got functions, put them all together near the top of the file. Only includes, `set` statements and setting constants may be done before declaring functions. ### main A function called `main` is required for scripts long enough to contain at least one other function. In order to easily find the start of the program, put the main program in a function called `main` as the bottom-most function. This provides consistency with the rest of the code base as well as allowing you to define more variables as `local` (which can't be done if the main code is not a function). The last non-comment line in the file should be a call to `main`: ```shell main "$@" ``` Obviously, for short scripts where it's just a linear flow, `main` is overkill and so is not required. ## Calling Commands ### Checking Return Values Always check return values and give informative return values. For unpiped commands, use `$?` or check directly via an `if` statement to keep it simple. Example: ```shell if ! mv "${file_list[@]}" "${dest_dir}/"; then echo "Unable to move ${file_list[*]} to ${dest_dir}" >&2 exit 1 fi # Or mv "${file_list[@]}" "${dest_dir}/" if (( $? != 0 )); then echo "Unable to move ${file_list[*]} to ${dest_dir}" >&2 exit 1 fi ``` Bash also has the `PIPESTATUS` variable that allows checking of the return code from all parts of a pipe. If it's only necessary to check success or failure of the whole pipe, then the following is acceptable: ```shell tar -cf - ./* | ( cd "${dir}" && tar -xf - ) if (( PIPESTATUS[0] != 0 || PIPESTATUS[1] != 0 )); then echo "Unable to tar files to ${dir}" >&2 fi ``` However, as `PIPESTATUS` will be overwritten as soon as you do any other command, if you need to act differently on errors based on where it happened in the pipe, you'll need to assign `PIPESTATUS` to another variable immediately after running the command (don't forget that `[` is a command and will wipe out `PIPESTATUS`). ```shell tar -cf - ./* | ( cd "${DIR}" && tar -xf - ) return_codes=( "${PIPESTATUS[@]}" ) if (( return_codes[0] != 0 )); then do_something fi if (( return_codes[1] != 0 )); then do_something_else fi ``` ### Builtin Commands vs. External Commands Given the choice between invoking a shell builtin and invoking a separate process, choose the builtin. We prefer the use of builtins such as the [*Parameter Expansion*](https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html) functionality provided by `bash` as it's more efficient, robust, and portable (especially when compared to things like `sed`). See also the [`=~` operator](https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html#index-_005b_005b). Examples: ```shell # Prefer this: addition="$(( X + Y ))" substitution="${string/#foo/bar}" if [[ "${string}" =~ foo:(\d+) ]]; then extraction="${BASH_REMATCH[1]}" fi ``` ```shell # Instead of this: addition="$(expr "${X}" + "${Y}")" substitution="$(echo "${string}" | sed -e 's/^foo/bar/')" extraction="$(echo "${string}" | sed -e 's/foo:\([0-9]\)/\1/')" ``` ## When in Doubt: Be Consistent Using one style consistently through our codebase lets us focus on other (more important) issues. Consistency also allows for automation. In many cases, rules that are attributed to “Be Consistent” boil down to “Just pick one and stop worrying about it”; the potential value of allowing flexibility on these points is outweighed by the cost of having people argue over them. However, there are limits to consistency. It is a good tie breaker when there is no clear technical argument, nor a long-term direction. Consistency should not generally be used as a justification to do things in an old style without considering the benefits of the new style, or the tendency of the codebase to converge on newer styles over time. ================================================ FILE: styleguide.css ================================================ body { background-color: #fff; color: #333; font-family: sans-serif; font-size: 10pt; margin-right: 100px; margin-left: 100px; } h1, h2, h3, h4, h5, h6, .toc_title { color: #06c; margin-top: 2em; margin-bottom: 1em; } h1 { text-align: center; font-size: 18pt; } h2, .toc_title { font-weight: bold; font-size: 12pt; margin-left: -40px; } h3, h4, h5, h6 { font-size: 10pt; margin-left: -20px; } .toc_category, .toc_stylepoint { font-size: 10pt; padding-top: 0.3em; padding-bottom: 0.3em; } table { border-collapse: collapse; } td, th { border: 1px solid #ccc; padding: 2px 12px; font-size: 10pt; } .toc td, .toc th { border-width: 1px 5px; } code, samp, var { color: #060; } pre { font-size: 10pt; display: block; color: #060; background-color: #f8fff8; border: 1px solid #f0fff0; border-left-width: 5px; padding: 4px 12px; } pre.badcode { color: #c00; background-color: #fff8f8; border-color: #fff0f0; } .showhide_button { float: left; cursor: pointer; border: 1px solid; border-color: #ddd #aaa #aaa #ddd; padding: 0 3px 1px; margin: 0 4px 8px 0; border-radius: 3px; -webkit-border-radius: 3px; -moz-border-radius: 3px; } .link_button { float: left; display: none; background-color: #f8f8ff; border: 1px solid #f0f0ff; font-size: 75%; margin-top: 0; margin-left: -50px; padding: 4px; border-radius: 3px; -webkit-border-radius: 3px; -moz-border-radius: 3px; } address { text-align: right; } hr { margin-top: 3.5em; border-width: 1px; color: #fff; } .stylepoint_section { display: block; margin-bottom: 1em; color: #58f; font-family: sans-serif; font-size: 90%; font-weight: bold; margin-left: -2%; } .stylepoint_subsection { color: #679; font-family: sans-serif; font-size: 90%; font-weight: bold; margin-left: -1%; } .stylepoint_subsubsection { color: #679; font-family: sans-serif; font-size: 80%; font-weight: bold; margin-left: 0; } .revision { text-align: right; } ================================================ FILE: styleguide.xsl ================================================ <xsl:value-of select="@title"/>

Each style point has a summary for which additional information is available by toggling the accompanying arrow button that looks this way: . You may toggle all summaries with the big arrow button:

Toggle all summaries

Parting Words

javascript:ShowHideByName(' ') ?showone=# link
display: inline display: none

Definition:

Pros:

Cons:

Decision:

TODO:


           
           
           
           
             
               
               
             
           
         

           
           
           
           
             
               
               
             
           
         

             
           

                             
                           
Table of Contents
_
================================================ FILE: tsguide.html ================================================ Google TypeScript Style Guide

Google TypeScript Style Guide

This guide is based on the internal Google TypeScript style guide, but it has been slightly adjusted to remove Google-internal sections. Google's internal environment has different constraints on TypeScript than you might find outside of Google. The advice here is specifically useful for people authoring code they intend to import into Google, but otherwise may not apply in your external environment.

There is no automatic deployment process for this version as it's pushed on-demand by volunteers.

Introduction

Terminology notes

This Style Guide uses RFC 2119 terminology when using the phrases must, must not, should, should not, and may. The terms prefer and avoid correspond to should and should not, respectively. Imperative and declarative statements are prescriptive and correspond to must.

Guide notes

All examples given are non-normative and serve only to illustrate the normative language of the style guide. That is, while the examples are in Google Style, they may not illustrate the only stylish way to represent the code. Optional formatting choices made in examples must not be enforced as rules.

Source file basics

File encoding: UTF-8

Source files are encoded in UTF-8.

Whitespace characters

Aside from the line terminator sequence, the ASCII horizontal space character (0x20) is the only whitespace character that appears anywhere in a source file. This implies that all other whitespace characters in string literals are escaped.

Special escape sequences

For any character that has a special escape sequence (\', \", \\, \b, \f, \n, \r, \t, \v), that sequence is used rather than the corresponding numeric escape (e.g \x0a, \u000a, or \u{a}). Legacy octal escapes are never used.

Non-ASCII characters

For the remaining non-ASCII characters, use the actual Unicode character (e.g. ). For non-printable characters, the equivalent hex or Unicode escapes (e.g. \u221e) can be used along with an explanatory comment.

// Perfectly clear, even without a comment.
const units = 'μs';

// Use escapes for non-printable characters.
const output = '\ufeff' + content;  // byte order mark
// Hard to read and prone to mistakes, even with the comment.
const units = '\u03bcs'; // Greek letter mu, 's'

// The reader has no idea what this is.
const output = '\ufeff' + content;

Source file structure

Files consist of the following, in order:

  1. Copyright information, if present
  2. JSDoc with @fileoverview, if present
  3. Imports, if present
  4. The file’s implementation

Exactly one blank line separates each section that is present.

If license or copyright information is necessary in a file, add it in a JSDoc at the top of the file.

@fileoverview JSDoc

A file may have a top-level @fileoverview JSDoc. If present, it may provide a description of the file's content, its uses, or information about its dependencies. Wrapped lines are not indented.

Example:

/**
 * @fileoverview Description of file. Lorem ipsum dolor sit amet, consectetur
 * adipiscing elit, sed do eiusmod tempor incididunt.
 */

Imports

There are four variants of import statements in ES6 and TypeScript:

Import type Example Use for
module[module_import] import * as foo from '...'; TypeScript imports
named[destructuring_import] import {SomeThing} from '...'; TypeScript imports
default import SomeThing from '...'; Only for other external code that requires them
side-effect import '...'; Only to import libraries for their side-effects on load (such as custom elements)
// Good: choose between two options as appropriate (see below).
import * as ng from '@angular/core';
import {Foo} from './foo';

// Only when needed: default imports.
import Button from 'Button';

// Sometimes needed to import libraries for their side effects:
import 'jasmine';
import '@polymer/paper-button';

Import paths

TypeScript code must use paths to import other TypeScript code. Paths may be relative, i.e. starting with . or .., or rooted at the base directory, e.g. root/path/to/file.

Code should use relative imports (./foo) rather than absolute imports path/to/foo when referring to files within the same (logical) project as this allows to move the project around without introducing changes in these imports.

Consider limiting the number of parent steps (../../../) as those can make module and path structures hard to understand.

import {Symbol1} from 'path/from/root';
import {Symbol2} from '../parent/file';
import {Symbol3} from './sibling';

Namespace versus named imports

Both namespace and named imports can be used.

Prefer named imports for symbols used frequently in a file or for symbols that have clear names, for example Jasmine's describe and it. Named imports can be aliased to clearer names as needed with as.

Prefer namespace imports when using many different symbols from large APIs. A namespace import, despite using the * character, is not comparable to a wildcard import as seen in other languages. Instead, namespace imports give a name to all the exports of a module, and each exported symbol from the module becomes a property on the module name. Namespace imports can aid readability for exported symbols that have common names like Model or Controller without the need to declare aliases.

// Bad: overlong import statement of needlessly namespaced names.
import {Item as TableviewItem, Header as TableviewHeader, Row as TableviewRow,
  Model as TableviewModel, Renderer as TableviewRenderer} from './tableview';

let item: TableviewItem|undefined;
// Better: use the module for namespacing.
import * as tableview from './tableview';

let item: tableview.Item|undefined;
import * as testing from './testing';

// Bad: The module name does not improve readability.
testing.describe('foo', () => {
  testing.it('bar', () => {
    testing.expect(null).toBeNull();
    testing.expect(undefined).toBeUndefined();
  });
});
// Better: give local names for these common functions.
import {describe, it, expect} from './testing';

describe('foo', () => {
  it('bar', () => {
    expect(null).toBeNull();
    expect(undefined).toBeUndefined();
  });
});
Special case: Apps JSPB protos

Apps JSPB protos must use named imports, even when it leads to long import lines.

This rule exists to aid in build performance and dead code elimination since often .proto files contain many messages that are not all needed together. By leveraging destructured imports the build system can create finer grained dependencies on Apps JSPB messages while preserving the ergonomics of path based imports.

// Good: import the exact set of symbols you need from the proto file.
import {Foo, Bar} from './foo.proto';

function copyFooBar(foo: Foo, bar: Bar) {...}

Renaming imports

Code should fix name collisions by using a namespace import or renaming the exports themselves. Code may rename imports (import {SomeThing as SomeOtherThing}) if needed.

Three examples where renaming can be helpful:

  1. If it's necessary to avoid collisions with other imported symbols.
  2. If the imported symbol name is generated.
  3. If importing symbols whose names are unclear by themselves, renaming can improve code clarity. For example, when using RxJS the from function might be more readable when renamed to observableFrom.

Exports

Use named exports in all code:

// Use named exports:
export class Foo { ... }

Do not use default exports. This ensures that all imports follow a uniform pattern.

// Do not use default exports:
export default class Foo { ... } // BAD!

Why?

Default exports provide no canonical name, which makes central maintenance difficult with relatively little benefit to code owners, including potentially decreased readability:

import Foo from './bar';  // Legal.
import Bar from './bar';  // Also legal.

Named exports have the benefit of erroring when import statements try to import something that hasn't been declared. In foo.ts:

const foo = 'blah';
export default foo;

And in bar.ts:

import {fizz} from './foo';

Results in error TS2614: Module '"./foo"' has no exported member 'fizz'. While bar.ts:

import fizz from './foo';

Results in fizz === foo, which is probably unexpected and difficult to debug.

Additionally, default exports encourage people to put everything into one big object to namespace it all together:

export default class Foo {
  static SOME_CONSTANT = ...
  static someHelpfulFunction() { ... }
  ...
}

With the above pattern, we have file scope, which can be used as a namespace. We also have a perhaps needless second scope (the class Foo) that can be ambiguously used as both a type and a value in other files.

Instead, prefer use of file scope for namespacing, as well as named exports:

export const SOME_CONSTANT = ...
export function someHelpfulFunction()
export class Foo {
  // only class stuff here
}

Export visibility

TypeScript does not support restricting the visibility for exported symbols. Only export symbols that are used outside of the module. Generally minimize the exported API surface of modules.

Mutable exports

Regardless of technical support, mutable exports can create hard to understand and debug code, in particular with re-exports across multiple modules. One way to paraphrase this style point is that export let is not allowed.

export let foo = 3;
// In pure ES6, foo is mutable and importers will observe the value change after a second.
// In TS, if foo is re-exported by a second file, importers will not see the value change.
window.setTimeout(() => {
  foo = 4;
}, 1000 /* ms */);

If one needs to support externally accessible and mutable bindings, they should instead use explicit getter functions.

let foo = 3;
window.setTimeout(() => {
  foo = 4;
}, 1000 /* ms */);
// Use an explicit getter to access the mutable export.
export function getFoo() { return foo; };

For the common pattern of conditionally exporting either of two values, first do the conditional check, then the export. Make sure that all exports are final after the module's body has executed.

function pickApi() {
  if (useOtherApi()) return OtherApi;
  return RegularApi;
}
export const SomeApi = pickApi();

Container classes

Do not create container classes with static methods or properties for the sake of namespacing.

export class Container {
  static FOO = 1;
  static bar() { return 1; }
}

Instead, export individual constants and functions:

export const FOO = 1;
export function bar() { return 1; }

Import and export type

Import type

You may use import type {...} when you use the imported symbol only as a type. Use regular imports for values:

import type {Foo} from './foo';
import {Bar} from './foo';

import {type Foo, Bar} from './foo';

Why?

The TypeScript compiler automatically handles the distinction and does not insert runtime loads for type references. So why annotate type imports?

The TypeScript compiler can run in 2 modes:

  • In development mode, we typically want quick iteration loops. The compiler transpiles to JavaScript without full type information. This is much faster, but requires import type in certain cases.
  • In production mode, we want correctness. The compiler type checks everything and ensures import type is used correctly.

Note: If you need to force a runtime load for side effects, use import '...';. See

Export type

Use export type when re-exporting a type, e.g.:

export type {AnInterface} from './foo';

Why?

export type is useful to allow type re-exports in file-by-file transpilation. See isolatedModules docs.

export type might also seem useful to avoid ever exporting a value symbol for an API. However it does not give guarantees, either: downstream code might still import an API through a different path. A better way to split & guarantee type vs value usages of an API is to actually split the symbols into e.g. UserService and AjaxUserService. This is less error prone and also better communicates intent.

Use modules not namespaces

TypeScript supports two methods to organize code: namespaces and modules, but namespaces are disallowed. That is, your code must refer to code in other files using imports and exports of the form import {foo} from 'bar';

Your code must not use the namespace Foo { ... } construct. namespaces may only be used when required to interface with external, third party code. To semantically namespace your code, use separate files.

Code must not use require (as in import x = require('...');) for imports. Use ES6 module syntax.

// Bad: do not use namespaces:
namespace Rocket {
  function launch() { ... }
}

// Bad: do not use <reference>
/// <reference path="..."/>

// Bad: do not use require()
import x = require('mydep');

NB: TypeScript namespaces used to be called internal modules and used to use the module keyword in the form module Foo { ... }. Don't use that either. Always use ES6 imports.

Language features

This section delineates which features may or may not be used, and any additional constraints on their use.

Language features which are not discussed in this style guide may be used with no recommendations of their usage.

Local variable declarations

Use const and let

Always use const or let to declare variables. Use const by default, unless a variable needs to be reassigned. Never use var.

const foo = otherValue;  // Use if "foo" never changes.
let bar = someValue;     // Use if "bar" is ever assigned into later on.

const and let are block scoped, like variables in most other languages. var in JavaScript is function scoped, which can cause difficult to understand bugs. Don't use it.

var foo = someValue;     // Don't use - var scoping is complex and causes bugs.

Variables must not be used before their declaration.

One variable per declaration

Every local variable declaration declares only one variable: declarations such as let a = 1, b = 2; are not used.

Array literals

Do not use the Array constructor

Do not use the Array() constructor, with or without new. It has confusing and contradictory usage:

const a = new Array(2); // [undefined, undefined]
const b = new Array(2, 3); // [2, 3];

Instead, always use bracket notation to initialize arrays, or from to initialize an Array with a certain size:

const a = [2];
const b = [2, 3];

// Equivalent to Array(2):
const c = [];
c.length = 2;

// [0, 0, 0, 0, 0]
Array.from<number>({length: 5}).fill(0);

Do not define properties on arrays

Do not define or use non-numeric properties on an array (other than length). Use a Map (or Object) instead.

Using spread syntax

Using spread syntax [...foo]; is a convenient shorthand for shallow-copying or concatenating iterables.

const foo = [
  1,
];

const foo2 = [
  ...foo,
  6,
  7,
];

const foo3 = [
  5,
  ...foo,
];

foo2[1] === 6;
foo3[1] === 1;

When using spread syntax, the value being spread must match what is being created. When creating an array, only spread iterables. Primitives (including null and undefined) must not be spread.

const foo = [7];
const bar = [5, ...(shouldUseFoo && foo)]; // might be undefined

// Creates {0: 'a', 1: 'b', 2: 'c'} but has no length
const fooStrings = ['a', 'b', 'c'];
const ids = {...fooStrings};
const foo = shouldUseFoo ? [7] : [];
const bar = [5, ...foo];
const fooStrings = ['a', 'b', 'c'];
const ids = [...fooStrings, 'd', 'e'];

Array destructuring

Array literals may be used on the left-hand side of an assignment to perform destructuring (such as when unpacking multiple values from a single array or iterable). A final rest element may be included (with no space between the ... and the variable name). Elements should be omitted if they are unused.

const [a, b, c, ...rest] = generateResults();
let [, b,, d] = someArray;

Destructuring may also be used for function parameters. Always specify [] as the default value if a destructured array parameter is optional, and provide default values on the left hand side:

function destructured([a = 4, b = 2] = []) { … }

Disallowed:

function badDestructuring([a, b] = [4, 2]) { … }

Tip: For (un)packing multiple values into a function’s parameter or return, prefer object destructuring to array destructuring when possible, as it allows naming the individual elements and specifying a different type for each.

Object literals

Do not use the Object constructor

The Object constructor is disallowed. Use an object literal ({} or {a: 0, b: 1, c: 2}) instead.

Iterating objects

Iterating objects with for (... in ...) is error prone. It will include enumerable properties from the prototype chain.

Do not use unfiltered for (... in ...) statements:

for (const x in someObj) {
  // x could come from some parent prototype!
}

Either filter values explicitly with an if statement, or use for (... of Object.keys(...)).

for (const x in someObj) {
  if (!someObj.hasOwnProperty(x)) continue;
  // now x was definitely defined on someObj
}
for (const x of Object.keys(someObj)) { // note: for _of_!
  // now x was definitely defined on someObj
}
for (const [key, value] of Object.entries(someObj)) { // note: for _of_!
  // now key was definitely defined on someObj
}

Using spread syntax

Using spread syntax {...bar} is a convenient shorthand for creating a shallow copy of an object. When using spread syntax in object initialization, later values replace earlier values at the same key.

const foo = {
  num: 1,
};

const foo2 = {
  ...foo,
  num: 5,
};

const foo3 = {
  num: 5,
  ...foo,
}

foo2.num === 5;
foo3.num === 1;

When using spread syntax, the value being spread must match what is being created. That is, when creating an object, only objects may be spread; arrays and primitives (including null and undefined) must not be spread. Avoid spreading objects that have prototypes other than the Object prototype (e.g. class definitions, class instances, functions) as the behavior is unintuitive (only enumerable non-prototype properties are shallow-copied).

const foo = {num: 7};
const bar = {num: 5, ...(shouldUseFoo && foo)}; // might be undefined

// Creates {0: 'a', 1: 'b', 2: 'c'} but has no length
const fooStrings = ['a', 'b', 'c'];
const ids = {...fooStrings};
const foo = shouldUseFoo ? {num: 7} : {};
const bar = {num: 5, ...foo};

Computed property names

Computed property names (e.g. {['key' + foo()]: 42}) are allowed, and are considered dict-style (quoted) keys (i.e., must not be mixed with non-quoted keys) unless the computed property is a symbol (e.g. [Symbol.iterator]).

Object destructuring

Object destructuring patterns may be used on the left-hand side of an assignment to perform destructuring and unpack multiple values from a single object.

Destructured objects may also be used as function parameters, but should be kept as simple as possible: a single level of unquoted shorthand properties. Deeper levels of nesting and computed properties may not be used in parameter destructuring. Specify any default values in the left-hand-side of the destructured parameter ({str = 'some default'} = {}, rather than {str} = {str: 'some default'}), and if a destructured object is itself optional, it must default to {}.

Example:

interface Options {
  /** The number of times to do something. */
  num?: number;

  /** A string to do stuff to. */
  str?: string;
}

function destructured({num, str = 'default'}: Options = {}) {}

Disallowed:

function nestedTooDeeply({x: {num, str}}: {x: Options}) {}
function nontrivialDefault({num, str}: Options = {num: 42, str: 'default'}) {}

Classes

Class declarations

Class declarations must not be terminated with semicolons:

class Foo {
}
class Foo {
}; // Unnecessary semicolon

In contrast, statements that contain class expressions must be terminated with a semicolon:

export const Baz = class extends Bar {
  method(): number {
    return this.x;
  }
}; // Semicolon here as this is a statement, not a declaration
exports const Baz = class extends Bar {
  method(): number {
    return this.x;
  }
}

It is neither encouraged nor discouraged to have blank lines separating class declaration braces from other class content:

// No spaces around braces - fine.
class Baz {
  method(): number {
    return this.x;
  }
}

// A single space around both braces - also fine.
class Foo {

  method(): number {
    return this.x;
  }

}

Class method declarations

Class method declarations must not use a semicolon to separate individual method declarations:

class Foo {
  doThing() {
    console.log("A");
  }
}
class Foo {
  doThing() {
    console.log("A");
  }; // <-- unnecessary
}

Method declarations should be separated from surrounding code by a single blank line:

class Foo {
  doThing() {
    console.log("A");
  }

  getOtherThing(): number {
    return 4;
  }
}
class Foo {
  doThing() {
    console.log("A");
  }
  getOtherThing(): number {
    return 4;
  }
}

Overriding toString

The toString method may be overridden, but must always succeed and never have visible side effects.

Tip: Beware, in particular, of calling other methods from toString, since exceptional conditions could lead to infinite loops.

Static methods

Avoid private static methods

Where it does not interfere with readability, prefer module-local functions over private static methods.

Do not rely on dynamic dispatch

Code should not rely on dynamic dispatch of static methods. Static methods should only be called on the base class itself (which defines it directly). Static methods should not be called on variables containing a dynamic instance that may be either the constructor or a subclass constructor (and must be defined with @nocollapse if this is done), and must not be called directly on a subclass that doesn’t define the method itself.

Disallowed:

// Context for the examples below (this class is okay by itself)
class Base {
  /** @nocollapse */ static foo() {}
}
class Sub extends Base {}

// Discouraged: don't call static methods dynamically
function callFoo(cls: typeof Base) {
  cls.foo();
}

// Disallowed: don't call static methods on subclasses that don't define it themselves
Sub.foo();

// Disallowed: don't access this in static methods.
class MyClass {
  static foo() {
    return this.staticField;
  }
}
MyClass.staticField = 1;
Avoid static this references

Code must not use this in a static context.

JavaScript allows accessing static fields through this. Different from other languages, static fields are also inherited.

class ShoeStore {
  static storage: Storage = ...;

  static isAvailable(s: Shoe) {
    // Bad: do not use `this` in a static method.
    return this.storage.has(s.id);
  }
}

class EmptyShoeStore extends ShoeStore {
  static storage: Storage = EMPTY_STORE;  // overrides storage from ShoeStore
}

Why?

This code is generally surprising: authors might not expect that static fields can be accessed through the this pointer, and might be surprised to find that they can be overridden - this feature is not commonly used.

This code also encourages an anti-pattern of having substantial static state, which causes problems with testability.

Constructors

Constructor calls must use parentheses, even when no arguments are passed:

const x = new Foo;
const x = new Foo();

Omitting parentheses can lead to subtle mistakes. These two lines are not equivalent:

new Foo().Bar();
new Foo.Bar();

It is unnecessary to provide an empty constructor or one that simply delegates into its parent class because ES2015 provides a default class constructor if one is not specified. However constructors with parameter properties, visibility modifiers or parameter decorators should not be omitted even if the body of the constructor is empty.

class UnnecessaryConstructor {
  constructor() {}
}
class UnnecessaryConstructorOverride extends Base {
    constructor(value: number) {
      super(value);
    }
}
class DefaultConstructor {
}

class ParameterProperties {
  constructor(private myService) {}
}

class ParameterDecorators {
  constructor(@SideEffectDecorator myService) {}
}

class NoInstantiation {
  private constructor() {}
}

The constructor should be separated from surrounding code both above and below by a single blank line:

class Foo {
  myField = 10;

  constructor(private readonly ctorParam) {}

  doThing() {
    console.log(ctorParam.getThing() + myField);
  }
}
class Foo {
  myField = 10;
  constructor(private readonly ctorParam) {}
  doThing() {
    console.log(ctorParam.getThing() + myField);
  }
}

Class members

No #private fields

Do not use private fields (also known as private identifiers):

class Clazz {
  #ident = 1;
}

Instead, use TypeScript's visibility annotations:

class Clazz {
  private ident = 1;
}

Why?

Private identifiers cause substantial emit size and performance regressions when down-leveled by TypeScript, and are unsupported before ES2015. They can only be downleveled to ES2015, not lower. At the same time, they do not offer substantial benefits when static type checking is used to enforce visibility.

Use readonly

Mark properties that are never reassigned outside of the constructor with the readonly modifier (these need not be deeply immutable).

Parameter properties

Rather than plumbing an obvious initializer through to a class member, use a TypeScript parameter property.

class Foo {
  private readonly barService: BarService;

  constructor(barService: BarService) {
    this.barService = barService;
  }
}
class Foo {
  constructor(private readonly barService: BarService) {}
}

If the parameter property needs documentation, use an @param JSDoc tag.

Field initializers

If a class member is not a parameter, initialize it where it's declared, which sometimes lets you drop the constructor entirely.

class Foo {
  private readonly userList: string[];

  constructor() {
    this.userList = [];
  }
}
class Foo {
  private readonly userList: string[] = [];
}

Tip: Properties should never be added to or removed from an instance after the constructor is finished, since it significantly hinders VMs’ ability to optimize classes' shape. Optional fields that may be filled in later should be explicitly initialized to undefined to prevent later shape changes.

Properties used outside of class lexical scope

Properties used from outside the lexical scope of their containing class, such as an Angular component's properties used from a template, must not use private visibility, as they are used outside of the lexical scope of their containing class.

Use either protected or public as appropriate to the property in question. Angular and AngularJS template properties should use protected, but Polymer should use public.

TypeScript code must not use obj['foo'] to bypass the visibility of a property.

Why?

When a property is private, you are declaring to both automated systems and humans that the property accesses are scoped to the methods of the declaring class, and they will rely on that. For example, a check for unused code will flag a private property that appears to be unused, even if some other file manages to bypass the visibility restriction.

Though it might appear that obj['foo'] can bypass visibility in the TypeScript compiler, this pattern can be broken by rearranging the build rules, and also violates optimization compatibility.

Getters and setters

Getters and setters, also known as accessors, for class members may be used. The getter method must be a pure function (i.e., result is consistent and has no side effects: getters must not change observable state). They are also useful as a means of restricting the visibility of internal or verbose implementation details (shown below).

class Foo {
  constructor(private readonly someService: SomeService) {}

  get someMember(): string {
    return this.someService.someVariable;
  }

  set someMember(newValue: string) {
    this.someService.someVariable = newValue;
  }
}
class Foo {
  nextId = 0;
  get next() {
    return this.nextId++; // Bad: getter changes observable state
  }
}

If an accessor is used to hide a class property, the hidden property may be prefixed or suffixed with any whole word, like internal or wrapped. When using these private properties, access the value through the accessor whenever possible. At least one accessor for a property must be non-trivial: do not define pass-through accessors only for the purpose of hiding a property. Instead, make the property public (or consider making it readonly rather than just defining a getter with no setter).

class Foo {
  private wrappedBar = '';
  get bar() {
    return this.wrappedBar || 'bar';
  }

  set bar(wrapped: string) {
    this.wrappedBar = wrapped.trim();
  }
}
class Bar {
  private barInternal = '';
  // Neither of these accessors have logic, so just make bar public.
  get bar() {
    return this.barInternal;
  }

  set bar(value: string) {
    this.barInternal = value;
  }
}

Getters and setters must not be defined using Object.defineProperty, since this interferes with property renaming.

Computed properties

Computed properties may only be used in classes when the property is a symbol. Dict-style properties (that is, quoted or computed non-symbol keys) are not allowed (see rationale for not mixing key types. A [Symbol.iterator] method should be defined for any classes that are logically iterable. Beyond this, Symbol should be used sparingly.

Tip: be careful of using any other built-in symbols (e.g. Symbol.isConcatSpreadable) as they are not polyfilled by the compiler and will therefore not work in older browsers.

Visibility

Restricting visibility of properties, methods, and entire types helps with keeping code decoupled.

  • Limit symbol visibility as much as possible.
  • Consider converting private methods to non-exported functions within the same file but outside of any class, and moving private properties into a separate, non-exported class.
  • TypeScript symbols are public by default. Never use the public modifier except when declaring non-readonly public parameter properties (in constructors).
class Foo {
  public bar = new Bar();  // BAD: public modifier not needed

  constructor(public readonly baz: Baz) {}  // BAD: readonly implies it's a property which defaults to public
}
class Foo {
  bar = new Bar();  // GOOD: public modifier not needed

  constructor(public baz: Baz) {}  // public modifier allowed
}

See also export visibility.

Disallowed class patterns

Do not manipulate prototypes directly

The class keyword allows clearer and more readable class definitions than defining prototype properties. Ordinary implementation code has no business manipulating these objects. Mixins and modifying the prototypes of builtin objects are explicitly forbidden.

Exception: Framework code (such as Polymer, or Angular) may need to use prototypes, and should not resort to even-worse workarounds to avoid doing so.

Functions

Terminology

There are many different types of functions, with subtle distinctions between them. This guide uses the following terminology, which aligns with MDN:

  • function declaration: a declaration (i.e. not an expression) using the function keyword
  • function expression: an expression, typically used in an assignment or passed as a parameter, using the function keyword
  • arrow function: an expression using the => syntax
  • block body: right hand side of an arrow function with braces
  • concise body: right hand side of an arrow function without braces

Methods and classes/constructors are not covered in this section.

Prefer function declarations for named functions

Prefer function declarations over arrow functions or function expressions when defining named functions.

function foo() {
  return 42;
}
const foo = () => 42;

Arrow functions may be used, for example, when an explicit type annotation is required.

interface SearchFunction {
  (source: string, subString: string): boolean;
}

const fooSearch: SearchFunction = (source, subString) => { ... };

Nested functions

Functions nested within other methods or functions may use function declarations or arrow functions, as appropriate. In method bodies in particular, arrow functions are preferred because they have access to the outer this.

Do not use function expressions

Do not use function expressions. Use arrow functions instead.

bar(() => { this.doSomething(); })
bar(function() { ... })

Exception: Function expressions may be used only if code has to dynamically rebind this (but this is discouraged), or for generator functions (which do not have an arrow syntax).

Arrow function bodies

Use arrow functions with concise bodies (i.e. expressions) or block bodies as appropriate.

// Top level functions use function declarations.
function someFunction() {
  // Block bodies are fine:
  const receipts = books.map((b: Book) => {
    const receipt = payMoney(b.price);
    recordTransaction(receipt);
    return receipt;
  });

  // Concise bodies are fine, too, if the return value is used:
  const longThings = myValues.filter(v => v.length > 1000).map(v => String(v));

  function payMoney(amount: number) {
    // function declarations are fine, but must not access `this`.
  }

  // Nested arrow functions may be assigned to a const.
  const computeTax = (amount: number) => amount * 0.12;
}

Only use a concise body if the return value of the function is actually used. The block body makes sure the return type is void then and prevents potential side effects.

// BAD: use a block body if the return value of the function is not used.
myPromise.then(v => console.log(v));
// BAD: this typechecks, but the return value still leaks.
let f: () => void;
f = () => 1;
// GOOD: return value is unused, use a block body.
myPromise.then(v => {
  console.log(v);
});
// GOOD: code may use blocks for readability.
const transformed = [1, 2, 3].map(v => {
  const intermediate = someComplicatedExpr(v);
  const more = acrossManyLines(intermediate);
  return worthWrapping(more);
});
// GOOD: explicit `void` ensures no leaked return value
myPromise.then(v => void console.log(v));

Tip: The void operator can be used to ensure an arrow function with an expression body returns undefined when the result is unused.

Rebinding this

Function expressions and function declarations must not use this unless they specifically exist to rebind the this pointer. Rebinding this can in most cases be avoided by using arrow functions or explicit parameters.

function clickHandler() {
  // Bad: what's `this` in this context?
  this.textContent = 'Hello';
}
// Bad: the `this` pointer reference is implicitly set to document.body.
document.body.onclick = clickHandler;
// Good: explicitly reference the object from an arrow function.
document.body.onclick = () => { document.body.textContent = 'hello'; };
// Alternatively: take an explicit parameter
const setTextFn = (e: HTMLElement) => { e.textContent = 'hello'; };
document.body.onclick = setTextFn.bind(null, document.body);

Prefer arrow functions over other approaches to binding this, such as f.bind(this), goog.bind(f, this), or const self = this.

Prefer passing arrow functions as callbacks

Callbacks can be invoked with unexpected arguments that can pass a type check but still result in logical errors.

Avoid passing a named callback to a higher-order function, unless you are sure of the stability of both functions' call signatures. Beware, in particular, of less-commonly-used optional parameters.

// BAD: Arguments are not explicitly passed, leading to unintended behavior
// when the optional `radix` argument gets the array indices 0, 1, and 2.
const numbers = ['11', '5', '10'].map(parseInt);
// > [11, NaN, 2];

Instead, prefer passing an arrow-function that explicitly forwards parameters to the named callback.

// GOOD: Arguments are explicitly passed to the callback
const numbers = ['11', '5', '3'].map((n) => parseInt(n));
// > [11, 5, 3]

// GOOD: Function is locally defined and is designed to be used as a callback
function dayFilter(element: string|null|undefined) {
  return element != null && element.endsWith('day');
}

const days = ['tuesday', undefined, 'juice', 'wednesday'].filter(dayFilter);

Arrow functions as properties

Classes usually should not contain properties initialized to arrow functions. Arrow function properties require the calling function to understand that the callee's this is already bound, which increases confusion about what this is, and call sites and references using such handlers look broken (i.e. require non-local knowledge to determine that they are correct). Code should always use arrow functions to call instance methods (const handler = (x) => { this.listener(x); };), and should not obtain or pass references to instance methods (const handler = this.listener; handler(x);).

Note: in some specific situations, e.g. when binding functions in a template, arrow functions as properties are useful and create much more readable code. Use judgement with this rule. Also, see the Event Handlers section below.

class DelayHandler {
  constructor() {
    // Problem: `this` is not preserved in the callback. `this` in the callback
    // will not be an instance of DelayHandler.
    setTimeout(this.patienceTracker, 5000);
  }
  private patienceTracker() {
    this.waitedPatiently = true;
  }
}
// Arrow functions usually should not be properties.
class DelayHandler {
  constructor() {
    // Bad: this code looks like it forgot to bind `this`.
    setTimeout(this.patienceTracker, 5000);
  }
  private patienceTracker = () => {
    this.waitedPatiently = true;
  }
}
// Explicitly manage `this` at call time.
class DelayHandler {
  constructor() {
    // Use anonymous functions if possible.
    setTimeout(() => {
      this.patienceTracker();
    }, 5000);
  }
  private patienceTracker() {
    this.waitedPatiently = true;
  }
}

Event handlers

Event handlers may use arrow functions when there is no need to uninstall the handler (for example, if the event is emitted by the class itself). If the handler requires uninstallation, arrow function properties are the right approach, because they automatically capture this and provide a stable reference to uninstall.

// Event handlers may be anonymous functions or arrow function properties.
class Component {
  onAttached() {
    // The event is emitted by this class, no need to uninstall.
    this.addEventListener('click', () => {
      this.listener();
    });
    // this.listener is a stable reference, we can uninstall it later.
    window.addEventListener('onbeforeunload', this.listener);
  }
  onDetached() {
    // The event is emitted by window. If we don't uninstall, this.listener will
    // keep a reference to `this` because it's bound, causing a memory leak.
    window.removeEventListener('onbeforeunload', this.listener);
  }
  // An arrow function stored in a property is bound to `this` automatically.
  private listener = () => {
    confirm('Do you want to exit the page?');
  }
}

Do not use bind in the expression that installs an event handler, because it creates a temporary reference that can't be uninstalled.

// Binding listeners creates a temporary reference that prevents uninstalling.
class Component {
  onAttached() {
    // This creates a temporary reference that we won't be able to uninstall
    window.addEventListener('onbeforeunload', this.listener.bind(this));
  }
  onDetached() {
    // This bind creates a different reference, so this line does nothing.
    window.removeEventListener('onbeforeunload', this.listener.bind(this));
  }
  private listener() {
    confirm('Do you want to exit the page?');
  }
}

Parameter initializers

Optional function parameters may be given a default initializer to use when the argument is omitted. Initializers must not have any observable side effects. Initializers should be kept as simple as possible.

function process(name: string, extraContext: string[] = []) {}
function activate(index = 0) {}
// BAD: side effect of incrementing the counter
let globalCounter = 0;
function newId(index = globalCounter++) {}

// BAD: exposes shared mutable state, which can introduce unintended coupling
// between function calls
class Foo {
  private readonly defaultPaths: string[];
  frobnicate(paths = defaultPaths) {}
}

Use default parameters sparingly. Prefer destructuring to create readable APIs when there are more than a small handful of optional parameters that do not have a natural order.

Prefer rest and spread when appropriate

Use a rest parameter instead of accessing arguments. Never name a local variable or parameter arguments, which confusingly shadows the built-in name.

function variadic(array: string[], ...numbers: number[]) {}

Use function spread syntax instead of Function.prototype.apply.

Formatting functions

Blank lines at the start or end of the function body are not allowed.

A single blank line may be used within function bodies sparingly to create logical groupings of statements.

Generators should attach the * to the function and yield keywords, as in function* foo() and yield* iter, rather than function *foo() or yield *iter.

Parentheses around the left-hand side of a single-argument arrow function are recommended but not required.

Do not put a space after the ... in rest or spread syntax.

function myFunction(...elements: number[]) {}
myFunction(...array, ...iterable, ...generator());

this

Only use this in class constructors and methods, functions that have an explicit this type declared (e.g. function func(this: ThisType, ...)), or in arrow functions defined in a scope where this may be used.

Never use this to refer to the global object, the context of an eval, the target of an event, or unnecessarily call()ed or apply()ed functions.

this.alert('Hello');

Interfaces

Primitive literals

String literals

Use single quotes

Ordinary string literals are delimited with single quotes ('), rather than double quotes (").

Tip: if a string contains a single quote character, consider using a template string to avoid having to escape the quote.

No line continuations

Do not use line continuations (that is, ending a line inside a string literal with a backslash) in either ordinary or template string literals. Even though ES5 allows this, it can lead to tricky errors if any trailing whitespace comes after the slash, and is less obvious to readers.

Disallowed:

const LONG_STRING = 'This is a very very very very very very very long string. \
    It inadvertently contains long stretches of spaces due to how the \
    continued lines are indented.';

Instead, write

const LONG_STRING = 'This is a very very very very very very long string. ' +
    'It does not contain long stretches of spaces because it uses ' +
    'concatenated strings.';
const SINGLE_STRING =
    'http://it.is.also/acceptable_to_use_a_single_long_string_when_breaking_would_hinder_search_discoverability';

Template literals

Use template literals (delimited with `) over complex string concatenation, particularly if multiple string literals are involved. Template literals may span multiple lines.

If a template literal spans multiple lines, it does not need to follow the indentation of the enclosing block, though it may if the added whitespace does not matter.

Example:

function arithmetic(a: number, b: number) {
  return `Here is a table of arithmetic operations:
${a} + ${b} = ${a + b}
${a} - ${b} = ${a - b}
${a} * ${b} = ${a * b}
${a} / ${b} = ${a / b}`;
}

Number literals

Numbers may be specified in decimal, hex, octal, or binary. Use exactly 0x, 0o, and 0b prefixes, with lowercase letters, for hex, octal, and binary, respectively. Never include a leading zero unless it is immediately followed by x, o, or b.

Type coercion

TypeScript code may use the String() and Boolean() (note: no new!) functions, string template literals, or !! to coerce types.

const bool = Boolean(false);
const str = String(aNumber);
const bool2 = !!str;
const str2 = `result: ${bool2}`;

Values of enum types (including unions of enum types and other types) must not be converted to booleans with Boolean() or !!, and must instead be compared explicitly with comparison operators.

enum SupportLevel {
  NONE,
  BASIC,
  ADVANCED,
}

const level: SupportLevel = ...;
let enabled = Boolean(level);

const maybeLevel: SupportLevel|undefined = ...;
enabled = !!maybeLevel;
enum SupportLevel {
  NONE,
  BASIC,
  ADVANCED,
}

const level: SupportLevel = ...;
let enabled = level !== SupportLevel.NONE;

const maybeLevel: SupportLevel|undefined = ...;
enabled = level !== undefined && level !== SupportLevel.NONE;

Why?

For most purposes, it doesn't matter what number or string value an enum name is mapped to at runtime, because values of enum types are referred to by name in source code. Consequently, engineers are accustomed to not thinking about this, and so situations where it does matter are undesirable because they will be surprising. Such is the case with conversion of enums to booleans; in particular, by default, the first declared enum value is falsy (because it is 0) while the others are truthy, which is likely to be unexpected. Readers of code that uses an enum value may not even know whether it's the first declared value or not.

Using string concatenation to cast to string is discouraged, as we check that operands to the plus operator are of matching types.

Code must use Number() to parse numeric values, and must check its return for NaN values explicitly, unless failing to parse is impossible from context.

Note: Number(''), Number(' '), and Number('\t') would return 0 instead of NaN. Number('Infinity') and Number('-Infinity') would return Infinity and -Infinity respectively. Additionally, exponential notation such as Number('1e+309') and Number('-1e+309') can overflow into Infinity. These cases may require special handling.

const aNumber = Number('123');
if (!isFinite(aNumber)) throw new Error(...);

Code must not use unary plus (+) to coerce strings to numbers. Parsing numbers can fail, has surprising corner cases, and can be a code smell (parsing at the wrong layer). A unary plus is too easy to miss in code reviews given this.

const x = +y;

Code also must not use parseInt or parseFloat to parse numbers, except for non-base-10 strings (see below). Both of those functions ignore trailing characters in the string, which can shadow error conditions (e.g. parsing 12 dwarves as 12).

const n = parseInt(someString, 10);  // Error prone,
const f = parseFloat(someString);    // regardless of passing a radix.

Code that requires parsing with a radix must check that its input contains only appropriate digits for that radix before calling into parseInt;

if (!/^[a-fA-F0-9]+$/.test(someString)) throw new Error(...);
// Needed to parse hexadecimal.
// tslint:disable-next-line:ban
const n = parseInt(someString, 16);  // Only allowed for radix != 10

Use Number() followed by Math.floor or Math.trunc (where available) to parse integer numbers:

let f = Number(someString);
if (isNaN(f)) handleError();
f = Math.floor(f);

Implicit coercion

Do not use explicit boolean coercions in conditional clauses that have implicit boolean coercion. Those are the conditions in an if, for and while statements.

const foo: MyInterface|null = ...;
if (!!foo) {...}
while (!!foo) {...}
const foo: MyInterface|null = ...;
if (foo) {...}
while (foo) {...}

As with explicit conversions, values of enum types (including unions of enum types and other types) must not be implicitly coerced to booleans, and must instead be compared explicitly with comparison operators.

enum SupportLevel {
  NONE,
  BASIC,
  ADVANCED,
}

const level: SupportLevel = ...;
if (level) {...}

const maybeLevel: SupportLevel|undefined = ...;
if (level) {...}
enum SupportLevel {
  NONE,
  BASIC,
  ADVANCED,
}

const level: SupportLevel = ...;
if (level !== SupportLevel.NONE) {...}

const maybeLevel: SupportLevel|undefined = ...;
if (level !== undefined && level !== SupportLevel.NONE) {...}

Other types of values may be either implicitly coerced to booleans or compared explicitly with comparison operators:

// Explicitly comparing > 0 is OK:
if (arr.length > 0) {...}
// so is relying on boolean coercion:
if (arr.length) {...}

Control structures

Control flow statements and blocks

Control flow statements (if, else, for, do, while, etc) always use braced blocks for the containing code, even if the body contains only a single statement. The first statement of a non-empty block must begin on its own line.

for (let i = 0; i < x; i++) {
  doSomethingWith(i);
}

if (x) {
  doSomethingWithALongMethodNameThatForcesANewLine(x);
}
if (x)
  doSomethingWithALongMethodNameThatForcesANewLine(x);

for (let i = 0; i < x; i++) doSomethingWith(i);

Exception: if statements fitting on one line may elide the block.

if (x) x.doFoo();
Assignment in control statements

Prefer to avoid assignment of variables inside control statements. Assignment can be easily mistaken for equality checks inside control statements.

if (x = someFunction()) {
  // Assignment easily mistaken with equality check
  // ...
}
x = someFunction();
if (x) {
  // ...
}

In cases where assignment inside the control statement is preferred, enclose the assignment in additional parenthesis to indicate it is intentional.

while ((x = someFunction())) {
  // Double parenthesis shows assignment is intentional
  // ...
}

Iterating containers

Prefer for (... of someArr) to iterate over arrays. Array.prototype.forEach and vanilla for loops are also allowed:

for (const x of someArr) {
  // x is a value of someArr.
}

for (let i = 0; i < someArr.length; i++) {
  // Explicitly count if the index is needed, otherwise use the for/of form.
  const x = someArr[i];
  // ...
}
for (const [i, x] of someArr.entries()) {
  // Alternative version of the above.
}

for-in loops may only be used on dict-style objects (see below for more info). Do not use for (... in ...) to iterate over arrays as it will counterintuitively give the array's indices (as strings!), not values:

for (const x in someArray) {
  // x is the index!
}

Object.prototype.hasOwnProperty should be used in for-in loops to exclude unwanted prototype properties. Prefer for-of with Object.keys, Object.values, or Object.entries over for-in when possible.

for (const key in obj) {
  if (!obj.hasOwnProperty(key)) continue;
  doWork(key, obj[key]);
}
for (const key of Object.keys(obj)) {
  doWork(key, obj[key]);
}
for (const value of Object.values(obj)) {
  doWorkValOnly(value);
}
for (const [key, value] of Object.entries(obj)) {
  doWork(key, value);
}

Grouping parentheses

Optional grouping parentheses are omitted only when the author and reviewer agree that there is no reasonable chance that the code will be misinterpreted without them, nor would they have made the code easier to read. It is not reasonable to assume that every reader has the entire operator precedence table memorized.

Do not use unnecessary parentheses around the entire expression following delete, typeof, void, return, throw, case, in, of, or yield.

Exception handling

Exceptions are an important part of the language and should be used whenever exceptional cases occur.

Custom exceptions provide a great way to convey additional error information from functions. They should be defined and used wherever the native Error type is insufficient.

Prefer throwing exceptions over ad-hoc error-handling approaches (such as passing an error container reference type, or returning an object with an error property).

Instantiate errors using new

Always use new Error() when instantiating exceptions, instead of just calling Error(). Both forms create a new Error instance, but using new is more consistent with how other objects are instantiated.

throw new Error('Foo is not a valid bar.');
throw Error('Foo is not a valid bar.');
Only throw errors

JavaScript (and thus TypeScript) allow throwing or rejecting a Promise with arbitrary values. However if the thrown or rejected value is not an Error, it does not populate stack trace information, making debugging hard. This treatment extends to Promise rejection values as Promise.reject(obj) is equivalent to throw obj; in async functions.

// bad: does not get a stack trace.
throw 'oh noes!';
// For promises
new Promise((resolve, reject) => void reject('oh noes!'));
Promise.reject();
Promise.reject('oh noes!');

Instead, only throw (subclasses of) Error:

// Throw only Errors
throw new Error('oh noes!');
// ... or subtypes of Error.
class MyError extends Error {}
throw new MyError('my oh noes!');
// For promises
new Promise((resolve) => resolve()); // No reject is OK.
new Promise((resolve, reject) => void reject(new Error('oh noes!')));
Promise.reject(new Error('oh noes!'));
Catching and rethrowing

When catching errors, code should assume that all thrown errors are instances of Error.

function assertIsError(e: unknown): asserts e is Error {
  if (!(e instanceof Error)) throw new Error("e is not an Error");
}

try {
  doSomething();
} catch (e: unknown) {
  // All thrown errors must be Error subtypes. Do not handle
  // other possible values unless you know they are thrown.
  assertIsError(e);
  displayError(e.message);
  // or rethrow:
  throw e;
}

Exception handlers must not defensively handle non-Error types unless the called API is conclusively known to throw non-Errors in violation of the above rule. In that case, a comment should be included to specifically identify where the non-Errors originate.

try {
  badApiThrowingStrings();
} catch (e: unknown) {
  // Note: bad API throws strings instead of errors.
  if (typeof e === 'string') { ... }
}

Why?

Avoid overly defensive programming. Repeating the same defenses against a problem that will not exist in most code leads to boiler-plate code that is not useful.

Empty catch blocks

It is very rarely correct to do nothing in response to a caught exception. When it truly is appropriate to take no action whatsoever in a catch block, the reason this is justified is explained in a comment.

  try {
    return handleNumericResponse(response);
  } catch (e: unknown) {
    // Response is not numeric. Continue to handle as text.
  }
  return handleTextResponse(response);

Disallowed:

  try {
    shouldFail();
    fail('expected an error');
  } catch (expected: unknown) {
  }

Tip: Unlike in some other languages, patterns like the above simply don’t work since this will catch the error thrown by fail. Use assertThrows() instead.

Switch statements

All switch statements must contain a default statement group, even if it contains no code. The default statement group must be last.

switch (x) {
  case Y:
    doSomethingElse();
    break;
  default:
    // nothing to do.
}

Within a switch block, each statement group either terminates abruptly with a break, a return statement, or by throwing an exception. Non-empty statement groups (case ...) must not fall through (enforced by the compiler):

switch (x) {
  case X:
    doSomething();
    // fall through - not allowed!
  case Y:
    // ...
}

Empty statement groups are allowed to fall through:

switch (x) {
  case X:
  case Y:
    doSomething();
    break;
  default: // nothing to do.
}

Equality checks

Always use triple equals (===) and not equals (!==). The double equality operators cause error prone type coercions that are hard to understand and slower to implement for JavaScript Virtual Machines. See also the JavaScript equality table.

if (foo == 'bar' || baz != bam) {
  // Hard to understand behaviour due to type coercion.
}
if (foo === 'bar' || baz !== bam) {
  // All good here.
}

Exception: Comparisons to the literal null value may use the == and != operators to cover both null and undefined values.

if (foo == null) {
  // Will trigger when foo is null or undefined.
}

Type and non-nullability assertions

Type assertions (x as SomeType) and non-nullability assertions (y!) are unsafe. Both only silence the TypeScript compiler, but do not insert any runtime checks to match these assertions, so they can cause your program to crash at runtime.

Because of this, you should not use type and non-nullability assertions without an obvious or explicit reason for doing so.

Instead of the following:

(x as Foo).foo();

y!.bar();

When you want to assert a type or non-nullability the best answer is to explicitly write a runtime check that performs that check.

// assuming Foo is a class.
if (x instanceof Foo) {
  x.foo();
}

if (y) {
  y.bar();
}

Sometimes due to some local property of your code you can be sure that the assertion form is safe. In those situations, you should add clarification to explain why you are ok with the unsafe behavior:

// x is a Foo, because ...
(x as Foo).foo();

// y cannot be null, because ...
y!.bar();

If the reasoning behind a type or non-nullability assertion is obvious, the comments may not be necessary. For example, generated proto code is always nullable, but perhaps it is well-known in the context of the code that certain fields are always provided by the backend. Use your judgement.

Type assertion syntax

Type assertions must use the as syntax (as opposed to the angle brackets syntax). This enforces parentheses around the assertion when accessing a member.

const x = (<Foo>z).length;
const y = <Foo>z.length;
// z must be Foo because ...
const x = (z as Foo).length;
Double assertions

From the TypeScript handbook, TypeScript only allows type assertions which convert to a more specific or less specific version of a type. Adding a type assertion (x as Foo) which does not meet this criteria will give the error: Conversion of type 'X' to type 'Y' may be a mistake because neither type sufficiently overlaps with the other.

If you are sure an assertion is safe, you can perform a double assertion. This involves casting through unknown since it is less specific than all types.

// x is a Foo here, because...
(x as unknown as Foo).fooMethod();

Use unknown (instead of any or {}) as the intermediate type.

Type assertions and object literals

Use type annotations (: Foo) instead of type assertions (as Foo) to specify the type of an object literal. This allows detecting refactoring bugs when the fields of an interface change over time.

interface Foo {
  bar: number;
  baz?: string;  // was "bam", but later renamed to "baz".
}

const foo = {
  bar: 123,
  bam: 'abc',  // no error!
} as Foo;

function func() {
  return {
    bar: 123,
    bam: 'abc',  // no error!
  } as Foo;
}
interface Foo {
  bar: number;
  baz?: string;
}

const foo: Foo = {
  bar: 123,
  bam: 'abc',  // complains about "bam" not being defined on Foo.
};

function func(): Foo {
  return {
    bar: 123,
    bam: 'abc',   // complains about "bam" not being defined on Foo.
  };
}

Keep try blocks focused

Limit the amount of code inside a try block, if this can be done without hurting readability.

try {
  const result = methodThatMayThrow();
  use(result);
} catch (error: unknown) {
  // ...
}
let result;
try {
  result = methodThatMayThrow();
} catch (error: unknown) {
  // ...
}
use(result);

Moving the non-throwable lines out of the try/catch block helps the reader learn which method throws exceptions. Some inline calls that do not throw exceptions could stay inside because they might not be worth the extra complication of a temporary variable.

Exception: There may be performance issues if try blocks are inside a loop. Widening try blocks to cover a whole loop is ok.

Decorators

Decorators are syntax with an @ prefix, like @MyDecorator.

Do not define new decorators. Only use the decorators defined by frameworks:

  • Angular (e.g. @Component, @NgModule, etc.)
  • Polymer (e.g. @property)

Why?

We generally want to avoid decorators, because they were an experimental feature that have since diverged from the TC39 proposal and have known bugs that won't be fixed.

When using decorators, the decorator must immediately precede the symbol it decorates, with no empty lines between:

/** JSDoc comments go before decorators */
@Component({...})  // Note: no empty line after the decorator.
class MyComp {
  @Input() myField: string;  // Decorators on fields may be on the same line...

  @Input()
  myOtherField: string;  // ... or wrap.
}

Disallowed features

Wrapper objects for primitive types

TypeScript code must not instantiate the wrapper classes for the primitive types String, Boolean, and Number. Wrapper classes have surprising behavior, such as new Boolean(false) evaluating to true.

const s = new String('hello');
const b = new Boolean(false);
const n = new Number(5);

The wrappers may be called as functions for coercing (which is preferred over using + or concatenating the empty string) or creating symbols. See type coercion for more information.

Automatic Semicolon Insertion

Do not rely on Automatic Semicolon Insertion (ASI). Explicitly end all statements using a semicolon. This prevents bugs due to incorrect semicolon insertions and ensures compatibility with tools with limited ASI support (e.g. clang-format).

Const enums

Code must not use const enum; use plain enum instead.

Why?

TypeScript enums already cannot be mutated; const enum is a separate language feature related to optimization that makes the enum invisible to JavaScript users of the module.

Debugger statements

Debugger statements must not be included in production code.

function debugMe() {
  debugger;
}

with

Do not use the with keyword. It makes your code harder to understand and has been banned in strict mode since ES5.

Dynamic code evaluation

Do not use eval or the Function(...string) constructor (except for code loaders). These features are potentially dangerous and simply do not work in environments using strict Content Security Policies.

Non-standard features

Do not use non-standard ECMAScript or Web Platform features.

This includes:

  • Old features that have been marked deprecated or removed entirely from ECMAScript / the Web Platform (see MDN)
  • New ECMAScript features that are not yet standardized
    • Avoid using features that are in current TC39 working draft or currently in the proposal process
    • Use only ECMAScript features defined in the current ECMA-262 specification
  • Proposed but not-yet-complete web standards:
  • Non-standard language “extensions” (such as those provided by some external transpilers)

Projects targeting specific JavaScript runtimes, such as latest-Chrome-only, Chrome extensions, Node.JS, Electron, can obviously use those APIs. Use caution when considering an API surface that is proprietary and only implemented in some browsers; consider whether there is a common library that can abstract this API surface away for you.

Modifying builtin objects

Never modify builtin types, either by adding methods to their constructors or to their prototypes. Avoid depending on libraries that do this.

Do not add symbols to the global object unless absolutely necessary (e.g. required by a third-party API).

Naming

Identifiers

Identifiers must use only ASCII letters, digits, underscores (for constants and structured test method names), and (rarely) the '$' sign.

Naming style

TypeScript expresses information in types, so names should not be decorated with information that is included in the type. (See also Testing Blog for more about what not to include.)

Some concrete examples of this rule:

  • Do not use trailing or leading underscores for private properties or methods.
  • Do not use the opt_ prefix for optional parameters.
  • Do not mark interfaces specially (IMyInterface or MyFooInterface) unless it's idiomatic in its environment. When introducing an interface for a class, give it a name that expresses why the interface exists in the first place (e.g. class TodoItem and interface TodoItemStorage if the interface expresses the format used for storage/serialization in JSON).
  • Suffixing Observables with $ is a common external convention and can help resolve confusion regarding observable values vs concrete values. Judgement on whether this is a useful convention is left up to individual teams, but should be consistent within projects.

Descriptive names

Names must be descriptive and clear to a new reader. Do not use abbreviations that are ambiguous or unfamiliar to readers outside your project, and do not abbreviate by deleting letters within a word.

  • Exception: Variables that are in scope for 10 lines or fewer, including arguments that are not part of an exported API, may use short (e.g. single letter) variable names.
// Good identifiers:
errorCount          // No abbreviation.
dnsConnectionIndex  // Most people know what "DNS" stands for.
referrerUrl         // Ditto for "URL".
customerId          // "Id" is both ubiquitous and unlikely to be misunderstood.
// Disallowed identifiers:
n                   // Meaningless.
nErr                // Ambiguous abbreviation.
nCompConns          // Ambiguous abbreviation.
wgcConnections      // Only your group knows what this stands for.
pcReader            // Lots of things can be abbreviated "pc".
cstmrId             // Deletes internal letters.
kSecondsPerDay      // Do not use Hungarian notation.
customerID          // Incorrect camelcase of "ID".

Camel case

Treat abbreviations like acronyms in names as whole words, i.e. use loadHttpUrl, not loadHTTPURL, unless required by a platform name (e.g. XMLHttpRequest).

Dollar sign

Identifiers should not generally use $, except when required by naming conventions for third party frameworks. See above for more on using $ with Observable values.

Rules by identifier type

Most identifier names should follow the casing in the table below, based on the identifier's type.

Style Category
UpperCamelCase class / interface / type / enum / decorator / type parameters / component functions in TSX / JSXElement type parameter
lowerCamelCase variable / parameter / function / method / property / module alias
CONSTANT_CASE global constant values, including enum values. See Constants below.
#ident private identifiers are never used.

Type parameters

Type parameters, like in Array<T>, may use a single upper case character (T) or UpperCamelCase.

Test names

Test method names inxUnit-style test frameworks may be structured with _ separators, e.g. testX_whenY_doesZ().

_ prefix/suffix

Identifiers must not use _ as a prefix or suffix.

This also means that _ must not be used as an identifier by itself (e.g. to indicate a parameter is unused).

Tip: If you only need some of the elements from an array (or TypeScript tuple), you can insert extra commas in a destructuring statement to ignore in-between elements:

const [a, , b] = [1, 5, 10];  // a <- 1, b <- 10

Imports

Module namespace imports are lowerCamelCase while files are snake_case, which means that imports correctly will not match in casing style, such as

import * as fooBar from './foo_bar';

Some libraries might commonly use a namespace import prefix that violates this naming scheme, but overbearingly common open source use makes the violating style more readable. The only libraries that currently fall under this exception are:

Constants

Immutable: CONSTANT_CASE indicates that a value is intended to not be changed, and may be used for values that can technically be modified (i.e. values that are not deeply frozen) to indicate to users that they must not be modified.

const UNIT_SUFFIXES = {
  'milliseconds': 'ms',
  'seconds': 's',
};
// Even though per the rules of JavaScript UNIT_SUFFIXES is
// mutable, the uppercase shows users to not modify it.

A constant can also be a static readonly property of a class.

class Foo {
  private static readonly MY_SPECIAL_NUMBER = 5;

  bar() {
    return 2 * Foo.MY_SPECIAL_NUMBER;
  }
}

Global: Only symbols declared on the module level, static fields of module level classes, and values of module level enums, may use CONST_CASE. If a value can be instantiated more than once over the lifetime of the program (e.g. a local variable declared within a function, or a static field on a class nested in a function) then it must use lowerCamelCase.

If a value is an arrow function that implements an interface, then it may be declared lowerCamelCase.

Aliases

When creating a local-scope alias of an existing symbol, use the format of the existing identifier. The local alias must match the existing naming and format of the source. For variables use const for your local aliases, and for class fields use the readonly attribute.

Note: If you're creating an alias just to expose it to a template in your framework of choice, remember to also apply the proper access modifiers.

const {BrewStateEnum} = SomeType;
const CAPACITY = 5;

class Teapot {
  readonly BrewStateEnum = BrewStateEnum;
  readonly CAPACITY = CAPACITY;
}

Type system

Type inference

Code may rely on type inference as implemented by the TypeScript compiler for all type expressions (variables, fields, return types, etc).

const x = 15;  // Type inferred.

Leave out type annotations for trivially inferred types: variables or parameters initialized to a string, number, boolean, RegExp literal or new expression.

const x: boolean = true;  // Bad: 'boolean' here does not aid readability
// Bad: 'Set' is trivially inferred from the initialization
const x: Set<string> = new Set();

Explicitly specifying types may be required to prevent generic type parameters from being inferred as unknown. For example, initializing generic types with no values (e.g. empty arrays, objects, Maps, or Sets).

const x = new Set<string>();

For more complex expressions, type annotations can help with readability of the program:

// Hard to reason about the type of 'value' without an annotation.
const value = await rpc.getSomeValue().transform();
// Can tell the type of 'value' at a glance.
const value: string[] = await rpc.getSomeValue().transform();

Whether an annotation is required is decided by the code reviewer.

Return types

Whether to include return type annotations for functions and methods is up to the code author. Reviewers may ask for annotations to clarify complex return types that are hard to understand. Projects may have a local policy to always require return types, but this is not a general TypeScript style requirement.

There are two benefits to explicitly typing out the implicit return values of functions and methods:

  • More precise documentation to benefit readers of the code.
  • Surface potential type errors faster in the future if there are code changes that change the return type of the function.

Undefined and null

TypeScript supports undefined and null types. Nullable types can be constructed as a union type (string|null); similarly with undefined. There is no special syntax for unions of undefined and null.

TypeScript code can use either undefined or null to denote absence of a value, there is no general guidance to prefer one over the other. Many JavaScript APIs use undefined (e.g. Map.get), while many DOM and Google APIs use null (e.g. Element.getAttribute), so the appropriate absent value depends on the context.

Nullable/undefined type aliases

Type aliases must not include |null or |undefined in a union type. Nullable aliases typically indicate that null values are being passed around through too many layers of an application, and this clouds the source of the original issue that resulted in null. They also make it unclear when specific values on a class or interface might be absent.

Instead, code must only add |null or |undefined when the alias is actually used. Code should deal with null values close to where they arise, using the above techniques.

// Bad
type CoffeeResponse = Latte|Americano|undefined;

class CoffeeService {
  getLatte(): CoffeeResponse { ... };
}
// Better
type CoffeeResponse = Latte|Americano;

class CoffeeService {
  getLatte(): CoffeeResponse|undefined { ... };
}

Prefer optional over |undefined

In addition, TypeScript supports a special construct for optional parameters and fields, using ?:

interface CoffeeOrder {
  sugarCubes: number;
  milk?: Whole|LowFat|HalfHalf;
}

function pourCoffee(volume?: Milliliter) { ... }

Optional parameters implicitly include |undefined in their type. However, they are different in that they can be left out when constructing a value or calling a method. For example, {sugarCubes: 1} is a valid CoffeeOrder because milk is optional.

Use optional fields (on interfaces or classes) and parameters rather than a |undefined type.

For classes preferably avoid this pattern altogether and initialize as many fields as possible.

class MyClass {
  field = '';
}

Use structural types

TypeScript's type system is structural, not nominal. That is, a value matches a type if it has at least all the properties the type requires and the properties' types match, recursively.

When providing a structural-based implementation, explicitly include the type at the declaration of the symbol (this allows more precise type checking and error reporting).

const foo: Foo = {
  a: 123,
  b: 'abc',
}
const badFoo = {
  a: 123,
  b: 'abc',
}

Use interfaces to define structural types, not classes

interface Foo {
  a: number;
  b: string;
}

const foo: Foo = {
  a: 123,
  b: 'abc',
}
class Foo {
  readonly a: number;
  readonly b: number;
}

const foo: Foo = {
  a: 123,
  b: 'abc',
}

Why?

The badFoo object above relies on type inference. Additional fields could be added to badFoo and the type is inferred based on the object itself.

When passing a badFoo to a function that takes a Foo, the error will be at the function call site, rather than at the object declaration site. This is also useful when changing the surface of an interface across broad codebases.

interface Animal {
  sound: string;
  name: string;
}

function makeSound(animal: Animal) {}

/**
 * 'cat' has an inferred type of '{sound: string}'
 */
const cat = {
  sound: 'meow',
};

/**
 * 'cat' does not meet the type contract required for the function, so the
 * TypeScript compiler errors here, which may be very far from where 'cat' is
 * defined.
 */
makeSound(cat);

/**
 * Horse has a structural type and the type error shows here rather than the
 * function call.  'horse' does not meet the type contract of 'Animal'.
 */
const horse: Animal = {
  sound: 'niegh',
};

const dog: Animal = {
  sound: 'bark',
  name: 'MrPickles',
};

makeSound(dog);
makeSound(horse);

Prefer interfaces over type literal aliases

TypeScript supports type aliases for naming a type expression. This can be used to name primitives, unions, tuples, and any other types.

However, when declaring types for objects, use interfaces instead of a type alias for the object literal expression.

interface User {
  firstName: string;
  lastName: string;
}
type User = {
  firstName: string,
  lastName: string,
}

Why?

These forms are nearly equivalent, so under the principle of just choosing one out of two forms to prevent variation, we should choose one. Additionally, there are also interesting technical reasons to prefer interface. That page quotes the TypeScript team lead: Honestly, my take is that it should really just be interfaces for anything that they can model. There is no benefit to type aliases when there are so many issues around display/perf.

Array<T> Type

For simple types (containing just alphanumeric characters and dot), use the syntax sugar for arrays, T[] or readonly T[], rather than the longer form Array<T> or ReadonlyArray<T>.

For multi-dimensional non-readonly arrays of simple types, use the syntax sugar form (T[][], T[][][], and so on) rather than the longer form.

For anything more complex, use the longer form Array<T>.

These rules apply at each level of nesting, i.e. a simple T[] nested in a more complex type would still be spelled as T[], using the syntax sugar.

let a: string[];
let b: readonly string[];
let c: ns.MyObj[];
let d: string[][];
let e: Array<{n: number, s: string}>;
let f: Array<string|number>;
let g: ReadonlyArray<string|number>;
let h: InjectionToken<string[]>;  // Use syntax sugar for nested types.
let i: ReadonlyArray<string[]>;
let j: Array<readonly string[]>;
let a: Array<string>;  // The syntax sugar is shorter.
let b: ReadonlyArray<string>;
let c: Array<ns.MyObj>;
let d: Array<string[]>;
let e: {n: number, s: string}[];  // The braces make it harder to read.
let f: (string|number)[];         // Likewise with parens.
let g: readonly (string | number)[];
let h: InjectionToken<Array<string>>;
let i: readonly string[][];
let j: (readonly string[])[];

Indexable types / index signatures ({[key: string]: T})

In JavaScript, it's common to use an object as an associative array (aka map, hash, or dict). Such objects can be typed using an index signature ([k: string]: T) in TypeScript:

const fileSizes: {[fileName: string]: number} = {};
fileSizes['readme.txt'] = 541;

In TypeScript, provide a meaningful label for the key. (The label only exists for documentation; it's unused otherwise.)

const users: {[key: string]: number} = ...;
const users: {[userName: string]: number} = ...;

Rather than using one of these, consider using the ES6 Map and Set types instead. JavaScript objects have surprising undesirable behaviors and the ES6 types more explicitly convey your intent. Also, Maps can be keyed by—and Sets can contain—types other than string.

TypeScript's builtin Record<Keys, ValueType> type allows constructing types with a defined set of keys. This is distinct from associative arrays in that the keys are statically known. See advice on that below.

Mapped and conditional types

TypeScript's mapped types and conditional types allow specifying new types based on other types. TypeScript's standard library includes several type operators based on these (Record, Partial, Readonly etc).

These type system features allow succinctly specifying types and constructing powerful yet type safe abstractions. They come with a number of drawbacks though:

  • Compared to explicitly specifying properties and type relations (e.g. using interfaces and extension, see below for an example), type operators require the reader to mentally evaluate the type expression. This can make programs substantially harder to read, in particular combined with type inference and expressions crossing file boundaries.
  • Mapped & conditional types' evaluation model, in particular when combined with type inference, is underspecified, not always well understood, and often subject to change in TypeScript compiler versions. Code can accidentally compile or seem to give the right results. This increases future support cost of code using type operators.
  • Mapped & conditional types are most powerful when deriving types from complex and/or inferred types. On the flip side, this is also when they are most prone to create hard to understand and maintain programs.
  • Some language tooling does not work well with these type system features. E.g. your IDE's find references (and thus rename property refactoring) will not find properties in a Pick<T, Keys> type, and Code Search won't hyperlink them.

The style recommendation is:

  • Always use the simplest type construct that can possibly express your code.
  • A little bit of repetition or verbosity is often much cheaper than the long term cost of complex type expressions.
  • Mapped & conditional types may be used, subject to these considerations.

For example, TypeScript's builtin Pick<T, Keys> type allows creating a new type by subsetting another type T, but simple interface extension can often be easier to understand.

interface User {
  shoeSize: number;
  favoriteIcecream: string;
  favoriteChocolate: string;
}

// FoodPreferences has favoriteIcecream and favoriteChocolate, but not shoeSize.
type FoodPreferences = Pick<User, 'favoriteIcecream'|'favoriteChocolate'>;

This is equivalent to spelling out the properties on FoodPreferences:

interface FoodPreferences {
  favoriteIcecream: string;
  favoriteChocolate: string;
}

To reduce duplication, User could extend FoodPreferences, or (possibly better) nest a field for food preferences:

interface FoodPreferences { /* as above */ }
interface User extends FoodPreferences {
  shoeSize: number;
  // also includes the preferences.
}

Using interfaces here makes the grouping of properties explicit, improves IDE support, allows better optimization, and arguably makes the code easier to understand.

any Type

TypeScript's any type is a super and subtype of all other types, and allows dereferencing all properties. As such, any is dangerous - it can mask severe programming errors, and its use undermines the value of having static types in the first place.

Consider not to use any. In circumstances where you want to use any, consider one of:

Providing a more specific type

Use interfaces , an inline object type, or a type alias:

// Use declared interfaces to represent server-side JSON.
declare interface MyUserJson {
  name: string;
  email: string;
}

// Use type aliases for types that are repetitive to write.
type MyType = number|string;

// Or use inline object types for complex returns.
function getTwoThings(): {something: number, other: string} {
  // ...
  return {something, other};
}

// Use a generic type, where otherwise a library would say `any` to represent
// they don't care what type the user is operating on (but note "Return type
// only generics" below).
function nicestElement<T>(items: T[]): T {
  // Find the nicest element in items.
  // Code can also put constraints on T, e.g. <T extends HTMLElement>.
}

Using unknown over any

The any type allows assignment into any other type and dereferencing any property off it. Often this behaviour is not necessary or desirable, and code just needs to express that a type is unknown. Use the built-in type unknown in that situation — it expresses the concept and is much safer as it does not allow dereferencing arbitrary properties.

// Can assign any value (including null or undefined) into this but cannot
// use it without narrowing the type or casting.
const val: unknown = value;
const danger: any = value /* result of an arbitrary expression */;
danger.whoops();  // This access is completely unchecked!

To safely use unknown values, narrow the type using a type guard

Suppressing any lint warnings

Sometimes using any is legitimate, for example in tests to construct a mock object. In such cases, add a comment that suppresses the lint warning, and document why it is legitimate.

// This test only needs a partial implementation of BookService, and if
// we overlooked something the test will fail in an obvious way.
// This is an intentionally unsafe partial mock
// tslint:disable-next-line:no-any
const mockBookService = ({get() { return mockBook; }} as any) as BookService;
// Shopping cart is not used in this test
// tslint:disable-next-line:no-any
const component = new MyComponent(mockBookService, /* unused ShoppingCart */ null as any);

{} Type

The {} type, also known as an empty interface type, represents a interface with no properties. An empty interface type has no specified properties and therefore any non-nullish value is assignable to it.

let player: {};

player = {
  health: 50,
}; // Allowed.

console.log(player.health) // Property 'health' does not exist on type '{}'.
function takeAnything(obj:{}) {

}

takeAnything({});
takeAnything({ a: 1, b: 2 });

Google3 code should not use {} for most use cases. {} represents any non-nullish primitive or object type, which is rarely appropriate. Prefer one of the following more-descriptive types:

  • unknown can hold any value, including null or undefined, and is generally more appropriate for opaque values.
  • Record<string, T> is better for dictionary-like objects, and provides better type safety by being explicit about the type T of contained values (which may itself be unknown).
  • object excludes primitives as well, leaving only non-nullish functions and objects, but without any other assumptions about what properties may be available.

Tuple types

If you are tempted to create a Pair type, instead use a tuple type:

interface Pair {
  first: string;
  second: string;
}
function splitInHalf(input: string): Pair {
  ...
  return {first: x, second: y};
}
function splitInHalf(input: string): [string, string] {
  ...
  return [x, y];
}

// Use it like:
const [leftHalf, rightHalf] = splitInHalf('my string');

However, often it's clearer to provide meaningful names for the properties.

If declaring an interface is too heavyweight, you can use an inline object literal type:

function splitHostPort(address: string): {host: string, port: number} {
  ...
}

// Use it like:
const address = splitHostPort(userAddress);
use(address.port);

// You can also get tuple-like behavior using destructuring:
const {host, port} = splitHostPort(userAddress);

Wrapper types

There are a few types related to JavaScript primitives that should not ever be used:

  • String, Boolean, and Number have slightly different meaning from the corresponding primitive types string, boolean, and number. Always use the lowercase version.
  • Object has similarities to both {} and object, but is slightly looser. Use {} for a type that include everything except null and undefined, or lowercase object to further exclude the other primitive types (the three mentioned above, plus symbol and bigint).

Further, never invoke the wrapper types as constructors (with new).

Return type only generics

Avoid creating APIs that have return type only generics. When working with existing APIs that have return type only generics always explicitly specify the generics.

Toolchain requirements

Google style requires using a number of tools in specific ways, outlined here.

TypeScript compiler

All TypeScript files must pass type checking using the standard tool chain.

@ts-ignore

Do not use @ts-ignore nor the variants @ts-expect-error or @ts-nocheck.

Why?

They superficially seem to be an easy way to fix a compiler error, but in practice, a specific compiler error is often caused by a larger problem that can be fixed more directly.

For example, if you are using @ts-ignore to suppress a type error, then it's hard to predict what types the surrounding code will end up seeing. For many type errors, the advice in how to best use any is useful.

You may use @ts-expect-error in unit tests, though you generally should not. @ts-expect-error suppresses all errors. It's easy to accidentally over-match and suppress more serious errors. Consider one of:

  • When testing APIs that need to deal with unchecked values at runtime, add casts to the expected type or to any and add an explanatory comment. This limits error suppression to a single expression.
  • Suppress the lint warning and document why, similar to suppressing any lint warnings.

Conformance

Google TypeScript includes several conformance frameworks, tsetse and tsec.

These rules are commonly used to enforce critical restrictions (such as defining globals, which could break the codebase) and security patterns (such as using eval or assigning to innerHTML), or more loosely to improve code quality.

Google-style TypeScript must abide by any applicable global or framework-local conformance rules.

Comments and documentation

JSDoc versus comments

There are two types of comments, JSDoc (/** ... */) and non-JSDoc ordinary comments (// ... or /* ... */).

  • Use /** JSDoc */ comments for documentation, i.e. comments a user of the code should read.
  • Use // line comments for implementation comments, i.e. comments that only concern the implementation of the code itself.

JSDoc comments are understood by tools (such as editors and documentation generators), while ordinary comments are only for other humans.

Multi-line comments

Multi-line comments are indented at the same level as the surrounding code. They must use multiple single-line comments (//-style), not block comment style (/* */).

// This is
// fine
/*
 * This should
 * use multiple
 * single-line comments
 */

/* This should use // */

Comments are not enclosed in boxes drawn with asterisks or other characters.

JSDoc general form

The basic formatting of JSDoc comments is as seen in this example:

/**
 * Multiple lines of JSDoc text are written here,
 * wrapped normally.
 * @param arg A number to do something to.
 */
function doSomething(arg: number) { … }

or in this single-line example:

/** This short jsdoc describes the function. */
function doSomething(arg: number) { … }

If a single-line comment overflows into multiple lines, it must use the multi-line style with /** and */ on their own lines.

Many tools extract metadata from JSDoc comments to perform code validation and optimization. As such, these comments must be well-formed.

Markdown

JSDoc is written in Markdown, though it may include HTML when necessary.

This means that tooling parsing JSDoc will ignore plain text formatting, so if you did this:

/**
 * Computes weight based on three factors:
 *   items sent
 *   items received
 *   last timestamp
 */

it will be rendered like this:

Computes weight based on three factors: items sent items received last timestamp

Instead, write a Markdown list:

/**
 * Computes weight based on three factors:
 *
 * - items sent
 * - items received
 * - last timestamp
 */

JSDoc tags

Google style allows a subset of JSDoc tags. Most tags must occupy their own line, with the tag at the beginning of the line.

/**
 * The "param" tag must occupy its own line and may not be combined.
 * @param left A description of the left param.
 * @param right A description of the right param.
 */
function add(left: number, right: number) { ... }
/**
 * The "param" tag must occupy its own line and may not be combined.
 * @param left @param right
 */
function add(left: number, right: number) { ... }

Line wrapping

Line-wrapped block tags are indented four spaces. Wrapped description text may be lined up with the description on previous lines, but this horizontal alignment is discouraged.

/**
 * Illustrates line wrapping for long param/return descriptions.
 * @param foo This is a param with a particularly long description that just
 *     doesn't fit on one line.
 * @return This returns something that has a lengthy description too long to fit
 *     in one line.
 */
exports.method = function(foo) {
  return 5;
};

Do not indent when wrapping a @desc or @fileoverview description.

Document all top-level exports of modules

Use /** JSDoc */ comments to communicate information to the users of your code. Avoid merely restating the property or parameter name. You should also document all properties and methods (exported/public or not) whose purpose is not immediately obvious from their name, as judged by your reviewer.

Exception: Symbols that are only exported to be consumed by tooling, such as @NgModule classes, do not require comments.

Class comments

JSDoc comments for classes should provide the reader with enough information to know how and when to use the class, as well as any additional considerations necessary to correctly use the class. Textual descriptions may be omitted on the constructor.

Method and function comments

Method, parameter, and return descriptions may be omitted if they are obvious from the rest of the method’s JSDoc or from the method name and type signature.

Method descriptions begin with a verb phrase that describes what the method does. This phrase is not an imperative sentence, but instead is written in the third person, as if there is an implied This method ... before it.

Parameter property comments

A parameter property is a constructor parameter that is prefixed by one of the modifiers private, protected, public, or readonly. A parameter property declares both a parameter and an instance property, and implicitly assigns into it. For example, constructor(private readonly foo: Foo), declares that the constructor takes a parameter foo, but also declares a private readonly property foo, and assigns the parameter into that property before executing the remainder of the constructor.

To document these fields, use JSDoc's @param annotation. Editors display the description on constructor calls and property accesses.

/** This class demonstrates how parameter properties are documented. */
class ParamProps {
  /**
   * @param percolator The percolator used for brewing.
   * @param beans The beans to brew.
   */
  constructor(
    private readonly percolator: Percolator,
    private readonly beans: CoffeeBean[]) {}
}
/** This class demonstrates how ordinary fields are documented. */
class OrdinaryClass {
  /** The bean that will be used in the next call to brew(). */
  nextBean: CoffeeBean;

  constructor(initialBean: CoffeeBean) {
    this.nextBean = initialBean;
  }
}

JSDoc type annotations

JSDoc type annotations are redundant in TypeScript source code. Do not declare types in @param or @return blocks, do not write @implements, @enum, @private, @override etc. on code that uses the implements, enum, private, override etc. keywords.

Make comments that actually add information

For non-exported symbols, sometimes the name and type of the function or parameter is enough. Code will usually benefit from more documentation than just variable names though!

  • Avoid comments that just restate the parameter name and type, e.g.

    /** @param fooBarService The Bar service for the Foo application. */
    
  • Because of this rule, @param and @return lines are only required when they add information, and may otherwise be omitted.

    /**
     * POSTs the request to start coffee brewing.
     * @param amountLitres The amount to brew. Must fit the pot size!
     */
    brew(amountLitres: number, logger: Logger) {
      // ...
    }
    

Comments when calling a function

“Parameter name” comments should be used whenever the method name and parameter value do not sufficiently convey the meaning of the parameter.

Before adding these comments, consider refactoring the method to instead accept an interface and destructure it to greatly improve call-site readability.

Parameter name comments go before the parameter value, and include the parameter name and a = suffix:

someFunction(obviousParam, /* shouldRender= */ true, /* name= */ 'hello');

Existing code may use a legacy parameter name comment style, which places these comments ~after~ the parameter value and omits the =. Continuing to use this style within the file for consistency is acceptable.

someFunction(obviousParam, true /* shouldRender */, 'hello' /* name */);

Place documentation prior to decorators

When a class, method, or property have both decorators like @Component and JsDoc, please make sure to write the JsDoc before the decorator.

  • Do not write JsDoc between the Decorator and the decorated statement.

    @Component({
      selector: 'foo',
      template: 'bar',
    })
    /** Component that prints "bar". */
    export class FooComponent {}
    
  • Write the JsDoc block before the Decorator.

    /** Component that prints "bar". */
    @Component({
      selector: 'foo',
      template: 'bar',
    })
    export class FooComponent {}
    

Policies

Consistency

For any style question that isn't settled definitively by this specification, do what the other code in the same file is already doing (be consistent). If that doesn't resolve the question, consider emulating the other files in the same directory.

Brand new files must use Google Style, regardless of the style choices of other files in the same package. When adding new code to a file that is not in Google Style, reformatting the existing code first is recommended, subject to the advice below. If this reformatting is not done, then new code should be as consistent as possible with existing code in the same file, but must not violate the style guide.

Reformatting existing code

You will occasionally encounter files in the codebase that are not in proper Google Style. These may have come from an acquisition, or may have been written before Google Style took a position on some issue, or may be in non-Google Style for any other reason.

When updating the style of existing code, follow these guidelines.

  1. It is not required to change all existing code to meet current style guidelines. Reformatting existing code is a trade-off between code churn and consistency. Style rules evolve over time and these kinds of tweaks to maintain compliance would create unnecessary churn. However, if significant changes are being made to a file it is expected that the file will be in Google Style.
  2. Be careful not to allow opportunistic style fixes to muddle the focus of a CL. If you find yourself making a lot of style changes that aren’t critical to the central focus of a CL, promote those changes to a separate CL.

Deprecation

Mark deprecated methods, classes or interfaces with an @deprecated JSDoc annotation. A deprecation comment must include simple, clear directions for people to fix their call sites.

Generated code: mostly exempt

Source code generated by the build process is not required to be in Google Style. However, any generated identifiers that will be referenced from hand-written source code must follow the naming requirements. As a special exception, such identifiers are allowed to contain underscores, which may help to avoid conflicts with hand-written identifiers.

Style guide goals

In general, engineers usually know best about what's needed in their code, so if there are multiple options and the choice is situation dependent, we should let decisions be made locally. So the default answer should be leave it out.

The following points are the exceptions, which are the reasons we have some global rules. Evaluate your style guide proposal against the following:

  1. Code should avoid patterns that are known to cause problems, especially for users new to the language.

  2. Code across projects should be consistent across irrelevant variations.

    When there are two options that are equivalent in a superficial way, we should consider choosing one just so we don't divergently evolve for no reason and avoid pointless debates in code reviews.

    Examples:

    • The capitalization style of names.
    • x as T syntax vs the equivalent <T>x syntax (disallowed).
    • Array<[number, number]> vs [number, number][].
  3. Code should be maintainable in the long term.

    Code usually lives longer than the original author works on it, and the TypeScript team must keep all of Google working into the future.

    Examples:

    • We use software to automate changes to code, so code is autoformatted so it's easy for software to meet whitespace rules.
    • We require a single set of compiler flags, so a given TS library can be written assuming a specific set of flags, and users can always safely use a shared library.
    • Code must import the libraries it uses (strict deps) so that a refactor in a dependency doesn't change the dependencies of its users.
    • We ask users to write tests. Without tests we cannot have confidence that changes that we make to the language, don't break users.
  4. Code reviewers should be focused on improving the quality of the code, not enforcing arbitrary rules.

    If it's possible to implement your rule as an automated check that is often a good sign. This also supports principle 3.

    If it really just doesn't matter that much -- if it's an obscure corner of the language or if it avoids a bug that is unlikely to occur -- it's probably worth leaving out.


  1. Namespace imports are often called 'module imports' 

  2. named imports are sometimes called 'destructuring imports' because they use similar syntax to destructuring assignments. 

================================================ FILE: vimscriptfull.xml ================================================

Revision 1.1

Nate Soares
Artemis Sparks
David Barnett

This is the in-depth vimscript guide. If you're just a casual user looking to write a plugin, the abbreviated style guide is for you.

This rather rotund guide dives into justifications and clarifications. It provides an idealized set of rules that are rather too draconian to push on casual scripters.

It's for users who want to know why certain decisions were made in the abbreviated guide and who want to learn a thing or two about using vimscript safely.

Fair warning: Vimscript is a maddening abyss. When you gaze into it, it gazes also into you. Proceed with caution.

Vim is highly configurable. Users can change many of the default settings, including the case sensitivity, the regular expression rules, the substitution rules, and more. In order for your vimscript to work for all users, follow these guidelines:

  • Always prefix regular expressions with one of \m, \v, \M, or \V (prefer tersity)
    • Users can change the global "magic level" of regular expressions. This changes how atoms are parsed in regular expressions, including ., *, and {.
    • Even if your regular expression does not contain characters which are affected by the magic setting you must prefix it with one of the magic control atoms. This future-proofs your regular expression against other devs modifying it and forgetting to add the control atom.
    • If you have no opinion about what type of regular expression to use, prefer the one which makes your regular expression most concise.
  • Avoid using :s[ubstitute] in scripts.
    • :substitute moves the cursor.
    • :substitute outputs an error message when the match does not exist.
    • The meaning of the g flag depends upon the gdefault setting. If you do use :substitute you must save gdefault, set it to 0 or 1, perform the substitution, and then restore it.
    • Script authors who want a safe way to replace text in the buffer are encouraged to use maktaba#buffer#Replace.
  • Always use case-explicit operators for strings (=~# and =~?, never =~).
    • This also applies to !~ == != > >= < and <=
    • This only applies for strings. == and >= are fine for numbers, but ==# and >=# must be used for strings.
    • The behavior of =~ and friends is dependent upon the ignorecase setting.
    • You may break this rule when you explicitly want to obey the user's ignorecase setting. Be prepared to justify your reasoning.
  • When using regular expressions as arguments to functions, prepend them with \c or \C.
    • This forces case to be either explicitly matched or ignored.
    • This is recommended, but not required, when comparing regexes with operators that specify case sensitivity (=~#, etc.).
    • This rule applies when your regexes are matching syntax, external APIs, external messages, and most other cases.
    • It does not apply when matching text in the buffer. When matching text in the buffer you should honor the ignorecase setting.
    • You may also ignore this rule any time that you explicitly want to honor the ignorecase setting. Be prepared to justify your reasoning.
  • Always use normal! instead of normal.
    • If you forgo the ! the command will use the user's key mappings and you have literally no idea what your macro will do.
  • Always use the noremap family of commands.
    • Your plugins generally shouldn't introduce mappings, but if they do, the map command respects the users existing mappings and could do anything.
  • When using catch, match the error code rather than the error text.
    • The error text may be locale-dependant.
    • See :help error-messages.

In general, guard all commands and functions against user settings.

  • Line continuations: Yes
    • Plugins that support vi compatibility mode must save and restore compatibility options as described in the Errata section so line continuations work properly.
  • Exceptions: Yes, with caution
    • Always use an error code in thrown exception messages.
    • Prefer the maktaba#error codes found in maktaba.
    • Fall back to the vim error codes. See :help error-messages.
    • Generate custom error messages using maktaba#error#Message.
  • Global Variables: As configuration only
    • See the plugin guide.
  • Messaging: As little as possible.
    • Loud scripts are annoying.
    • Message the user when an error has occurred.
    • Message the user when an operation which takes a long time has begun work.
    • Avoid messaging otherwise.
  • Type checking: Use strict and explicit checks where possible.
    • Vimscript has unsafe, unintuitive behavior when dealing with some types. For instance, 0 == 'foo' evaluates to true.
    • Use strict comparison operators where possible. When comparing against a string literal, use the is# operator. Otherwise, prefer maktaba#value#IsEqual or check type() explicitly.
    • Check variable types explicitly before using them. Use functions from maktaba#ensure, or check maktaba#value or type() and throw your own errors.
    • Use :unlet for variables that may change types, particularly those assigned inside loops.
  • FuncRefs: No in most cases.
    • FuncRefs have inconsistently enforced naming restrictions. (Functions can have names that FuncRefs can not.)
    • FuncRefs have inconsistent ability to be reassigned (in Vim 7.2 and before you must unlet a FuncRef before assigning it).
    • In most instances where a FuncRef is needed a string works just as well: just pass the string that you would use to make the FuncRef.
    • Consider using maktaba#function instead to create and manipulate handles to functions.
  • Python: Sparingly
    • Hurts code reuse since python code embedded in python plugins is awkward to share between plugins.
    • Using python introduces python language version dependencies, which are likely to get stale.
    • Exception: It's reasonable to use python for plugin functionality that needs to do work in the background, as vimscript can not do this.
  • Ruby: No
    • We can not assume ruby interoperability.
    • You shouldn't depend upon the version of the ruby language that the user has installed.
  • Lua: No
    • For the same reasons an Ruby.
  • Dict Functions: Encouraged
    • Vimscript can attach functions to dictionaries. Such functions have access to the self parameter which access the dict state.
    • Use these where you would use a class in python.
    • Do not over-use this feature; it is not necessary for helper functions or API functions, only for encapsulated objects.

All other language features are fair game.

  • Provided functionality should be packed into modular plugins.
    • Every function in your plugin should be specific to your plugin.
    • General utility functions should be abstracted into library plugins.
    • Manage dependencies with maktaba.
  • plugin-names-like-this
    • Plugin names should be descriptive and concise.
  • Each plugin must consist of one directory (or code repository), sharing a name with the plugin (with a "vim-" prefix or ".vim" suffix if desired).
  • Plugin metadata should be declared in the addon-info.json format (see the VAM documentation for details).
  • Functions should go in the autoload/ subdirectory of your plugin.
    • This allows them to be late-loaded, which speeds up startup time.
    • This helps vim enforce namespacing conventions.
  • Each file in the plugin/ or instant/ directory should begin with the boilerplate let [s:plugin, s:enter] = maktaba#plugin#Enter(expand('<sfile>:p')) if !s:enter finish endif (This prevents re-entry and allows users to selectively disable functionality.)
  • User configuration should be via plugin flags defined in instant/flags.vim.
    • Define flags with call s:plugin.Flag('FLAGNAME', DEFAULT_VALUE).
    • Users can configure these flags using the :Glaive command (see glaive).
  • Commands, autocommands, mappings, and settings changes should occur either in the plugin/ or the ftplugin/ subdirectories.
    • All commands should be defined in plugin/commands.vim or ftplugin/ files.
    • Autocommands should be defined in plugin/autocmds.vim, inside an augroup.
    • Mappings should be defined in plugin/mappings.vim and will be disabled unless explicitly enabled by users.
    • If the plugin configures any standard vim settings, those should be configured in plugin/settings.vim or instant/settings.vim.
  • Avoid using the after/ subdirectory.
    • after/ should be reserved for the user.
    • It is difficult for the user to add their own overrides when plugins use after/.
Separate library-providing plugins from command-providing plugins.

Many plugins provide either user functionality (commands, autocommands, etc) or an API (of autoloaded functions) but not both. This separation is encouraged, as it allows other plugins to pull in a library without also pulling in commands, setting changes, and other plugin functionality that affects the end user.

Don't clobber user settings. Provide as much configurability as possible: that's what Vim's all about.
  • Use maktaba flags for plugin configuration. Users can configure them using the :Glaive command.
  • Check if configuration variables exist before setting them. if !exists('g:myplugin_option') let g:myplugin_option = 1 endif

Follow google-wide style conventions. Mimic google python style when in doubt.

Use vimdoc.

Provide help files generated by vimdoc. Write documentation in .vim files in conformance with the vimdoc standards and include fields like "description" and "author" in the addon-info.json file (see the VAM documentation).

Follow google-wide conventions.
  • Use two spaces for indents.
  • Do not use tabs.
  • Use spaces around operators except for arguments to commands.
    • Using spaces around operators for commands is often invalid syntax. This is inconsistently enforced by vimscript. To be safe, always omit whitespace around arguments to commands.
    • let s:variable = "concatenated " . "strings" command -range=% MyCommand let s:variable="concatenated "."strings" command -range = % MyCommand
  • Do not introduce trailing whitespace.
    • You need not go out of your way to remove it.
  • Restrict lines to 80 columns wide.
  • Indent continued lines by two tabs (four spaces).
  • Do not waste whitespace aligning common segments of similar commands. It is both difficult and expensive to maintain.
    • command -bang MyCommand call myplugin#foo() command MyCommand2 call myplugin#bar() command -bang MyCommand call myplugin#foo() command MyCommand2 call myplugin#bar()
  • Prefer line continuations on semantic boundaries.
    • command SomeLongCommand \ call some#function() command SomeLongCommand call \ some#function()
    • Use your best judgement.
  • Place one space after the backslash denoting a line continuation.
    • When continuing a multi-line command a pipe can be substituted for this space as necessary, as follows: autocommand BufEnter <buffer> \ if !empty(s:var) \| call some#function() \|else \| call some#function(s:var) \|endif
  • Do not continue multi-line commands when you can avoid it. Prefer function calls.
  • Place a space after the " before the comment text.
    • " I am a line comment. call call(s:my_function)
  • Do not use inline comments.
    • Some commands treat them as comments and others as unclosed quotes. There are many edge cases. It's difficult to get right and difficult to maintain.
    • Where you would use an inline comment, put a line comment on the line above.
  • When leaving blank lines in comments, include the quote in the blank line.
    • " I am one continuous " " comment block

plugin-names-like-this, FunctionNamesLikeThis, CommandNamesLikeThis, augroup_names_like_this, variable_names_like_this.

Prefix all variables with their scope.

  • variable_names_like_this
    • FuncRef variables count as functions and should be named like functions.
    • This (pathological) convention is enforced by vim itself.
  • Prefix global variables with g:
    • Vimscript allows you to create global variables without prefixing them.
    • It is very bad practice to introduce non-prefixed global variables into scope.
    • Global variables should only be used for plugin configuration.
    • This does not apply to functions defined in autoload directories.
  • Prefix script-local variables with s:
    • This prevents namespace collisions between plugins.
    • This also applies to script-local functions.
  • Prefix function arguments with a:
    • This is enforced by vim itself.
  • Prefix function-local variables with l:
    • This is not enforced by vimscript but is good practice.
    • It helps you remember that all other variables must be prefixed with scope.
    • l: disambiguates between function-local and vim-predefined variables. For example, count refers to v:count, not l:count.
    • It future proofs your scripts against the introduction of new vim-predefined variables.
  • Prefix pre-defined vim variables with v:
    • This is not enforced by vimscript but is good practice.
    • It provides context as to where the (undeclared) variable is coming from.
    • It reminds you that the variable can not be assigned to.
  • Prefix buffer-local variables with b:
    • This is useful for plugins that keep per-buffer state.
Prefer single quotes.

Prefer single quoted strings. Specifically, in order of precedence:

  • Always use single quotes for regular expressions.
    • '\s*' is not the same as "\s*"
    • Single quotes will prevent the need for excessive backslashes.
    • Double single quotes escape to one single quote in single quoted strings: 'example ('')' represents the string example (')
  • If your string requires escape characters (\n, \t, etc.) use double quotes.
    • Escapes can not be expressed in single quoted strings.
    • Remember that '\n' in a regex does not represent a newline, but rather "\n". You only need to use double quotes when you want to embed the represented character itself (e.g. a newline) in the string.
  • If your string contains no escapes nor single quotes, use single quoted strings.
    • Most strings in vimscript are regexes, so this provides maximum consistency.
  • If your non-regex string contains single quotes but no double quotes, use double quotes.
    • Don't bother escaping strings if you don't have to.
    • This is similar to the python string rules.
  • If your string contains both single and double quotes, use whichever quoting style requires less escaping.
    • Break ties in favor of single quotes.
Prefer long names. Set settings locally.
  • Prefer long names of built in settings (i.e. tabstop over ts).
  • Set local settings unless you explicitly want to set global settings.
    • Use setlocal and &l: instead of set and &.

Vim plugins should provide any or all of the following: Commands, Autocommands, Functions, Statusline Flags, and Mappings.

  • Define in plugin/commands.vim.
  • CommandNamesLikeThis.
  • Prefer semantic names to a unified prefix.
  • Do not use [!]
  • Extract logic into functions.
  • CommandNamesLikeThis
  • Commands should be defined in one block with no whitespace between them.
    • Name commands semantically at the expense of a common prefix.
    • command WhitespaceFixTrailing command WhitespaceFixIndentation command FixTrailingWhitespace command FixIndentation
  • Use command without a bang.
    • This notifies users to command name conflicts immediately at startup.
    • Command name collisions are an error and should not fail silently.
    • Plugins are guarded against re-entry, so a single vim session should never attempt to re-define defined commands.
  • Do not put logic in commands.
    • Delegate to functions instead.
    • Pass non-argument command parameters (<bang>, <register>, etc.) before argument parameters (<f-args>, etc.).
    • Otherwise variable-length argument functions are difficult to implement.
  • Do not autoload commands.
    • Autoloaded commands will not be available until after a function in the same file is called.
    • Commands intended to be used in the .vimrc should be defined in a instant/commands.vim file in plugins using maktaba, or explicitly installed via an autoload function in non-maktaba plugins.
  • Pass <bang> to functions with '<bang>' == '!'.
    • The function should receive a boolean parameter, not a string.
  • Define in plugin/autocmds.vim.
  • Use augroups.
  • augroup_names_like_this.
  • Clear the augroup first.
  • Extract logic into functions.
  • All autocommands should be defined in the plugin/autocmds.vim file.
    • This allows users to disable your autocommands with Glaive myplugin !plugin[autocmds].
  • Declare all autocommands in an augroup block.
    • This allows your autocommands to be cleared with autocmd!.
    • If your plugin only has one augroup, the augroup name should be the same as your plugin name, with underscores in place of any hyphens.
    • Otherwise augroup names should start with your plugin name followed by an underscore.
  • Do not put logic in autocommands.
    • Delegate to functions instead.
  • When creating a new augroup, clear it with autocmd!
    • This allows your plugins to be re-enterable.
  • FunctionNamesLikeThis.
  • Autoload all functions.
  • Prefix script-local functions with s:
  • Use [!].
  • Use [abort].
  • FunctionNamesLikeThis
  • Prefix all script-local functions with s:
  • Do not provide global functions. Use autoloaded functions instead.
  • Place two blank lines between top-level functions.
  • Declare all functions with abort.
    • If you do not do this, the function's behavior depends upon whether it is called within a try..endtry block somewhere on the stack.
    • The abort keyword forces the function to act consistently.
    • Without it, the function may (or may not) attempt to continue execution after an error occurs.
  • Use function! with a bang.
    • This allows developers to re-source their scripts and have the functions reloaded without complaint.
    • Function names should never collide because functions should always be either script-local or defined in an autoload directory.
    • Failing to use a bang in any function in an autoload file will lead to cryptic errors if vim tries to re-source the file (e.g., if you refer to an nonexistent autoload function).
  • Use ... for optional arguments, not for lists of arguments.
    • Vimscript functions take at most 20 arguments.
    • Lists have no such length restriction.
    • Your function is likely to break when given too many arguments if you use ... for a list of arguments.
  • Throw exceptions rather than printing errors.
    • Printed errors can not be caught.
    • Top-level functions expecting errors may catch them and print error messages, but even those should throw their own errors when they choke.
  • Provide opt-in key mappings in plugin/mappings.vim.
  • <Plug> mappings can be defined in plugin/plugs.vim (unlike mappings.vim, plugs.vim is opt-out).
  • Define key mappings in plugin/mappings.vim, using maktaba#plugin#MapPrefix to get a prefix.
    • Mappings defined in the special plugin/mappings.vim file will be disabled by default (by the standard maktaba#plugin#Enter() boilerplate).
    • Users can enable key mappings with Glaive myplugin plugin[mappings].
  • Make all mappings with <unique>.
    • This will inform the user when they have a mapping conflict instead of silently clobbering their existing mappings.
  • You may provide pseudo-mappings using <Plug> and your plugin's name in plugin/plugs.vim (separate from standard key mappings).
    • <Plug> is a sequence which can not be typed.
    • You can do something like noremap <Plug>namespace#MappingName some_key_sequence and then users can do noremap <leader>x <Plug>namespace#MappingName to take advantage of your pseudo-mapping.
    • Pseudo-mappings should not be in plugin/mappings.vim or they will be disabled by default.
    • Such pseudo-mappings should be named <Plug> followed by your plugin name, a pound sign, and a unique mapping name (CamelCased like a function).
  • Always use the noremap family of commands. Never use the map family.
    • map depends upon the user's existing mappings, and could do anything.
  • Only use noremap for commands that both make a motion and take a range.
    • noremap makes mappings in normal, visual, and operator-pending modes.
    • If you don't want all these use nnoremap onoremap or vnoremap explicitly.
  • Always use <SID> in place of s: when accessing script locals in mappings.
    • Using s: will often fail as the mapping attempts to type a literal s and colon.
Declare dependencies in addon-info.json and use maktaba.

Declaring dependencies in addon-info.json allows conformant plugin managers (like VAM) to ensure dependencies are installed. See the VAM documentation for details.

Calling maktaba#library#Require from dependent code at runtime ensures that dependencies have been installed and that they don't include unsafe non-library files.

Use <plugin-name>#status#Status() or its finer-grained variants to provide statusline flags.

Following is a convention for exposing statusline flags to the user. A plugin should never modify the user's statusline except for when that is the only purpose of the plugin (powerline, etc.).

  • Provide the Info, Alert, Warning, and Error functions under the <plugin-name>#status namespace.
  • Info should provide information about the state of the buffer.
    • Example: The current git branch.
  • Alert should provide a quiet reminder that the buffer is non-standard.
    • Example: The readonly setting is on.
  • Warning should provide a warning about the current state of the buffer.
    • Example: The file has been edited elsewhere.
  • Error should bring to attention a loud issue with the buffer.
    • Example: The file does not pass the syntax checker.
  • By following these conventions, users can easily build up their own statusline customizing the verbosity and colors to their tastes.
  • All functions should take no arguments and should return either empty strings or strings enclosed by square brackets, e.g. [Google]. For example:
    • A trailing whitespace plugin might return [$] if the file contains trailing whitespace
    • A prose writing plugin might return [write] if vim is in writing mode.
  • Consider providing the <plugin-name>#status#Status function.
    • It should return the first non-empty of Error, Warning, Alert, or Info.
    • This is useful for users who want only the most relevant flag and do not have a colored statusline.

These are commands which can only be used by a limited number of plugins, and should not in general be used by yours.

  • Do not use :match :2match or :3match
    • These are reserved for the user and for vim itself.
    • Use matchadd() to create a matchlevel unique to your plugin.
  • Do not use echoerr.
    • echoerr does not print the red error message that you might think it does.
    • echoerr prints an error message as well as context about the code where echoerr was called.
    • echoerr is best suited for debugging.
    • Use echohl in tandem with echomsg if you want the red error bar.
  • Use echomsg instead of echo.
    • echomsg messages can be reviewed with the :messages command.
    • echo messages disappear permanently on redraw, which can be very annoying to users who failed to read the message in time.

Lay out plugin/ files in the following sections, if applicable, separated by two blank lines:

  • Declaration of script constants
  • Declaration of configuration variables
  • Other declarations (commands in commands.vim file, autocommands in autocmds.vim file, etc.)

Lay out autoload/ files in the following sections, if applicable, separated by two blank lines:

  • maktaba#library#Require calls
  • Script-local variables
  • Script-local functions
  • Private autoloaded functions
  • Public autoloaded functions

This is recommended convention and is not enforced.

Use the following shortcuts:

  • catch over catch /.*/
  • return over return 0 when the return value has no semantic purpose.

This section plumbs some of the darker corners of vimscript, explaining the language pathologies that you wish you didn't have to know.

If you don't support vi-compatibility mode, fail gracefully.

When compatible is set, many vim features are not available. The vim feature which most commonly affects vimscript authors is line continuations.

If you want your plugin to work in vim with vi compatibility on, you will need to save the compatibility options at the beginning of each plugin file, clear them, and restore them at the end of each plugin file. See :help use-cpo-save for details.

Plugins that depend on maktaba generally don't need to worry about compatible mode since maktaba currently just disables it, printing a warning.

Revision 1.1

Nate Soares
Artemis Sparks
David Barnett
================================================ FILE: vimscriptguide.xml ================================================

Revision 1.1

Nate Soares
Artemis Sparks
David Barnett

This is a casual version of the vimscript style guide, because vimscript is a casual language. When submitting vim plugin code, you must adhere to these rules. For clarifications, justifications, and explanations about the finer points of vimscript, please refer to the heavy guide.

It's hard to get vimscript right. Many commands depend upon the user's settings. By following these guidelines, you can hope to make your scripts portable.

Prefer single quoted strings

Double quoted strings are semantically different in vimscript, and you probably don't want them (they break regexes).

Use double quoted strings when you need an escape sequence (such as "\n") or if you know it doesn't matter and you need to embed single quotes.

Use the =~# or =~? operator families over the =~ family.

The matching behavior depends upon the user's ignorecase and smartcase settings and on whether you compare them with the =~, =~#, or =~? family of operators. Use the =~# and =~? operator families explicitly when comparing strings unless you explicitly need to honor the user's case sensitivity settings.

Prefix all regexes with \m\C.

In addition to the case sensitivity settings, regex behavior depends upon the user's nomagic setting. To make regexes act like nomagic and noignorecase are set, prepend all regexes with \m\C.

You are welcome to use other magic levels (\v) and case sensitivities (\c) so long as they are intentional and explicit.

Avoid commands with unintended side effects.

Avoid using :s[ubstitute] as it moves the cursor and prints error messages. Prefer functions (such as search()) better suited to scripts.

For many vim commands, functions exist that do the same thing with fewer side effects. See :help functions() for a list of built-in functions.

Avoid commands that rely on user settings.

Always use normal! instead of normal. The latter depends upon the user's key mappings and could do anything.

Avoid :s[ubstitute], as its behavior depends upon a number of local settings.

The same applies to other commands not listed here.

Match error codes, not error text.

Error text may be locale dependent.

Message the user infrequently.

Loud scripts are annoying. Message the user only when:

  • A long-running process has kicked off.
  • An error has occurred.

Use strict and explicit checks where possible.

Vimscript has unsafe, unintuitive behavior when dealing with some types. For instance, 0 == 'foo' evaluates to true.

Use strict comparison operators where possible. When comparing against a string literal, use the is# operator. Otherwise, prefer maktaba#value#IsEqual or check type() explicitly.

Check variable types explicitly before using them. Use functions from maktaba#ensure, or check maktaba#value or type() and throw your own errors.

Use :unlet for variables that may change types, particularly those assigned inside loops.

Use sparingly.

Use python only when it provides critical functionality, for example when writing threaded code.

Use vimscript instead.

Avoid using other scripting languages such as ruby and lua. We can not guarantee that the end user's vim has been compiled with support for non-vimscript languages.

Use maktaba.

maktaba removes boilerplate, including:

  • Plugin creation
  • Error handling
  • Dependency checking

Organize functionality into modular plugins

Group your functionality as a plugin, unified in one directory (or code repository) which shares your plugin's name (with a "vim-" prefix or ".vim" suffix if desired). It should be split into plugin/, autoload/, etc. subdirectories as necessary, and it should declare metadata in the addon-info.json format (see the VAM documentation for details).

In the autoload/ directory, defined with [!] and [abort].

Autoloading allows functions to be loaded on demand, which makes startuptime faster and enforces function namespacing.

Script-local functions are welcome, but should also live in autoload/ and be called by autoloaded functions.

Non-library plugins should expose commands instead of functions. Command logic should be extracted into functions and autoloaded.

[!] allows developers to reload their functions without complaint.

[abort] forces the function to halt when it encounters an error.

In the plugin/commands.vim or under the ftplugin/ directory, defined without [!].

General commands go in plugin/commands.vim. Filetype-specific commands go in ftplugin/.

Excluding [!] prevents your plugin from silently clobbering existing commands. Command conflicts should be resolved by the user.

Place them in plugin/autocmds.vim, within augroups.

Place all autocommands in augroups.

The augroup name should be unique. It should either be, or be prefixed with, the plugin name.

Clear the augroup with autocmd! before defining new autocommands in the augroup. This makes your plugin re-entrable.

Place them in plugin/mappings.vim, using maktaba#plugin#MapPrefix to get a prefix.

All key mappings should be defined in plugin/mappings.vim.

Partial mappings (see :help using-<Plug>.) should be defined in plugin/plugs.vim.

Change settings locally

Use :setlocal and &l: instead of :set and & unless you have explicit reason to do otherwise.

Follow google style conventions. When in doubt, treat vimscript style like python style.

Similar to python.

  • Use two spaces for indents
  • Do not use tabs
  • Use spaces around operators

    This does not apply to arguments to commands.

    let s:variable = "concatenated " . "strings" command -range=% MyCommand
  • Do not introduce trailing whitespace

    You need not go out of your way to remove it.

    Trailing whitespace is allowed in mappings which prep commands for user input, such as "noremap <leader>gf :grep -f ".

  • Restrict lines to 80 columns wide
  • Indent continued lines by four spaces
  • Do not align arguments of commands command -bang MyCommand call myplugin#foo() command MyCommand2 call myplugin#bar() command -bang MyCommand call myplugin#foo() command MyCommand2 call myplugin#bar()

In general, use plugin-names-like-this, FunctionNamesLikeThis, CommandNamesLikeThis, augroup_names_like_this, variable_names_like_this.

Always prefix variables with their scope.

Keep them short and sweet.

Prefix script-local functions with s:

Autoloaded functions may not have a scope prefix.

Do not create global functions. Use autoloaded functions instead.

Prefer succinct command names over common command prefixes.

Augroup names count as variables for naming purposes.

  • Global variables with g:
  • Script-local variables with s:
  • Function arguments with a:
  • Function-local variables with l:
  • Vim-predefined variables with v:
  • Buffer-local variables with b:

g:, s:, and a: must always be used.

b: changes the variable semantics; use it when you want buffer-local semantics.

l: and v: should be used for consistency, future proofing, and to avoid subtle bugs. They are not strictly required. Add them in new code but don’t go out of your way to add them elsewhere.

Revision 1.1

Nate Soares
Artemis Sparks
David Barnett
================================================ FILE: xmlstyle.html ================================================

Google XML Document Format Style Guide

Version 1.0
Copyright Google 2008

Introduction

This document provides a set of guidelines for general use when designing new XML document formats (and to some extent XML documents as well; see Section 11).  Document formats usually include both formal parts (DTDs, schemas) and parts expressed in normative English prose.

These guidelines apply to new designs, and are not intended to force retroactive changes in existing designs.  When participating in the creation of public or private document format designs, the guidelines may be helpful but should not control the group consensus.

This guide is meant for the design of XML that is to be generated and consumed by machines rather than human beings.  Its rules are not applicable to formats such as XHTML (which should be formatted as much like HTML as possible) or ODF which are meant to express rich text.  A document that includes embedded content in XHTML or some other rich-text format, but also contains purely machine-interpretable portions, SHOULD follow this style guide for the machine-interpretable portions.  It also does not affect XML document formats that are created by translations from proto buffers or through some other type of format.

Brief rationales have been added to most of the guidelines.  They are maintained in the same document in hopes that they won't get out of date, but they are not considered normative.

The terms MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are used in this document in the sense of RFC 2119.
 

1. To design or not to design, that is the question

  1. Attempt to reuse existing XML formats whenever possible, especially those which allow extensions.  Creating an entirely new format should be done only with care and consideration; read Tim Bray's warnings first.  Try to get wide review of your format, from outside your organization as well, if possible.  [Rationale: New document formats have a cost: they must be reviewed, documented, and learned by users.]

  2. If you are reusing or extending an existing format, make sensible use of the prescribed elements and attributes, especially any that are required.  Don't completely repurpose them, but do try to see how they might be used in creative ways if the vanilla semantics aren't suitable.  As a last resort when an element or attribute is required by the format but is not appropriate for your use case, use some fixed string as its value.  [Rationale:  Markup reuse is good, markup abuse is bad.]

  3. When extending formats, use the implicit style of the existing format, even if it contradicts this guide.  [Rationale: Consistency.]

2. Schemas

  1. Document formats SHOULD be expressed using a schema language.  [Rationale: Clarity and machine-checkability.]

  2. The schema language SHOULD be RELAX NG compact syntax.  Embedded Schematron rules MAY be added to the schema for additional fine control.  [Rationale: RELAX NG is the most flexible schema language, with very few arbitrary restrictions on designs.  The compact syntax is quite easy to read and learn, and can be converted one-to-one to and from the XML syntax when necessary.  Schematron handles arbitrary cross-element and cross-attribute constraints nicely.]

  3. Schemas SHOULD use the "Salami Slice" style (one rule per element).  Schemas MAY use the "Russian Doll" style (schema resembles document) if they are short and simple.  The "Venetian Blind" style (one rule per element type) is unsuited to RELAX NG and SHOULD NOT be used.

  4. Regular expressions SHOULD be provided to assist in validating complex values.

  5. DTDs and/or W3C XML Schemas MAY be provided for compatibility with existing products, tools, or users.  [Rationale: We can't change the world all at once.]

3. Namespaces

  1. Element names MUST be in a namespace, except when extending pre-existing document types that do not use namespaces.  A default namespace SHOULD be used.  [Rationale: Namespace-free documents are obsolete; every set of names should be in some namespace.  Using a default namespace improves readability.]

  2. Attribute names SHOULD NOT be in a namespace unless they are drawn from a foreign document type or are meant to be used in foreign document types.  [Rationale: Attribute names in a namespace must always have a prefix, which is annoying to type and hard to read.]

  3. Namespace names are HTTP URIs.  Namespace names SHOULD take the form https://example.com/whatever/year, where whatever is a unique value based on the name of the document type, and year is the year the namespace was created.  There may be additional URI-path parts before the year.  [Rationale: Existing convention.  Providing the year allows for the possible recycling of code names.]

  4. Namespaces MUST NOT be changed unless the semantics of particular elements or attributes has changed in drastically incompatible ways.  [Rationale: Changing the namespace requires changing all client code.]

  5. Namespace prefixes SHOULD be short (but not so short that they are likely to be conflict with another project).  Single-letter prefixes MUST NOT be used. Prefixes SHOULD contain only lower-case ASCII letters.  [Rationale: Ease of typing and absence of encoding compatibility problems.]

4. Names and enumerated values

Note: "Names" refers to the names of elements, attributes, and enumerated values.

  1. All names MUST use lowerCamelCase. That is, they start with an initial lower-case letter, then each new word within the name starts with an initial capital letter. [Rationale: Adopting a single style provides consistency, which helps when referring to names since the capitalization is known and so does not have to be remembered.  It matches Java style, and other languages can be dealt with using automated name conversion.]

  2. Names MUST contain only ASCII letters and digits.  [Rationale: Ease of typing and absence of encoding compatibility problems.]

  3. Names SHOULD NOT exceed 25 characters. Longer names SHOULD be avoided by devising concise and informative names.  If a name can only remain within this limit by becoming obscure, the limit SHOULD be ignored.  [Rationale: Longer names are awkward to use and require additional bandwidth.]

  4. Published standard abbreviations, if sufficiently well-known, MAY be employed in constructing names. Ad hoc abbreviations MUST NOT be used.  Acronyms MUST be treated as words for camel-casing purposes: informationUri, not informationURI. [Rationale:  An abbreviation that is well known to one community is often incomprehensible to others who need to use the same document format (and who do understand the full name); treating an acronym as a word makes it easier to see where the word boundaries are.]


5. Elements

  1. All elements MUST contain either nothing, character content, or child elements.  Mixed content MUST NOT be used.  [Rationale: Many XML data models don't handle mixed content properly, and its use makes the element order-dependent.  As always, textual formats are not covered by this rule.]

  2. XML elements that merely wrap repeating child elements SHOULD NOT be used.  [Rationale: They are not used in Atom and add nothing.]


6. Attributes

  1. Document formats MUST NOT depend on the order of attributes in a start-tag.  [Rationale: Few XML parsers report the order, and it is not part of the XML Infoset.]

  2. Elements SHOULD NOT be overloaded with too many attributes (no more than 10 as a rule of thumb).  Instead, use child elements to encapsulate closely related attributes.  [Rationale: This approach maintains the built-in extensibility that XML provides with elements, and is useful for providing forward compatibility as a specification evolves.]

  3. Attributes MUST NOT be used to hold values in which line breaks are significant.  [Rationale: Such line breaks are converted to spaces by conformant XML parsers.]

  4. Document formats MUST allow either single or double quotation marks around attribute values.  [Rationale:  XML parsers don't report the difference.]


7. Values

  1. Numeric values SHOULD be 32-bit signed integers, 64-bit signed integers, or 64-bit IEEE doubles, all expressed in base 10.  These correspond to the XML Schema types xsd:int, xsd:long, and xsd:double respectively.  If required in particular cases, xsd:integer (unlimited-precision integer) values MAY also be used.  [Rationale: There are far too many numeric types in XML Schema: these provide a reasonable subset.] 

  2. Boolean values SHOULD NOT be used (use enumerations instead).  If they must be used, they MUST be expressed as true or false, corresponding to a subset of the XML Schema type xsd:boolean.  The alternative xsd:boolean values 1 and 0 MUST NOT be used.  [Rationale: Boolean arguments are not extensible.  The additional flexibility of allowing numeric values is not abstracted away by any parser.]

  3. Dates should be represented using RFC 3339 format, a subset of both ISO 8601 format and XML Schema xsd:dateTime format.  UTC times SHOULD be used rather than local times.  [Rationale: There are far too many date formats and time zones, although it is recognized that sometimes local time preserves important information.]

  4. Embedded syntax in character content and attribute values SHOULD NOT be used.  Syntax in values means XML tools are largely useless.  Syntaxes such as  dates, URIs, and XPath expressions are exceptions.  [Rationale:  Users should be able to process XML documents using only an XML parser without requiring additional special-purpose parsers, which are easy to get wrong.]

  5. Be careful with whitespace in values.  XML parsers don't strip whitespace in elements, but do convert newlines to spaces in attributes.  However, application frameworks may do more aggressive whitespace stripping.  Your document format SHOULD give rules for whitespace stripping.


8. Key-value pairs

  1. Simple key-value pairs SHOULD be represented with an empty element whose name represents the key, with the value attribute containing the value. Elements that have a value attribute MAY also have a unit attribute to specify the unit of a measured value.  For physical measurements, the SI system SHOULD be used.  [Rationale: Simplicity and design consistency.  Keeping the value in an attribute hides it from the user, since displaying just the value without the key is not useful.]

  2. If the number of possible keys is very large or unbounded, key-value pairs MAY be represented by a single generic element with key, value, and optional unit and scheme attributes (which serve to discriminate keys from different domains).  In that case, also provide (not necessarily in the same document) a list of keys with human-readable explanations.

9. Binary data

Note: There are no hard and fast rules about whether binary data should be included as part of an XML document or not.  If it's too large, it's probably better to link to it.


  1. Binary data MUST NOT be included directly as-is in XML documents, but MUST be encoded using Base64 encoding.  [Rationale: XML does not allow arbitrary binary bytes.]

  2. The line breaks required by Base64 MAY be omitted.  [Rationale: The line breaks are meant to keep plain text lines short, but XML is not really plain text.]

  3. An attribute named xsi:type with value xs:base64Binary MAY be attached to this element to signal that the Base64 format is in use.  [Rationale: Opaque blobs should have decoding instructions attached.]

10. Processing instructions

  1. New processing instructions MUST NOT be created except in order to specify purely local processing conventions, and SHOULD be avoided altogether.  Existing standardized processing instructions MAY be used.  [Rationale: Processing instructions fit awkwardly into XML data models and can always be replaced by elements; they exist primarily to avoid breaking backward compatibility.]

 

 

11. Representation of XML document instances

Note:  These points are only guidelines, as the format of program-created instances will often be outside the programmer's control (for example, when an XML serialization library is being used).  In no case should XML parsers rely on these guidelines being followed.  Use standard XML parsers, not hand-rolled hacks.


  1. The character encoding used SHOULD be UTF-8.  Exceptions should require extremely compelling circumstances.  [Rationale: UTF-8 is universal and in common use.]

  2. Namespaces SHOULD be declared in the root element of a document wherever possible.  [Rationale: Clarity and consistency.]

  3. The mapping of namespace URIs to prefixes SHOULD remain constant throughout the document, and SHOULD also be used in documentation of the design.  [Rationale: Clarity and consistency.]

  4. Well-known prefixes such as html: (for XHTML), dc: (for Dublin Core metadata), and xs: (for XML Schema) should be used for standard namespaces.  [Rationale: Human readability.]

  5. Redundant whitespace in a tag SHOULD NOT be used.  Use one space before each attribute in a start-tag; if the start tag is too long, the space MAY be replaced by a newline.  [Rationale: Consistency and conciseness.]

  6. Empty elements MAY be expressed as empty tags or a start-tag immediately followed by an end-tag. No distinction should be made between these two formats by any application.  [Rationale: They are not distinguished by XML parsers.]

  7. Documents MAY be pretty-printed using 2-space indentation for child elements.  Elements that contain character content SHOULD NOT be wrapped.  Long start-tags MAY be broken using newlines (possibly with extra indentation) after any attribute value except the last.  [Rationale: General compatibility with our style.  Wrapping character content affects its value.]

  8. Attribute values MAY be surrounded with either quotation marks or apostrophes. Specifications MUST NOT require or forbid the use of either form.  &apos; and &quot; may be freely used to escape each type of quote.  [Rationale: No XML parsers report the distinction.]

  9. Comments MUST NOT be used to carry real data.  Comments MAY be used to contain TODOs in hand-written XML.  Comments SHOULD NOT be used at all in publicly transmitted documents. [Rationale:  Comments are often discarded by parsers.]

  10. If comments are nevertheless used, they SHOULD appear only in the document prolog or in elements that contain child elements.  If pretty-printing is required, pretty-print comments like elements, but with line wrapping.  Comments SHOULD NOT appear in elements that contain character content.  [Rationale:  Whitespace in and around comments improves readability, but embedding a comment in character content can lead to confusion about what whitespace is or is not in the content.]

  11. Comments SHOULD have whitespace following <!-- and preceding -->.  [Rationale: Readability.]

  12. CDATA sections MAY be used; they are equivalent to the use of &amp; and &lt;.  Specifications MUST NOT require or forbid the use of CDATA sections.  [Rationale: Few XML parsers report the distinction, and combinations of CDATA and text are often reported as single objects anyway.]

  13. Entity references other than the XML standard entity references &amp;, &lt;, &gt;, &quot;, and &apos; MUST NOT be used.  Character references MAY be used, but actual characters are preferred, unless the character encoding is not UTF-8.  As usual, textual formats are exempt from this rule.

 



12. Elements vs. Attributes

Note:  There are no hard and fast rules for deciding when to use attributes and when to use elements.  Here are some of the considerations that designers should take into account; no rationales are given.

12.1. General points:

  1. Attributes are more restrictive than elements, and all designs have some elements, so an all-element design is simplest -- which is not the same as best.


  2. In a tree-style data model, elements are typically represented internally as nodes, which use more memory than the strings used to represent attributes.  Sometimes the nodes are of different application-specific classes, which in many languages also takes up memory to represent the classes.


  3. When streaming, elements are processed one at a time (possibly even piece by piece, depending on the XML parser you are using), whereas all the attributes of an element and their values are reported at once, which costs memory, particularly if some attribute values are very long.


  4. Both element content and attribute values need to be escaped appropriately, so escaping should not be a consideration in the design.


  5. In some programming languages and libraries, processing elements is easier; in others, processing attributes is easier.  Beware of using ease of processing as a criterion.  In particular, XSLT can handle either with equal facility.


  6. If a piece of data should usually be shown to the user, consider using an element; if not, consider using an attribute.  (This rule is often violated for one reason or another.)


  7. If you are extending an existing schema, do things by analogy to how things are done in that schema.


  8. Sensible schema languages, meaning RELAX NG and Schematron, treat elements and attributes symmetrically.  Older and cruder schema languages such as DTDs and XML Schema, tend to have better support for elements.

12.2 Using elements

  1. If something might appear more than once in a data model, use an element rather than introducing attributes with names like foo1, foo2, foo3 ....


  2. Use elements to represent a piece of information that can be considered an independent object and when the information is related via a parent/child relationship to another piece of information.


  3. Use elements when data incorporates strict typing or relationship rules.


  4. If order matters between two pieces of data, use elements for them: attributes are inherently unordered.


  5. If a piece of data has, or might have, its own substructure, use it in an element: getting substructure into an attribute is always messy.  Similarly, if the data is a constituent part of some larger piece of data, put it in an element.


  6. An exception to the previous rule: multiple whitespace-separated tokens can safely be put in an attribute.  In principle, the separator can be anything, but schema-language validators are currently only able to handle whitespace, so it's best to stick with that.


  7. If a piece of data extends across multiple lines, use an element: XML parsers will change newlines in attribute values into spaces.

  8. If a piece of data is very large, use an element so that its content can be streamed.

  9. If a piece of data is in a natural language, put it in an element so you can use the xml:lang attribute to label the language being used.  Some kinds of natural-language text, like Japanese, often make use annotations that are conventionally represented using child elements; right-to-left languages like Hebrew and Arabic may similarly require child elements to manage bidirectionality properly.

12.3 Using attributes

  1. If the data is a code from an enumeration, code list, or controlled vocabulary, put it in an attribute if possible.  For example, language tags, currency codes, medical diagnostic codes, etc. are best handled as attributes.


  2. If a piece of data is really metadata on some other piece of data (for example, representing a class or role that the main data serves,  or specifying a method of processing it), put it in an attribute if possible.


  3. In particular, if a piece of data is an ID for some other piece of data, or a reference to such an ID, put the identifying piece in an attribute.  When it's an ID, use the name xml:id for the attribute.


  4. Hypertext references are conventionally put in href attributes.


  5. If a piece of data is applicable to an element and any descendant elements unless it is overridden in some of them, it is conventional to put it in an attribute.  Well-known examples are xml:lang, xml:space, xml:base, and namespace declarations.


  6. If terseness is really the most important thing, use attributes, but consider gzip compression instead -- it works very well on documents with highly repetitive structures.



13. Parting words

Use common sense and BE CONSISTENT.   Design for extensibility.  You are gonna need it.  [Rationale: Long and painful experience.]


When designing XML formats, take a few minutes to look at other formats and determine their style.  The point of having style guidelines is so that people can concentrate on what you are saying, rather than on how you are saying it.


Break ANY OR ALL of these rules (yes, even the ones that say MUST) rather than create a crude, arbitrary, disgusting mess of a design if that's what following them slavishly would give you.  In particular, random mixtures of attributes and child elements are hard to follow and hard to use, though it often makes good sense to use both when the data clearly fall into two different groups such as simple/complex or metadata/data.


Newbies always ask:

    "Elements or attributes?

Which will serve me best?"

    Those who know roar like lions;

    Wise hackers smile like tigers.

                    --a tanka, or extended haiku



[TODO: if a registry of schemas is set up, add a link to it]