I'm building a WPF application using MVVM pattern, and Caliburn.Micro is the framework choice to boost up the development.
Different from a conventional MVVM-based application, I add a business layer (BL) below the ViewModel (VM) layer to handle logic for specific business cases. VM is left with data binding and simple conversion/presentation logic. Below BL is an extra Data Access layer (DAL) that encapsulates the Data model (DM) underneath built with Entity Framework.
I'm pretty new to both WPF, MVVM and, of course, know almost nothing about Caliburn. I have read plenty of questions and answers about the Caliburn usage and now trying to use what I've learnt so far in my application.
My questions are:
Does it sound okay with the above layered architecture?
In the application bootstrapper, is it correct that we can register all services that will later be used (like EventAgreggator (EA), WindowManager or extra security and validation services), and also all the concerned VMs? These should be injected into VM instances via constructors or so (supposed I'll be using SimpleContainer). So from any VM that are properly designed and instantiated, we can have these services ready to be used. If I understand correctly, Caliburn and its IoC maintain a kind of global state so that different VMs can use and share it.
Navigation: I know this topic has been discussed so many times. But just to be sure I'm doing the right way: There'd be a ShellViewModel acting as the main window for the whole application with different VMs (or screens) loaded dynamically. Each VM can inherit either Screen or ViewModelBase or NotifyChangedBase. When I'm in, let's say, VM A and want to switch to VM B. I'd from inside VM A send a message (using EA) to the ShellViewModel, saying that I want to change to B. ShellViewModel receives the message and reloads its CurrentViewModel property. What should be a proper data structure to maintain the list of VMs to be loaded? How can stuffs like Conductor or WindowManger come into the place?
Can/Should Caliburn in one way or another support the access to the database (via EF). Or this access should be exposed to VM and/or BL only?
Thanks a lot!
Different from a conventional MVVM-based application, I add a business layer (BL) below the ViewModel (VM) layer
That's the standard case. ViewModels can't/shouldn't contain business logic which is considered to be part of the Model (Model in MVVM is considered a layer, not an object or data structure) in the MVVM. ViewModel is for presentation logic only.
Yes, as long as your Business (Domain) Layer has no dependency on the DAL (no reference to it's assembly). Repository interfaces should be defined in the Business Layer, their implementations in the Data Access Layer.
Yes, Bootstrapper is where you build your object graph (configuration the IoC container).
Registering ViewModels: Depends on IoC framework. Some frameworks let you resolve unregistered types, as long as they are not abstract or interfaces (i.e. Unity). Not sure about Caliburn, haven't used it. If the IoC supports it, you don't need to register them.
One possible way to do it. I prefer navigation services though, works better for passing around parameters to views and windows that are not yet instantiated and you always know there is exactly one objects handling it.
With messages, there could be 0, 1 or many objects listening to it. Up to you
What do you mean with support access to the database? You can use it to inject your repositories and/or services into your ViewModels, other than that there isn't much DB related stuff to it.
Related
When starting a new mvvm-wpf-application, I usually include mvvm-light right at the start. That works fine, until my application grows.
Some where along the line the ViewModelLocator becomes huge (many ViewModels for all kinds of ChildViewodels). And even further down the rabbit hole I need multiple distinct instances of the same viewmodel. (eg for a List of items, with which one would like to interact on the same screen). This is where the struggle begins, how to handle that nice, consistently en keep the code testable?
So, if i want to get rid of the ViewModelLocator (is it an antipattern? is feels like a ServiceLocator) should I move to ViewModel-first and create (many) abstract factories for all ViewModels?
The ViewModelLocator is a fancy name for a Navigation Bus used for Inversion of Control (IoC). Though this appears to be a newer technology, a navigation bus is really using a Service Bus in a different way. It is not anti-pattern if you have a static (shared in VB) container. The anti-pattern comes in if you are passing the container around in your ViewModels.
The thing to keep in mind in MVVM is that it is versatile design pattern, and you can extend it in many ways. The best solution for large projects is component design (a design where each feature of your application is in it's own namespace or project).
A design diagram may look like so:
Customer
Models
ViewModels
Services
Orders
Models
ViewModels
Services
etc...
It really comes down to the flavor of the developer. As long as your design is consistent.
Further reading:
To better understand the ViewModelLocator search for the Navigation Bus.
To better understand the EventAggregator, search for Message Bus
Well, yes, if you use the built in IOC container with MVVMLight. If you use things like AutoFac or Ninject, you can register all classes that are based on ViewModelBase. Another option is to use code generation to generate the ViewModelLocator. With the two approaches, you can get it down to one line per view model.
public MyViewModel MyView => serviceLocator.Resolve<MyViewModel>();
I am currently developing a Xamarin Forms app and am in the process of reworking it to work with Prism. I'm really trying to adhere to MVVM design patterns (I'm trying to grow as an amateur developer and learn how to use them).
1) Is it improper from a MVVM design pattern perspective to utilize messaging services (Prism's EventAggregator) and UI interactions (Prism's PageDialogService) outside of VMs? I've written several "services" that are called from the VM and have found a need to access both messaging and UI services. As one example, The VM calls a service, the service retrieves and processes some data, ask a question to the user based upon those calculations and then continue to finish processing returning the desired value. To be proper, should control be returned back to the VM to "just" ask the question?
2) If it's not verboten, is it possible to access the services outside of VMs? It does not readily appear to me that I can inject them into the constructor of the service. Is it okay to "pass" them into the service's function I'm calling along with other parameters? That just seems un... MVVM-ish?
Update:
I'm not sure all my steps were necessary, but with the help below I got it working. First I converted my singleton service into an interface (IMyService) and an implementing class (MyService). Next, I overrode ConfigureContainer in App.xaml.cs and called Container.RegisterType<IMyService, MyService>(new ContainerControlledLifetimeManager());
I could then inject IMyService, just like IEventAggregator and IPageDialogService into my ViewModels and I could also inject those services into the public constructor of my implementing class (MyService).
ad 1) the event aggregator is meant primarily for UI, but you can use it as message bus in other parts of the app, too, if you don't need the more advanced features of a "real" message bus.
ad 2) unity will happily inject dependencies into services that are themselves dependencies of view models or other services. That's what a dependency injection container does :-)
I've been studying Spring State Machine and State design pattern since I have to develop a microservice with Spring Boot and persisted objects with a lot of confused states that need to be cleared up, and I am looking for a clean design solution out of that mess. I checked DDD, State concepts and State Machine seeing which ones to apply
I am not sure about how to implement some concepts, and how to connect them. I would like to understand if:
Spring State Machine can work on entities during transitions, or only on a global application state level?
To manage multiple entities each in its own state does it have to have be created as a prototype scoped component?
Does it integrate easily with the State pattern or should it not be used together?
To manage this, I should inject state or state machines into the Entities (feasible, I know, but I do not like the idea of using #Configurable and appropriate AspectJ weaving configuration)? I share someone's impression that it could make it more complex, and maybe I would have to use #Scope("prototype")
Instead if it is possibile to have Domain Services delegate State Machines per entity basis (so another Domain Service) for single entities to change state? Or this is anemic domain antipattern, but if so, how well do State Machine integrates with DDD?
Is there any example on how Spring State Machine would allow me to do what I want to do, how lightweight it is, and how slow and memory consuming that would be?
I got that:
- DDD wants Domain Objects that have more functionality that simple Data Objects like in this quite complete but a little dated article on DDD
- State pattern should encapsulate how the Context element should behave in that particular case
- The State Machine is about encapsulating the management of the passage between one State and another
- Should they work together, the State should not dictate which is the next State on a specific command, but generate an Event for the State machine and the State machine would choose (or block if there are Guards that fail) the new State
- Somehow the new State would have to be set in the Context by the State Machine
Usually the Context object should delegate directly to the State object. But since the State machine dictates the change in the State of the object, should't in this case the Context delegate to a sort of Proxy State? Should be a/the State Machine be injected into the Entity or the Proxy?
Any thoughts, suggestions, even partial answers on some of these questions would be really appreciated.
BTW I just
DDD is all about protecting the business logic and make sure that it's not affected, or coupled, with infrastructure. When you look at an entity, you should directly understand what it's capable of and which part of the domain that it takes care of.
To me, state machines is not part of the domain. They are a facilitator and part of the application layer which controls what should happen in the domain. Then again, it's really hard to answer on an abstract level since DDD is all about modeling on a very "real" level.
If you could explain with a simple example what you are trying to accomplish it would also make it easier to write a more specific answer.
just starting with DDD. I understand that all the domain entities and their logic should be kept in Domain layer along with repository interfaces. In my application I store some data in the database that is used to construct parts of the user interface (presentation layer) at run time. Where should I keep the poco classes and repository interfaces for such types, in Application layer or Domain layer. I can not make out because these objects will not have any domain related business logic but they need to be hydrated from the database and I am using EF so for data access I will need entities and repositories so to me obvious choice is to keep them with all other entities and repository interfaces in domain layer but that breaks DDD rules
I think you've answered your own question:
In my application I store some data in the database that is used to
construct parts of the user interface (presentation layer) at run
time.
Access to data that is used to serve the UI should be encapsulated in the presentation layer. This is different from the application layer in that a DDD application layer implements use cases by orchestrating repositories and delegating to appropriate entities, domain services - it forms an API around your domain layer. Different presentation implementations can use the same application service.
However, different presentation layer implementations may require different data. Therefore, place presentation data access directly in the presentation layer. This can be implemented with EF which is not exclusive for DDD scenarios.
A good way to think of it is this - if you had to replace EF with stored procedures for performance reasons, you should not have to modify your domain code. So anything that blocks that needs to be hidden behind an interface and made replaceable.
Repositories CAN be a part of domain logic. However what should not be is the mechanism for persistence. This can easily be encapsulated into a DAL service or other object, which of course is programmed to an IDALService interface. So when you need to switch persistance (for example, moving from EF to a NoSQL solution) you simply write an alternative version that implements the IDALService interface, and you're good to go. The repositories can still do the logic within them, but are now using a new way to store them (this is an Inversion of Control idea).
As for the POCO objects, in DDD the real question is what do they represent? Are they entities, that need to be persisted? Are they value objects? Don't let the technology (EF) determine what the structure of your object model is, instead provide means to translate to an application scope.
In the Application layer. Keep the domain intact and isolated.
I'm new to MVVM. Currently I'm developing a WPF project in C# that will have a SQl Server backend and I'll be using a standard WCF service to communicate with it. All the tutorials I've seen on MVVM thus far always seem to use some static data repository such as an xml file for their backend. I haven't yet seen implemenations using a database and a data access layer, so I'm confused as to where my WCF service fits in. The service has all data objects defined in it, so does the service itself then become the model? In addition, how do I go about including the service in the ViewModel so that the designer doesn't throw an error stating that it cannot create an instance f the service class? Any help here would be greatly appreciated as I find it strange that so many tutorials on this subject omit the most prctical implementation for a line-of-business application.
PS I would like to steer clear of WCF RIA services and Silverlight as the Silverlight's lack of support for commands makes the book I'm following (Pro WPF and Silverlight MVVM Effective Application Development with Model-View-ViewModel) difficult to understand.
OK, I'll try to get you up to speed ...
First, I do recognize the question about the model and the object model exposed with WCF. Are they the same? Well, I would like to make that assumption currently, for sake of simplicity. So then we do not need the model part of MVVM on the client side? Depends ...
The ViewModel is in the driving seat. We let it create the client proxy to your WCF service. The objects used in the request and returned as result makes your model. Anything you want to cache on the client side or is not directly bindable with the UI will be put in properties in your model container class. Generate bindable properties from these model properties for consumption in your UI. Every else will just be direct properties in your view model.
About WCF and the data access layer, there are a few important thing to recognize. First of all, you will need to have a seperation between you logical (information) model and your physical (database) model. One reason is to abstract your database technology away from your application. Another to allow small deviations between your application / domain logic and your physical implementation. Make sure your (entity) model classes are generic enough to support changes in your UI without having to modify the complete application stack for every UI change.
It is hard to talk about this matter without a clear example, so to wrap up I would like to invite you to look at http://aviadezra.blogspot.com/2010/10/silverlight-mvvm-odata-wcf-data.html. I know, it IS using WCF data services and SilverLight. Don't be mad at me directly for directing to this sample and give me the thumb down. It is just such a damn good example of what you want to achieve and what to introduce and what to think about setting up such an application. Just replace Silverlight by WPF and Data Services by regular typed data contracts and the rest of the story will help to get your thoughts clear.
Hope it helps you in your quest!