I have developed some MVVM based WPF code and am in need of some minor refactoring but prior to doing that I need to decide the best architecture.
I originally started with an application that could present several similar (but separate) representations of my data. Let's call it RecordsViewModel which had a corresponding RecordsView. As time went on, I introduced a SettingsViewModel which was passed into the constructor of the RecordsViewModel and published visibly (allowing RecordsView to use it). The SettingsViewModel is registered to so that changes are reflected in all of my views.
Now I want to split RecordsView a little because it now contains two distinct views.
The problem I have is:
the new (RecordsMainView and RecordsAlternativeView) both want to see Settings.
unlike the earlier RecordsView which is programmatically instantiated, these new views are instantiated from Xaml (default constructor).
So my options seem to be:
Walk the Tree Model upwards to find a parent with a Settings
Make Settings a DependencyProperty on the controls and make the Xaml join the Property to the instance.
Make SettingsViewModel a Singleton.
Any other, better, options? Which would you consider best?
I would turn your settings logic into a service (ISettingsService) and use service locator or dependency injection to get at that service from whichever view models need it.
Services are great for managing shared state, and service locator / DI makes it very easy for your VMs to get a reference to the service. Storing shared state in a VM is a bit hacky and - as you've found - doesn't really scale. A good rule of thumb might be to ask yourself whether the state in the VM exists only to support the corresponding view, or whether other components will need access to that state. If the latter, move it into a service.
Related
I have recently learned that you can provide cascadingValues to the entire project by wrapping the Router component in the provider Microsoft doc. How is this different to using dependency injection with a singleton pattern? (I know how injection works, I mean performance and architecture wise)
Which do you think is better to use?
There has been some discussion about the performance impact of CascadingValues. I can recommend this article (it is an excellent tutorial as well).
As you mentioned, there are two aspects: performance and architecture.
Performance
I'd see [CascadingParameter] are costly compared to [Parameter] or "normal" fields and properties. Each component down the tree, subscribe to the [CascadingParameter] changes. If the value changes, a new cycle of ParamtersSet is started, which could lead to a call to the render tree and check if something in DOM needs to be changed. So, even if no rerendering is required, the process to reach this conclusion consumes time. The more components, the more depth the tree has, the slower this process becomes.
Architecture
To discuss this aspect, we can think about the CascadingAuthenticationState. It is part of the authentication framework for Blazor and provides access to check whether a user is authenticated or not. It is implemented as a cascading value instead of a singleton. Components down the tree, like menus, can easily use this value to hide/show items for non authenticated users. Why?
Frequency of change and impact to the DOM
A question to answer is regarding the impact of the change of a cascading value. If a user logins/log out, it is reasonable to assume that this will trigger a huge DOM change. So, checking a huge part of the tree (if not the entire based on where the cascading value is placed) is not overhead.
Besides, it is a good guess that there will be few changes to AuthenticationState during the lifetime of the application.
Simplicity
The menu component uses the AuthorizeView which uses the cascading parameter of Task<AuthenticationState>.
<AuthorizeView>
<Authorized>
<li>Admin</li>
</Authorized>
<NotAuthorized>
<li>Log in</li>
</NotAuthorized>
</AuthorizeView>
This snippet is easy to read, and you can understand it very quickly. If you did the same thing with a singleton service, you would need to implement the "communication" between component and service. It would be best to implement a subscribe/unsubscribe scenario, maybe using events or more advanced technologies. You will need to write your own code, and again don't forget to write your implementation of IDisposable to unsubscribe.
Cascading parameters are focused on UI
While a singleton service is a very generic approach to solve many different issues, cascading values are specially designed to solve UI update problems. They are doing it very efficiently. In the case of the AuthenticationState, it uses a specialized view.
There is space for arguments if Blazor isn't all about UI, but with modern, rich features GUI, sometimes we have a layered approach inside the application. So, with UI, I mean the part of the application ultimately responsible for rendering.
Services could be used outside of this inner UI layer, through the entire application, and then reused in the UI as well, while cascading parameters could only be used inside components.
Cascading parameters are (mostly one way)
A cascading parameter is "owned" by a component. Usually, the component where it is declared. From that point, it is passed down the tree. All other components can consume it. There is no straightforward, easy, and scalable way to update a value from a child component. As I said, mostly, there are ways to do it, but it is a dirty path, in my view.
Summary
As with a lot of other technologies, the answer is: It depends on the use case.
top-down usage: cascading values
Components need to update the value: service
many changes: It highly depends on the tree structures if easiness outweighs the performance impact.
use outside and inside the inner UI layer: service
And, another approach to this problem could be something like Blazor Component Bus
Update
In addition to what was said by Just the benno, I may add that there is a fundamental difference between a CascadingValue component and a Singleton service regarding their scope. A Singleton service, in Blazor Server App, is singleton across the lifetime of the application, across multiple connections, and across multiple browsers... while CascadingValue component is scoped to the current instance of your app. Changing the state of an object provided by a CascadingValue component has no effect on a new instance of the app. But if you change the state of a Singleton service in an instance of your app, this change will be propagated to other instances of your app. Try to imagine what would be the implications of implementing the functionality of the CascadingAuthenticationState component as a Singleton service rather than CascadingValue.
Right now I am coding an application and am thinking that there has to be a better solution to what I am doing right now.
I have a main window which shall handle the settings of the program. Then I have further classes and windows. For example a language handler class and a form that is handling the user input needed for the "main function".
However, until now I always have to pass my main window to each of this classes, because the language handler shall be able to change the main window's strings. And the other form should also be able to pass data to the main Window.
If we imagine there will be much more classes and every class needs a copy of the main window this would consume a lot of resources depending on the main window's "size".
So, is there a better/more efficient way to communicate between these classes.
Common way to do that is to use observer pattern, which in .NET is events system. Simply said, your classes subscribe to each other's events and perform action when event is raised. As noted in comment, passing references is not memory heavy, but it results in tight coupling between different pieces of your code - observer pattern addresses that problem.
Another option is to consider you classes as services. Code them to an interface and then use dependency injection (aka Inversion of Control) to build up the object graph (You tell the IoC container you want a frmSomething and it will determine what services/classes it needs and instantiate them as appropriate).
This means that:
you only ever have to code against an interface not an implementation
your code is loosely coupled (You can swap an OldTranslator for a NewTranslator and as long as they both comply to the same interface, nothing has to be changed except the configuration of the container)
you can develop high-level features which rely on services that haven't been written yet and your code will compile
You can very easily change how your app works, at run-time if needs be, by changing what classes/services are registered in your container.
Have a look at Unity for the MS-Supported DI container. Castle Windsor is a popular alternative but there are many more
It's worth noting that passing a "Copy" of the main window around as you've said is not a bad thing - You're actrually only passing a reference (effectively a pointer) to the main window (since anything more complex than the real primitives are reference types). This means that there's very little overhead whatsoever
I would suggest you to use Galasoft or Prism MVVM implementations. There you can use their messaging service which is quite easy to use. The class that needs info just sends a message to the subscriber and they in turn can send all data needed. I think that this is the easiest way to handle communication.
in addition to the ans given by IVAN.. if we look at a higher level view without all those terminologies then you should probably create a static class which would server as InMemoryStorage and defines fields on it to save information
this what you will have complete control over what is being shared and multiple components can change it
moreover you can defined getters and setters and raise an event whenever the property is changed so that different forms or windows (views) can subscribe to the change and take action accordingly
I'm building a Visual Studio-like application in WPF and I'm having some problems identifying the best architectural design organization of my components. I plan to use Unity as my dependency-injection container and Visual Studio Unit Testing framework and probably moq for mocking library.
I'll first describe the structure of my solution, then my questions:
I have a WPF project that contains:
My Unity container initialization (bootstrapper) on application startup (in App.xaml.cs)
All my application Views (XAML).
Another project called ViewModel this contains:
All my application ViewModels. All my ViewModels inherit from a ViewModelBase which exposes a ILogger property
My initialization logic is as follows:
Application Startup
Unity container creation and registration of types: MainView and MainViewModel
Resolve my MainView and show it.
var window = Container.Resolve<MainView>();
window.Show();
My MainView constructor receives a MainViewModel object in its constructor:
public MainView(MainViewModel _mvm)
My MainViewModel has a Child ViewModel for each of its panels:
public ToolboxViewModel ToolboxVM{get; set;}
public SolutionExplorerViewModel SolutionExplorerVM { get; set; }
public PropertiesViewModel PropertiesVM { get; set; }
public MessagesViewModel MessagesVM { get; set; }
And I'm planning to create a InitializePanels() method that initializes each of the panels.
Now here my questions:
How can my MainViewModel.InitializePanels() initialize all those panels? given the following options:
Option 1: Initialize the ViewModels manually:
ToolboxVM = new ToolboxViewModel();
//Same for the rest of VM...
Cons:
I'm not using the Unity container so my dependencies (e.g. ILogger) are not automatically resolved
Option 2: Use setter injection by annotating my properties:
[Dependency]
public ToolboxViewModel ToolboxVM{get; set;}
//... Same for rest of Panel VM's
Cons:
I've read that Unity Setter dependencies should be avoided since they generate a dependency with Unity in this case
I've also read that you should avoid using Unity for Unit Tests, so how to make this dependency clear in my Unit Tests? Having many dependent properties could be a nightmare to configure.
Option 3: Use Unity Constructor injection to pass ALL my Panel ViewModels to the MainViewModel constructor so they are automatically resolved by Unity container:
public MainViewModel(ToolboxViewModel _tbvm, SolutionExploerViewModel _sevm,....)
Pros:
The dependency would be evident and clear at time of creation, which could help building my ViewModel UnitTests.
Cons:
Having so many constructor parameters could get ugly pretty quickly
Option 4: Registering all my VM types at container buildup. Then passing the UnityContainer instance through constructor injection to my MainViewModel:
public MainViewModel(IUnityContainer _container)
That way I could do something like:
Toolbox = _container.Resolve<ToolboxViewModel>();
SolutionExplorer = _container.Resolve<SolutionExplorerViewModel>();
Properties = _container.Resolve<PropertiesViewModel>();
Messages = _container.Resolve<MessagesViewModel>();
Cons:
If I decide NOT to use Unity for my UnitTests, as many people suggest,then I won't be able to resolve and initialize my Panel ViewModels.
Given that lengthy explanation, what is the best approach so that I can take advantage of a Dependency Injection Container and end up with a Unit-Testable solution??
Thanks in advance,
First things first... As you noticed, your current setup might be problematic when unit testing (complex VM initialization). However, simply following DI principle, depend on abstractions, not on concretions, makes this problem go away immediately. If your view models would implement interfaces and dependencies would be realized through interfaces, any complex initialization becomes irrelevant as in test you'll simply use mocks.
Next, problem with annotated properties is that you create high coupling between your view model and Unity (this is why it is most likely wrong). Ideally, registrations should be handled at single, top level point (which is bootstrapper in your case), so container is not bound in any ways to object it provides. Your options #3 and #4 are most common solutions for this problem, with few notes:
to #3: too many constructor dependencies is usually mitigated by grouping common functionality in facade classes (however 4 is not that many after all). Usually, properly designed code doesn't have this problem. Note that depending on what your MainViewModel does maybe all you need is dependency to list of child view models, not concrete ones.
to #4: you shouldn't use IoC container in unit tests. You simple create your MainViewModel (via ctor) manually and inject mocks by hand.
I'd like to address one more point. Consider what happens when your project grows. Packing all view models into single project might not be good idea. Each view model will have its own (often unrelated to others) dependencies, and all this stuff will have to sit together. This might quickly become difficult to maintain. Instead, think whether you can extract some common functionalities (for example messaging, tools) and have them in separate groups of projects (again, split into M-VM-V projects).
Also, it's much easier to swap views when you have functionality related grouping. If project structure looks like this:
> MyApp.Users
> MyApp.Users.ViewModels
> MyApp.Users.Views
> ...
Trying out different view for user edit window is a matter of recompiling and swapping single assembly (User.Views). With all in one bag approach, you'll have to rebuild much larger part of application, even tho majority of it haven't changed at all.
Edit: keep in mind that changing existing structure of project (even tiny one), is usually a very costly process with minor/none business results. You might not be allowed or simply not be able to afford doing so. Usage-based (DAL, BLL, BO, etc) structure does work, it just gets heavier with time. You can just as well use mixed mode, with core functionalities grouped by their usage and simply adding new functionalities utilizing modular approach.
First off, you'd probably want to use interfaces rather than concrete classes, so that you'll be able to pass you mock objects when unit testing, i.e IToolboxViewModel instead of ToolboxViewModel, etc.
That being said, I would recommend the third option - constructor injection. This makes the most sense, since otherwise you could call var mainVM = new MainViewModel() and end up with a non-functional view model. By doing that, you're also making it very easy to understand what are your view-model's dependencies, which makes it easier to write unit tests.
I would check out this link, as it's relevant to your question.
I agree with Lester's points but wanted to add a few other options and opinions.
Where you are passing the ViewModel to the View through the constructor, this is a bit unconventional as WPF's binding capability allows you to completely decouple the ViewModel from the View by binding to the DataContext object. In the design you've outlined, the View is coupled to a concrete implementation and limits reuse.
While a service facade will simplify option 3, it is not uncommon (as you've outlined) for top-level ViewModels to have a lot of responsibilities. Another pattern you can consider is a controller or factory pattern that assembles the viewmodel. The factory can be be backed by the container to do the work but the container is abstracted away from the caller. A key goal in building container-driven apps is to limit the number of classes that understand how the system is assembled.
Another concern is the amount of responsibilities and object relationships that belong to the top-level viewmodel. If you look at Prism (a good candidate with WPF + Unity) it introduces the concept of "regions" that are populated by modules. A region may represent a toolbar which is populated by mutliple modules. Under such a design, the top-level viewmodel has fewer responsibilities (and dependencies!) and each module contains Unit-testable DI components. Big shift in thinking from the example you've provided.
Regarding option 4, where the container is passed in through the constructor is technically dependency inversion but it's in the form of service location instead of dependency injection. Having gone down this path before I can tell you it's a very slippery slope (more like a cliff): Dependencies are hidden inside classes and your code becomes a web of "just in time" madness -- completely unpredictable, totally untestable.
I'm not a hater of singletons, but I know they get abused and for that reason I want to learn to avoid using them when not needed.
I'm developing an application to be cross platform (Windows XP/Vista/7, Windows Mobile 6.x, Windows CE5, Windows CE6). As part of the process I am re-factoring out code into separate projects, to reduce code duplication, and hence a chance to fix the mistakes of the inital system.
One such part of the application that is being made separate is quite simple, its a profile manager. This project is responsible for storing Profiles. It has a Profile class that contains some configuration data that is used by all parts of the application. It has a ProfileManager class which contains Profiles. The ProfileManager will read/save Profiles as separate XML files on the harddrive, and allow the application to retrieve and set the "active" Profile. Simple.
On the first internal build, the GUI was the anti-pattern SmartGUI. It was a WinForms implementation without MVC/MVP done because we wanted it working sooner rather than being well engineered. This lead to ProfileManager being a singleton. This was so from anywhere in the application, the GUI could access the active Profile.
This meant I could just go ProfileManager.Instance.ActiveProfile to retrieve the configuration for different parts of the system as needed. Each GUI could also make changes to the profile, so each GUI had a save button, so they all had access to ProfileManager.Instance.SaveActiveProfile() method as well.
I see nothing wrong in using the singleton here, and because I see nothing wrong in it yet know singletons aren't ideal. Is there a better way this should be handled? Should an instance of ProfileManager be passed into every Controller/Presenter? When the ProfileManager is created, should other core components be made and register to events when profiles are changed. The example is quite simple, and probably a common feature in many systems so think this is a great place to learn how to avoid singletons.
P.s. I'm having to build the application against Compact Framework 3.5, which does limit alot of the normal .Net Framework classes which can be used.
One of the reasons singletons are maligned is that they often act as a container for global, shared, and sometimes mutable, state. Singletons are a great abstraction when your application really does need access to global, shared state: your mobile app that needs to access the microphone or audio playback needs to coordinate this, as there's only one set of speakers, for instance.
In the case of your application, you have a single, "active" profile, that different parts of the application need to be able to modify. I think you need to decide whether or not the user's profile truly fits into this abstraction. Given that the manifestation of a profile is a single XML file on disk, I think it's fine to have as a singleton.
I do think you should either use dependency injection or a factory pattern to get a hold of a profile manager, though. You only need to write a unit test for a class that requires the use of a profile to understand the need for this; you want to be able to pass in a programatically created profile at runtime, otherwise your code will have a tightly coupled dependency to some XML file on disk somewhere.
One thing to consider is to have an interface for your ProfileManager, and pass an instance of that to the constructor of each view (or anything) that uses it. This way, you can easily have a singleton, or an instance per thread / user / etc, or have an implementation that goes to a database / web service / etc.
Another option would be to have all the things that use the ProfileManager call a factory instead of accessing it directly. Then that factory could return an instance, again it could be a singleton or not (go to database or file or web service, etc, etc) and most of your code doesn't need to know.
Doesn't answer your direct question, but it does make the impact of a change in the future close to zero.
"Singletons" are really only bad if they're essentially used to replace "global" variables. In this case, and if that's what it's being used for, it's not necessarily Singleton anyway.
In the case you describe, it's fine, and in fact ideal so that your application can be sure that the Profile Manager is available to everyone that needs it, and that no other part of the application can instantiate an extra one that will conflict with the existing one. This reduces ugly extra parameters/fields everywhere too, where you're attempting to pass around the one instance, and then maintaining extra unnecessary references to it. As long as it's forced into one and only one instantiation, I see nothing wrong with it.
Singleton was designed to avoid multiple instantiations and single point of "entry". If that's what you want, then that's the way to go. Just make sure it's well documented.
I was just curious if this is a good or bad practice or what the most preferred way of doing this is.
The practice I am referring to is that as I am a newb to WPF as I'm going along I have found it handy and useful to put strings, xdocuments, and domain objects into the Application.Resources in the app.xaml when their data is to be needed across the application, and for the simplicity of the static resource binding by x:key.
Good? Bad? Why? What should I do instead? Please no links to large MVVM tutorials and such, just looking for a concise answer regarding this specific practice, if MVVM has an answer for it I'm glad to hear what it is, I just don't want to read a 6 page tutorial or blog to find out..
I implement an application view model (AVM) object. Anything that needs to get exposed to the application views globally gets implemented as a property in the application view model so that I can get to it via binding. This makes for a nice consistent access method, gets me testability, implements property-change notification, gives me a place to put application-wide commands, all the stuff that you'd expect from using a view model.
The data context for every top-level window is set to the instance of the application view model. So I don't need to mess around with the resource dictionary or remember key values at all. That may sound a little weird at first - why would two windows use the same view model? - but if you want to put the same File/Exit command on every window that the application spawns, this actually makes logical sense. In such a case, the window's data context is set to the AVM, and then it contains a panel whose data context is set to a property on the AVM that's the actual context for that window. As long as you give your window element a name, binding to objects on the AVM is trivial - {Binding ElementName=TheWindow, Path=DataContext.TheProperty} - or you could expose the AVM as a property of the child view models.
The AVM pattern is subject to the same pitfalls as any one-object-to-rule-them pattern - e.g. creating a shambling beast with 200 unrelated properties. The solution's the same: aggregate those properties into service classes.
I generally don't put anything in the resource dictionary that doesn't get created in XAML. I can think of lots of valid exceptions to this general rule, but they haven't occurred in my programs yet.
Putting things in App.xaml could be a problem when:
You start branching your application into separate assemblies as the assemblies cannot 'see' app.xaml design-time - you can only find bugs run-time.
You have a magic string for pointing at your resource which is easy to misspell - or worse yet, duplicate by accident.
It is hard later to find the places any given resource is used and whether it can be safely changed ('What was it UpdateFrequency was for...')
You want it to be configurable - the AppSettings part of the app.config file is much better for these kinds of settings.
It's essentially the same problems as using global static variables for settings.
EDIT: Things, I prefer to have in App.Xaml is:
Global Styles and DataTemplates - in other words - things used for visual presentation that is there to override 'standard' settings - so usually they have no x:Key tag but rather a TargetType="{x:Type SomeType}"
Hope this helps!
This does make sense for ones shared across the application - "don't repeat yourself". I would also recommend having a project-specific resource that merges the application resources. The controls should reference that rather than the application resources.
This makes the controls in the project more self-contained.
I'd also recommend breaking resources into logical groups and merging them rather than having "one big bucket".