Data Driven Programming

Data-Driven versus Command-Driven Programming

Control-Driven and Data-Driven programming can be viewed as two broad programming paradigms that underlie the more specific procedural and object-oriented paradigms, respectively.

In the Control-Driven Paradigm the programmer's job is to specify the flow of control. This is done by creating complex control structures out of simpler control structures by nesting and sequencing.

In the Data-Driven paradigm the programmer's job is to specify the data. The data decides how data flows through the program.

Data-Driven Programming depends on two fundamental principles: The Subsumption Rule and the Dynamic Dispatch Rule.

Types

Examples of primitive types include:

boolean, char, int, long, float, double

The type of an object is its class.

Interfaces and abstract classes are types, too.

If A is a type, then so are:

A[]   arrays over A
A*    pointers to A (C++)
A->B  functions with domain A and range B (Haskell)
AxB pairs with first component from A and second from B (Haskell)

Subtypes

If A and B are types, and if A extends or implements B, then we say that A is a subtype of B and write:

A <: B

The subtype relation is reflexive. This means for every type A, A is a subtype of itself:

A <: A

The subtype relationship is also transitive:

A <: B and B <: C, then A <: C

By definition:

char <: int <: long <: float <: double

If A is any object type in Java, then:

A <: Object

Example

In the following hierarchy:

We have:

Manager <: Executive <: Employee <: Role
Executive <: Stockholder <: Role
Customer <: Role

By transitivity we have:

Manager <: Role

By reflexivity we have:

Role <: Role

Note that Employee is not a subtype of Customer or Stockholder, nor is the reverse true.

How many subtypes does Role have?

The Subsumption Rule

A variable also has a declared type. For example:

double x;
Employee y;

Normally, a variable of type A can only store a value of type A. However, in object-oriented languages the subsumption rule allows us to relax this constraint:

A variable of type A can hold a value of type B if B <: A

For example, the following assignments are legal:

x = 3;
y = new Manager();

We can broaden the subsumption rule:

An object of type B can be used in any context where an object of type A is expected if B <: A

For example, the sin function expects a double as input, but will take an int:

sin(3); // same as sin(3.0)

To put it another way, values of type B can masquerade as values of type A.

Another way to think of it is that a data value can have many types. For example, an instance of the Manager class has Manager, Executive, Employee, and Role (and Object) as its types. If we think of the type of an object as its form, then we can say that a value has many forms or is polymorphic.

The Subsumption Rule is also called the Liskov Substitution Principle.

Inheritance

If an object x of type B can masquerade as an object of type A, where B <: A, then this implies that x can do everything an object of type B can do. This means that type B implements the same operations as type A. We can spare the author of B from having to re-declare all of the methods of A if we assume B automatically inherits the methods of A. Then, the author of B can simply override the methods of A that he wishes to implement in a different way.

Dynamic Dispatch Principle

The Dynamic Dispatch Principle states:

Objects, not compilers, decide which methods to invoke

Example

Assume each subtype of Employee declares a method for calculating bonuses:

We say that the calcBouns method in the Executive class overrides the calcBonus method inherited from the Employee class, and the calcBonus method of the Manager class overrides the calcBonus method inherited from the Executive class.

Assume an Employee variable stores a Manager object:

Employee e;
// and later:
e = new Manager(); // ok since Manager <: Employee

 According to the compiler, the method invocation:

e.calcBonus();

should call the Employee calcBonus method, but according to the Dynamic Dispatch Principle, the Manager calcBonus method should be called.

Subsumption and Dynamic Dispatch in C++

Implementing Dynamic Dispatch

Example: The Cyber-Air Flight Simulator