Designing for Extensibility

Substrate

The interfaces defined within Substrates API are designed with extensibility and evolution in mind, both from a client library and provider implementation perspective. Extensibility starts with the Substrate interface, a foundational interface extended by all interfaces annotated with @Provided, that defines a single method, named environment, that returns an Environment instance.

Environment

The Environment interface, originally designed to allow for interfacing with existing configuration stores and systems, offers a standard way for implementation providers to expose additional extension properties to each of the @Provided annotated interfaces.

The Environment interface extends the Lookup interface with additional type-specific methods for common class types, such as Integer, Long, String, Double, Boolean, etc., where typed values are accessed using a predefined Name, think of a key into a map structure, that can be specified in a provider’s supporting documentation or published within a utility class or interface.

A benefit of this design choice is that the surface area of the interfaces that extend the Substrate interface can be kept to a bare minimum, a “least common denominator” set of properties and operations across all implementations of the Substrates API, while still allowing for the environment-, configuration-, provider-, runtime-specific state of being publically accessible without impacting the ability of a client codebase (agent, application, plugin) to move from one implementation provider to another.

Variable

Using the Variable interface is recommended when working with the Environment interface in repeatedly looking up a particular named value as a provider can optimize the underlying internal implementation, such as adding caching and short-circuiting code paths.

The Cortex interface, the Substrates API root fabrication runtime component, offers various overloaded methods to create a type-specific Variable instance, such as specifying a default value when a lookup does not succeed and a transformation when it does.