Sunday, September 13, 2015

Features, Interfaces, & Data as Resources

What are Resources?

A resource is something that is available to fulfill some systemic or human need.The IETF Uniform Resource Identifiers (URIs): General syntax specification [RFC 3986] defines a resource simply as "whatever might be identified by a URI." This broad and generic definition of a resource allows for many possibilities in software applications, as resources may be systems, devices, services, components, data, and even program units.

What is an Interface?

Generally speaking an interface is a contract of behavior, defined so that two or more resources can interoperate with one another. Interfaces may be defined using formal definition languages, such as IDL, within programming languages, such as Java, or they can simply be human-readable documents. 

What is a Feature?

For the purposes of this document, a feature is the "smallest unit of control" or more specifically a collection of variables and units of code, e.g., attributes, properties, procedures, functions, and/or methods, that interact with those variables to perform a an atomic user requirement, e.g., change a TV channel, setting the output volume of an audio device, set the temperature of a heater, or get the temperature reading from a thermostat. When defined in such a granular fashion features can be combined to construct complex behaviors, using standard, interoperable, and/or well-known methods that resources and programs can use to interact.
For example, setting and getting the temperature of a thermostat, an oven, an air conditioner, or a water heater are essentially the same for all of these resources / devices, just as playing, fast forwarding, and rewinding media is the same for the media devices and services that implement the playout of media, whether the resource is a software service, a Blu Ray players, a digital Video Recorder (DVR), video camera, or a professional digital media server.

Feature Interfaces

In most legacy applications interfaces were defined as monolithic structures, including all of the behaviors and attributes implemented by an object, service, or component. But with the advent of Microservices and other feature-based development methodologies, such as the Capabilities defined in the SMPTE ST2071 suite of standards, interfaces can be used to define the behavior and attributes of individual features, with these feature interfaces being plain old interfaces defining a narrow scope of behavior, one feature, e.g., Get Temperature. This programmers to describe the behavior of resources in a standard, vendor, device, and service agnostic fashion and for client developers to write to a set of predefined features without regard for the resource that will be implementing the feature interfaces. Since each feature interface contains a small number of functions and variables, comprehensive tests can more easily be developed against the feature interface. Thus allowing for greater security and better overall quality of the implementations; as developers are more willing to write 10 to 15 unit and security tests for an interface that defines only 2 or 3 functions than they are to write the equivalent test coverage for monolithic interfaces containing 15, 20, 30 or more functions. Developers are also more likely to miss the full gamut of functional and security related tests for larger interfaces, the chances of and number of tests missing growing with the size of the interface. These tests can be developed against the ideal expectation of the feature interface, guaranteeing that compatible implementations perform exactly as the API designer intended.

Feature interfaces can also be aggregated like building blocks to describe complex behaviors and interactions, while adding a measure of isolation between each feature. When done properly, a resource can have its functionality fully described and allow new features added without negatively impacting clients. While REST helps to mitigate this specific issue, the client compatibility issue still remains for strongly types systems and does not provide a standardized means for a resource to implement multiple versions of the same featureset, making backward compatibility with older clients much easier. In addition, new resources can be added to the network or system and clients written to specific features will be able to interact with those new resources without change. When combined with a service discovery protocol, the clients will not even need a configuration change.

Interfaces as Resources that Describe Features

Using the generic definition of a resource, an interface can also be a resource; a resource that defines how two or more other resources will interoperate with one another. Each of these feature interfaces can then be uniquely identified using a URI. With the unique identification of these feature interfaces methods can easily be constructed to facilitate the discovery of the resources that implement these feature interfaces in an automated fashion.

Please note that the programming language(a) used to implement these concepts do not need to implement formal interface support, as these interface definitions can be defined in human-readable documentation.

Example of a Feature Interface and Its Identity

The following is a series of feature interfaces used to define the features implemented by a thermostat. The interfaces can be mixed and matched, like Lego(tm) blocks to define the specific thermostat implementation, e.g., household tempurature control, an oven, an air conditioner, a generic tempurature sensor, or a centralized service controlling such a system.

@Identity("feature://api.example.com/thermostat/TempuratureSupport")
public interface TempuratureSupport
{
    float getTemperature();
}


@Identity("feature://api.example.com/thermostat/SetTempurature")
public interface SetTemperature
{
    public void setTemperature(float temperature);
}


@Identity("feature://api.example.com/thermostat/ZoneSupport")
public interface ZoneSupport
{
    public int[] getZones();
    public int getZone();
    public String[] getZoneNames();
    public void setZone(int zone);
}


@Identity("feature://api.example.com/thermostat/SetZone")
public interface SetZone
{
    public void setZoneName(String name);
}


@Identity("feature://api.example.com/thermostat/ModeSupport")
public interface ModeSupport
{
    public enum MODE {
        HEAT, COOL, AUTO;
    }
    public MODE getMode();
}


@Identity("feature://api.example.com/thermostat/SetMode")
public interface SetMode
{
    public void setMode(MODE mode);
}