What is a Data Concept?

A data concept describes a kind of data that exists in a program or application and would be visible to an end user. Examples of data concepts in a course-registration system, for example, would include: Course, Time Slot, Catalog, Schedule, and Shopping Cart.

Note: Our notion of data concepts is inspired by Daniel Jackson's notion of software concepts, as explained in his book The Essence of Software. Our data concepts are oriented towards beginning programmers: they are more abstract than data types or data structures, but more concrete than Jackson's concepts by virtue of being tied to specific applications. We envision slowly showing students how to abstract over data concepts to arrive at something closer to Jackson's concepts.

Example of a Data Concept: Catalog

There are five components to a concept (plus a sixth that get expressed separately). Here is a complete example for the Catalog in the registration system. The text below the code explains each part.

concept Catalog [Entry]

purpose   provide access to a collection of entries, perhaps filtered
          by descriptive labels

scenario  someone searches the catalog to find entries that meet
          certain criteria

state     entries : Set(Entry)
          labels  : Map(Label, Set(Entry))   # a label is a string

actions
  add     : (Catalog, Entry) -> Catalog
            result: a state in which the entry is in the catalog,
            under no labels

  remove  : (Catalog, Entry) -> Catalog
            pre-req: the entry is in the catalog
            result: a state in which the entry is gone, and appears
            under no label

  tag     : (Catalog, Entry, Label) -> Catalog
            pre-req: the entry is in the catalog
            result: a state in which the entry appears under that label

  untag   : (Catalog, Entry, Label) -> Catalog
            pre-req: the entry appears under that label
            result: a state in which it no longer does

queries
  find     : (Catalog, Label) -> Set(Entry)
  labelsOf : (Catalog, Entry) -> Set(Label)

Name and type parameters

Each concept has a name followed (in brackets) by the names of types used in the concept. A concept can't assume anything about the named types, other than that they exist. Catalog works the same way whether an Entry is a course, a book, or a recipe; the registration system fills Entry in with Course.

Purpose

One sentence, stating what the concept provides. A good purpose is:

Core Scenario

A short archetypal scenario, in the form if you do this and this, then that happens, showing the concept delivering on its purpose. It is not a complete description of the behavior — it's the defining story, the thing you'd tell someone who asked "so what's the point?"

State

What the concept has to remember, described with types. Keep it minimal: include only what the actions and queries below actually need.

Why does a Catalog need entries as well as labels?

entries earns its place because an entry can carry no labels. Without it, a course just added to the catalog would not be in the catalog until someone tagged it, which is not what a user means by adding a course.

Actions and Queries

Actions summarize the ways the state can change, written as functions from a state to a new state. This is the same idea we've seen with reactors and functions like on-tick: an action takes the current state (plus whatever arguments it needs) and returns the next state. An action that only reads the state and returns an answer is called a query: find and labelsOf don't change anything, but they summarize questions we might ask of a Catalog.

Some actions only make sense in some states. For example, you can't remove a course from the catalog that was never in it. The pre-req(uisite) line of the action describes when it can be used.

Constraints

A constraint is a condition that has to hold in every state. The state says what the concept can remember; the constraints say which of those states actually make sense. Often, constraints are about a single state, such as "no course appears twice in the catalog". Actions are responsible for maintaining the constraints. Sometimes, constraints are phrased as relationships between the states before and after an action. Here's an example of each:

  1. Every entry appearing under a label in labels is also in entries — nothing is tagged that isn't in the catalog.
  2. An add action results in the number of entries increasing by one.

Constraints across concepts

Combining concepts in an application can yield additional constraints that discuss multiple concepts. The registration system also has a Cart, holding the courses a student is considering. Putting it beside Catalog gives us:

  1. Every course in a Cart is an entry in the Catalog — a student cannot be shopping for a course the university does not offer.
  2. Once a course is removed from the Catalog, it appears in no student's Cart. Neither concept can arrange this on its own: the application has to call Cart.remove for each affected student when it calls Catalog.remove.
Consider 'no two courses in a Cart meet at the same time' — should we make this a constraint?No. A cart is for comparing options, and students deliberately carry conflicting ones while they decide. The constraint belongs to the Schedule the student finally registers for, not to the Cart.