I have a control in which we show some links to different sites based on some business rules. Currently all business logic to build link list is in control.
I plan to move out the busincess logic from the control.
what will be a good design for this?
can I use any design pattern?
You shouldn't get too caught up in thinking about patterns. Most of the time they are overkill and add too much complexity. Particularly with a trivial scenario like this.
Just utilize good object-oriented practices and you'll be fine. Encapsulate your business logic in another class and provide public properties for your control to access it. Keep it simple!
How about the Model-View-Presenter pattern?
Another good choice might be the Mediator pattern.
Do you really need a custom control for this?
Model-View-Controller suggests that you only have display logic in a control.
Find a solution that allows you to make small changes to a built in control (ListView) and create a custom data set somewhere else to pass to it.
I not sure how you implement your business rules but here is an idea...
I would databind your web forms list control.
public class YourLinks
{
// You could do it by overloading the constructor...
// Again not sure how you determine what links should be displayed...
// If you had consistent types you could make your constructor internal
// and then create a YourLinkBuilder see below...
public YourLinks(User user, Region region)
{
}
public YourLinks(City city)
{
}
// Databind to this method...
public IEnumerable<string> GetLinks()
{
// return your links...
}
}
public class YourLinkBuilder
{
public static YourLinks BuildPowerUserLinks()
{
return new YourLinks(new PowerUser(), new Region("Washington"));
}
public static YourLinks BuildVisitorLinks()
{
return new YourLinks(new VisitorUser(), new Region("Empty"));
}
}
Given the little information provided, I would suggest you create a model of just the links (and its related data). So that you can pass the LinksModel to your views for rendering. Or pass your LinksModel to your existing model (as a sub-model).
Either way, all this data is encapsulated. So if you want to add data to it later, it will not change your method signatures (or general contract). If you want to remove data from it, same advantage. If you want to remove it entirely, its only one object and simplifies the removal.
You can also build links view renderers so that it and only it knows how to visually display the LinksModel. So within your view, you can delegate the visual aspects of the links info to such renderers instead of having logic within your existing view. If you want to change how links view looks later or want to give the user the power of selecting different renditions, you can simply use different renderers rather than jamming your entire code with 'if' blocks.
Jeach!
You should use Model-View-Presenter for sure. In the view, you should have your control.
The control's responsibility should be merely to take input from the user, validate it, and pass that information to the presenter. The presenter should then interact with the model, where your business rules are stored.
From the model, you may wish to return the links that are then passed to the control for display, or you may wish to return some metadata that is passed to another system to retrieve the links.
What I would do is use the Strategy pattern in the model, so that you can easily swap in and out different versions of your business rules.
To abstract interaction with your backend datasource (if you have one) have a look at Martin Fowler's Gateway pattern.
Related
I heard its the next best thing in building WPF UIs, but all existing
examples have dozens of lines of code - can I get a Hello World
for MVVM that explains in no uncertain terms what its all about?
I'm fairly new to C#/.net as well, so maybe point me to some
resources that could help too?
Much appreciated!
One sentence explanation:
MVVM is a reimagining of the well loved Model-View-Presenter (MVP) pattern that is designed to work especially well with databinding facilities supplied with WPF to separate application logic from UI design.
Longer, more useful, explanation:
The basic concept of MVVM is the break apart a WPF application into separate components each of which has one responsibility in the process of getting information on screen.
Firstly you have the model. This is a class with very limited functionality that is generally populated from some outside source such as a database or webservice. For example:
public class MessageModel
{
public string Message { get; set; }
}
On top of that you layer the ViewModel, this is where the logic of the application sits, it notifies the view of changes to the model and ensures data consistency. By implementing the INotifyPropertyChanged interface two way databinding between the ViewModel and the view is given for free by WPF:
public class MessageViewModel : INotifyPropertyChanged
{
private MessageModel _model;
public string Message
{
get { return _model.Message; }
set
{
if (_model.Message != value)
{
_model.Message = value;
OnPropertyChanged("Message");
}
}
}
}
Finally you have the View. This is a xaml file that describes the layout of the controls used to display and edit the data in the ViewModel:
<Canvas>
<TextBox Text={"Binding Message"} />
</Canvas>
The reason that you go to all this effort is that the Model is very lightweight and easily passed across domain boundaries. It is simple to send or receive it from a webservice or map it to a database table. The ViewModel, on the other hand is complex, but has few dependencies - it doesn't care where the model gets it's data from, only that it is there and it has no concept of a view at all which makes it very testable (the logic of your application doesn't rely on a UI to test). Finally the xaml is well compartmentalised and can be handed off to a designer who needs to know nothing about the logic of the application, only that the ViewModel will present certain data under certain names. This encapsulation makes it very easy to define roles in large projects, or put together a limited UI to test logic against while the real one is being polished.
MVVM is a star-fan relationship. The fan knows the star but the star does not know the fan. The fan loves his star so much that if the star changes himself ( I mean his dressing style ), the fan changes himself accordingly.
Now replace "star" with "ViewModel" and "fan" with "View" and read it once again.
One sentence? Here goes.
MVVM is a UI segregation pattern where the Xaml (View) binds to a facade (View Model) allowing the guts of your program (Model) to avoid having UI concerns leak down a layer.
The simple statement that helped me get my head around it best was "Could I unit test my business logic without the user interface?" I think this should be the question you ask while learning and designing using MVVM concepts.
This site has a great diagram that explains it.
Basically you have 3 components:
1) Model - The data model of your application. this is pretty standard and the same as any MVP or MVC app.
2) View - The XAML that defines the view/layout of your app.
3) View Model - Because WPF demands that the view attach to things in certain ways (like requires that collections implement INotifyCollectionChanged and stuff like that) it normally requires that you massage your data a little bit to get it in a form suitable for the view to display. This is where the view model codes in. It packages up the data into view models that the view can easily display. This is what your view XAML will bind to. It must respond to events from the model layer and update itself.
(Then your controllers hang on the side somewhere - ideally using WPF commands - and make changes to the model, which fires events to update the view model)
a pattern where the frontend(view) and backend(modal) communicates (back and forth) using a common mediator(view-modal).
The MVVM pattern is when the UI interfaces with an xaml-friendly intermediate object to get at your xaml-unfriendly actual data.
I would say something like: "Presentation pattern for separation of concern between user interface and it's logic"
An improved answer:
MVVM is all about the future; you want to separate your application logic from the framework so that either the framework can evolve, and your app may not have to change, or your app can evolve and you won't have to worry so much about changing the actual UI aspects.
Actually, MVVM is a refinement of a pattern that has been around for some time. I can remember evolving the pattern when I was working in MFC. There are at least two reasons for doing so. MFC or <> is fairly complex, and mixing MFC constructs in with your application logic makes the application kind of brittle. Example: replacing a listbox with a combobox (or selector in modern terms) is much more difficult if the logic for supporting the content of the list/selector is combined with the logic to manipulate list/selector itself.
Some really good one-sentence (or close to it) explanations already. I'll just add to it by saying that if you're past the basic level and you want an example of how to use MVVM in a real-world app that has menus, tool bar, options dialogs, docking tools windows, etc., take a look at SoapBox Core and this demo using SoapBox Core. It is open sourced so you can get lots of ideas.
Because you can't data-bind to your own codebehind
(only half joking here)
I know there's a lot of questions on the topic and I understand how to do it but I need some help on the design of my architecture. I'm using the Simple MVVM Toolkit.
Architecture
I have a ShellVM which is the main VM for my app. It dishes out navigation and props that my main view binds to.
Then I have a ManageVM that does all the grit work for managing the client, stores, imports, exports etc. It also handles navigation of all my management views.
Then I have an ImportVM that fleshes out the importing of data.
I also have a static PageValues dictionary that stores pages and specific properties and values that should be retained when switching views. It also stores any 'global' properties that is used throughout certain VMs.
I'm using Messaging to pass data between the VMs. The validation and prompts (using dialogs) of the PageValues data is controlled in my ManageVM. I placed it here as I feel my ManageVM should handle all 'management' like setting the client and store. Setting the actual values is done by sending a message to the ShellVM that handles this.
The ShellVM handles the CRUD of the PageValues. So in other words, if any VM gets or sets a global/shell-wide property, it does so by means of messaging to the ShellVM. The ShellVM then sends the message/result back to whichever VM requested it.
Question
This feels very spaghetti-like. I've got a ManageVM that does the loading and validations on PageValues that are actually CRUD'ed in the ShellVM.
Am I on the right track or is there any other suggestion I can try to make this feel a bit cleaner?
Thanks for reading.
Edit
What I'm trying to achieve is to have a container that holds values (ie client and store) that could be accessible from multiple VMs. A bonus is to have each page's/view's values in this container too. Then on showing of the view, it will grab its values from the container and populate the view.
You said
if any VM gets or sets a global/shell-wide property, it does so by
means of messaging to the ShellVM
I propose an interface based approach instead of message passing for this purpose. ViewModels passing messages is for view models to communicate,not for setting a global state. If there is a global state of the application,it is better handled through a dedicated service, IMO.
public interface IApplicationService
{
//your applcation methods here
}
public class ApplicationService:IApplicationService
{
}
public class ManageVM
{
public ManageVM(IApplicationService){}
}
public class ShellVM
{
public ShellVM(IApplicationService){}
}
public class SomeOtherVM
{
public SomeOtherVM(IApplicationService){}
}
Yes, this does sound rather messy. You need to try and isolate areas of functionality into their own VMs so they are not dependent on one another.
One of the tricks I use to do this is to try and imagine that I suddenly need to copy a blob of functionality (say one of your pageviews) into another application. How easy would it be? Would it be a case of just copying one VM and injecting a few dependencies? Or is the VM impossibly coupled to the rest of the app?
It's a bit difficult to give advice without knowing exactly what your app is doing, but really you want each PageVM to be in charge of it's own validation, and CRUD. Or, if the data is shared between many pages, then you need to pass in some kind of repository than the PageVMs can query for data. If validation logic is specific to some data, then put it on the model itself and just leave the presentation of that validation to the VM.
For global settings, I tend to pass around a settings object rather than using messaging.
Have a read up on inversion of control, and dependency injection. These can help you to keep objects loosely coupled because you can see exactly what other things your object is depending upon by looking at the constructor. If you are passing in half the application then it can serve as a warning alarm to try and reduce the coupling.
I've created a sample app, just to test and try out some of wpf's capabilities. I was basically trying out the databinding in wpf, and did the rest of stuff more or less quickly. THen, i faced an arquitectural problem (yes, should have thought in advance before starting coding :) ) and i wanted to know what's the best refactoring solution for it.
I have a simple interface that returns a list of objects, based on a defined process.
public interface IDoStuff<out T>
{
IEnumerable<T> Do(string someParam);
}
i've created a couple of implementations for this interface. Then i have a view in wpf, which has a dropdown with hardcoded values, and depending on what you select, instatiates the implementation of the interface and populates some list
foreach (var item in new IDoSTuffImplementation1()<MyObj>.Do("imp 1"))
{
MyObjs.Add(item);
}
ater on MyObjs is the DataContext for a listview, and displays things and so on and so forth, but it's out of the main question.
this is all hardcoded and not very nice. If i was ever to implement a new interface, i'd need to add it to the dropdown, and create a new foreach for that specific implementation (more duplicated code)
Ok, here's my impression on making this better/refactoring for extensibility.
I was thinking a good approach would be to use some kind of MVVM pattern, making the wpf view into a view + viewmodel. the viewmodel would use some kind of IoC like spring, which would (by xml) instantiate one specific implementation of the interface, and inject it to the viewmodel, which would then call its "Do" method and everyone happy. So this way, the only thing that would be needed to do when we implement a new component, is to add it to the xml config file.
Suggestions, Comments? what's the best approach, if any?
thanks!!
Actually I don't see any architecture changes if you provide another implementation of the interface. You already have a good architecture when using MVVM, so the task you are trying to accomplish will not change the architecture, but will extend your application using the architecture.
I suggest you change you Method to a Property instead. And assign that property to ComboBox's ItemsSource property to ease up your coding using data binding.
In my continuing journey through ASP.NET MVC, I am now at the point where I need to render an edit/create form for an entity.
My entity consists of enums and a few other models, created in a repository via LINQtoSQL.
What I am struggling with right now is finding a decent way to render the edit/create forms which will contain a few dropdown lists and a number of text fields. I realize this may not be the most user-friendly approach, but it is what I am going with right now :).
I have a repository layer and a business layer. The controllers interface with the service layer.
Is it best to simply create a viewmodel like so?
public class EventFormViewModel
{
IEventService _eventService;
public IEvent Event { get; private set; }
public IEnumerable<EventCampaign> Campaigns { get; private set; }
public IEnumerable<SelectListItem> Statuses { get; private set; }
// Other tables/dropdowns go here
// Constructor
public EventFormViewModel(IEventService eventService, IEvent ev)
{
_eventService = eventService;
Event = ev;
// Initialize Collections
Campaigns = eventService.getCampaigns().ToSelectList(); //extn method maybe?
Statuses = eventService.getStatus().ToSelectList(); /extn for each table type?
}
So this will give me a new EventFormViewModel which I'll bind to a view. But is this the best way? I'd essentially be pulling all data back from the database for a few different tables and converting them to an IEnumerable. This doesn't seem overly efficient, but I suppose I could cache the contents of the dropdowns.
Also, if all I have is methods that get data for a dropdown, should I just skip the service layer and go right to the repository?
The last part of my question: For the ToSelectList() extension method, would it be possible to write one method for each table and use it generically even if some tables have different columns ("Id" and "Name" versus "Id" and "CampaignName").
Forgive me if this is too general, I'm just trying to avoid going down a dead-end road - or one that will have a lot of potholes.
I wouldn't provide an IEventService for my view model object. I prefer to think of the view model object as a dumb data transfer object. I would let the controller take care of asking the IEventService for the data and passing it on to the view model.
I'd essentially be pulling all data
back from the database for a few
different tables and converting them
to an IEnumerable
I don't see why this would be inefficient? You obviously shouldn't pull all data from the tables. Perform the filtering and joining you need to do in the database as usual. Put the result in the view model.
Also, if all I have is methods that
get data for a dropdown, should I just
skip the service layer and go right to
the repository?
If your application is very simple, then a service layer may be an unneeded layer of abstraction / indirection. But if your application is just a bit complex (from what you've posted above, I would guess that this is the case), consider what you will by taking a shortcut and going straight to a repository and compare this to what you will win in maintainability and testability if you use a service layer.
The worst thing you could do, would be to go through a service layer only when you feel there is a need for it, and go straight to the repository when the service layer will not be providing any extra logic. Whatever you do, be consistent (which almost always means: go through a service layer, even when your application is simple. It won't stay simple).
I would say if you're thinking of "skipping" a layer than you're not really ready to use MVC. The whole point of the layers, even when they're thin, is to facilitate unit testing and try to enforce separation of concerns.
As for generic methods, is there some reason you can just use the OOB objects and then extend them (with extension methods) when they fail to meet your needs?
I am investigating WPF's MVVM design pattern. But am unsure where to put the Data Acess code?
In some examples I have looked at, data access is performed directly in the ViewModel. It seems odd to put something like linq to sql in the ViewModel? Other examples have a seperate project for Data Access, this seems more like it?
Is this there a general approach? I feel like I am missing something here!
Thanks
Here's how I've been organizing my MVVM w/ LINQ projects:
Model - I think of the Model as the state of the system. It provides an interface to the data, and it keeps track of system status. The Model does not know about the ViewModel or View--it just provides a public interface to its data and various events to let the consumers (usually ViewModels) know when the state has changed.
ViewModel - The ViewModel is in charge of organizing or structuring all the data needed by the View, keeping track of the status of the view (such as the currently selected row of a data grid), and responding to actions on the view (such as button pushes). It knows what the view needs, but it doesn't actually know about the view.
View - The View is the actual look and feel of the UI. It contains all the built-in and custom controls, how they arranged, and how they are styled. It knows about the ViewModel, but only for the purpose of binding to its properties.
Gateway - This is the part that directly addresses your question. The Gateway (which is basically my way of saying "DataAccessLayer") is its own separate layer. It contains all the code (including LINQ queries) to CRUD or select, insert, update, and delete data from/to your data source (database, XML file, etc.). It also provides a public interface to the Model, allowing the Model to focus on maintaining system state without having to concern itself with the details (i.e., the queries) needed to update the data source.
DataAccess Classes - In C#, these are very simple classes that model your elemental data objects. When you select something using a LINQ query, you will usually create an IEnumerable<T> or List<T> where T is one of your data objects. An example of a data object would be:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
The big advantage of a design like this is that it really separates your concerns. Everything has a specialized job, and it's (usually) pretty easy to know what kind of thing goes where.
The disadvantage is that it may be overkill for small projects. You end up creating a lot of infrastructure for public interfaces that basically pass a single wish through several layers. So, you might end up with a scenario like this: [user clicks Submit, ViewModel tells Model to AddNewPerson, Model tells Gateway to InsertPerson] instead of a scenario like this [user clicks Submit, ViewModel adds new record to the database directly].
Hope that helps.
I would add another layer, essentially what you want is a data factory. You want to create a set of classes that will CRUD to the database for you and return clean POCO objects to the ViewModel.
A good example to look at would the Nerd Dinner book. It covers MVC not MVVM but the patterns are very similar and the way they access data in that solution would be good starting point.
Hope this helps.
Data access should not be in the view model, as this is supposed to be a view specific (possibly simplified) representation of the domain model.
Use a mapper of some sort to map your view model (the VM in MVVM) to your model (the first M). New objects in your model can be created using the factory pattern. Once created, you can store them in a database using the repository pattern. The repositories would then represent your data access layer. In your repository you could use an O/R mapper like NHibernate or Entity Framework.
EDIT:
I see that GraemeF suggests putting the data access code in the model. This is a NOT a good approach, as this would force you to update your domain model if you were to move from e.g. SQL Server to Oracle or XML files. The domain objects should not have to worry about how they are persisted. The repository pattern isolates the domain from its persistence.
MVVM stands for Model, View, and ViewModel. The piece you are missing is the Model, which is where your data access code lives.
The ViewModel takes the Model and presents it to the View for display, so typically you would have something like this:
class PersonModel : IPerson
{
// data access stuff goes in here
public string Name { get; set; }
}
class PersonViewModel
{
IPerson _person;
public PersonViewModel(IPerson person)
{
_person = person;
}
public Name
{
get { return _person.Name; }
set { _person.Name = value; }
}
}
The PersonView would then bind to the properties of the PersonViewModel rather than directly to the model itself. In many cases you might already have a data access layer that knows nothing about MVVM (and nor should it) but you can still build ViewModels to present it to the view.
Your ViewModel should be a thin layer that just services the view. My rule of thumb: if it has to do with the presentation of the UI, then it belongs in the ViewModel, otherwise it should be in the Model.
The WPF Application Framework (WAF) contains a sample application that shows how the Model-View-ViewModel (MVVM) pattern might be used in combination with the Entity Framework.