...
Our programming model could provide several syntaxes to put these responsibilities in different places. It already supports two (standard actions, and mixins).
Standard syntax
...
To compare these syntaxes, we'll use a concrete example:
Code Block |
---|
public class Customer { |
...
... public Customer placeOrder(Product p, int quantity) { ... } |
...
public boolean hidePlaceOrder() { return this.isBlackListed(); } |
...
public String disablePlaceOrder() { return clockService.outsideShoppingHours(); } |
...
public String disable1PlaceOrder(Product p) { return p.isOutOfStock() ? "Out of stock": null; } // could also hide parameters similarly |
...
public Collection<Product> choices0PlaceOrder() { ... } // or autoComplete0PlaceOrder(String search) { ... } |
...
public Product default0PlaceOrder() { return orderService.findLastProductPurchasedBy(this); } |
...
public int default1PlaceOrder() { return 1; } |
...
public String validate1PlaceOrder(int quantity) { return quantity <= 0 ? "Can only order +ve amounts": null; } |
...
public String validatePlaceOrder(Product p, int quantity) { return catalogService.runningLowOn(p) && quantity > 4 ? "We're running low on that product, no more than 4" : null; } ... @Inject CatalogService catalogService; @Inject ClockService clockService; @Inject OrderService orderService; } |
Standard syntax
The standard syntax uses regular methods on the target object. Naming conventions are used to associate the action with supporting methods (default, choices, hide, disable and validate).
Here's the same example as before, but with implementation stripped out so that it is easier to compare with the alternate syntaxes that follow:
Code Block |
---|
public class Customer { public Customer placeOrder(Product p, int quantity) { ... } public boolean hidePlaceOrder() { ... } public String disablePlaceOrder() { ... } public String disable1PlaceOrder(Product p) { ... } public Collection<Product> choices0PlaceOrder() { ... } public Product default0PlaceOrder() { ... } public int default1PlaceOrder() { ... } public String validate1PlaceOrder(int quantity) { ... } public String validatePlaceOrder(Product p, int quantity) { ... } } |
Mixins syntax
Mixins change the target, by allowing this set of methods to be moved to a different object target:
Code Block |
---|
public class Customer { ... } |
...
@Action // or @Mixin(method="act") and a bunch of other annotations |
...
public class Customer_placeOrder() { // infer action name from the mixin class name |
...
private final Customer target; // constructor omitted |
...
public Customer act(Product p, int quantity) { ... } |
...
public boolean hideAct() { ... } |
...
public String disableAct() { ... } |
...
public String disable1Act(Product p) { ... } |
...
public Collection<Product> choices0Act() { ... } |
...
public Product default0Act() { ... } |
...
public int default1Act() { ...} |
...
public String validate1Act(int quantity) { ... } |
...
public String validateAct(Product p, int quantity) { ... |
...
}
} |
Instead of \@Action, the \@Mixin(method="act") could also be used, with additional annotations on the "act" method. I've chosen the version with the least boilerplate here.
Parameters syntax (proposed)
...