The guidance below is for the code of the Theia framework only. End products will get better development experience by using private visibility.
Theia is a framework embracing openness, extensibility, and customizability as much as possible:
Usually, the version management is built around API visibility. Particularly, when a public API is broken a new major release is required.
Since all APIs are more or less public, following the conventional approach is not practicable for Theia. It will slow down API innovation, accumulate technical debt or require many major releases.
Instead, we demand a major release only if a stable API is broken. Breaking an experimental API is allowed in a minor release.
Conceptually, an API consists of all assumptions adopters depend on to make use or extend Theia. A stable API is based on assumptions that are not subject to change. It does not matter whether an API is public or internal, or whether it is used a lot or never.
For instance, the language server protocol (LSP) depends on such data types like URIs and positions since they don't change from language to language. It ensures its stability.
API stability is indicated explicitly by adding @experimental
or @stable
js-doc tags.
The explicit stability tag should be accompanied by @since
tag indicating when API was added.
The @stable
tag should mention since which version an API was finalized.
An API without a stability tag is considered to be experimental and does not require @since
tag.
/**
* One does not need any annotations while working on experimental APIs.
*/
export interface ExperimentalInterface {
}
/**
* @since 0.1.0
* @stable since 1.0.0
*/
export interface StableInterface {
/**
* The same as `StableInterface`.
*/
stableMethod(): void;
/**
* Adding new API to stable API should be explicit.
*
* @since 1.1.0
* @experimental
*/
experimentalMethod(): void;
}
stable
via the finalization cycle.API finalization should be requested via GitHub issues with api-finalization
label.
Such request should be resolved via a pull request following to PR guidelines.
Finalization implies a review of the adoption, stability, and documentation of APIs. One cannot judge stability without gaining enough experience and provide stable documentation without API stability in the first place.
If there is not enough adoption, then finalization should be postponed. If it does not get adopted later, it should be considered to move APIs from the framework to another repository managed by requesting adopters.
Why? Consider the case if the LSP would have a feature that can be supported only by one tool. It is reasonable to move such a feature to a tool specific LSP extension instead of bloating the protocol. The same applies to the framework: If API is added and used only by one adopter, then such API has to be moved to the adopter. It ensures control of API for such adopters and reduces the API surface of the framework.
If APIs are based on design decisions that are subject to change, then one could postpone finalization before such decisions are resolved.
Why? Some design decisions are only temporarily subject to change, for instance, which layout framework should be used. After it is resolved, such a design decision becomes fundamental, cannot be changed, and can be adopted.
If it is not possible, then APIs should be refactored to hide such assumptions.
Why? Some design decisions are changeable by nature, for instance, for the LSP, kind of symbols of a concrete language. In such a case, API should be changed to operate abstract symbol data type to hide concrete symbols.
If sufficient adoption and API stability are established, documentation should be reviewed and completed.
API deprecation is indicated by adding @deprecated
js-doc tag.
The deprecation tag should mention, since which version it is deprecated, explain why and what should be used instead.
/**
* @since 0.1.0
* @stable since 1.0.0
* @deprecated since 1.1.0 - because that and that, use that instead
*/
export interface DeprecatedStableInterface {
}
Deprecated stable API can be removed in one of the next major releases
Deprecated experimental API can be removed in one of the next minor releases
Breaking changes should be documented in CHANGELOG. Each breaking change should be justified to adopters and guide what should be done instead.