Can you tell this code was fully generated from a UML model?
This is all live in AlphaSimple – every time you hit those URLs the code is being regenerated on the fly. If you are curious, the UML model is available in full in the TextUML’s textual notation, as well as in the conventional graphical notation. For looking at the entire project, including the code generation templates, check out the corresponding AlphaSimple project.
Preconditions
Operation preconditions impose rules on the target object state or the invocation parameters. For instance, for making a deposit, the amount must be a positive value:
operation deposit(amount : Double);
precondition (amount) { return amount > 0 }
begin
...
end;
which in Java could materialize like this:
public void deposit(Double amount) {
assert amount > 0;
...
}
Not related to preconditions, another case assertions can be automatically generated is if a property is required (lowerBound > 0):
public void setNumber(String number) {
assert number != null;
...
}
Imperative behavior
In order to achieve 100% code generation, models must specify not only structural aspects, but also behavior (i.e. they must be executable). For example, the massAdjust
class operation in the model is defined like this:
static operation massAdjust(rate : Double);
begin
Account extent.forEach((a : Account) {
a.deposit(a.balance*rate)
});
end;
which in Java results in code like this:
public static void massAdjust(Double rate) {
for (Account a : Account.allInstances()) {
a.deposit(a.getBalance() * rate);
};
}
Derived properties
Another important need for full code generation is proper support for derived properties (a.k.a. calculated fields). For example, see the Account.inGoodStanding
derived attribute below:
derived attribute inGoodStanding : Boolean := () : Boolean {
return self.balance >= 0
};
which results in the following Java code:
public Boolean isInGoodStanding() {
return this.getBalance() >= 0;
}
Set processing with higher-order functions
Any information management application will require a lot of manipulation of sets of objects. Such sets originate from class extents (akin to “#allInstances
” for you Smalltalk heads) or association traversals. For that, TextUML supports the higher-order functions select (filter), collect (map) and reduce (fold), in addition to forEach already shown earlier. For example, the following method returns the best customers, or customers with account balances above a threshold:
static operation bestCustomers(threshold : Double) : Person[*];
begin
return
(Account extent
.select((a:Account) : Boolean { return a.balance >= threshold })
.collect((a:Account) : Person { return a->owner }) as Person);
end;
which even though Java does not yet support higher-order functions, results in the following code:
public static Set<Person> bestCustomers(Double threshold) {
Set<Person> result = new HashSet<Person>();
for (Account a : Account.allInstances()) {
if (a.getBalance() >= threshold) {
Person mapped = a.getOwner();
result.add(mapped);
}
}
return result;
}
which demonstrates the power of select
and collect
. For an example of reduce
, look no further than the Person.totalWorth
attribute:
derived attribute totalWorth : Double := () : Double {
return (self<-PersonAccounts->accounts.reduce(
(a : Account, partial : Double) : Double { return partial + a.balance }, 0
) as Double);
};
which (hopefully unsurprisingly) maps to the following Java code:
public Double getTotalWorth() {
Double partial;
partial = 0;
for (Account a : this.getAccounts()) {
partial = partial + a.getBalance();
}
return partial;
}
Would you hire AlphaSimple?
Would you hire a developer if they wrote Java code like AlphaSimple produces? For one thing, you can’t complain about the guy not being consistent. Do you think the code AlphaSimple produces needs improvement? Where?
Want to try by yourself?
There are still some bugs in the code generation that we need to fix, but overall the “POJO” target platform is working quite well. If you would like to try by yourself, create an account in AlphaSimple and to make things easier, clone a public project that has code generation enabled (like the “AlphaSimple” project).
Andrey Loskutov
October 31, 2011 at 8:17amLet’s see:
– the code is not thread safe
– uses global static instances map
– uses double arithmetics for financial data
ergo => I would NOT hire the developer who wrote it
rafael.chaves
October 31, 2011 at 9:26pmThanks for your reply, Andrey. Very good point about using double.
Re: thread safety – one could assume thread safety is ensured by some other means (say, service level). The code generated here (the “POJO” target platform) is intentionally simple and ignores non-essential/non-functional concerns. The same thing explains the use of a static slot to keep all instances, which has no role in a real-world application.
MDD meets TDD (part II): Code Generation | abstratt's blog
November 7, 2011 at 8:37pm[...] like it too. That is how we got the spanking new version of the POJO target platform to work (see post describing it and the actual project) – we actually wrote the test cases first before writing [...]