I am currently redesigning a piece of software from an aspx application, to support winforms as well, and by doing this I am implementing the MVP pattern to easier handle further development and make it easier to maintain two versions of the same application.
But this the first time I am implementing this pattern, so a couple of questions manifest themselves.
Since this application has several pages/forms, should I have one presenter per view (one view = one aspx file)? I am guessing yes to make is easier to maintain and to keep the IView interfaces tidyer.
What is the 'standard' detail I should write the IView at? ie. To test this I am writing the RegisterUser.aspx view, and there are some controls I want to disable at certain times, should I have a generic 'void DisableControl(string name); void EnableControl(string name);' or a more specialized 'void DisablePasswordControl(); void EnablePasswordControl();'?
I can see pros and cons to both approaches, so I thought I should at least ask before I make any bad habits here.
1 Yes
2 I would go with a property like this:
public class RegisterUser : IRegisterUserView
{
bool IRegisterUserView.PasswordEnabled
{
get { return tbPassword.Visible ; }
set { tbPassword.Visible = value; }
}
}
For point 1 it should be 1 presenter per view, unless you have a very similar presenter which would use an identical view.
For point 2, you should have this as just either the void DisableControl(string name) although this isn't too necessary as it can all be handled within your aspx.cs part of the page. It depends what and when you are hiding the control.
Good luck!
Related
I have a BaseViewModel which is inherited by multiple ViewModel classes. In my BaseViewModel I have a couple of dependencies which get injected from ViewModel. Now if I need to add a new dependency in my BaseViewModel I need to change all the VM which inherit BaseViewModel. Please let me know how can it be handled in Simple Injector. Following is my code structure:
How can I make my base class injection independent so that I don't need to make changes in all my inherited class?
Code:
public class BaseViewModel
{
protected readonly IAESEnDecrypt AESEnDecrypt;
protected readonly IDataService DataService;
protected readonly INavigationService NavigateToPage;
public BaseViewModel(INavigationService nav, IDataService data, IAESEnDecrypt encrypt)
{
AESEnDecrypt= encrypt;
NavigateToPage = nav;
DataService = data;
}
}
public class ViewModel
{
public ViewModel(INavigationService nav, IDataService data, IAESEnDecrypt encrypt) : base (nav, data, encrypt)
{
}
}
My BaseViewModel Contains some of the following Interfaces whose implementation is injected through constructor:
- NavigationService
- DataService
- GeoLocationService
- SmartDispatcher
- MessageBus which implement Message Aggregator
It also Contains some common properties as static variables whose data is used throughout the application like UserDetails. And also contains CancellationToken, IsBusy to display progressbar.
BaseViewModel also contain HandleException method which handle all the incoming exceptions from all ViewModel.
Also Contains some common Commands which are used in all the Views like Si
gnoutCommand, NavigationBar Commands.
Actually it has started to contain all kinds of common methods used among various ViewModel.
Please suggest how can i refactor this code?
Your last sentence:
Actually it has started to contain all kinds of common methods used among various ViewModel
Precisely describes your problem! As Steven already described, that you're building almost the complete application through a single base class. Thereby infringing the Open-Closed principle which you are heavinly experiencing now.
The trick is design your application around very small SOLID ViewModels of which you compose the application at runtime. By splitting the ViewModels and using a UserControl as your views you can compose big complicated views for the user, while you still get all the benefits from using a SOLID design. So let’s take a look at some of your different interfaces that you implement and some of the functions you ‘handle’ in the base class:
NavigationService
This sounds like a service which controls the flow in your application. This sounds to me like your mainview(model). You could create a single MainViewModel which as a single property, let’s say CurrentView.Assuming you’re using WPF you typically would bind this property to a ContentControl. The content of this control can be everything from a single TextBlock to a complete UserControl. The UserControls can still be very complicated as they could be composed of multiple child usercontrol and so on. Using a MVVM framework (like e.g. Caliburn Micro or MVVM Light) for this is optionally but will come in handy.
It could also be an application global service with some of kind of callback or delegate function to perform navigation to a certain View(Model). It is in any case an infrastructural part of your application that deserves it own class and shouldn't be put away in a base class.
DataService
A single dataservice was the way I worked for over 10 years. Every time I hit my head against the wall. There comes a point in time that you need something special which is not included in your dataservice and you will probably go through your complete code base to make the right adjustments. Speaking of the Open-Closed principle…
Than I learned about the Command/Handler and Query/Handler pattern. You can read about this here and here. Using this pattern everywhere you need data you just inject the correct IQueryHandler<,> and use it right there. Not every view(model) needs data and certainly not the same data. So why use a global DataService? This is will also improve your Lifetime management of your DBContext object.
HandleException
Why is your base class responsible for handling the exceptions of your viewmodel? What does the base class know about this exceptions? What does the base class do? Log the exception, show a message to the user (what kind of message?) and silently continue? Letting the application break down 3 minutes later and leaving a user ignorant of what happened?
I.M.O. exception should not be catched if you didn’t expect them to be thrown in the first place. Than log the exception at an application level (e.g. in your Main), show an ‘Excuse me’ message to the user and close the application. If you expect an exception, handle it right there and then and handle according.
UserDetails
Ask yourself the question how many of your 40 ViewModels actually need this information? If all 40 are in need of this information, there is something else wrong with your design. If not, only inject this details (or even better an IUserContext) in the ViewModels that actually use them.
If you use it for some kind of authentication consider using a decorator wrapping the task they need permission for performing it.
IsBusyIndicator
Again: do you need this in every ViewModel? I think not. I think furthermore, showing the user a busy indicator is a responsibility of the View, not the ViewModel and the as the length of the task determines if you need to show this, make it a responsibility of the task (assuming you’re looking at your tasks also in a SOLID manner by using e.g. the already mentioned Command/Handler pattern).
With WPF you could define a Dependency Property that you can bind to the view, thereby showing some kind of busy indicator. Now just inject a ShowBusyIndicatorService in the task that needs to show it. Or wrap all your (lengthy) tasks in a ShowBusyIndicatorDecorator.
Design
Now let’s look at some simple interfaces you could define to build up your View(Model)s. Let’s say we decide to make every ViewModel responsible for a single task and we define the following (typical LoB) tasks:
Show (any kind of) data
Select or choose data
Edit data
A single task can be stripped down to ‘Show data of single datatype (entity)’. Now we can define the following interfaces:
IView<TEntity>
ISelect<TEntity>
IEdit<TEntity>
For each interface type you would create a Processor/Service or DialogHandler depending on your semantic preferences which would do the typical MVVM stuff like finding a corresponding view and binding this to viewmodel and show this in some way (a modal window, inject it as usercontrol in some contentcontrol etc.).
By injecting this single Processor/Service or DialogHandler in the your ‘Parent’ ViewModel where you need to navigate or show a different view you can show any type of entity by a single line of code and transfer the responsibility to the next ViewModel.
I’m using these 3 interfaces now in a project and I really can do everything I could do in the past, but now in SOLID fashion. My EditProcessor, interface and viewmodel look like this, stripped down from all not so interesting stuff. I’m using Caliburn Micro for the ViewModel-View Binding.
public class EditEntityProcessor : IEditEntityProcessor
{
private readonly Container container;
private readonly IWindowManager windowManager;
public EditEntityProcessor(Container container, IWindowManager windowManager)
{
this.container = container;
this.windowManager = windowManager;
}
public void EditEntity<TEntity>(TEntity entity) where TEntity : class
{
// Compose type
var editEntityViewModelType =
typeof(IEntityEditorViewModel<>).MakeGenericType(entity.GetType());
// Ask S.I. for the corresponding ViewModel,
// which is responsible for editing this type of entity
var editEntityViewModel = (IEntityEditorViewModel<TEntity>)
this.container.GetInstance(editEntityViewModelType);
// give the viewmodel the entity to be edited
editEntityViewModel.EditThisEntity(entity);
// Let caliburn find the view and show it to the user
this.windowManager.ShowDialog(editEntityViewModel);
}
}
public interface IEntityEditorViewModel<TEntity> where TEntity : class
{
void EditThisEntity(TEntity entity);
}
public class EditUserViewModel : IEntityEditorViewModel<User>
{
public EditUserViewModel(
ICommandHandler<SaveUserCommand> saveUserCommandHandler,
IQueryHandler<GetUserByIdQuery, User> loadUserQueryHandler)
{
this.saveUserCommandHandler = saveUserCommandHandler;
this.loadUserQueryHandler = loadUserQueryHandler;
}
public void EditThisEntity(User entity)
{
// load a fresh copy from the database
this.User = this.loadUserQueryHandler.Handle(new GetUserByIdQuery(entity.Id));
}
// Bind a button to this method
public void EndEdit()
{
// Save the edited user to the database
this.saveUserCommandHandler.Handle(new SaveUserCommand(this.User));
}
//Bind different controls (TextBoxes or something) to the properties of the user
public User User { get; set; }
}
From you IView<User> you can now edit the current selected User with this line of code:
// Assuming this property is present in IView<User>
public User CurrentSelectedUser { get; set; }
public void EditUser()
{
this.editService.EditEntity(this.CurrentSelectedUser);
}
Note that by using this design you can wrap your ViewModels in a decorator to do crosscutting concerns, like logging, authentication and so on.
So this was the long answer, the short one would be: loose the base class, it is biting you and it will bite you more and harder!
Prevent having this base class in the first place. This base class is a big code smell and the result is your current pain. Such a base class will violate the Single Responsibility Principle (SRP) and will just act as a big helper class for all derived view models, or it even seems that you are putting cross-cutting concerns in there. The base class might even hide the fact that your view models violate the SRP. They probably do too much; have too many responsibilities.
Instead, try to do the following:
Move cross-cutting concerns out of the base class into decorators or find another way to apply cross-cutting concerns.
Group related dependencies together into a aggregate service and inject such aggregate service into your view model.
In a well designed application, there is hardly ever a need for having such base class that takes dependencies.
If you aren't able to change your design (but please do take a look it this; you will be in a much better place without that base class), you can revert to explicit property injection. Simple Injector does not do this out-of-the-box, but the documentation describes how to do this.
Basically, it comes down to writing a custom IPropertySelectionBehavior, moving the constructor dependencies of the BaseViewModel to public properties and marking them with a custom attribute.
But again, only use property injection as a last resort. Property injection will only hide the design problem; it will not solve it.
You can use the ServiceLocator (anti)pattern to make the injection independent, HOWEVER you should not do this as it violates the principles of SOLID. Mark Seemann - Service Locator violates SOLID
You should rather stick to adding the dependencies in the constructor as this is in line with SOLID OO design principles.
Currently I'm developing two solutions (first for country A, second for country B), which are very similar. I'm using wpf, c#, mvvm, sql server.
Some of modules are identical in every solution, some of them are partially different (ex. some classes have additional fields or methods), and some are completely different (ex. VAT module). For me, developing completely independent solutions is not the best solution (time cost).
So, I was thinking of creating two solutions (A and B) which will contain only main screen where would I prepare user interface. Then, in third solution (C) I would have project (=modules) and link them from A or B.
If module is identical for both version - no problem. If it is completely different - ok, I must develop it independently. But, the question is how to design modules which are slightly different?
Should I use abstract factory design pattern and put in AbstractProduct everything that is identical, and in ConcreteProducts put additional fields/methods? For WPF forms I can't use this pattern - I must develop a form for every version.
Thx.
what you really want to use is Dependency injection.
First you create an Interface then have your concrete impls implement this interface per country.
interface ISolution
{
....
}
class CountryA : ISolution{
...
}
class CountryB : ISolution{
...
}
Then register these Interface to impl mapping at composition root.
private static IContainer ConfigureDependencies() {
return new Container(x =>{
x.For<ISolution>().Use<CountryA>();
});
}
Then you ask the container to give you an instance of ISolution. and it will provide you the correct impl.
You can do the same for CountryB.
You can have auto wiring or late binding, something more dynamic. and you can switch impls.
Take a look at structuremap for examples.
I need to create general actions menu for my pages. All of pages will implement some basical functionality, i.e adding new rows to some table, editing them, calling filters. Many of this pages will need only basical logic to run this functionality. But some of the pages will implement their own logic for options in menu.
I want to make this happen by using events in menu. So I'll need not the only events, but some basic event handler for all pages. And this handler schould be constructed in a way it could be overriden. The problem is I don't know how to create handler for all future uses of menu. Sounds kind of utopic in some way. Is it real to create architecture like this?
I thought about two ways of doing this: Master page or user control. But I don't really know if it's even possible. So what do you think?
UPD: Upvoted both answers about basic pages: you guys are surely know what you're talking about. Thanks. Sorry that right answer can be selected only once.
You really shouldn't instantiate objects on pages unnecessarily, as this approach would most certainly do.
Keeping that in mind, you can make a base page that relevant pages inherit from, so you have access to the methods you need.
Create a class of type System.Web.UI.Page. (Let's name it MyBasePageClass)
Implement common methods needed in this class
Inherit this class on the pages you need to expose the methods to. For example, change your definition of the Default.aspx page class to this:
public partial class Default : MyBasePageClass
The methods created in MyBasePageClass must be public to be seen by Default.aspx.cs.
In many of my applications, I use a common base class if I have functionality to share across many pages. It's not uncommon practice, really.
The implementation might look something like this:
public class MyApplicationPage : System.Web.UI.Page
{
public virtual void RaiseMyCustomEvent(EventArgs e)
{
}
}
The virtual keyword makes the method overridable.
In my individual code behinds, the page inheritance might look like this:
public partial class MyPage : MyApplicationPage
{
public override void RaiseMyCustomEvent(EventArgs e)
{
// ...
}
}
Finally, in my master page, I might find code like this in a method:
if (Page is MyApplicationPage)
{
((MyApplicationPage)Page).RaiseMyCustomEvent(EventArgs.Empty);
}
I think that to "create handler for all future uses" sounds scary.
What I would do was to create the pages individually, and only when I identify some piece of logic that is equal or similar I would refactor that out to a separate class that several forms could use.
After all, code needs to be used before it can be reused.
I have an application in C#/Winforms that lets users place objects on a grid to create levels for a game. It has several tools for placing tiles/lights/doors/entities etc. Currently I just use an enum for storing the currently selected tool and have a switch statement to run each tools code. As I've been adding more tools to the application it's starting to get spaghetti like, with lots of duplicated code.
Here is a cutdown version of the mouse down function in my editor class:
public void OnEditorViewMouseDown(Point mousePos)
{
// Check if the click is out of bounds.
if (IsLocationOOB(mousePos)) return;
if (CurrentTool == ToolType.GroundTile)
{
// Allow drags along whole tiles only.
m_DragManager.DragType = DragManager.DragTypeEnum.Tile;
m_DragManager.StartDrag(mousePos);
}
else if (CurrentTool == ToolType.WallTile)
{
// Allow drags along grid edges only.
m_DragManager.DragType = DragManager.DragTypeEnum.Edge;
m_DragManager.StartDrag(mousePos);
}
else if (CurrentTool == ToolType.PostTile)
{
// Allow drags along grid points only.
m_DragManager.DragType = DragManager.DragTypeEnum.Point;
m_DragManager.StartDrag(mousePos);
}
else if (CurrentTool == ToolType.AreaLight)
{
// Allow drags anywhere. ie. not snapped to the grid in some way.
m_DragManager.DragType = DragManager.DragTypeEnum.FreeForm;
m_DragManager.StartDrag(mousePos);
}
else if (CurrentTool == ToolType.PointLight)
{
m_CurrentWorld.AddLight(TranslateToWorldCoords(mousePos));
}
else if (CurrentTool == ToolType.PlaceEntity)
{
m_CurrentWorld.PlaceEntity(TranslateToWorldCoords(mousePos));
}
}
The switch is used in several other functions (OnMouseMove, OnMouseUp) and it seems like bad design (big switch copied in several functions). Any advice for refactoring something like this in a cleaner and more extensible way? I'm currently thinking of having a base Tool class and having each tool it's own class that overrides the functions it uses (OnMouseDown() etc.). Does this sound sensible?
Thanks for reading.
You have the good intuition.
Usually, in OOP, when you have rows of if's or humongous switches, it's a strong code smell. The best way to make this smell go away is to go with polymorphism.
You should go ahead with your idea, having a base abstract class BaseTool, with the different OnXXX methods implemented as nops (just returns, so you only have to specify the behavior if your tool knows how to act on the method), and have each tool inherit from BaseTool and implement its own behavior by overriding the relevant methods.
So your method ends up being
public void OnEditorViewMouseDown(Point mousePos)
{
currentTool.OnEditorViewMouseDown(mousePos);
}
Depending on your design, you should also consider passing the DragManager to the method, so as not to be tied to instance variables laying around. An EditorContext (containing the DragManager) fitted with everything the method needs without having to fetch "global" variables would make your method more self-contained and less brittle when refactoring. The design itself will depend on the responsability: who is in charge of what.
Sounds like a good place to use the Strategy Pattern: http://www.google.com/search?q=c%23+strategy+pattern
Yea, you should absolutley have a base class (or at the very least an interface) that defines all the common methods needed across all Tools. Try to make this code work, and it'll give you a good idea of how to design your classes:
m_DragManager.DragType = CurrentTool.DragType;
m_DragManager.StartDrag(mousePos);
where "CurrentTool" is an instance of your base class or your interface.
So basically, when a "Tool" is selected, at that point you determine which derived Tool you're dealing with, but from that point on, you deal with the base class only, and forget about any enums or anything like that to determine the currently selected tool. Make sense?
Yes, polymorphism is what you want here. You should define either an abstract base class Tool or an interface ITool depending on if you need to add implementation to the base or not (i.e. if there there common functionality among all tools, you might use an abstract base class).
Your manager should then take a Tool or ITool when something needs to be done. Your tool will implement a Drag function that takes the information it needs and either return what it needs to return or do what it needs to do. Or you could implement an inversion of control between your Manager and your Tool and inject the Manager into the Tool via property injection (Tool.Manager = dragManager) and let the tool do what it needs to do using the manager.
http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html
I'm not terribly familiar with the syntax of C# but in general you could make the CurrentTool an object that has methods StartDrag, EndDrag which accept a DragManager as an argument. Then when the mouse is pressed down on the view you just invoke CurrentTool.StartDrag(m_DragManager).
Try flag enums. Each bit would be a different feature and would allow for better stacking of features per cell.
Then you could just check for each bit even in different methods.
I tend to implement UI functionality using fairly self-documenting void doSomething() methods, i.e. if the user presses this button then perform this action then enable this list box, disable that button, etc. Is this the best approach? Is there a better pattern for general UI management i.e. how to control when controls are enabled/disabled/etc. etc. depending on user input?
Often I feel like I'm veering towards the 'big class that does everything' anti-pattern as so much seems to interact with the 'main' form class. Often, even if I'm including private state variables in the class that have been implemented using a relatively modular design, I'm still finding it grows so quickly it's ridiculous.
So could people give me some good advice towards producing quality, testable, decoupled WinForms design without falling into these traps?
You can try MVP if you want to put the logic of the UI in a separate class..
In model view presenter just as Martin Fowler or Michael Feathers say, the logic of the UI is separated into a class called presenter, that handles all the input from the user and that tells the "dumb" view what and when to display. The special testability of the pattern comes from the fact that the entire view can be replaced with a mock object and in this way the presenter, which is the most important part, can be easily unit tested in isolation.
using the MVP pattern is pretty good with winforms.
have a look at http://www.objectmentor.com/resources/articles/TheHumbleDialogBox.pdf
I would only put UI logic in the Form class and put any application logic in its own class:
class Form1 : Form
{
void Button1_Click
{
Program.DoCommand1();
}
}
static class Program
{
internal static void DoCommand1() {/* ... */}
}
One thing I have been dong lately is leveraging the partial class feature of .NET for some of these larger type forms. If I have a tab control with 5 different tabs on it. I'll create partial classes and name the files CardImportMethods.cs, ManageLookupTables.cs, etc. while leaving it all a part of the CentralizedForm class.
Even with just the UI logic, having this breakdown has helped when it comes to managing those things.