The basic point of Names on Nodes, as I've mentioned before, is to automate taxonomy. That is, you feed it:
- a bunch of phylogenetic definitions,
- a phylogeny, and
- specifier links, that is, correlations between definition specifiers (apomorphies, species, specimens) and units in the phylogeny (e.g., taxa in NEXUS trees).
That part of it is pretty much done. But there are two tricky parts I have yet to complete: data persistence and user interface. And what both basically boil down to is CRUD.
I've mentioned CRUD before here. It's an acronym for the four basic operations involved with data persistence, the four things you can do to a stored object. Those are:
- Create
- Retrieve
- Update
- Delete
As often happens in programming, I started out with an ad hoc sort of approach that worked well enough up to a point, but then I started finding myself in trouble. Duplicated code. Unnecessarily complex code. Code that was hard to update.
It was time to refactor.
Here's a breakdown of the new system.
Every user interface involved with persistent objects is managed by something called a
FlowManager
. This stores a navigable tree of FlowEntry
objects, each associated with a visual FlowComponent
.The main application handles requests from all components within. These are sent to the application as bubbling events, that is, events that "bubble" up through the display hierarchy (say, from a button, to the form that contains it, to the flow manager, on up to the main application). Two of the major types of request are
EditEntityEvent
and DemandEntityEvent
.An
EditEntityEvent
comes with a persistent object (e.g., a species, a definition, a NEXUS file, etc.). The application's responsibility is to create a FlowComponent
object that will display the entity and allow the user to edit it (Update).A
DemandEntityEvent
comes with a class of persistent object (e.g., Species
, Definition
, Nexus
, etc.). The application's responsibility, then, is to provide the "demander" with an object of that class, either by making a new one (Create) or by selecting an existing one (Retrieve).(Note that I haven't mentioned Delete. I'm leaving that out of the first version. Any deletions will have to be made by myself, manually.)
One problem with my old approach was that I had different user interface components for each combination of CRU[D] action and persistent object. Take a couple dozen types of persistent object and multiply by three: that's how many components I had to make.
The new system, though, has just two types of
FlowComponent
: one for handling EditEntityEvent
requests and the other for handling DemandEntityEvent
requests.The first one is the simplest:
EntityEditor
. It basically consists of the following components:- a form which shows all data in the persistent entity;
- a bit of text that summarizes the entity in its current state (e.g., for a
Binomen
entity, something like "Prenomen nomen Author 1970"); - a button that updates the entity in the database, or, if it is a new entity, creates it in the database; and
- a "cancel" button.
The other
FlowComponent
object, EntitySupplier
, actually uses an EntityEditor
object. Once the EntitySupplier
object is given the class of entity that it's supposed to supply, it creates a default instance of that class and gives it to an EntityEditor
, which it displays to the left. To the right, it displays a SuggestionBox
, a grid showing various existing entities that might match what's in the editor.The
SuggestionBox
uses a nonvisual object called an EntitySuggester
, whose job is to watch for changes that the user makes to the persistent entity and come up with relevant, existing suggestions. For example, suppose the user is editing a new Publication
object and starts to type in the authorship as "Linn". The PublicationSuggester
sees this and checks the database for possible matches, coming up with "Linnaeus 1758". If this is the publication that the user wanted, then they can select it from the SuggestionBox
without having to fill in any more information.I still have to create a form and a suggester for every type of persistent entity, but this is a much neater division of labor than I had in the last version, where forms generated their own suggestions (which would be wasteful if you were just editing an existing entity).
Hope to get much done this weekend.
(Have to get much done this weekend....)
No comments:
Post a Comment