Skip to content

API Design guidelines

Aleksey edited this page Oct 23, 2019 · 3 revisions

Terms

API - code supposed to be implemented by qbit and called by client.

SPI - code supposed to be implemented by client and called by qbit.

API surface

qbit's API surface consist of packages:

  1. classes directly placed in qbit package. The package defines entry points (Factories) for qbit functionality.
  2. classes placed in package qbit.api and all it subpackages. These packages defines model of qbit intended to be used by qbit users
  3. classes placed in package qbit.spi and all it subpackages. These packages defines qbit extension points intended to be implemented by qbit users.

Everything in qbit and qbit.api packages should be defensed from subclassing by users. Everything in qbit.api packages should be defensed from direct instantiation by user. Everything in qbit.spi packaged should be designed for subclassing and/or implementation. Everything in all other packages should have internal access.

Hide everything

Keep API surface as small as possible.

Rationale

Anything you publish can be used against you

Minimally complete

Each API element should be backed by well-reasoned use case

Rationale

  • Anything you publish can be used against you
  • Anything published should be maintained for all life span of qbit

Separate API from SPI

Each API element should be either defensed from subclassing/implementation or designed for it.

Rationale

API and SPI have different evolution modes. For API addition of methods is allowed, but removal is prohibited. For SPI the rules is reversed.

Discoverability

User should be able to find out how to perform given task without reading documentation.

Rationale

It increases convenience and ease of use of qbit

Defense from misuse

Rationale

It decreases annoyance of users

Tips

Prefer enums to booleans in params to defense from misuse and improve code readability.

Consistancy

API classes, methods params and properties should be named and behave consistently with each other.

Rationale

It increases convenience and ease of use of qbit and decreases annoyance of users

Tips

Use exact same name for same things

Use same order of same parameters in different methods

Consistently use funs and val props