As part of the twelve days of code, I’m building a Pomodoro style task tracking application and blogging about it. You can play along at home too. This post talks about the process of defining the object model and parts of the presentation model. Most of the Model-View-ViewModel examples I’ve seen have not put emphasis on the design of the Model, so I’m not sure that I can call what I’m doing proper MVVM, but i like to have a fully functional application independent of its presentation and then extend parts of the model into presentation model objects. As I was designing the object model, I chose to use interfaces rather than concrete classes. There are several reasons for this, but the main factor was to apply a top-down Test-Driven-Development methodology. On Top-Down Test-Driven-Development… The theory behind “top-down TDD” is that by using the Application or other top-level object as the starting point, I only have to work with that object and its immediate dependencies rather than the entire implementation. As dependencies for that object are realized, I create a simple interface rather than a fully flushed out implementation -- I find using interfaces really helps to visualize the code’s responsibilities. Using interfaces also makes the design more pliable, in that I can move responsibilities around without having to overhaul the implementation. This approach plays well into test-driven-development since tools like RhinoMocks and Moq can quickly generate mock implementations for interfaces at runtime. These dynamic implementations make it possible to define how dependencies will operate under normal (and irregular) circumstances which allows me to concentrate on the object I’m currently constructing rather than several objects at once. After writing a few small tests, I make a conscious effort to validate or rework the object model. Using the Context/Specification strategy I outlined a few posts ago, the process I followed resembled something like this: Design a simple interface (one or two simple methods) Create the concrete class and the test fixture After spending a few minutes thinking about the different scenarios or states this object could represent, I create a test class for that context Write a specification (test) for that context Write the assertion for that specification Refine the context / subject-initialization / because Write the implementation until the test passes Refactor. Add more tests. (Confession: I started writing the ITaskApplication first but then switched to ITaskSessionController because I had a clearer vision of what it needed to do.) More on tests later, first let’s look more at the object model. The Pomodoro Object Model Here’s a quick diagram of the object model as seen by its interfaces. Note that instead of referring to “Pomodoro” or “Tomato”, I’m using a more generic term “Task”: [Image] In the above diagram, the Task Application represents the top of the application where the user will interact to start and stop (cancel) a task session. By design, the application seats one session at a time and it delegates the responsibility for constructing and initializing a task session to the Session Controller. The Task Application is also responsible for monitoring the session’s SessionFinished event, which when fired, the Application delegates to the AlarmController and SessionController to notify the user and track completion of the session. Presently the TaskController acts primarily as a factory for new sessions and has no immediate dependencies, though it would logically communicate with a persistence store to track usage information (when I get around to that). The TaskSession object encapsulates the internal state of the session as well as the timer logic. When the timer completes, the SessionFinished event is fired. The Realized Implementation Using a TDD methodology, I created concrete implementations for each interface as I went. At this point, the division between Presentation Model (aka ViewModel) and Controller Logic (aka Model) are clearly visible: [Image] To help realize the implementation, I borrowed a few key classes from the internets: BaseViewModel When starting out with the Presentation Model, I found this article as a good background and starting point for the Model-View-ViewModel pattern. The article provides a ViewModelBase implementation which contains the common base ViewModel plumbing, including the IDisposable pattern. The most notable part is the implementation for INotifyPropertyChanged which contains debug only validation logic that throws an error if the ViewModel attempts to raise a PropertyChanged event for a property that does not exist. This simple trick does away with stupid bugs related to ViewModel binding errors caused by typos. I’ve also added BeginInitialization and EndInitialization members which prevent the PropertyChanged event from firing during initialization. This trick comes in handy when the ViewModel is sufficiently complicated enough that raising the event needlessly impacts performance. For some reason, I prefer the name BaseViewModel over ViewModelBase. How about you? DelegateCommand When it came time to add Commands to my ViewModels, I considered brining Prism to my application primarily to get the DelegateCommand implementation. Perhaps I missed something, but I was only able to find the source code for download. Ultimately, I chose to take the DelegateCommand code-file and include it as part of the Core library instead of compiling the libraries for Prism. The decision to not compile the libraries was based on some tweaking and missing references for .NET 4.0, and the projects were not configured to compile against a strong-name which I would need for my strongly-named application. The DelegateCommand provides an implementation of the ICommand interface that accepts delegates for the Execute and CanExecute methods, as well as a hook to raise the CanExecuteChanged event. At some point, I may choose to pull the implementation for the Start and Cancel commands out of the TaskApplicationViewModel and into separate classes. More About the Tests As promised, here is some more information about the tests and methodology. Rather than list the code for the tests, I thought it would be fun to list the names of the tests that were created during this stage of the development process. Because I’m using a context/specification test-style, my tests should read like specifications: TaskApplicationSpecs: when_a_task_completes should_display_an_alarm should_record_completed_task when_a_task_is_cancelled should record cancellation when_a_task_is_started should_create_a_new_session ensure_new_tasks_cannot_be_started ensure_running_task_can_be_cancelled when_no_task_is_running ensure_new_task_can_be_started ensure_cancel_task_command_is_disabled TaskSessionControllerSpecs: when_cancelling_a_tasksession ensure_session_is_stopped when_creating_a_tasksession should_create_a_task_with_a_valid_identifier ensure_start_date_is_set ensure_session_is_started ensure_session_length_is_set when_finishing_a_tasksession ensure_session_is_stopped TaskSessionViewModelspecs: given_a_default_session should_be_disabled should_not_have_start_date_set should_not_have_end_date_set should_have_valid_id when_session_is_ended ensure_endtime_is_recorded when_session_is_started should_be_active should_have_initial_time_interval_set should_have_less_time_remaining_than_original_session_length should_notify_the_ui_to_update_the_counter_periodically should_record_start_time_of_task ensure_end_time_of_task_has_not_been_recorded when_timer_completes should_raise_finish_event ensure_finish_event_is_only_raised_once should_run_the_counter_down_to_zero should_disable_task ensure_endtime_has_not_been_recorded Next Steps The next logical step in the twelve days of code is creating the View and wiring it up to the ViewModel.
"Twelve Days of Code – Pomodoro Object Model"
No comments yet. -