Design Principles - adewg/ICAR GitHub Wiki

The ADE standards are intended to be used in a wide variety of industry applications. As a result, the priorities of the working group are in order:

  • Defining a robust and documented data model at appropriate granularity that allows it to be used for a variety of purposes, extended, and to support a variety of permission models (including granting access to some data types and not others).
  • Defining an API specification that behaves consistently - implementing standard status codes, query string filtering and pagination.
  • Making the API specification able to be navigated or predicted by specification of the URL path, and/or by linking.

Resource (message) Design

When designing a resource or message, the working group considers:

  • Isolated usage - does it make sense for the resource to be used by itself (for a client to GET a single resource or a collection of these resources?
  • Granularity of permission - does it make sense for some fields to be shared with a party while other fields are not shared? If sets of fields require different permissions, they should be in a separate message or resource.
  • Multi-vendor support - is this a specific feature that can be supported or not by a vendor. The preference is to have availability of endpoints as an indication of availability of features. However, if this is simply a more detailed extension to a message, it may be simply modelled as some optional field(s).
  • Simplest implementation first - prefer a simpler implementation first, and avoid large messages or embedded resources unless the embedded types reflect genuinely nested structures (for example, metadata and ID formats). Linking should be explicit where used.
  • Smallest implementation first - favour more, smaller messages because it is easier to combine messages (by adding optional fields) in future than to split messages.

Fault-tolerance and extensibility

  • When consuming the data, use a tolerant-reader pattern. If there are any fields in the message that you do not recognise, simply ignore them. This allows the standard to add new fields while maintaining backwards compatibility.
  • Optimise for 80% of the use cases, and allow extension. Implementers may add additional, non-mandatory fields to their implementations, and also propose these for future inclusion in the standard.

URL or Endpoint Design

  • The transport of messages is a separate recommended layer in the specs; the defined messages can be transported by any means. We do however specify a recommended URL scheme for REST end-points since we expect that that will be the most used transportation mechanism.
  • There should be clear endpoints that combine a verb with the resource - for instance an endpoint to GET a resource, or to get a list of resources.
  • This allows service implementations to allow specific access to only the data authorised for the use case.
  • Allow service implementers to decide which endpoints are implemented and which are not implemented.
  • In developing the standard we expect to recommend standard endpoint names and standard query parameters (services may implement additional query parameters). See Filtering resources for more details.
  • Avoid output-parameters that steer what the end-point should produce. Prefer specialised endpoints if special functionality is required.

Dealing with id's

All resources have an id. The standard strongly recommends to use UUID's for this field. If that is not possible, the id scheme used should at least provide for unique ids for your system.

Id's may originate from different systems somewhere in the chain. Systems may require their own ids to be used. To track a single event over multiple systems, the source and sourceId fields are introduced. If your system is the originating system (the first to record the event) you should populate these fields. The sourceId should be unique for your system (ideally a UUID), and the source should indicate a unique name for your system. Systems that pass along these events should keep and transfer these source values, even if they assign new ids to events or resources.

We consider that eventually an alternativeIdentifiers[] array should be added to all resources (it is currently available for icarAnimalCoreResource) but we will wait until there is clear demand.

Dealing with multiple standards in different countries, devices or software

When defining id's or enum's, often there are multiple existing standards to choose from. Rather than adding our own standard to the list, we prefer to absorb existing standards. For that, we adopt a scheme+value or scheme+id strategy where the scheme points to an existing standard, and the value or id to defined value within that standard. For example, to indicate a specific location or farm in the Netherlands, we may use the Dutch ubn scheme: location-scheme=nl.ubn&location-id=12345.

For more information on this, see Schemes.

Dealing with time

In numerous messages, the notion of time and timestamps pop up. Within the ICAR ADE standard the following design principles have been decided on:

  • all timestamps are in ISO 8601 format ("2020-10-25T09:00Z")
  • we strongly recommend to only use the 'Z' (Zulu, UTC) time offset.

To convert a timestamp to a local datetime, it is recommended to work with timezones. The standard will provide an API to retrieve the timezone for a specific location, but other timezones could be configured locally.

  • timezones are based on the ICANN tz database (Wikipedia)

Providing other offsets (e.g. "2020-10-25T09:00+01:00"), while semantically the same as the Zulu offset, offer no real benefits and as such are discouraged.

Style Guidelines

We have defined some style guides which help make the standard more predictable. The following style guides define the syntax of messages, of our recommended url scheme. We also have some style guides on the source of the standard.

Messages

  • field names are denoted as camelCase. E.g. id, pageSize, ...
  • enum values preferably point to an existing defined standard. If there is none, enum values are denoted as PascalCase. E.g. the enum traitScored can be: Angularity, BackLength, ...
  • values that consist of more than one field (e.g. scheme + id) are always grouped together in a new object type (e.g. "location": {"id": "...","scheme": "..."}.

URL Scheme

  • end-points have a location in the URL scheme to set a base scope for the message
  • resources are denoted as kebab-case
  • resources are plural if they return a collection
  • filter parameters as denoted as kebab-case as described in Filtering resources

Source layout

  • the message definitions are split up in small files so that we can track individual changes to a specific message.
  • resources are messages that are directly retrievable via an endpoint. They may make use of other resources, types or enums.
  • types are small objects that are not retrievable by themselves. They form a complex object that can be used by resources.
  • enums are string objects with a limited set of values, that are not retrievable by themselves and can be used by resources.
  • collections define a set of resources.
  • in examples, some example messages can be found.
  • in 'url-schemes, the recommended url schemes can be found.