Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
public class Customer {                                                              // target
    
     public static class PlaceOderEvent extends ActionDomainEvent<Customer> {}                                      

    @Action(domainEvent = PlaceOrderEvent.class)                                     // event publishing
    public Customer placeOrder(Product p, int quantity) { ... }                      // action execution

    public boolean hidePlaceOrder() { ... }                                          // supporting methods
    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 change the target, by allowing this set of methods to be moved to a different object.  In other words, the target responsibility changes.

So the real target is simply:

Code Block
public class Customer {}


and the action itself moves onto the mixin:

Code Block
 ... }

@Action                                                        //
public orclass @Mixin(method="act") and a bunch of other annotations
public classCustomer_placeOrder() {                           

    private final Customer target;                                                // target
    public Customer_placeOrder(Customer target) { ... }

    public static class PlaceOrderEvent extends ActionDomainEvent<Customer> {}                             // infer action name from the mixin class name 

    private final Customer target;@Action(domainEvent = PlaceOrderEvent.class)                                  // constructorevent omitted
publishing
    public Customer act(Product p, int quantity) { ... }                          // action execution

    public boolean hideAct() { ... }                                              // supporting methods
    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) { ... }
}

Notes:

  • 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.
  • Mixins are also used for derived properties or collections (ie query-only actions with no side-effects).  These are specified using @Property or @Collection 
  • We now have two classes here: the mixin, and the domain event within.

Parameters syntax (proposed)

Per this thread on slack, we could introduce a Parameters object (in Java 14+, this might be a record) to bring together all of the parameters into a single object.  This would make it easier to avoid issues with numbering etc.

This syntax syntax changes the way in which supporting methods are associated back to the main execution method.

Code Block
languagejava
public class Customer {                                                           // target

    @Value @Accessors(fluent = true)                   
    public class PlaceOrderParameters {                                           // to assist supporting methods 
        Product product;
        int quantity;
    }

    public static class PlacerOrderEvent extends ActionDomainEvent<Customer> {}                                      

    @Action(domainEvent = PlaceOrderEvent.class)                                  // event publishing
    public Customer placeOrder(Product p, int quantity) { ... }                   // execution    

    public boolean hidePlaceOrder() { ... }                                       // supporting methods use PlaceOrderParameters
    public String disablePlaceOrder() { ... }
    public String disable1PlaceOrder(PlaceOrderParameters params) { ... }
    public Collection<Product> choices0PlaceOrder() { ... }              
    public Product default0PlaceOrder() { ... }
    public int default1PlaceOrder() { ... }
    public String validate1PlaceOrder(PlaceOrderParameters params) { ... }
    public String validatePlaceOrder(PlaceOrderParameters params) { ... }
}

Notes:

  • The

...

  • @Value

...

  • @Accessors(fluent=true) allows us to use a syntax that is very similar to Java 14 records.

...

  • There is some duplication here: the list of the parameter types appears both in the

...

  • placeOrder(...)

...

  •  method, as well as in the PlacerOrdersParameters class.

The above would also be supported with mixins:

Code Block
@Action
public class Customer_placeOrder {

    private final Customer target;                                                // target
    public Customer_placeOrder(Customer target) { ... }

    @Value @Accessors(fluent = true)             
    public static class PlaceOrderParameters {                                    // to assist supporting methods
        Product product;
        int quantity;
    }

    public static class PlaceOrderEvent extends ActionDomainEvent<Customer> {}                                      

    @Action(domainEvent = PlaceOrderEvent.class)                                  // event publishing
    public Customer act(Product p, int quantity) { ... }                          // execution

    public boolean hideAct() { ... }                                              // supporting methods
    public String disableAct() { ... }
    public String disable1Act(PlaceOrderParameters params) { ... }
    public Collection<Product> choices0Act() { ... }              
    public Product default0Act() { ... }
    public int default1Act() { ... }
    public String validate1Act(PlaceOrderParameters params) { ... }
    public String validateAct(PlaceOrderParameters params) { ... }
}

Notes:

  • we now have three classes here: the mixin, the domain event, and the parameters object.

Parameters on Act syntax (proposed)

...