Balsamiq Mockups - WOW!
It is rare that I get impressed by something, but I have to admit that balsamiq has managed to really impress me.
Balsamiq mockups is a flash application that you can use to very quickly build a UI mockup. That in itself is not really new. What is new is that they have somehow managed to take this to a completely new level from the point of view of usability. It took me 7 minutes, from first use of their program, to get this thing working:
Aaron Jensen talked about it as well, which is how I heard about it, and damn am I thankful for that.
To say that I am impressed is not sufficient, I am going to buy a copy just because I didn't have to (I was able to create the above picture using the free version). If I could do it, and I am so dense in matters of UI that I cannot draw a straight line with a ruler, that is saying a lot. That I could do it so far, that is saying even more.
Let us make the UI complex, just because we feel like it
Let us take a look at this dialog, shall we?
What I see is that we have two text fields and two checkboxes, in a fairly big dialog, to express the following bit of information:
I honestly have no idea what the purpose of this is. To make it harder to input the information, presumably. Given a URL, I now need to split it apart manually, I need to know that https is usually on 443, etc.
It also mean that when I am talking to a user, I need to give her three pieces of information, and explain where to put each of them, rather than sending a URL that she can just copy / paste in place and be done with it.
How not to go about "Building user interfaces for object-oriented systems"
Update: This article is fron 1999, which I somehow missed, not news by far. Still wrong, even for its time, though.
This really annoys me, the author of the article tries to preach an OO methodology for writing UI. In general, I don't have an issue with that, but his arguments contains this:
Name class, objects of which know how to both display and initialize themselves.I am not sure where to begin. To start with, an entity should not have ties to the UI. Then we have this dream vision about editing a single class, and suddenly all the relveant screen sprout the new field, and we can start working on it. UI doesn't work like this. It doesn't work like this because adding a new field to screen can horribly break the screen. It might push the Ok/Cancel button outside of the visible realm of the screen, it might break the tab order, it will definately break the flow of the screen.
I am all for OO and encapsulation, but this is not a problem that you can generalize.
This just gets better when you keep on reading:
The other bugaboo that I want to put to death is the notion of different views into the same object, usually characterized by the question: "Suppose you need to display this data as a pie chart over here and a grid over there? How can you do this if the object displays itself?"
Now let's get real. How often in your work has this problem actually come up?
Um, all the time? The simplest version is showing items in a list and then in a details view, but I just finished talking about the different views that I present to the various aspects in my systems. Beyond that, I have different views for different screens. In one screen, I am showing an Employee's personal data, in another the Employee's salary data, etc.
Integration Tests in ASP.Net
As you probably noticed, I am doing a fair amount of integration testing with ASP.Net currently. I am using Selenium, and after a brief struggle to get myself aligned with it, I think that I like it :-)
It is simple, it is extensible, and it works. Here is a simple example, I needed to check that a drop down is disabled, Selenium has no support for this out of the box, so I could just extend the DefaultSelenium class (in Selenium RC for .NET) and add this:
public bool IsDisabled(string partialElementId)
{
string result = GetElementAttribute(partialElementId, "disabled");
return bool.Parse(result);
}
public string GetElementAttribute(string partialElementId, string attribute)
{
string evalScript = string.Format(@"
this.page().findElement('//select[contains(@id, \'{0}\')]').{1};
", partialElementId.Replace("'", @"\'"), attribute);
string result = GetEval(evalScript);
return result;
}
Note the funky syntax that I have to use in order to get around the ASP.Net element naming. Another thing that I run into was the compilation model for ASP.Net. That one was a biggie.
The problem was that I wanted to specify a default value for page load times (all pages must load in under 0.5 seconds, for instnace). The problem was the just from the command line build, it started giving errors about timeouts when loading a page. Accessing the page manually or running the tests from Visual Stuido always succeeded.
After a bit of head scratching I realized that the problem was that the build recompiled the site, so every time that I hit a new page, ASP.Net had to compile it for the first time. I ended up keeping a list of pages that I already visited and increasing the wait time for pages that I access for the first time.
The last problem that I have is getting the correct information from the pages, let us take a page that threw an error, in the Selenium test, I usually just get an error about an expected element not found. I added an assert that check that "error" and "exception" do not appear on the page, but I didn't figure out yet how to take just the exception text from the page and put it in the error message for the test.
With or without you: Ajax
David Hayden has a post (ASP.NET AJAX Web Controls - AJAX Experience Without Learning AJAX) that really bothers me. He talks about the different components that he tested for Ajax support, and conclude with:
Frankly, I would like to know as much about Ajax as I could get away with. The problem is that you can't escape from the complexity. You can wrap it, hide it, stash it in the attic and throw away the key, but it will come back and hunt you.
Complexity, meet Ajax, you are going to be best friends.
The law of leaky abstractions holds quite well for Ajax. Eventually, you will need to do something slightly beyond what is supported by the controls, or you will get an error that can't be fixed by setting a property somewhere, or you'll need to debug an issue. Those are the cases where the willful ignorance will come to haunt you.
Building Reusable UI Components In MonoRail
I have talked recently about the problems with 3rd party controls and I made the statement that most of the time, I would want to do this on my own, since figuring out how to get to where I want with a 3rd party control often takes as much time as developing the functionality myself. Scott Bellware commented on this post, asking how to get this functionality in MonoRail.
Here is a simple implementation of a grid ViewComponent in MonoRail. It supports header / footer (which the GridView doesn't), empty template, alternating rows schemes, and pagination. I feel that this encompass quite a large precentage of the feature that are in the ASP.Net GridView, so let us see how we build it. We start by deriving from ViewComponent:
public class BasicGridComponent : ViewComponent
We then define the sections that we support. If you are coming from Web Forms world, you can think of View Components as Server / User Controls and sections as the equipollent of ITemplate.
static readonly string[] sections = new string[]
{
"header", "footer",
"pagination", "empty",
"item", "alternateItem",
"tablestart", "tableend"
};
public override bool SupportsSection(string name)
{
return Array.IndexOf(sections, name) != -1;
}
Now, let us build the all important Render() method:
public override void Render()
{
IPaginatedPage source = (IPaginatedPage) ComponentParams["source"];
ShowStartTable();
ShowHeader(source);
if(source != null && source.TotalItems>0)
{
ShowRows(source);
}
else
{
ShowEmpty();
}
ShowFooter();
ShowEndTable();
ShowPagination(source);
}
One interesting thing to note here is that we are using IPaginatedPage as our data source, which provides us with most of the paging support out of the box. We are mostly delegating to methods that does a single thing, mostly, they provide default overridable functionality. Here is a sample of such a method:
private void ShowEmpty()
{
if(Context.HasSection("empty"))
{
Context.RenderSection("empty");
}
else
{
RenderText("Grid has not data");
}
}
Most of the other methods are implemented in a similar fashion, we provide a default implementation and we can override it in place by specifying the appropriate section. ShowStartTable, ShowHeader, ShowEmpty and ShowFooter all share the same concepts. ShowPagination share the same idea, but is a bit more complex, because it outputs the entire pagination toolbar, which has a lot of conditionals.
ShowRows, however, is very interesting:
protected virtual void ShowRows(IPaginatedPage source)
{
bool hasAlternate = Context.HasSection("alternateItem");
bool isAlternate = false;
foreach(object item in source)
{
PropertyBag["item"] = item;
if (hasAlternate && isAlternate)
Context.RenderSection("alternateItem");
else
Context.RenderSection("item");
isAlternate = !isAlternate;
}
}
We check if we have an alternateItem section, and render the sections accordingly. The PropertyBag["item"] allows the section to access the current item in a convient fashion.
Here is the code for this View Component:
<?brail
component BasicGridComponent, {"source": contacts}:
section header:
?>
<th>EMail</th>
<th>Phone</th>
<?brail
end
section item:
?>
<tr style="background-color: #fea;">
<td>${item.Email}</td>
<td>${item.Phone}</td>
</tr>
<?brail
end
section alternateItem:
?>
<tr style="background-color: white;">
<td>${item.Email}</td>
<td>${item.Phone}</td>
</tr>
<?brail
end
end
?>
But, you know what, this is too much for me to write. Let us say that I love the AutoGenerateColumns option in the GridView. What would it take to implement it as a ViewComponent? Well, as it turns out, not much, really.
public class GridComponentWithAutoGenerateColumns : BasicGridComponent
{
private PropertyInfo[] properties;
protected override void ShowRows(IPaginatedPage source)
{
if (properties == null)//there are no rows, if this is the case
return;
bool isAlternate = false;
foreach(object item in source)
{
RenderText("<tr>");
foreach(PropertyInfo info in properties)
{
if(isAlternate)
RenderText("<td class='alternateItem'>");
else
RenderText("<td class='item'>");
RenderText(info.GetValue(item,null).ToString());
RenderText("</td>");
isAlternate = !isAlternate;
}
RenderText("</tr>");
}
}
protected override void ShowHeader(IPaginatedPage source)
{
if(source!=null && source.TotalItems>0)
{
IEnumerator enumerator = source.GetEnumerator();
enumerator.MoveNext();
object first = enumerator.Current;
properties = first.GetType().GetProperties();
foreach(PropertyInfo property in this.properties)
{
RenderText("<th>");
RenderText(property.Name);
RenderText("</th>");
}
}
else
{
RenderText("<th>empty grid</th>");
}
}
}
And now, the code for this view component turns into:
<?brail component GridComponentWithAutoGenerateColumns, {"source": contacts} ?>
So, in about 170 lines of code we created a grid components that gives you quite a bit of functionality. It is an basic grid component that we can configure quite liberaly all over the place. It supports paging seamlessly, and with a tiny bit of work, we managed to make it support AutoGenerateColumns in another 30 lines or so. The full code is here, feel free to poke around.
All in all, it took me about half an hour to write this View Component. Just to put this in perspective, I spent more time writing this entry...
Office UI Licensable?
Mike Gunderloy is talking about the "royality free" office UI license. He raises some very important issues with regard to the mere feasability of the license. The basic issue here is that the ability to license a UI improvement means that you are allow to not license the improvement. And if Microsoft manage to make this a legal thing, all software deveopers are going to be in a very sad state all of a sudden.
The problem with this is that Apple has previously successfully sued people for copying their Look & Feel, so I can see where Microsoft is coming from...
Presenting Trac UI
So, after praising Trac so much, I decided that I need another this from it, and that was a windows client. Specifically, what I wanted is for QA to be able to enter bug reports that included screen shots without a lot of hassle. There is nothing that explains most bugs better than a screen shot with some marking.
The result is this:



The easiest part of this application was capturing the screen, actually. The hardest was interfacing with Trac. Xml RPC is not as easy as it can be when you are used to wsdl generated code, I am afraid.
Note: This is not public yet. The code is in the rhino tools repository, but I want to test it in more scenarios, specifically, ones hat involve windows authentication.
Polymorphic Databinding Solutions
Let us assume that you have the following class hierarchy:

Now, what do you think the result of this code will be?
BindingList<Animal> animals = new BindingList<Animal>();
animals.Add(new Dog());
animals.Add(new Cat());
GridView gridView = new GridView();
gridView.DataSource = animals;
gridView.DataBind();
Ten points goes to the lady on the right that said that it will produce the following error:
The reason for this bug is that the TypeDescriptors in .Net are not aware of polymorphism. Even though both Cat and Dog inherit from Animal and has a Name property, and that the list that I passed to the DataSource is BindingList<T>, the TypeDescriptor only looks at the first item in the list, and uses it to describe all types in the list. This can cause problems when the collection that you pass to the GridView contains an inheritance hierarchy.
After butting my head against this issue for too long, I finally came up with this solution:
public class AnimalTypeDescriptionProvider : TypeDescriptionProvider
{
public AnimalTypeDescriptionProvider()
:base(TypeDescriptor.GetProvider(typeof(Animal)))
{
}
public override Type GetReflectionType(Type objectType, object instance)
{
return base.GetReflectionType(typeof(Animal), instance);
}
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
return base.GetTypeDescriptor(typeof(Animal), instance);
}
public static void Register()
{
TypeDescriptor.AddProvider(new AnimalTypeDescriptionProvider(), typeof(Animal));
}
}
Then, I call the AnimalTypeDescriptionProvider.Register(); method in the start of the application.
What this does is it lies to the data binding infrastructure, and tells them that any type that inherits from Animal is actually an Animal, and should be treated appropriately.
This solution is good enough for now, but it will prevent me from databinding a list of Dogs, for instance.
Testing UI - A Challange
Here is the story:
I got this to work without tests, since I just can't think of how to test this stuff. Right now I'm heavily using the functionality that Netron provides (which does 96% of the above) and the implementation uses windows events and state tracking quite heavily to get this functionality.
I suppose I can try to refactor the logic out so it would be testable, but that would mean duplicating the events structure for WinForms. In addition, I can see no way to test that the correct stuff is drawn to the screen and I am not fond of taking a screen shot and then comparing the known good to the result on a bit by bit basis. If for no other reason than that I can think of several dozens of tests for the functionality that I need.
Any suggestions on how to test this?
UI Design for the Web
Here is a nice post by Jeff Atwood, with a really cool idea that I like. Using a free form address field instead of seperating the fields.
On the one hand, it's easier for the user, since this is easy to grasp. On the other hand, we can't you auto complete. Read the comments, they are interesting, and be sure to check the screen shot he has there.
Cool Linq Idea: UI Mapping
This is purely hypotetical, but imagine the following way to show the user's details:
User user = ... ;//Get user something
var view = new View( user,
new Text(u => u.Name, s => user.Name = s),
new Password( u => u.Password, s => user.Password = s ),
new List(from g in user.Groups select g, g => user.Groups.Add(g), g => user.Groups.Remove(g)) );
view.Show();
Where View is a class which display view items in a TableLayout. And each item knows how to handle changes. This could be a very rapid way to create UI.
What do you think?
Wanted controls...
I'm currently developing an application that need to display source code (XML & Sql).
Most of the works goes into the UI, I rarely touch the back-end, just put stuff in the UI to make it nicer to work with the application.
I desperately need stable control for source editing (syntax highighting a must, code completion would be nice.)
Currently I'm at a loss.
I tried RichTextEditor and ICSharpCode.TextEditor but both doesn't work for me.
I need a configurable editor that can handle XML, C# & SQL, support
word-wrapping (where ICSharpCode.TextEditor failed) and that I can
actually understand how to use (Which was the deciding point of not
using RichTextEditor).
I would've gone with ScintillaNET but while I'm certain that it can support my needs, there isn't any documentation about using it.
The second control that I need is a TreeListView (you know, a tree with columns) but all the controls that I've found so far were buggy. (I tried everything that I found in Code Project
These UI problems are holding me from going on with the interesting stuff :-(