Control Table

A table (usually relational) that contains programming code and/or tends to have "high-level" information in it. It is generally altered only by a software expert or an administrative user. It also tends to scale at about the log of total data size for a given application. If its "cells" do contain code, then the code can be in the form of small snippets of code or script/module/function names. Compiled binaries, such as DLL's, are also a possibility, but may not be supported directly by most tool environments.

DataDictionarys are sometimes considered a special case of ControlTables.


A simple example is a "menu table". I see these often in web applications. It might have a structure similar to:

  Table: menu
  -----------
  menuItemID
  title
  scriptName    // script to run
  ordering      // sequence order in the menu (real or int)
  indentLevel   // optional

The "indentLevel" is one way to make a hierarchical menu system. Another way is a "parentID" column. On a smaller system, "menuItemID" may be unnecessary. The script name or an integer sequence number (instead of "ordering") could serve as the primary table key.


Regarding the Menus example, in practice you'll likely have a few more scripts:

  checkmark     // script evaluated to control checkmark of menu entry, or empty for no checkmark
  disable       // script evaluated to disable and gray menu entry, or empty for enabled
  hidden        // script to hide or show menu entry

I mention this because it was stated below that ControlTables rarely end up with many scripts, pointing to the menu table as an example. That has not been my experience. Each 'feature' of a display item, at least those that can only be computed at runtime, e.g. relative to the state of the world model or the database, will end up with its own script. Even things like 'title' may end up being scripted, e.g. for a toggle behavior or to change text based on the operator's current selection (e.g. selected text, or selected units) or hand (HandVsPointer).

These behaviors and features, especially insofar as they are configured by intermediate users of the application, cannot reasonably be embedded elsewhere in the application... except, perhaps, by defining some scripts or plugin modules that watch the world model and keep, say, a boolean 'checkmark' property correct on a continuous basis.

I kept the example simple for illustration purposes. And, while I agree that each widget should have the *potential* to have an event hooked to it, in practice it may merely change the column value of "Checked", and the processing script can choose to read and use such information or not. In other words, don't put behavior wrappers/accessors around activities as a first resort. For one, it makes it easier to share the interface between different languages. (Check-boxes in menus are perhaps not a good design choice anyhow. Menus are not forms. But that's another topic.) But here's a more thorough example:

  Table: menu
  -----------
  menuItemID
  title
  checkBoxState   // values: HIDE, ON, OFF
  etc...

function onMenuClick(record[], etc) { ... if (record.menuItemID==7 && record.checkBoxState=="ON") { record.checkBoxState="OFF"; // un-check doSomething(...); updateMenu(record); } ... }
--top

[The need for scripting or not (and, therefore, whether a ControlTable is appropriate or not) is highly dependent on the type of application. CrudScreen-based data entry applications often have relatively little interactivity between the form widgets. For these, ControlTables may be appropriate, and indeed are a common approach on BigIron information management systems. An entertainment application like a game or media player, on the other hand, often requires a complex set of interactions between the UI widgets. For these, a ControlTable would be an awkward way of defining the interactions, and the associated DBMS would be needless overhead.]

I generally agree (at least with the state of existing tools). If you need very fine control and language independence is not a big goal, then the current approaches favored are probably the way to go. (Note that a more generic way to do check-boxes is just support left-side icons. Change the icon image as needed for checking and un-checking. This way icons are supported also and can serve as check-boxes so that we don't have to support two infrastructures: one for icons and one for checkboxes. But of course the decision depends on expected usage patterns.) --top


Are ControlTable`s Really OOP in Disguise?

It is sometimes said that putting programming code in tables is really ObjectOrientedProgramming using tables instead of code classes.

This of course depends on which definition of OOP you use. One definition is that objects are based on a dictionary (sometimes called a "jump table") where a method or attribute name is the key, and the method code or attribute value is the result. (TypeOverloading? complicates this a bit. Then again, type overloading is not considered OOP by some people.)

I disagree that they are the same because tables can have multiple columns and multiple keys. A dictionary is a sub-set of a table (in the RelationalDatabase sense). A dictionary might be considered the basis for objects, using the above definition, but a table is not.

In my opinion, the fact that a table is more powerful than a dictionary is what gives TableOrientedProgramming and ControlTables their potential over OOP. You are not limited to a simple structure with 2 columns and one key. A table also lets you access all the niceties of databases (search, sort, filter, join, save, etc.).

But you can search, sort, filter, join, etc., with objects too. Simply create an object and inherit the appropriate classes. You are not limited to just using dictionaries in OOP

Are you confused, or am I ? The above definition gives me a picture of a 2 column table. The left column lists the names of all data values (and methods) of the class. The right column lists (possibly pointers to) the corresponding values (and the method implementation). I see how filtering that list might be an interesting thing to do -- but I would enjoy reading a practical example. How can I "search, sort, filter, join, or save" that table with objects ? The "Simple" explanation leaves me mystified -- could you give a more detailed example, please ? If you're saying that I can create classes with a foo.filter() method, then I think you missed the point.

{OO puts you in a rock and a hard place here. If you do all that in your application code, other languages and tools cannot readily share such data. (Plus it is a lot of coding). If you factor it into a central service or set of services, you are essentially reinventing a database. OODBMS tend to resemble the NetworkDatabases of the 1960's, which fell out of favor when relational came along. See ModernDinosaur}

Further, the practice of putting code in data structures can be found at least far back as LISP, born in the late 1950's. OOP was allegedly born in 1967 with a new version of Simula.

Further, tables put restrictions on the "shape" of the information that OO does not require (for good or bad). TablesAndObjectsAreTooDifferent.

It is not so much the matter of mixing code and data, it is the nature of the result. TOP and LISP tend to tilt toward the data side, while OO tilts toward a code-centric approach. The first two tend to put code in data, or treat code like data, but OO tends to treat data like code. -- Rest of discussion moved to ImplementationHidingDiscussion?.

While this is true, it is less marked in the more dynamic OO languages - Smalltalk, Self, CLOS - than in languages like C++ or Java, which generally do not give programs much reflectivity. - JayOsako

It's also argued that such is "less OO" because encapsulation is not as strong. The boundary between OOP and NavigationalDatabase-with-behavioral-hooks is fuzzy. But this all depends on which definition of OO is being used, and NobodyAgreesOnWhatOoIs. But I do agree that OOP and ControlTables share many things in common. --top


Often I have a "what to do next" array ("in data"). It has a column listing events, a column of function pointers (and possibly columns for various data values). When an event comes in, rather than test it in a big case statement ("in code"), I look for it in the array and fire off the corresponding function. Does this count as a "Control Table" ?

It sounds like half of the implementation of a state machine, similar to one I (and many others) used to use for telephony apps. I used a 2 dimensional array, where one dimension corresponds to all the possible events and the other dimension corresponds to all the possible states. Each element refers to a function that returns the next state. Behavior is defined for every event in every state.

I used to use arrays extensively, but when better table tools came out, I was happy to say goodbye to arrays. Yes, I suppose that is a kind of ControlTable, but not my favorite form. -- top


Note that putting code in tables is *not* a prerequisite for a ControlTable. I am debating about whether CodeInTables? (or CodeEmbeddedInTables?) should be its own topic, because it is a popular issue, and sometimes over-emphasized in ControlTable and TableOrientedProgramming lore.


Code per Row

In practice I don't put a lot of code in tables (if I have good table tools) because the association between code and specific rows is weak in practice. It is a little hard to pin down exactly why this is. I believe it is that in reality, multiple orthogonal factors interweave to determine real-life dispatching of behavior. In TextbookOo you have mostly just two factors: operation and subtype. Thus, a "shape" control table under this view would look something like this:

  Table: shapes  (schema)
  ---------
  shapeId    // 'rectangle', 'circle', etc...
  draw       // contains code or DLL for "draw" method
  rotate     // contains code or DLL for "rotate" method
  resize     // etc....
  fill
  volume
  etc...

But in practice this kind of arrangement usually does not emerge. The reason appears to be that multiple interweaving factors eventually affect dispatching, rather than just two (subtype and operation). More on multiple orthogonal interweaving factors is at http://www.geocities.com/tablizer/struc.htm#if . I have yet to find a paradigm that handles these well. OO proponents seem to want to turn every combination into a flat list of subtypes, but I see no advantage of this. The list generally cannot be reused in other tasks, so it is a waste of code. (There used to be a wiki topic on this interweaving, but somebody deleted it.)

In practice tables rarely end up with more than one or two code cells per row. Thus, they will look more like the above menu table example than our Shapes example.

The discussion in http://www.geocities.com/tablizer/struc.htm#if is very interesting, especially as it seems like a nice clear description of (the rationale for) what used to be called Decision Tables. If you were careful to make the condition side of the table "complete", i.e. no "don't care" slots (just like the table in the referenced page), it was beautifully easy to check that you had all the cases covered. Then somebody introduced "triangular decision tables", which were simply disguised nested if-then-else's, and the whole concept got shot to h*** and it seems like Decision Tables fell out of favour.

In practice they are rarely purely triangular or purely rectangular, but rather a mix of sub-patterns and randomness, and which may change over time. The nice things about tables is that they allow one to still see a tree view if so desired. As far as inspecting or ensuring there are no accidental gaps (which may differ from purposeful gaps), without clean patterns automated checking is very difficult if not impossible. My approach is to make the inspection process easier by inspecting it with multiple viewpoints. No single perspective is the One Best perspective. A tree view may help inspect the tree-ish portions, but not the non-tree patterns. See SeparateMeaningFromPresentation. --top


MicrosoftAccess's "switchboard" is implemented using a form of ControlTable. The schema resembles this (names changed to protect the innocent):

 table: switchboards
 --------
 Menu_ID   // menu group (panel) ID
 Menu_Item_Sequence_Number
 Menu_Item_Description  
 Command_Type  // A code the represents macros, queries, other menus, etc.
 Command_Name  // Name of the macro, query, menu, etc. to run when item clicked
 (Primary key: Menu_ID + Menu_Item_Sequence_Number)

Unfortunately, it doesn't have a menu panel title, which would require a 2nd table if we don't want duplication.


See Also:


EditText of this page (last edited June 21, 2010) or FindPage with title or text search