Skip to content

Architecting Digital Twins ontologies with Liskov's substitution principle

June 4, 2023 | 03:00 PM

The Liskov Substitution Principle is a fundamental principle in object-oriented programming that defines the behavior of subtypes in relation to their base types. It was introduced by Barbara Liskov in 1987 and is an essential principle for ensuring the correctness and maintainability of object-oriented systems. and was originally defined as follows:

Let q(x) be a provable property of objects x of type T. Then q(y) should be provable for objects y of type S. Where S is a subtype of T.

The Liskov substitution principle defines the following:

In other words, if a class B inherits from a class A, then class B must be able to be used anywhere an instance of class A is expected, without requiring modification to the code that uses that class A.

Table of contents

Open Table of contents

How to apply the principle

The Liskov substitution principle can also be applied to the design of a Digital Twin. A Digital Twin is a virtual representation of a physical object or system in real-time. By applying the Liskov substitution principle in this context, we seek to ensure that Digital Twins are substitutable and consistent in their behavior with the physical objects they represent.

Implementation of this principle ensures that Digital Twins is replaceable in the system without affecting the behavior or integrity of the system. This is especially important in applications where Digital Twins are used to simulating and control complex systems, such as in manufacturing or infrastructure management, where consistency and coherence between Digital Twins and physical objects are critical for safe and efficient operations.

Some guidelines for applying the Liskov substitution principle in a Digital Twin:

Building a DTDL example appliying Liskov principle

DTDL (Digital Twins Definition Language) is a definition language used to describe models of Digital Twins. DTDL is a standard developed by Microsoft and is used to define the structure, attributes, and behavior of digital twins.

Suppose we are building an Industrial plant management system and we want to model Digital Twins for different types of assets used in industrial automation. We have a base model called “IAsset” that defines the basic properties and behavior of a generic industrial asset. Next, we create two derived models, “Machine” and “Robot”, which represent different industrial models. Each derived model inherits the properties and behavior defined in the base model.

liskov-diagram

Base model: IAsset

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:IAsset;1",
  "@type": "Interface",
  "displayName": "IAsset",
  "contents": [
    {
      "@type": "Property",
      "name": "status",
      "schema": "string"
    },
    {
      "@type": "Command",
      "name": "start"
    },
    {
      "@type": "Command",
      "name": "stop"
    },
    {
      "@type": "Property",
      "name": "powerConsumption",
      "schema": "double"
    }
  ]
}

Derivated models: Machine and Robot

{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:Machine;1",
  "@type": "Interface",
  "displayName": "Machine",
  "extends": "dtmi:com:example:IAsset;1"
}
{
  "@context": "dtmi:dtdl:context;2",
  "@id": "dtmi:com:example:Robot;1",
  "@type": "Interface",
  "displayName": "Robot",
  "extends": "dtmi:com:example:IAsset;1"
}

Testing Liskov principle in DTDL

You can check this simple example in my github of testing DTDL interfaces to ensure compliance with the Liskov principle. By running the tests, you can verify that the derived interface does not violate the principle and that it does not introduce new properties, promoting interoperability and code reusability in the context of Industry 4.0.

describe("Machine - Liskov Principle", () => {
  let machineModel;
  let iAsset;

  beforeAll(async () => {
    const models = await getAllModels();
    machineModel = models["dtmi:com:example:Machine;1"];
    iAsset = models["dtmi:com:example:IAsset;1"];
  });

  it("Interface should exists", () => {
    expect(machineModel.sourceObject["@type"]).toBe("Interface");
  });

  it("Should extend IAsset Base Model", () => {
    const iAsset = machineModel.extends.filter(
      id => id === "dtmi:com:example:IAsset;1"
    );
    expect(iAsset).toBeDefined();
  });

  it("Verifies does not have new properties", () => {
    const machineProperties = Object.keys(machineModel.contents);
    const iAssetProperties = Object.keys(iAsset.contents);
    const newProperties = machineProperties.filter(
      property => !iAssetProperties.includes(property)
    );
    expect(newProperties.length).toBe(0);
  });
});

The test results will be displayed in the terminal/console, indicating whether the DTDL models comply with the Liskov principle and the absence of new properties in the derived interface.

liskov-dtdl

References