My current clunky “put all the code in the view” approach to V-Drum Explorer is creaking at the seams. I’m really not a WPF developer, and my understanding of MVVM is more theoretical than practical. I’ve read a reasonable amount, but quite a lot of aspects of V-Drum Explorer don’t really fit with the patterns described.
Eventually I’d like to present blog posts with a nice clean solution, and details of how it avoids all the current problems – but I’m not there yet, and pretending that good designs just drop fully formed onto the keyboard doesn’t feel healthy. So this blog post is a pretty raw copy/paste of the notes I’ve made around what I think I’ll do.
There’s no conclusion here, because life isn’t that neatly defined. I do hope I find time to tackle this reasonably soon – it’s going to be fun, but I’m not sure it’s going to be feasible to refactor in small steps.
The current design has the following issues:
- A lot of the UI controls are created within the code-behind for the view, so styling is hard
- The logic handling “how the UI reacts to changes” is really tricky, due to chain reactions:
- Changing a tempo sync value changes which field is displayed next to it
- Selecting a MultiFX option changes all the fields in the overlay
- Selecting an instrument group changes which instruments are selected, and the vedit parameters available
- Selecting an instrument can change the vedit parameters (e.g. cymbal size)
- The UI currently “knows” about data segments, addresses etc – it shouldn’t need to care
- The way that the schema is constructed makes the address logic bleed out; we can populate all the “fixed” containers and only generate fields for overlay containers when necessary
- Using inheritance for the commonality between ModuleExplorer and KitExplorer is a bit weird
Ideas and questions that might end up being part of the answer
- My schema has a “physical layout” and a “logical layout” – for example (in the TD-27), each kit has 24x KitPadCommon, 24x KitPadMain, 24x KitPadSub, 24x KitPadMainVEdit, 24xKitPadSubVEdit. It makes more sense to show “24x instrument info”. Is that information part of the model or the view-model?
- I suspect it’s part of the model, effectively.
- Perhaps the ViewModel shouldn’t even see the physical layout at all?
- The logical layout is worryingly “tree view + details pane”-centric though
- We have “snapshotting” in two ways when editing:
- Overall commit/cancel
- Remembering values for each multi-fx / vedit overlay while editing, so you can tweak, change to a different overlay accidentally, then change back to the original one and still have the tweaked values.
- Should this logic be in the ViewModel or the Model?
- Should the model implement INotifyPropertyChanged (et al)?
- Looks like there’s genuine disagreement between practitioners on this
- Feels like a pretty stark choice: either ViewModel controls everything, including how overlays work (i.e. when changing instrument, change the overlay too) or the model needs to tell the ViewModel when things are changing.
- Where do we keep the actual data? Still in a ModuleData?
- We could generate a model (e.g. with Kit, KitPadInst etc being full types)
- We’d then either need to generate all the corresponding ViewModels, or access everything via reflection, which defeats half the point
- Would definitely be easier to debug using a model
- Generators are a lot of work…
- Possibly reify “schema + data” in the model, to avoid having to pass the data in all over the place (hard to do binding on properties without this…)
- Reify overlays in just-in-time fashion, to avoid creating vast numbers of fields.
- Broadly the same UI we have now. At least the same features.
- No code in the View – eventually. Not clear what creates a new window when we load a file etc, but we can try to remove as much as possible to start with and chip away at the rest.
- ViewModel shouldn’t need to touch ModuleAddress. Access is view ModuleSchema, containers, ModuleData.
- 7-bit addressing should be isolated even within the model, ideally to just ModuleAddress.
- ViewModel interaction with fields should be simple.
- The command line app should be able to work with the model easily – and may require lower-level access than the UI.