balance between UI responsiveness and avoiding race conditions

by KolA   Last Updated August 13, 2019 08:05 AM - source

To keep scope small I will talk about UI race conditions initiated by the same user in the same app sessions. The question is general and not specific to mobile, web or desktop UI.

The issue

Modern UI expected to be responsive i.e. commands triggered by user executed asyncronously while UI remains responsive and available. This is perfect breeding ground for all sorts of race conditions because async command can potentially take a lot of time (e.g. if connection is slow/unresponsive) and during that time user can initiate potentially conflicting command in parallel.

There are "bruteforce" workarounds such as make all command synchronous or disable screen / show blocking progress bar or ring for any command / blocking modal dialogs etc. however I don't consider them here.

In my experience it's a serious mental overhead to keep track of all UI elements that can potentially lead to race conditions / conflicting commands and remember to enable/disable them accordingly. The payoff (better UX) is not always worth it. Rx/Reactive programming makes it easier to automatically enable/disable UI elements but it doesn't relieve need to keep many dependencies in one's head. It's especially bad when many people work on a project and write different components/views separately.

Example

For example consider a simple app for editing orders. Order has lines. There are some asynchronous commands (e.g. they all eagerly write to database or other backend).

Order commands (with UI elements)

  • Delete (button)
  • Change customer (dropdown)
  • Change shipping date (calendar)
  • Confirm (button)

Line commands

  • Create line (new row in grid)
  • Edit line (row in grid)
  • Delete line (button)

It's easy to come up with examples of commands which are safe or not safe to run concurrently. E.g. it's OK to edit a line and delete another line at the same time as these commands don't interfere. It's OK to change order shipping date while lines are being saved (shipping date doesn't affect lines), but it's not not OK to change order's customer (e.g. it will refresh pricing for lines i.e. no line command should be in progress). Let's say we add rule that only order without lines, now Delete Order button must be disabled if there's any line command in progress... And so on and so forth.

In large apps there are more entities and dependencies between them and hence risk of more subtle race conditions.

Example is for illustration only, the question is more general.

The question

Do you know any disciplined approach to maintain good balance between UX/responsiveness and risk of allowing conflicting commands/race conditions? I don't expect a silver bullet and suppose that answer won't be short and will accept relevant links to other resources or books as answers. Any platform or language will do but ideally it has to be in spirit of Rx / (functional) reactive programming.



Related Questions




Should web forms allow invalid input?

Updated September 05, 2016 09:02 AM