What causes UI updates in the CQRS client application?

I am trying to learn and apply the CQRS design approach (template and architecture) to a new project, but the key part seems to be missing.

The client application executes the query and retrieves a read-only list of read-only DTO data from the read model. The user selects an item and presses a button to initiate some actions. The action is performed by creating and sending the corresponding command object to the recording model (where the command handler performs the action, updates the data store, etc.). However, at some point I need to update the user interface to reflect changes in the state of the application caused by the action.

How does the user interface know when it's time to update the original list?

Additional Information

I noticed that most articles / blogs discussing CQRS use MVC client applications in their examples. I am currently working on a Silverlight client and am starting to wonder if the template is working in this case.

Follow up question

After thinking more about Bartlomiej's answer and the discussion that follows, I wonder about error handling in CQRS. Given that commands are mostly fire-and-forget asynchronous operations, how do we report an error in the user interface?

I see a "user interface update" to take one of two forms:

  • The operation succeeds, the data has changed, and the user interface must be updated to reflect these changes.
  • The operation failed, the data has not changed, but the user must be notified of failures and possible corrective actions.

Even with the Post-Redirect-Get pattern in MVC, you cannot redirect until you know the outcome of the operation. None of the examples that I have seen so far address these problems of the real world.

+6
source share
4 answers

I am trying to deal with similar issues for a WPF client. The re-request trigger for any data depends on the data of your update, the teams usually fall into the categories:

  • A command is a true fire and forget method, it informs about the state of a state change, but this change does not need to be reflected in the user interface, or the change is simply not important for the user interface.

  • The command will change the result of a single request

  • The command will change the result of several queries, usually (in my domain, at least) in a cascading way, that is, changing the state of one "high" part of the data is likely to affect many "low level" ones.

My first trigger is page loading, very few elements are exempted from this, since most pages should assume that the data has been updated since the last visit. Despite the fact that some systems can escape, only in this way updating financial and other critical data.

For short commands, I also update the data when the success command returns from the command. Although this is mostly laziness, since IMHO all CQRS commands should be run asynchronously. This is still an option that I could not have lived without it, except for one that you might need if your implementation expects a high delay between the command and the request.

One template I'm starting to use is the mediator (most MVVM frameworks have one). When I run the command, I also launch a message to the broker indicating which command was run. Each Cache ( Retriever<T> view model property) listens for commands that affect it, and then updates accordingly. I try to minimize the number of messages, while still minimizing the number of caches that update the unnecessary from a single message, so I (hopefully) end up with a short list of reasons for the update, with each "reason" updating the list of caches.

Another approach is simple honesty, I find that by demonstrating graphically how the system updates itself, users become more willing to be patient with it. When you run the command, display some user interface that indicates that you are expecting a successful response if there is an error that you might suggest to repeat / show the error if the update fields for the corresponding fields are successfully started. Bearing in mind that this command could be launched from another terminal (which you do not have knowledge of), therefore, in the end, the data will need a timeout to avoid missing state changes caused by other machines.

Noting the irony that the only effective way to update the cache and values ​​on the client is to cancel the commands and requests again, whether using hard coding or something like a hash map.

+4
source

My two cents.

I think MVVM fits very well in CQRS. ViewModel just becomes an observable ReadModel.

1 - You initialize the state of the ViewModel with a request in the ReadModel.

2 - Changes to the ViewModel are automatically reflected in all Views associated with it.

3 - Certain changes in the ViewModel run a command to go to the message queue, the object responsible for sending these commands to the server sends these messages from the queue and sends them to WriteModel.

4 - Clients must be well-formed, that is, the ViewModel had to perform an appropriate check before it ever ran the command. After running the command, any event notifications can be published on the event bus so that the client can transfer changes to other ViewModels or components in the system that are interested in these changes. These events should contain the necessary information. Typically, this means that other view models usually do not need to re-query the reading model as a result of the change, if they are not dependent on other data to be obtained.

5 - There is an object that connects to the message bus on the server for real-time alerts when other clients make changes that this client is interested in knowing about them, if necessary, return to a lengthy survey. It distributes them to the internal message bus, which binds the components on the client together.

6 - The last part for processing is the fact that clients can connect from time to time, which should be the only reason for the team to refuse (at the moment they do not have access to the Internet), that is, when the client should be notified of problems.

+2
source

In my ASP.NET MVC 3, I use 2 methods depending on the use case:

  • The well-known Post-Redirect-Get template, which combines well with CQRS. The MVC action that runs the command returns a redirect to the action that executes the request.
  • in some cases, such as real-time updates from other clients, I rely on domain events / messages. I am creating an event handler that uses singlarR to modify all connected and interested clients.
+1
source

There are two main ways you can use, as far as I know:

1) create your user interface so that the user does not immediately see his changes. Like, for example, a message to tell him that his action is successful, and offers him various options for continuing his work. this should buy you enough time to update your readmodel.

2) more complicated, but you can save the information that you sent to the server and display it in the interface.

The most important thing, I think, is to educate your user if you can so that they know why there is no data here ...

I’m thinking about it just now, but they are designed to handle sync commands, not async, with asynchronous things it’s working harder and harder on the brain ... the client interface also becomes an event.

0
source

Source: https://habr.com/ru/post/919718/


All Articles