I'm attempting to refactor an existing Winform application to use the MVP Passive View pattern. The application's UI, business logic and data storage code have been freely intermingled for years. It looks like it either started out with separate layers or someone attempted to separate it into layers. In any case the layer boundaries weren't respected.
Since the forms directly manipulate the domain objects and the data source(and vice versa), my first task is to create presenter/controller objects and delegate those responsibilities.
The application is a .NET 1.1 app and I'm developing in VS.NET 2003 with a rather limited refactoring add-in. I used a test generator for the existing code to create the boiler plate unit tests then went through and hand edited each test. Granted, this winds up testing what the code does, not necessarily what it's suppose to do. For new classes I'm doing TDD.
Any tips, resources, pitfalls to look out for with a refactoring effort of this scale?
A couple of resources I already have at my disposal:
Collection of programming books; Refactoring, PEAA, WELC
The internet (obviously)
Large quantities of caffeinated beverages
Update:
As an example what steps would you take to turn this:
private void OneOfManyFormEventHandlers(object sender, System.EventArgs e)
{
string LocalVariable;
decimal AnotherLocal;
if (!this._SomeDomainObject.SomeMethod(ClassField, out LocalVariable, out AnotherLocal))
{
MessageBox.Show("An error occurred calling method");
return;
}
this.FormControl.Value = LocalVariable;
this.AnotherFormContorl.Value = AnotherLocal;
this.AnotherPrivateMethod();
}
Into this:
private void OneOfManyFormEventHandlers(object sender, System.EventArgs e)
{
this.FormPresenter.DoSomething();
}
The approach I've taken is too move the code out of the event handlers first. Essentially I've placed a class next to the form, which implements the event handlers and holds the UI state beside the controls.
Through this move I have gained a pretty clear seperation of the form and the actual interaction with the remaining app and was able to introduce tests at that level. Another result of this was that the view becomes passive pretty quickly.
I refactor the presenter (which now holds the event handlers) in a seperate step and introduce domain objects only after I've moved all uses of these objects out of all forms.
So my steps would be:
Remove the UI dependency from the logic
Create domain objects (if not available already)
Refactor the presenters to use the domain objects
Introduce services according to your design choice while you're at it
While I did this I started introducing tests at the newly introduced boundaries to ensure that I'm not breaking working code or to find bugs in the existing code I'm moving.
If you have the time, I'd recommend first writing some smoke tests using WinForms test frameworks like White on the existing application. This way you'll be able to check for any newly introduced bugs when you start refactoring the code.
You may find the answers to Implementing MVC with Windows Forms helpful as they talk about the different options when implementing MVC and MVP
Related
There is need to create small scale winform applications for private use by my company for interaction with our database. Period. I know that .NET MVC has a very mature unit testing framework for the MVC pattern as I want to do TDD.
Thus, is it possible to use NUnit or some other easy/mature unit testing framework (EDIT: Based on my experience with ASP.NET) with the following tutorial given here? I have googled and checked my technical book library, and there is a distinct lack of documentation for how to do effective unit testing for winforms. Thus, I am turning to this forum hoping individuals can share their domain knowledge with me.
The most I have found has recommended the MVC pattern (which I agree with), but not how to address specific issues with the winform. For example, how do I test a button click and subsequent action by that button?
I plan on using C# VS13 .NET 4.5. I am excited to join this resource and will contribute rep to all who answer my inquiry. Thanks.
As you have probably noticed, the idea there is to have your view described with an interface.
Thus, the controller doesn't really need a window, it needs a class implementing the interface.
And thus, you could have yet another, auto-mocked or manual implementation of the view interface that doesn't involve the WinForms subsystem but rather, exposes the data to write your assertios.
Having your stub view, you just write a script against it. You expose some methods from the class that allow you to automate the interaction:
public class ViewStub : IView
{
// implement the view interface as it is but also
// an extra stuff to let you automate this in your unit tests
public void RaiseButtonClick()
{
this.controller.DoTheButtonClickStuff();
}
}
Then your test becomes (I follow the convention from the tutorial)
ViewStub form = new ViewStub();
IModel mdl = new IncModel();
IController cnt = new IncController(view,mdl);
form.RaiseButtonClick();
Unit Testing a GUI is something that is independent of the GUI library used. The answer to the general case answers your case as well:
How can I unit test a GUI?
Unit testing a GUI is done by minimizing the footprint of classes that do depend on your GUI framework. Then the classes that still depend on the GUI framework are not unit tested (which is not at all the same as "are not tested"). Those classes are the "View" in patterns like MVP, MVC, MVVM.
Conclusion: Every good .Net Unit Testing framework is a good WinForms Unit Testing framework. One example of such a framework is NUnit, which you mentioned in your question.
Unit testing is not inteded for UI. Of course you can do it, but I don' recommend it for few reasons: You cannot unit test DPI changes, multiple screen, how your program acts in different window states or what happens if user moves with tabulator between your controls. Unit testing UI will only give you false safety.
Use UI automation tools to test UI automatically if you want to, but leave the unit testing out of it. You can keep the UI layer thin as possible and this is also a good design practice. You can use unit testing for other classes which are used in your winforms app.
I'm creating a signal analysis program that plots some data and compares sources and does some operations. I'll have to update the size of some elements of my UI and also create new elements (for example, I have a big plotter, and if user selects X it should to divide in 3 showing more data).
I'm pretty new in Visual Studio and in programming non-numerical stuff in general. I would appreciate enormously hints and advises to create a solid interface.
One of the issues that I currently have is that I've defined 15-20 elements in MainWindow.xaml and its code in MainWindow.cs but it's growing fast and it is a mess. For example, I have a button that loads a file and does a bunch of different operations (reads it, cuts, puts all in lists and then displays it). What do you recommend me to keep the code clean and readable? To create methods at the end of the file? Create separate class files?
I know its not very specific question but I think I'm not the only one that is having this kind of problems. Thank you.
A class with some static helper methods is a start. There are lots of different ways to go with this, but the main point of all of them is your MainWindow.cs should have only enough code to gather information together in the UI and then call on the other layer(we'll call it the business layer) to actually perform tasks or save/load data. MainWindow.cs should be like a seperator between your UI and your business layer. The business layer shouldn't know anything about buttons or textboxes. Instead it might take the string from the TitleTextbox and put it into a SignalFile.Title property of a simple class(called a POCO). You might have one business layer class that deals with operations related to this file, a method for each action you can perform on it.
I have some GUI controls in WinForms application. For example i have log control which logs each progress application makes so i can debug quickly, currently all "databinding" is on MainForm. I can create separate control but still it is coupled too much with application logic.
I've got advice to use partial MVC pattern in which I will update some object which saves log items and log control will get to this object and load the data to control.
I don't know how to implement it, besides creating a Class which will hold the data I need to load.
I have problems with Threads as many processes in the application run in different Threads.
Do you know any example of this done in C#?
I read the thread Mr Moose links to, but what finally got me going was this: http://www.c-sharpcorner.com/UploadFile/rmcochran/implementing-the-passive-view-a-derivative-of-the%C2%A0model-view-control/ is part of a series the guy wrote on this exact issue. I am currently using this scheme and am quite happy with it.
I added a ObservableDictionary to some of my Model classes. Key based lookup is nice for a lot of cases.
He has a whole series of articles with different implementations that may be more suitable for you.
I've written a simple desktop application with C#/WPF and I'm now looking to create another, larger application which will share much of the functionality. I'm thinking that I should create three separate projects: one containing the shared code, and one each for the two apps.
My problem is that I'm not entirely familiar with .NET/WPF so I don't know if there are some best practices for this sort of thing. Can anyone offer some good sources of information, example projects or just some brief advice?
Edit: To put a little more detail on the scenario, the first application is a specialised editor and the second application is taking this file editor and wrapping a project model around it to create a sort of basic IDE.
Honestly it depends on what level the code you intend to share is. For instance, it's entirely plausable to put all of your business logic code into one project/class library and maintain it independantly, but mixing biz logic with WPF custom controls should be STRONGLY discouraged. Think about the layers of abstraction you are modularizing, and the dependancy heiarchy you are introducing and refactor accordingly.
Edit:
In response to your above changes I suggest the following: The logic and DAL associated with the above should be pushed into a project as seperate namespaces. The visual elements (the view, viewmodel) should most likely be moved into a seperate project and namespace set as well. Once you can merge these together and launch them from an exe that contains a host window and a UserControl for the rest of your hosted visual content, you can then probably move forward with integration into your larger IDE project. The key here is:
Visual Layer and View Logic -> Editor.Visual.dll
Biz Logic & Data Access -> Editor.Core.dll
I hope this helps.
I have an ASP.NET Web Forms page which the presenter needs to populate with controls. This interaction is somewhat sensitive to the page-life cycle and I was wondering if there's a trick to it, that I don't know about.
I wanna be practical about the whole thing but not compromise testability.
Currently I have this:
public interface ISomeContract
{
void InstantiateIn(System.Web.UI.Control container);
}
This contract has a dependency on System.Web.UI.Control and I need that to be able to do things with the ASP.NET Web Forms programming model. But neither the view nor the presenter may have knowledge about ASP.NET server controls.
How do I get around this? How can I work with the ASP.NET Web Forms programming model in my concrete views without taking a System.Web.UI.Control dependency in my contract assemblies?
To clarify things a bit, this type of interface is all about UI composition (using MEF). It's known through-out the framework but it's really only called from within the concrete view. The concrete view is still the only thing that knows about ASP.NET Web Forms. However those public methods that say InstantiateIn(System.Web.UI.Control) exists in my contract assemblies and that implies a dependency on ASP.NET Web Forms.
I've been thinking about some double dispatch mechanism or even visitor pattern to try and work around this but I don't yet know in which direction I want to go and I would really like some input on the matter.
Not sure how a visitor would solve the problem. But why not have your contracts look like this:
public interface ISomeContract
{
void InstantiateIn(IControl container);
}
with an IControl implementation, possibly in another assembly to keep your contract assembly clean, that wraps over the ASP.NET System.Web.Control, like:
public class AspnetControl : IControl
{
public AspnetControl(System.Web.Control control) { }
// IControl members that dispatch to control
}
Although there's a high likelihood that eventually IControl would end up looking very much like a System.Web.Control (and hence defeat the point of abstracting it in the first place), it'd still be very testable, and your view and presenters won't have to know a thing about ASP.NET.
One way you can decouple your contract from your web control is to have a separate writer that handles getting the information from ISomeContract and places it in your Control container. This could reside in an assembly that references both the contract assembly and System.Web.
I have been reading about agile techniques, tdd, unit testing, solid, design patterns and felt utterly powerless to bridge the gap from all this wonderful theory to asp.net webforms.
I had another go at trying to find a solution to this problem earlier today and found this article:
http://p2p.wrox.com/content/articles/testing-aspnet-webforms
It is an excerpt from a book which I thought would solve all my problems but this chapter is really just an introduction to the possibilities of implementing the MVP pattern in webforms and it concludes with saying that its not really practical. The rest of the book is about testing asp.net MVC as far as I gathered.
There is also this new project which aims to bring the love back to the webforms platform:
http://webformsmvp.com/
In "normal" ASP.NET web forms, your page/user control is technically "in charge" of the processing, and imposes its life-cycle on the code. The page is the Presenter and the View, whether you like it or not.
Most attempts to implement the MVP pattern in this environment simply add excess complexity to an already overly complex environment! Pretending that another class is the Presenter is just that... pretending. (In MVC web sites, the Controller truly does control the code, and the View does not, so this argument no longer applies.)
My recommendation is to let the view look after its own life-cycle, and let it invoke Repositories and Model classes to retrieve/save data and invoke commands.
In this approach, the Model classes do not need to know anything about System.Web. These same Model classes could then be used in future MVC web sites, or Silverlight, or as a web service for WPF applications, or embedded in a WPF application, etc. It is up to the View to determine how to implement (using Controls) the response/data it gets from the Model.
The Model classes can be tested as much as you like if you correctly set them up to support dependency injection.
Hope that helps!