March 27, 2009

(not) Installing the TextUML Toolkit 1.2 on Eclipse 3.5 M6

Filed under: Eclipse, TextUML Toolkit, v1.2 — rafael.chaves @ 12:37 am

I decided it was time to start using Eclipse 3.5 before it went RC or else if I find any blockers there won’t be time left for them to get fixed before the next release this Summer. I have been on the other side of the fence and know how frustrating it is when people only really start reporting bugs at the very end of the release cycle.

After I installed the 3.5 M6 SDK, I decided to install the TextUML Toolkit 1.2

Nothing to install?

First surprise: no features would show on the update site! WTH? Well, turns out I had the Update UI to show available features grouped by category, but the TextUML Toolkit update site does not use categories. Unchecking the option to group by categories shows the four features in the TextUML Toolkit update site as it was usual in 3.4. Phew… I was just about to enter a bug report against the Eclipse update component (a.k.a. p2), when I found out that that unintuitive UI behavior has been recently addressed and the next milestone won’t show this problem any longer.

A roadblock

I managed to install the TextUML Toolkit, and that brought along EMF and UML2, which are required features. Since, at this time, the TextUML Toolkit does not specify version range for its dependencies, the latest versions of EMF and UML2 were automatically installed by Eclipse. That should be fine, I thought, as one of the Eclipse development key mandates has always been backward compatibility. But this time around that was not the case: the TextUML builder was failing to compile a TextUML source file that was making use of template parameters. Turns out the UML2 API around templates has changed in its version 3.0. Before (in UML2 2.2), a template parameter substitution could have multiple formal and actual parameters. Now it can have only one of each, and thus the TextUML Toolkit is (partially) broken in 3.5.

So much for core values, you might be thinking? Well, to be fair, this is a bit of a fringe case. The UML2 API is an Eclipse component, and as such should strive for backward compatibility too. However, it is also a high-fidelity rendition of the UML specification published by the OMG. In this case, the OMG fixed a bug (#9838) in the spec, and as often is the case with UML, that resulted in a change that was not backward compatible. If the OMG promotes changes that are not backward compatible, the UML2 team does not have much of a choice: in order to continue to closely implement the spec, it has to break the Eclipse guidelines.

And neither do I. For the TextUML Toolkit 1.2, I will have to issue a maintenance release (1.2.1) that will explicitly depend on UML2 2.2, thus avoiding the new version, and probably becoming incompatible with other UML modeling packages that only run on Galileo and UML2 3.0. For the next release of the TextUML Toolkit (1.3), I will have to adopt the new API and explicitly depend on UML 2 3.0.

That is how life goes… for some reason, I kind of feel like a flea crawling on the back of an elephant.

March 18, 2009

SQL queries in UML

Filed under: Eclipse, TextUML Toolkit, UML, action language, v1.2 — rafael.chaves @ 12:09 pm

I strongly believe queries are an essential part of a domain model. As such, in our quest to have (UML) models that can fully (yet abstractly) describe object models for the common enterprise applications, we cannot leave out first class support for queries.

But how do you do queries in UML? The obvious answer seems to be OCL, but that is not the approach I am taking as OCL and UML have serious interoperability/duplication issues. Instead, I took theĀ  middleweight extension approach.

First, we model a protocol for manipulating collections of objects (showing only a subset here):

class Collection specializes Basic
  operation includes(object : T) : Boolean;
  operation isEmpty() : Boolean;
  operation size() : Integer;
  operation exists(predicate : {(:T) : Boolean}) : Boolean;
  operation \any(predicate : {(:T) : Boolean}) : T;
  operation select(filter : {(:T) : Boolean}) : T[*];
  operation collect(mapping : {(:T) : any}) : any[*];
  operation forEach(predicate : {(:T)});
  operation union(another : T[*]) : T[*];
  (…)
end;

That protocol is available against any collection of objects, which in UML can be obtained by navigating an association, reading an attribute, invoking an operation, obtaining the extent of a class (remember Smalltalk’s allInstances), anything where the resulting value has multiplicity greater than one.

Note most of the operations in the Collection protocol take blocks/closures as arguments. Closures are used in this context to define the filtering criterion for a select, or the mapping function for a collect.

For instance, for obtaining all accounts that currently do not have sufficient funds, this method would do it:

static operation findNSFAccounts() : Account[*];
begin
    return Account extent.select(
        (a : Account) : Boolean {return a.balance < 0}
    );
end;

Note the starting collection is the extent of the Account class. That is very similar to what is done in the context of query languages for object-oriented databases, such as OQL or JDOQL. We then filter the class extent by selecting only those accounts that have a negative balance, by passing a block to the select operation.

When mapping that behavior to SQL, we could end up with a query like this:

select _account_.* from Account _account_ where _account_.balance < 0

Another example: we want to obtain all customers with a balance above a given amount, let’s say, to send them a letter to thank them for their business. The following method specifies that logic:

static operation findBestCustomers(minBalance : Real) : Customer[*];
begin
    return (Account extent.select(
          (a : Account) : Boolean { return a.balance >= minBalance }
    ).collect(
          (a : Account) : Customer { return a->AccountOwner->owner }
    ) as Customer);
end;

Note that we start off with the extent of Account class, filter it down to the accounts with good balance using select, and then map from that collection to a collection with the respective account owners by traversing an association using collect.

If that was going to be mapped to SQL, one possible mapping would be:

select _customer_.* from Account _account_
    inner join Customer _customer_
        on  _account_._accountID_ = _customer_._customerID_
    where _account_.balance >= ?

Much of this can be already modeled if you try it out with the TextUML Toolkit 1.2. But, you might ask, once you model that, what can you do with UML models containing queries like the ones shown here?

Since the models are complete (include structure and behavior), you can:

  1. Execute them. Imagine writing automated tests against your models, or letting your customer play with them before you actually start working on the implementation.
  2. Generate complete code. The generated code will include even your custom queries, not only those basic ones (findAll, findByPK) code generators can usually produce for you.

If you would like to see tools that support that vision, keep watching this blog.

So, what is your opinion?
Do you see value in being able to specify queries in your models? Is this the right direction? What would you do differently?

Copyright Abstratt Technologies - Powered by WordPress - Entries (RSS) - Comments (RSS)