UI Binding to Command

Hi all,

In our application, we bind UI widgets to Command object then when
user click 'Save' button for instance, the command object is sent
through command bus.

We have some complex screens in which some values are instantly
updated as other field's value changes. For example (simplified) when
user enters Price or Quantity, the Total field will be instantly
updated based on Price * Quantity calculation. Since the code to
calculate Total resides in AR which won't be touched until user click
'Save', how can we update the Total field as user enters Price or
Quantity value ?

Any advice would be greatly appreciated.

Thanks & Regards,

Setya

The is nothing wrong with a little bit of “predicting” in the UI. In other words, just calculate the totals in the UI itself when users add products.

An alternative, which has advantages and disadvantages, is to send commands to the server each time data in the form changes. The “submit” button would then just “confirm” a certain order. In this case, the server will contain all the calculation logic.

Cheers,

Allard

Hi Allard,

Thank you for your response.

The is nothing wrong with a little bit of "predicting" in the UI. In other
words, just calculate the totals in the UI itself when users add products.

I think this leads to code duplication. The sample I gave was
simplified, the actual might involve database querying, etc & complex
calculation.

An alternative, which has advantages and disadvantages, is to send commands
to the server each time data in the form changes. The "submit" button would
then just "confirm" a certain order. In this case, the server will contain
all the calculation logic.

With this approach, for each field involved in calculation we must
provide method (i.e updatePrice & updateQuantity) which emits events
subscribed by the controller which in turn will update UI when events
arrive. We must also provide a separate repository/factory to
instantiate AR instance for this purpose when UI is opened. The AR
will only live in memory & discarded when the 'submit' button is
clicked.

Any thoughts are welcome.

Thanks & Regards,

Setya

Hy Setya,

If the code is more complex than just adding up numbers, just consider extracting a “Domain Service”. Both the Query Side (which logically belongs to the UI it provides information for) and the Command Side could use this service to do the calculations.

Just make sure the service exclusively uses “shared” model objects. Model these as value objects (i.e. immutable) as much as possible.

Also make sure that the service doesn’t make any modifications by itself. Invoking the service should not have any side-effects. Those side effects may only occur on the command side, in the aggregates.

Hope this helps.

Cheers,

Allard

Hi Allard,

I'm not sure I understand what you proposed. A concrete yet simple
example would be helpful.

Thanks & Regards,

Setya

Let’s stick to your order example. Let’s assume the client continuously shows the grand total of an order. And let’s assume adding up these numbers is too complicated to have this code duplicated.

You’d just have to create an OrderTotalsCalculationsService that does the job for you. It would have a method with a signature like “OrderTotals calculateOrderTotals(List items, ShippingType shippingType)”. The parameters and result of this method should not be command-specific objects. In my projects, I always have a simple rule: an object can only be shared between command/query and UI side if it is immutable. And it should also “make sense” given the domain.

Since OrderTotalsCalculationsService is a Domain Service, it is part of the domain. It is also “side effect free”. Which means that invoking this method will not change the applications’ state. This makes it safe to be shared around the application, just like you share any other objects.

Another way to do it, is by implementing it on the query side. But, that will require your app to invoke a server component each time something changes. If you have a rich client, that might give some unwanted overhead. In that case, the OrderTotalsCalculationsService will only live on the server. It will still be used by both the command and the query side.

For an explanation of (Domain) Service: http://www.domaindrivendesign.org/node/125

Does this clarify?

Thank you for your explanation.

So basically you're suggesting that we move the code into a separate
service class and both party (client/server) share the service ?

Regards,

Setya

Exactly!