For a large team to co-create something of value, it must work on principles of shared goals, trust, and an ability to rely on outcomes produced by the sub-teams. This is true for teams working on a single project, teams working on larger programs, program teams working to achieve organization goals, as well as different organisations collaborating toward a larger outcome.

Before the advent of software, institutional mechanisms were designed to address trust and reliability concerns. “Contracts” were the essential mechanism to establish as well as enforce them. Organizational contracts are registered and enforced via trust intermediaries such as government departments, banks, courts, etc. Within organizations there are separate quality control departments that conduct periodic audits of programs and projects, which perform a similar function of ensuring that everyone plays by the rules to effectively achieve business goals.

As software projects became ubiquitous, they were plagued by similar issues of trust and reliability within teams collaborating toward a shared outcome. Initially developers tried to solve these by borrowing concepts from the non-IT world by creating documents that reflected the operating rules. Examples of these are architecture documents, design documents, coding standards, coding guidelines, etc. While we usually do not perceive these as contracts, they essentially serve the same purpose – establish common rules for separate parts of the sub-systems and expect teams to cooperate and adhere to them – with architects, managers, and quality control associates acting as trust intermediaries.

While the above attempt was successful, it still needed human intervention to enforce the contracts. As software tooling improved, it gave rise to various tools that can codify and enforce most of the software rules and guidelines by flagging violations during the development process. This is in fact the norm for most mature development teams.

Technology innovation also gave rise to Blockchain with a programmatic ability to codify and enforce business contracts within organizations in a decentralized manner without having a separate third-party intermediary. While the adoption has had a lukewarm start, it is in the right direction to enforce trust, which will form the bedrock of commerce.

Coming back to software development teams, a common issue that they faced was the distribution of work across multiple teams and the ability to integrate it seamlessly so that it provided a technically robust product. It is easier said than done because this problem needs to be solved on multiple levels.

In the rest of the article, we will explore these:

Intra-process dependency

In software terms, a process is the executable unit within the operating system. It contains programming instructions that are executed as the process runs. These instructions are written in programming languages such as C++, Java, Python, etc.

Typically, the programming instructions are composed using multiple programs within libraries or packages. It is common to have different teams that have ownership of a set of libraries. At the same time, the libraries owned by different teams have programmatic dependencies on each other. This is known as intra process dependency.

The common solution to establish and enforce trust in this context is to define explicit interfaces that abstract the functionality of the library and provide a mechanism for other teams to depend on it without bothering about the underlying implementation of the dependent library.

Here the “interface files” act as the contracts for intra process dependencies.

Inter-process dependency

Inter process dependency occurs when a program within one process depends on a program within another process. In this case the process boundary definition can be considered fluid. It can be two processes running on the same machine, two processes running on different machines within the same network, or even two processes running across network boundaries such as an on-premises machine to cloud dependency or vice-versa.

The most common way to facilitate inter-process communication is by exposing APIs that provide dependent functionality. REST APIs happen to be the most popular formats for designing APIs.

Here the APIs act as trust boundaries by abstracting the underlying functionality. They also define the expected inputs and resulting outputs. These input and output definitions act as contracts. Adherence to these is the essence to establishing and enforcing trust in this scenario.

Functional dependency

It is important to note that the end goal of any dependency is to rely on the agreed functionality and trust that it will be delivered. The intra/inter process dependencies manifest during development, while the functional dependency manifests when the functionality is requested at runtime.

The functionality can either be directly requested by an end-user interacting with the application (program), or one program requesting another program’s functionality by invoking APIs. Both applications as well as APIs that provide a predefined functionality are called Products. Products establish trust by guaranteeing SLAs on product metrics such as functional coverage, uptime, availability, reliability, quality, etc.

These SLAs are nothing but contracts in this context.
Until now we have seen that interfaces, APIs, and product SLAs are used as contracts within their respective problem domains.
But unfortunately, even today most of the applications deal with data in a loose manner without establishing explicit engagement rules. Typically, in any organization there would be systems of engagement that gather data from multiple channels in OLTP databases. The data from these databases is then periodically sent into a data warehouse for creating reports, analytics dashboards, or AI/ML workloads. The journey and the accompanying ETL programs that facilitate this journey are still thought of as internal details without considering contracts for inter-process boundaries.
One way to do this is by avoiding that the ETL programs have direct access to OLTP databases. Instead, the data from these databases can be curated in data files by ensuring data quality checks and be made available on a common platform, which ensures all the non-functional requirements mentioned for APIs. The common platform along with guaranteed SLAs will then act as the contract that ETL processes rely on.

This thought can further be expanded for data files exposed to end-customers by packaging them as data products governed by SLAs thus truly covering the entire data ecosystem under the gambit of contracts. Thus, data driven by contracts would be a key differentiator in our ability to harness data with purpose.