The existing model class
ModifyVocabularyWordScreen only handles the creation of a new word. We need to modify it to support the modification of an existing word as well.
Currently, our entry point for creating a new instance of ModifyVocabularyWordScreen is through its constructor. It might, therefore, seem appropriate to add another constructor, one that allows an existing word to be provided as a starting point.
However, this runs up against a design smell. Having multiple constructors is often considered unwise - and we already have two. Our saving grace is that one of them is private, so it’s just an internal implementation issue. Having multiple public constructors is distinctly worse.
Instead of adding a third constructor, I’ve introduced two different static factory methods:
Using static factory methods instead of overloaded constructors has the advantage that each can be given an intention-revealing name.
Both of these factory methods delegate to the same constructor, with an optional parameter for the word to modify:
If an existing word is passed, the properties of that word are used to initialize our screen for use. Conversely, if no existing word is passed, we initialize with some sensible defaults. In either case, we mark our screen as unmodified.
As our user makes changes, we want to track whether there have been any changes made. There are two ways we can do this.
- We can independently track modifications; or
- We can compare our current state to where we started
For now, we’re going to use the first approach, but we will be able to change to the later approach down the track if we choose.
We do this by introducing the property
Modified; when a new screen is created, we default this to false. Any change made to our screen results in the property being change to true, and it can be reset to false by calling ClearModified().
When a new word is saved, we need to add it to the VocabularySet we already have; this is handled by our existing message SaveNewVocabularyWordMessage.
For the situation when we’re modifying an existing word, we need a new message:
As we’ve done before, we enact this message in our reducer, modifying the state of our application.
I’ve shown the handling for both kinds of “save” message to emphasize their differences.
ViewModel & View Changes
Our ViewModel and the linked View also need to change, though the differences are minor.
Instead of a hard-coded caption, we now need one provided through data-binding, reflecting whether we are creating a new word or modifying an existing one.
We can now also use the command infrastructure we talked about a couple of weeks ago to hook up both Save and Close commands.
About the most complicated piece of the store is our Save() implementation which needs to choose which message to send:
The last changes to mention this week are a couple of fixes for errors I made last time.
Adding a namespace for our
Program class broke compilation by renaming the class; this is fixed by changing the
<StartupObject> property in the
WordTutorViewModel triggered a diagnostic warning from our DI framework. Ensuring we dispose of this ourselves in
Main() means that it’s safe to suppress that warning.