With subscriptions wired up to keep our view models updated, we can run our application and start clicking around. When we select a word, we can trace through the flow of messages to see how everything updates. But, it’s easy to crash. Let’s debug that crash and work out how to make the application more robust.
If you select a word in the list, and then control-click on that word a second time, the application will crash. Let’s work through fixing up this defect.
We’re getting an
ArgumentNullException, with the message “Message=Value cannot be null. (Parameter ‘word’)” in the preamble for this method:
While a good example of fail fast, this exception is still too late to tell us exactly where the problem came from.
Looking at the stack trace,
WithSelection is called from the
Reduce() method of
VocabularyBrowserScreenReducer, and the parameter value originates from an instance of
SelectWordMessage, we see that there’s nothing to stop its
Word property from being null. We could decide that this is okay, but there is history showing that null values cause bugs. So let’s take a different approach.
Modify the constructor for
SelectWordMessage by adding a guard clause so that it doesn’t accept a null selection:
Now, when we reproduce the bug, we get an earlier exception.
Selection property is being set to null via DataBinding with the
ListBox on screen.
What’s going on?
Ahh - it is possible for a WPF
ListBox control to have no selection - and we don’t currently handle that case. We’re blindly creating a
SelectWordMessage instance, even when we have no selection at all:
Now our required fix becomes clear - we need to send a different kind of message when the selection has been removed. The message definition is trivial - most of the value comes from it being a separate type.
Selection property is changed, we need to ensure we send the right kind of message:
After the message is sent, our
VocabularyBrowserScreenReducer needs to handle it by removing the selection from our application state:
This in turn, requires modifying
VocabularyBrowserScreen by adding the new method:
While this approach takes more code, it’s superior because it makes support for “no selection” explicit in the object model; it doesn’t happen “by accident”, as a side effect of tolerating null values. Being explicit in this way is valuable as our application evolves over time because future maintainers don’t have to guess (perhaps wrongly) our intentions.