The short Twitter answers are “yes”, “we’ve used it effectively with up to 4 people”, and “yes, because I can’t draw” – in that order.

But a slightly more detailed response would probably help.

Once upon a time, prototyping web apps was easy. You’d draw every page, and then use a site map to demonstrate which links went where. Every page was static; nothing moved, there was no Ajax, no infinite scrolling, no drag’n’drop, and most websites were actually about as interactive as a Choose Your Own Adventure novel. Well, those days are gone. People expect more – richer UIs, better responsiveness, less postbacks and waiting around for pages to load – and with libraries like jQuery, there’s really no excuse for not delivering code that satisfies those expectations.

Question is – how do you prototype a rich user interface? How do you draw a picture of something that won’t sit still? For me, that’s where Axure RP comes in. Axure is a “tool for rapidly creating wireframes, prototypes and specifications for applications and web sites”. It’s a commercial product, so it is, alas, not free (although to put it into perspective, it costs less than hiring a .NET developer for one day) – but it is a uniquely powerful and expressive piece of software that I find myself firing up on an almost daily basis.

In everyday use, it’s like a weird cross between Balsamiq, Visual Basic, and Lego.

Balsamiq, because it’s easy to mock up static user interfaces by dragging buttons, inputs and form elements on to your page.

Visual Basic, because it’s easy to add behaviour to those elements using click handlers, events and dynamic controls.

Lego, because it’s intuitive, and it’s fun, and there is no way anyone is going to look at what you’ve done and think the project is finished.

The game Populous was designed using Lego. I grew up with Lego*. From a very early age, I learned to use Lego bricks to express ideas. I knew every single brick I owned. I could demonstrate an idea I’d had for a car, or a spaceship, or a robot, by assembling these reusable components into a prototype with spinning wheels and moving parts and a sense of scale and colour. Working entirely in plastic bricks actually become very liberating, because it stops you worrying about materials and finishes, and allows you to focus entirely on expressing ideas.

Have you ever showed someone a Lego house and had them say “Hey, that looks great! When can we move in?” No. People know a Lego house is not a real house. They appreciate that the point of a Lego - or cardboard, or clay - model is to demonstrate what you’re planning to do, not show off what you’ve already done.

Have you ever showed anyone an HTML mockup of a web app and had them say “Hey, that looks great! When do we launch?” – and then they look horrifiedwhen you explain that you haven’t actually started the build yet?

People don’t grok the difference between HTML mockups and completed web apps the way they grok the difference between Lego houses and real ones. I can’t say I blame them. HTML is HTML – whether it was hacked together late last night in Notepad or generated in the cloud by your domain-driven MVC application framework. The difference doesn’t become apparent until they actually start clicking things – by which point it’s too late; you’ve made your first impression (“wow, the new app is done!”) and it’s all downhill from there.

I think the hardest questions in software are “what are we doing?” and “are we done yet?”. I think good prototypes are absolutely instrumental in answering those questions, and any tool that can help us refine those prototypes without falling into the trap of “well, it looks finished” has to be a Good Thing.

* Some people look at how much Lego I still have and conclude that I never grew up at all…

Thursday, 5 November 2009

Yesterday, I posted some code I’d hacked together as part of an MVC2 demo that would resolve ASP.NET virtual path URLs on the fly as pages were written to the ASP.NET response stream.

Having run some tests on this code in isolation – it’s actually quite nasty. For running ad-hoc demos on your workstation, it’s fine, but the performance hit of decoding the byte array, doing the regex transform and re-encoding it is something like two hundred times slower than a direct stream copy. Not good. There is now a modified version online at Google Code which is quite a bit faster, but there’s still huge scope for improvement. In particular, although it’s using byte comparisons now to work out where the ~/ combination occurs, it’s still falling back to string comparisons every time it finds a tilde to decide whether that tilde needs replacing or not.

These stats were created using a loop that spins up HTML pages of various sizes – one version full of ASP.NET-style tilde paths, one containing no tildes - and then writes them 100 times to both a normal MemoryStream and a UrlResolverStream in order to calculate the average rendering time. If a page doesn’t contain any tildes at all, performance is 5-6 times slower than the equivalent direct memory copy – i.e. 21ms instead of 4ms. For pages with lots of tildes, the additional string processing hits quite hard and you’re looking at a slowdown factor of around 30-35x.

Tildes?

Page Size

MemoryStream copy (ms)

UrlResolverStream copy (ms)

Ratio

Yes

50Kb

0.05

0.38

7

Yes

101Kb

0.17

2.51

14

Yes

202Kb

0.19

6.05

31

Yes

405Kb

0.37

13.88

37

Yes

809Kb

0.88

29.47

33

Yes

1,619Kb

1.62

60.55

37

Yes

3,238Kb

3.45

123.40

35

No

50Kb

0.02

0.34

17

No

101Kb

0.07

0.66

9

No

202Kb

0.15

1.28

8

No

405Kb

0.48

2.62

5

No

809Kb

0.83

5.26

6

No

1,619Kb

1.66

10.57

6

No

3,237Kb

3.53

21.17

5

It should be possible to make this considerably faster still; since the code basically scans byte arrays, this is one of those areas where using pointer arithmetic could make a huge difference. I’ll dig out my unsafe hat and my pointer-gloves this weekend and see what I can do to it. In the meantime – play with it, experiment with it, but it’s probably a good idea not to let it within a hundred miles of your live servers :)

Wednesday, 4 November 2009

Update: An improved version of this module, along with some performance stats, is available here. The original version posted here was very, very slow. Probably not a good idea to use it for anything. Ever.

One of the few things I actually liked about ASP.NET WebForms was that you could do things like

ASP.NET MVC doesn’t like things that are runat=”server” – and with good reason, I think – but this does mean you can end up with rather a lot of calls to ResolveUrl() sprinked throughout your code.

To get around this, I’ve hacked together an HTTP module that basically rewrites the output stream on the fly. It wraps the HTTP output stream (the thing you're writing to when you Response.Write stuff) in a 'smart' stream wrapper, and the magicnaively optimistic part looks like this:

Basically, it looks for HTML SRC, ACTION and HREF attributes whose value begins with ~/, and replaces the ~ with the application’s virtual path on the fly. I haven’t tested this code for performance, so I don’t know what kind of impact it’ll have on your page response times,This code is something like 200 times slower than a straight stream copy, but it’s running in a couple of demo apps I’m working on and it seems to work pretty nicely.

A big thank-you to everyone who came along to my HTML5 and MVC2 talk at SkillsMatter on Monday – and thanks also to SkillsMatter for hosting us! Whilst I’ve done plenty of talking at unconferences and events like BarCamp, this was the first proper full-length technical talk I’ve given, so I’d really appreciate any feedback – especially since we might be doing a re-run in a couple of weeks.

During the talk, I demo’ed a tiny web app – TagAlong - that I’ve built to showcase some of the new features in HTML 5 and ASP.NET MVC preview 2. This is by no means production code – if nothing else, I’m using static List<T>’s instead of having an actual database, so your changes will disappear every time you restart the app – but it should be pretty easy to get it up and running and poke around.