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
.
Looking at 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.
In VocabularyBrowserViewModel
, our 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.
When the 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.
Comments
blog comments powered by Disqus