MType vocabulary design principles

Mark Taylor m.b.taylor at bristol.ac.uk
Wed Jun 11 05:11:09 PDT 2008


All,

the issue of what MType(s) to use for progress messages brings up 
a question with much wider applicability in designing the MType 
vocabulary.  I think that getting the design principles of that right 
will be important to maximise interoperability in practice. 
In my opinion if the MType vocabulary becomes too large or fine-grained 
it will be hard to recover the kind of interoperability for PLASTIC-like 
applications which PLASTIC has achieved.  Because of the importance 
of this I would urge application authors to consider the points 
raised here (and perhaps subsequently on this thread) and to 
contribute their views to the debate.

On Tue, 10 Jun 2008, Mike Fitzpatrick wrote:

> On Mon, Jun 9, 2008 at 4:09 AM, Mark Taylor <m.b.taylor at bristol.ac.uk> wrote:
>
>>>  app.status.progress           msgid,str       progress string
>>>  app.status.progress.percent   msgid,float     percentage completed
>>> (float)
>>>  app.status.progress.timeLeft  msgid,int       est. time remaining (sec)
>>
>> As I've said, I think a progress MType is a good idea.  However, I would
>> rather see this as a single MType (app.status.progress) with required
>> arguments msgid and progress string, and optional arguments giving
>> percentage completed and time remaining.
>
>    Percent and timeLeft are just two examples, one might also consider
> 'bytesDownloaded', 'filesRemaining', 'messagesHandled', etc.  Some of
> these are likely to be application-specifc, the above hierarchy provides
> a framework to hang these new mtypes on without later polluting the
> list of optional args, and simply reserves the mtype for the types of
> progress most apps would likely implement.  As with any mtype, at
> least two apps would have to understand app.status.progress.frogsEaten
> for it to be meaningful, the rest would ignore it.  I don't see where
> interoperability is an issue.

Having multiple different MTypes which do similar things leads to a 
tradeoff between interoperability and burden on the participants.
The basic problem is that if there is a (wide) choice of MTypes which 
might apply to the message you want to send, then there is a (serious) 
risk that the sender and the recipient will fail to agree on which 
one to use.  To cope robustly with this, clients at both ends have
to use all the variants, which is more work.

This is an example of a general question which is going to come up 
in relation to many other MType definitions, so it's worth some
discussion.  It's the question of whether it is better to "pollute"
the namespace of defined MTypes or the per-MType namespaces of 
(maybe optional) MType parameters.  More neutrally: for a related
set of functionality, is it better to handle semantic flexibility
by defining one MType with flexible optional parameters, or multiple
MTypes each with relatively constrained parameters.

Looking at these progress messages specifically, consider the 
situation from the sender's point of view.  If there is a set of 
related app.status.progress.* MTypes as you suggest, the sender 
could just do:

    notify( clientId, app.status.progress.percent( percent="50" ) );

however, if the recipient is only subscribed to 
app.status.progress.timeLeft then there is no information exchanged
and no interoperation.  In general there is the possibility, and 
indeed likelihood, that the MType the sender decides to send is 
not the same as the MType the potential receiver will decide 
to subscribe to.

So, to be safe, the sender really ought to do this:

    notify( clientId, app.status.progress( txt="50% done" ) );
    notify( clientId, app.status.progress.percent( percent="50") );
    notify( clientId, app.status.progress.timeLeft( timeLeft="96" ) );

or, better (because it reduces unnecessary traffic), this:

    if ( isSubscribed( clientId, app.status.progress ) )
        notify( clientId, app.status.progress( txt="50% done" ) );
    if ( isSubscribed( clientId, app.status.progress.percent ) )
        notify( clientId, app.status.progress.percent( percent="50" ) );
    if ( isSubscribed( clientId, app.status.progress.timeLeft ) )
        notify( clientId, app.status.progress.timeLeft( timeLeft="96" ) );

There are three problems with this:

    1. It's more coding effort for the sender
    2. The number of messages transmitted through the system may be
       higher than it needs to be
    3. It will still fail to transmit progress information if the
       recipient is only subscribed to, e.g.,
       app.status.progress.frogsEaten

In the alternative way of doing it, there is one MType named 
app.status.progress with a required parameter txt and documented
optional parameters percent and timeLeft.  Then I can write just

    notify( clientId, app.status.progress( txt="50% done",
                                           percent="50",
                                           timeLeft="96" ) );

or, better,

    if ( isSubscribed( clientId, app.status.progress ) )
       notify( clientId, app.status.progress( txt="50% done",
                                              percent="50",
                                              timeLeft="96" ) );

I can add on frogsEaten="23" and byteDownloaded="9999" parameters 
if I want.

This is easier to code, it means there is only one message sent per 
progress event thus reducing load on the messaging infrastructure and
recipient, and it guarantees that if both sides are interested in
progress information at all they will be able to communicate about it 
to some extent, even if it's only a text string (which in practice
can always be generated by a sender, and can nearly always be made
some use of by the recipient).


This specific case aside: when deciding how broadly defined 
specific MTypes should be (what goes in parameters and what warrants a
new MType) it will in general be necessary to look at the details
on a case by case basis.  But I would say that in most cases, 
because of the kinds of considerations I've outlined above,
it is better to keep to a small number of MTypes, and to handle 
semantic flexibility with (perhaps optional) parameters.  I suggest 
the following rules of thumb:

    1. If an application wants to perform some specific kind of
       interoperation with another, it should be clear which MType
       to use for that, rather than there being a selection of
       similar ones available which differ in detail.

    2. It's OK to define or use as many optional parameters as are
       useful for an MType as long as a recipient which ignores
       all the optional parameters can still stand a good chance
       of processing the message in a sensible fashion.

These arguments are most important when considering a PLASTIC-like
scenario in which applications are communicating with other 
applications which they may never have met before in a relatively 
uncontrolled environment.  However I don't believe that doing it the
way I am advocating will be disadvantageous even in more controlled
environments.

Mark

-- 
Mark Taylor   Astronomical Programmer   Physics, Bristol University, UK
m.b.taylor at bris.ac.uk +44-117-928-8776 http://www.star.bris.ac.uk/~mbt/



More information about the apps-samp mailing list