I’ve been thinking a bit about what seems to me the hardest question here, which is the role of the templating concept. In short, @fabian’s idea was to be able to define a template of properties for a group of animals which the zoo keeper is then prompted to give values for when tracking the animal’s condition. The challenge is to design this as a separate concept without dependences between concepts.
Here’s one way to do it. First we define a very basic templating concept, which allows you to create a template consisting of a set of property names. The type parameter (Item) will be bound to the items of whatever type that have templates associated with them.
concept Template [Item]
purpose simplify customization of items
state
template: Item -> one Template
properties: Template -> set String
actions
createTemplate (ps: set String, out t: Template)
assignTemplate (i: Item, t: Template)
…
Now we define a concept for tracking the conditions of the animals. A priori, there’s no reason to make this animal-specific (although my guess is that you might well want to; I just don’t known enough about zoos). So I’m making it generic in the item type again.
concept PropertyTracking [Item]
purpose tracking over time of properties of items
state
records: Item -> set Record
propertyNames: Item -> set String
date: Record -> one Date
properties: Record -> set Property
name: Property -> one String
value: Property -> one Univ
actions
setItemPropertyNames (i: Item, ps: set String)
addRecord (i: Item, d: Date, props: String -> Univ)
// UI presents props as form using i.propertyNames
The interesting part here is that there is one action for setting the property names associated with an item (this will be an individual animal when we instantiate the concept in context), and another for setting the values of the properties. That second action takes a mapping from property names to values as an argument, but the property names will be provided by the UI.
Now we can instantiate our concepts. I’ll assume we have some AnimalTaxonomy concept that introduces a type AnimalTaxonomy.Class representing the particular category an animal falls in. Rather than an AnimalIdentity concept, I thought for now we might assume a standard Profile concept (as all web sites have), which also allows the subjects of the profiles to have categories assigned to them (in this forum, for example, there are 5 or so user categories); I’m assuming that’s a polymorphic reference, and I’m instantiating it with the taxonomy class. Then I instantiate the Template concept, with the items being the animal identifiers (the Id class exported by the Profile concept).
app Zoo
include
AnimalTaxonomy
Profile [AnimalTaxonomy.Class]
Template [Profile.Id]
PropertyTracking [Profile.Id]
Most of the actions of the app will be just the lifted actions of the concepts. The magic happens in the action that sets the property names of an individual animal. By using a sync, this is replaced by an action that lets the user select a template that has been previously created, and then uses that template to set the property names implicitly:
sync selectAnimalTemplate (i: Profile.Id, t: Template.Template)
Template.assignTemplate (i, t)
PropertyTracking.setItemPropertyNames (i, t.properties)
This design could be elaborated in various ways:
- Adding types to the properties (which would allow validation)
- Allowing templates to be modified and propagating the changes to the tracking records
- Associating templates with animal classes rather than (as here) letting them be independent.
A few notes on what’s involved in this kind of concept separation:
- Try to make each concept a plausible unit of functionality in its own right
- Avoid having any shared types across concepts, except for primitives like Date and String
- No function calls between concepts, even by registering callbacks
- Connect concepts using syncs, and try to avoid extending concepts with special actions needed only for syncs that aren’t plausible for the concept in other contexts.
Comments?