Data Hyperjump linking

Apr 2008

In the Chinese Intepreter rant, I lamented about the way the abominable "grid" makes most ASP.NET Web applications look and behave like Access. Display rows of data, allow edits, deletes and you're done. There is a great admiration in the ASP.NET world for tools and “controls” that produce the functionality to do that with as small an effort as possible, but other technologies are not immune to the Access virus either. Excuse me if I'm not thrilled, but a UI that displays dead data from a query does not qualify as a helpful one. By “dead”, I mean that all they do is show themselves to you, but they don't do anything more than a printed page would.

In another rant I am going to talk about temporal data and how working with them necessitates transcending the simple tabular display, and per-row editing, of data. Here, however, I am dealing with everyday data that are best served by exactly that lowly data table (“grid”), but can really benefit from doing more than Access does. In the sequel, I am going to present a zero-cost way to make data livelier, which I call “Data Hyperlinking”, and its natural extension together with some tools to help you.

Data Hyperlinking

I am not an expert in HCI, but there's a nice concept it shares with many other fields: “Affordances” (see sidebar). Briefly, this term refers to the action possibilities that are perceivable by an actor. What action possibilities does a traditional data grid offer? In the periphery of the data, one may find ways to sort, filter, group etc, but the data themselves are inert.

I remember some time ago, while I was watching people working with a customer's Unix terminal - based ERP. They switched from screen to screen, going through data. They had constant need of a paper pad, on which they jotted down IDs and such, in order to input them elsewhere and continue their quest for answers. The technology they were using was not suitable for easier interaction, but the way they were working was not very different from the way one works with a modern Web-based application.

A Web-based application should allow the most basic of Web idioms, which is hyperlinking. Data presented inside a Web page should be hyperlinked and hyperlinkable. The former is effortless so long as the latter is in place. All it takes is to link all references to entities to their corresponding pages. This is usually done by passing some form of identifier as a parameter, unless some form of URL rewriting is used, or a content-management system creates entity-specific pages.

The following screenshot (smudged to eliminate references to specific customer and people) displays the idea.

Data Hyperlinks

The first and fourth columns, both containing IDs, link to the detail pages for the corresponding entities. If blue, underlined text all over bothers you, you could devise some other style. The important thing is to follow this practice uniformly, so that users know that an ID links to the same page wherever they encounter it.

The second practice that is important, is to provide links to all entities related to the entity that the user focuses on. Links to single entities will be to their detail pages, while links to multiple entities can be enabled by having query pages that are also driven by parameters in the URL. If you do this consistently for all entities that reference or are referenced by the target one, the users can navigate endlessly throughout the data of the application. I call this practice “Data Hyperlinking”.

Hyperlinking further away

Making sure that all entities are linked to their immediately accessible ones is tedious, but not unmanageable. But I am now going to explore the possibilities that are opened if we devise a way to link to indirectly accessible entities, and how this, extremely more difficult, task can be automated. Moving more than one step away in the data space is akin to a hyperjump in the physical space, so I named this practice “Data Hyperjump Linking”.

First of all, let me present an example of Data Hyperjump interaction. Don't stick to the form, because the way a user will be able to choose a hyperjump is irrelevant to its essense, although a hierarchical menu is a strong contender, due to the large number of available options (easily more than one hundred). This example is a small part of the length-4 hyperjumps that start from the Customer entity of a real application.

  • From Customer 12345, ...
    • ...go to Contract having it as Customer
    • ...go to Contract having it as Customer, then ...
      • ...go to InvoiceDetail having it as Contract
      • ...go to InvoiceDetail having it as Contract, then ...
        • ...go to Customer using Customer
        • ...go to Customer using Customer, then ...
          • ...go to Contract having it as Customer
        • ...go to Item using Item
        • ...go to Item using Item, then ...
          • ... go to Brand using Brand
          • ... go to Contract having it as Item
          • ... go to Contract having it as TSItem

Hyperjumps are nothing more than paths in the graph whose nodes are the entities and whose arcs are relationships based on properties. If entity Contract has one or more properties of type Customer, then there are one or more arcs linking the two entities. In database terms, arcs are equivalent to foreign key relationships. Arcs can be traversed both ways; the directionality is only useful to direct code generation and inferencing of the multiplicity. When you go from the referencing entity to the referenced entity, I call it a forward link, else I call it a reverse link.

A reverse link cannot be followed by the corresponding forward link (because we would go back to the same entity). Other than that, all paths are valid and potentially useful. In fact, hyperjump links go beyond shortcutting a series of plain data hyperlinks. Sometimes they produce the union of all results from data hyperlinks along a specific path.

I will now introduce a minimal example for purposes of demonstration of the concepts, but also in order to introduce a tool that can produce hyperjump paths and their queries in HQL (for Hibernate/NHibernate). The formulation will be in Prolog, as the tool is written in this succint language that is very suited to similar tasks.

  • Concepts are introduced with the concept predicate. Concepts correspond to classes or tables.
  • Arcs and their directionality are introduced with the link predicate, with arguments the originating concept, the destination concept, and the linking property. The linking property corresponds to a class property or a database column.
  • Predicate significant lists all concepts that can appear as the origin or the destination of a path. These are concepts that can be shown in the UI. Non-significant concepts can be used only along a path.
% concept(concept_id)
concept('Person').
concept('Building').
concept('Floor').
concept('Manager').
concept('Dog').
concept('Pack').
concept('Flee').

% link(from_concept_id, to_concept_id,property_name)
link('Dog','Person',master1).
link('Dog','Person',master2).
link('Dog','Pack',pack).
link('Flee','Dog',dog).
link('Person','Building',building).
link('Person','Building',work_building).
link('Floor','Building',building).
link('Building','Manager',manager).

% significant(list of concepts that can serve as endpoints)
% concepts that are not "significant" can only be used along a path
significant(['Person','Building','Floor','Manager','Dog','Flee']).
				

The corresponding graph is shown below.

Person graph

The exclusion of paths that contain a reverse link followed by a forward link between the same entities should be evident, if one looks at a specific case: going from Person to Dog and then back to Person, we land on the same Person. Any path that includes such a construct is redundant, as there is a corresponding path that omits it and arrives at the same results.

Based on this concrete example, one should be able to see how Hyperjump linking allows access to results not immediately retrievable by plain hyperlinking. With a series of hyperlinks, one cannot arrive at a single results page listing all flees of all dogs of a person, for example.

Program navigate.pl, in SWI-Prolog, a distribution which can be freely downloaded for many platforms, can be used to process such a graph and output the possible paths. It is possible to drive it from a shell script, as shown below (for Windows; 1st parameter is the originating concept, 2nd parameter is the max length):

"\Program Files\SWI-Prolog\bin\plcon" -g consult(navigate),consult(persongraph),allaccesspathsfrom('%1',L,%2),significant(S),include(significant_endpoints(S),L,L1),include(not_retrogressive,L1,L2),print_paths(L2) -t 'halt' 
				

The specified command outputs paths that are not retrogressive (don't look it up in your graph theory book), meaning those paths that go back to a concept after having visiting it once. Retrogressive paths are more complicated for the user to understand, but they are not without value, and you may choose to include them.

An example from the output of the program is the following path. The first line is the path rendered in English, and the second line is the corresponding HQL query (containing a parameter to plug in the ID of the originating entity). The program can be extended to output the equivalent SQL query as well.

From Person, go to Building using work_building, go to Person having it as building, go to Dog having it as master2, go to Flee having it as dog

from Flee a21291 where a21291.dog in (select a10708.id from Dog a10708 where a10708.master2 in (select a21280.id from Person a21280 where a21280.building in (select a58985.work_building from Person a58985 where a58985.id in (:id ))))
				

Creating the graph by hand is tedious and error-prone. XSLT template hbm2prolog.xslt can be run on a Hibernate mapping file to extract the relevant predicates as text output. Run it on all mappings and concatenate outputs to arrive at a Prolog file containing the entire graph. Be sure to check the Hibernate contstructs that are covered, as you may be using others that are not taken into account.

Why not P#, to produce actual, linkable code?
To be frank, there is also a P# version, navigate_psharp.pl. I was halfway debugging it, which meant compiling it to uncover faults not flagged during interpretation, when I hit some critical size, after which compilation thrashes and I kill it after it crosses 1.5 Gb memory usage... However, using it as input to the interpreter from inside a .NET program should work and this is how I am planning to use it.

Conclusion

Is Data Hyperjump linking the sine qua non of Web UIs? Certainly not, although I believe plain Data Hyperlinking is. Data Hyperjump linking is a thought experiment for now. It could be too much for the average Web user. On the other hand, it could be used to automate the outwards links to other entities that should fan out of an entity, thus making sure that no outwards link is missed, a possibility that is very likely if one does this work by hand.

I plan to use it myself in a production environment and test-drive it with actual users, then report my conclusions here.

Back

Rants

Interesting reads