Thoughts on Martin Fowler's article on Passive View
The problem with MVP and MVC
The MVP and MVC design patterns are great but they are avoiding the real issue which is UI abstraction. UI code should be abstracted into libraries which are tested once and once only. I know that using the fundamental units of UI that are available today (e.g. HTML) give great flexibility in the design of the UI, however this should be present in abstracted libraries also.
So why is testing UI so difficult? There are two main reasons:
-
The UI is expensive to create. This is because it is rendering (and in the case of HTML being transmitted over a network as well) and creating complex and detailed visual elements. However these visual element don't have to be created in order to be tested.
-
Even if the UI is cheap and quick to create still is difficult to interact with in an automated way. This means that often manual testing is necessary. Note that this too is due to an actual property of the UI. It is through the choice of the UI designer that this is the case.
The primary function of the abstracted libraries I am advocating would be to enable fast automated UI testing.
For example, libraries would contain discrete UI components that have two functions. The first function is to display a UI to the user. The second function (which is not present in any of the currently available libraries) is to mock the UI via a purely code level interface. This means that each component in the library is able to guarantee (via one-time extensive testing) that all operations performed via the mock interface correctly mimic the corresponding operations performed by the UI interface.
A concrete example of this is a simple text box. Here is a prototype of this new type of library component:
public class Textbox : UIComponent, Mock
{
private string isMock;
public string CurrentText;
public string TextBeforeLastFocus;
public TextBox(isMock)
{
// Set flag to determine behaviour.
this.isMock = isMock;
}
public void KeyPress(KeyCode key)
{
// Implement mock
}
}
In the above example the constructor takes a boolean which specifies if the object will be used as a mock or as an actual UI component. This means that you can simply toggle this flag when moving from testing to production.
It also means that you can call methods (such as KeyPress) on the object when it is in “mock mode” so that the object mocks its own behaviour exactly as it would if being controlled by a user via its UI.
In general I believe that frameworks should support testing from the beginning. This means integrating testing interfaces into all parts of a library or framework. To be clear I am specifically talking about testing interfaces for client use of these libraries. Undoubtedly they should also have a means of testing the internal functions of their libraries.
Take the .NET Framework for example. This is rigorously tested by Microsoft internally to ensure that the function of each class and interface is correct. However there is no interface for consumers of this framework to use. I'm suggesting that the .NET framework would benefit from integrated testing frameworks such that (as shown above) a consumer of a class can mock the class. This is more needed in the areas of UI and database access but would be useful for all parts of the framework.
The real question about the Passive View pattern is "I know it decreases decoupling but does it increase cohesion?"