| # API Standards for Foundation Services |
| |
| In creating and maintaining the public-facing structure of a foundation service, |
| you should hold yourself to several first-order goals: |
| |
| * The purpose of the service should be readily apparent. |
| * The supported usage models of the service should be easy for a new |
| consumer to understand. |
| * The service should be consistent with other foundation services. |
| * From the API documentation and tests, it should be feasible |
| to develop a distinct implementation of the service (i.e., without having to |
| delve into the internals of the current implementation). |
| |
| Below we outline concrete standards that aid in achieving the above goals. |
| |
| ## Naming |
| |
| * Strive to give your service a name that makes it immediately obvious what the |
| service is for ("network", "metrics"). |
| |
| * Avoid the usage of "Service" in interface names. While the term "Service" is |
| overloaded in Chromium, in the context of //services it has a very specific |
| meaning and should not be overloaded. |
| |
| * Strive to avoid conceptual layering violations in naming -- e.g., references |
| to Blink or //content. |
| |
| * Use the names "FooClient" and "FooObserver" consistently in interfaces. If |
| there is an expected 1:1 correspondence between Foo and its counterpart, that |
| counterpart should be called FooClient. If there is an expected 1:many |
| correspondence between Foo and its counterparts, those counterparts should be |
| called FooObservers. |
| |
| ## Documentation |
| |
| * Every service should have a top-level README.md that explains the purpose and |
| supported usage models of the service. |
| |
| * Every public interface should be documented at the interface (class) level and |
| at the method level. |
| |
| * Interface documentation should be complete enough to serve as test |
| specifications. If the method returns information of a user's accounts, what |
| happens if the user is not signed in? If the method makes a request for an |
| access token, what happens if a client makes a second method call before a |
| first one has completed? If the method returns a nullable object, under which |
| conditions will it be null? |
| |
| * Strive to avoid your documentation being too specific to a given client. |
| |
| ## API Shape |
| |
| * Strive to avoid molding your API shape too specifically to the needs of a |
| given client. Most foundational services should make sense even in a |
| Chrome-less system environment. A good test is: Would your service's APIs seem |
| sensible to users who don't have knowledge of Chrome's specific needs? |
| |
| * If a given interface Foo requires "construction parameters" (e.g., the client |
| must give it a FooClient before calling any methods), provide a FooProvider |
| interface with a GetFoo() method that takes in the relevant construction |
| parameters. This approach eliminates the possibility of a badly-written (or |
| malevolent) client calling methods on a partially-constructed Foo. To be |
| concrete: |
| |
| ```` |
| // NO: Client will have access to partially-constructed Foo. |
| interface Foo { |
| SetClient(FooClient client); |
| ... |
| }; |
| |
| // YES: Foo will be completely constructed before client has access. |
| interface FooProvider { |
| GetFoo(Foo& request, FooClient client); |
| }; |
| interface Foo { ... }; |
| ```` |
| |
| * In the absence of specific guidance, strive for consistency with surrounding |
| interfaces and with interfaces in other services. |
| |
| ## Testing |
| |
| * Use service tests to test the public interfaces exposed by your service. |
| |
| * Every public method should be covered by at least one service test. Strive |
| to have your tests enforce your documentation (corollary: if you can enforce |
| your documentation without any tests, improve your documentation :). |
| |
| * Think of these tests as a form of "compliance tests": They should be written |
| in such a way that engineers with a distinct implementation of your |
| APIs should trivially be able to run your tests against their implementation. |
| Notably, try to avoid relying on implementation details of the service in its |
| tests. |
| |
| * Related to the above, aim for a high degree of coverage with these tests. If a |
| reimplementation passes your tests, you should have a high degree of |
| confidence that it will be usable by your consumers. |
| |
| ## Appendix: Responsibility for Upholding These Standards |
| |
| The responsibility for holding these standards is shared across |
| //services/OWNERS, individual service OWNERS, and services developers: |
| |
| * //services/OWNERS own the standards themselves and are responsible for |
| ensuring that quality and consistency are maintained across //services. |
| * Individual service OWNERS are responsible for ensuring that their service |
| adheres to these standards. |
| * Service developers are responsible for ensuring that their CLs adhere to |
| these standards (and thus making life easier for the OWNERS that must review |
| these CLs :). |
| |
| We expect that these standards will evolve over time. If you encounter a tricky |
| situation not covered here, please send an email to services-dev@. Similarly, if |
| you see inconsistency or violations of the standards, please file a bug and CC |
| relevant OWNERS (i.e., of the service in question and/or //services/OWNERS). |