Skip to content

Commit aad4172

Browse files
committed
Update design guidelines
1 parent a58ea91 commit aad4172

File tree

1 file changed

+13
-27
lines changed

1 file changed

+13
-27
lines changed

.gemini/styleguide.md

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,3 @@
1-
# Style Guide
2-
3-
## General Principles
4-
5-
APIs added should be:
6-
- Scalable
7-
- Robust
8-
- Backwards compatible
9-
- Future-proof
10-
- Interoperable
11-
- Must work across all backends
12-
13-
---
14-
151
# Keras API design guidelines
162

173
These guidelines are meant to help focus design discussions and help us create delightful developer experiences.
@@ -29,23 +15,23 @@ Some text remixed from external references:
2915

3016
When developing APIs, start by designing end-to-end workflows, and only sketch out specific function/class signatures at the end.
3117

32-
- The goal is to arrive at workflows that feel like they are purposefully designed and well-optimized, rather than cobbled together to route around the features provided by the API. The workflows should come first, before atomic features. **Features only exist to support a workflow.** No feature should exist to provide a capability just in case”, “because we can.
18+
- The goal is to arrive at workflows that feel like they are purposefully designed and well-optimized, rather than cobbled together to route around the features provided by the API. The workflows should come first, before atomic features. **Features only exist to support a workflow.** No feature should exist to provide a capability "just in case", "because we can".
3319
- **Every design review document should prominently feature a code example of one or two end-to-end workflows showing the canonical use-case for the new API.**
3420
- Every time we discuss choices surrounding a specific API feature, we should start by asking: **in what workflows will this be used?** Then we should make the choice that makes the most sense with respect to these workflows. We should not make API design decisions about features in isolation.
35-
- This implies that we will often ask the question: **do users really need to configure this parameter?**, and in many cases, the answer will be “no”, rather than being yes by default.
21+
- This implies that we will often ask the question: **do users really need to configure this parameter?**, and in many cases, the answer will be "no", rather than being "yes" by default.
3622

3723
---
3824

3925
## Carefully weigh whether a new feature should be included.
4026

41-
Its okay to say no: just because someone asks for a feature doesnt mean we should do it. Every feature has a cost that goes beyond the initial CL: maintenance cost, documentation cost, and cognitive cost for our users (a sprawling API surface is a major usability issue).
27+
It's okay to say no: just because someone asks for a feature doesn't mean we should do it. Every feature has a cost that goes beyond the initial CL: maintenance cost, documentation cost, and cognitive cost for our users (a sprawling API surface is a major usability issue).
4228

4329
In particular, in the Keras API, every new feature has to be maintained in perpetuity.
4430

4531
As such, our criteria for adding a new feature in the API is the following:
4632

4733
- **It should be broadly useful to our users**, rather than a niche feature that is only relevant to a specific vertical of researchers. Niche features should be maintained independently by those who need them (e.g. by extending the API via subclassing), as third-party add-on packages.
48-
- **It should be widely recognized as a machine learning best practice.** We will not add new layers/etc that were recently published to ArXiv.org, even in case of claims of increased accuracy/etc. We only add new objects that are already commonly used in the machine learning community. Presumably, a new technique that does result in meaningful gains would be broadly adopted after a few months anyway (like ResNet), and thats when we would be adding it to the core API. SIG-addons maintains a repository of significantly more volatile and independently maintained code to which the barriers to entry are lower.
34+
- **It should be widely recognized as a machine learning best practice.** We will not add new layers/etc that were recently published to ArXiv.org, even in case of claims of increased accuracy/etc. We only add new objects that are already commonly used in the machine learning community. Presumably, a new technique that does result in meaningful gains would be broadly adopted after a few months anyway (like ResNet), and that's when we would be adding it to the core API. SIG-addons maintains a repository of significantly more volatile and independently maintained code to which the barriers to entry are lower.
4935
- **It should have an owner committed to maintaining it in the long term.** In particular, the code should be maintainable by multiple people on the team, not just by one technical guru.
5036

5137
In addition, when saying yes to a request for supporting a new use case, remember that **literally adding what the user/team requested is often not the optimal choice**. Users are focused on their own specific use case, and we must counter this with a holistic and principled vision of the whole project (see: designing end-to-end workflows, not atomic functions/classes). Often, the right answer is to extend an existing feature. **Find the natural place to integrate the new feature in existing APIs.**
@@ -64,12 +50,12 @@ Always seek to minimize the cognitive load imposed on our users in the course of
6450
At a high level:
6551

6652
- **Automate everything that can be automated.**
67-
- **Minimize the actions & choices required from the user.** Make sure default values for arguments are sensible and reflect best practices (so that users usually wouldnt have to manually configure these). Dont expose options that are not important or do not match real use cases, just in case.
53+
- **Minimize the actions & choices required from the user.** Make sure default values for arguments are sensible and reflect best practices (so that users usually wouldn't have to manually configure these). Don't expose options that are not important or do not match real use cases, "just in case".
6854
- **Design simple and consistent workflows that reflect simple and consistent mental models.**
6955

7056
Here are a few practical rules:
7157

72-
- **No API should deal with internal implementation details.** An API is a language for our users to talk about the problem they care about -- and they dont care about our internal hacks. For instance, an option like `use_locking` in an optimizer should be avoided. If an argument requires users to understand the implementation (not just what the code is supposed to implement, like SGD in this case), then the argument should not be included in the public API. **An API is all about the problem it solves, not about how the code works in the background.**
58+
- **No API should deal with internal implementation details.** An API is a language for our users to talk about the problem they care about -- and they don't care about our internal hacks. For instance, an option like `use_locking` in an optimizer should be avoided. If an argument requires users to understand the implementation (not just what the code is supposed to implement, like SGD in this case), then the argument should not be included in the public API. **An API is all about the problem it solves, not about how the code works in the background.**
7359
- **Introduce as few new concepts as possible.** It's not just that additional data structures require more effort in order to learn about their methods and properties, it's that they multiply the number of **mental models** that are necessary to grok your API. Ideally, you should only need **a single universal mental model around which everything is organized** (in Keras, that's the `Layer`). Definitely avoid having more than 2 or 3 mental models underlying the workflows you design. Likewise, avoid having concepts that are mostly overlapping but subtly different, since the difference will be difficult to convey clearly and will confuse our users (like, say, `Network` and `Model` -- this is why we don't export `Network` as a public API).
7460
- **Objects that do interchangeable things should have identical or very close APIs.** In particular they should have the same positional arguments. For example, it should be possible to swap one optimizer for another in user code (when leaving all arguments to their default value) without editing the arguments.
7561
- **If you find yourself proposing a signature with more than 6-7 arguments, consider whether all of these arguments are useful.** How many people and use cases would be affected if you removed one argument? How much would they be affected -- would they be able to easily extend the API (e.g. via subclassing) to support their use case without that built-in argument? Could this API be broken up into smaller, modular objects?
@@ -79,10 +65,10 @@ Here are a few practical rules:
7965

8066
In particular, naming is important and difficult:
8167

82-
- **The meaning of an argument should be clear from its name and should not require knowledge that only the implementers have.** In particular, argument names should only involve recognized terms of art (L1 norm is a term of art), and should not involve implementation-related vocabulary (e.g. fused batchnorm).
83-
- **Avoid `OverlyLongAndSpecificNamingPatterns`.** If you find yourself with argument names with involve more than 3 subparts (e.g. squared_operator_norm), reconsider. Argument names should be intuitive and easy to remember.
68+
- **The meaning of an argument should be clear from its name and should not require knowledge that only the implementers have.** In particular, argument names should only involve recognized terms of art ("L1 norm" is a term of art), and should not involve implementation-related vocabulary (e.g. "fused batchnorm").
69+
- **Avoid `OverlyLongAndSpecificNamingPatterns`.** If you find yourself with argument names with involve more than 3 subparts (e.g. "squared_operator_norm"), reconsider. Argument names should be intuitive and easy to remember.
8470
- Avoid overly generic names (`x`, `variable`, `parameter`).
85-
- **Make sure you are consistent in your naming choices.** Naming consistency means both **internal naming consistency** (dont call `dim` what is called `axis` in other places, dont call `ndims` what is called `ndim` elsewhere) and **consistency with established conventions for the problem domain (terms of art)**. Before settling on a name, make sure to look up existing names used by domain experts (or other APIs). In our case, argument names should be consistent with the broader scientific Python conventions, in particular NumPy.
71+
- **Make sure you are consistent in your naming choices.** Naming consistency means both **internal naming consistency** (don't call `dim` what is called `axis` in other places, don't call `ndims` what is called `ndim` elsewhere) and **consistency with established conventions for the problem domain (terms of art)**. Before settling on a name, make sure to look up existing names used by domain experts (or other APIs). In our case, argument names should be consistent with the broader scientific Python conventions, in particular NumPy.
8672

8773
Note that Keras uses the following naming rules:
8874

@@ -130,7 +116,7 @@ What's nice about this?
130116

131117
### Simple use cases should be simple, advanced use cases should be possible:
132118

133-
**Dont increase the cognitive load of common use cases for the sake of niche use cases**, even minimally.
119+
**Don't increase the cognitive load of common use cases for the sake of niche use cases**, even minimally.
134120
**Make sure that advanced users have a path to support their use case**, even if this path requires the users to roll out plugins or other API extensions (in particular via subclassing). **It is ok for advanced use cases not to be directly supported in the built-in API options.**
135121

136122
### Keep our APIs modular.
@@ -146,7 +132,7 @@ For instance, the optimizer API or the layers API should not contain arguments f
146132

147133
---
148134

149-
## Dont neglect error messages, docstrings, and documentation.
135+
## Don't neglect error messages, docstrings, and documentation.
150136

151137
Documentation and error messages are an integral part of the API. Good docs and helpful error messages are key to a delightful user experience.
152138

@@ -155,8 +141,8 @@ Documentation and error messages are an integral part of the API. Good docs and
155141
- What happened, in what context?
156142
- What did the software expect?
157143
- How can the user fix it?
158-
- **A docstring should answer the question: what is this about, and why & how should I use it?** It should assume as little context as possible, and it shouldnt mention specialized terms without first introducing them (for example, num_blocks: Number of blocks in the kernel is not a good argument description if this is the first time you mention blocks in your docstring).
159-
- **Show, dont tell: your documentation should not talk about how the software works, it should show how to use it.** Show code examples for end-to-end workflows; show code examples for each and every common use case and key feature of your API. **All docstrings should include code examples.**
144+
- **A docstring should answer the question: what is this about, and why & how should I use it?** It should assume as little context as possible, and it shouldn't mention specialized terms without first introducing them (for example, "num_blocks: Number of blocks in the kernel" is not a good argument description if this is the first time you mention "blocks" in your docstring).
145+
- **Show, don't tell: your documentation should not talk about how the software works, it should show how to use it.** Show code examples for end-to-end workflows; show code examples for each and every common use case and key feature of your API. **All docstrings should include code examples.**
160146
- **Deliberately design the user onboarding process for your feature.** How are complete newcomers going to find out the best way to solve their use case with your tool? Have an answer ready. Make sure your onboarding material closely maps to what your users care about: don't teach newcomers how your framework is implemented, teach them how they can use it to solve their own problems. After shipping a CL and writing good docstrings, make sure to create a Colab guide / tutorial showcasing the target workflow, and post it on the docs website.
161147
- The feature is not ready until:
162148
- 1) Users know about it

0 commit comments

Comments
 (0)