Lessons from rewriting POP Forums for MVC, open source-like
It has been a ton of work, interrupted over the last two years by unemployment, moving, a baby, failing to sell houses and other life events, but it's really exciting to see POP Forums v9 coming together. I'm not even sure when I decided to really commit to it as an open source project, but working on the same team as the CodePlex folks probably had something to do with it. Moving along the roadmap I set for myself, the app is now running on a quasi-production site... we launched MouseZoom last weekend. (That's a post-beta 1 build of the forum. There's also some nifty Silverlight DeepZoom goodness on that site.)
I have to make a point to illustrate just how important starting over was for me. I started this forum thing for my sites in old ASP more than ten years ago. What a mess that stuff was, including SQL injection vulnerabilities and all kinds of crap. It went to ASP.NET in 2002, but even then, it felt a little too much like script. More than a year later, in 2003, I did an honest to goodness rewrite. If you've been in this business of writing code for any amount of time, you know how much you hate what you wrote a month ago, so just imagine that with seven years in between. The subsequent versions still carried a fair amount of crap, and that's why I had to start over, to make a clean break. Mind you, much of that crap is still running on some of my production sites in a stable manner, but it's a pain in the ass to maintain.
So with that clean break, there is much that I have learned. These are a few of those lessons, in no particular order...
Avoid shiny object syndrome
Over the years, I've
embraced new things without bothering to ask myself why. I
remember spending the better part of a year trying to adapt
this app to use the membership and profile API's in ASP.NET,
just because they were there. They didn't solve any known
problem. Early on in this version, I dabbled in exotic
ORM's, even though I already had the fundamental SQL that I
knew worked. I bloated up the client side code with all
kinds of jQuery UI and plugins just because, and it got in
the way. All the new shiny can be distracting, and I've come
to realize that I've allowed it to be a distraction most of
my professional life.
Just query what you need
I've spent a lot of
time over-thinking how to query data. In the SQL world, this
means exotic joins, special caches, the read-update-commit
loop of ORM's, etc. There are times when you have to remind
yourself that you aren't Facebook, you'll never be Facebook,
and that databases are in fact intended to serve data. In a
lot of projects, back in the day, I used to have these big,
rich data objects and pass them all over the place, through
various application tiers, when in reality, all I needed was
some ID from the entity. I try to be mindful of how many
queries hit the database on a given request, but I don't
obsess over it. I just get what I need.
Don't spend too much time worrying about your unit
tests
If you've looked at any of the tests for POP Forums,
you might offer an audible WTF. That's OK. There's a whole
lot of mocking going on. In some cases, it points out where
you're doing too much, and that's good for improving your
design. In other cases it shows where your design sucks. But
the biggest trap of unit testing is that you worry it should
be prettier. That's a waste of time. When you write a test,
in many cases before the production code, the important part
is that you're testing the right thing. If you have to mock
up a bunch of stuff to test the outcome, so be it, but it's
not wasted time. You're still doing up the typical
arrange-action-assert deal, and you'll be able to read that
later if you need to.
Get back to your HTTP roots
ASP.NET Webforms did
a reasonably decent job at abstracting us away from the
stateless nature of the Web. A lot of people criticize it,
but I think it all worked pretty well. These days, with MVC,
jQuery, REST services, and what not, we've gone back to
thinking about the wire. The nuts and bolts passing between
our Web browser and server matters. This doesn't make things
harder, in my opinion, it makes them easier. There is
something incredibly freeing about how we approach
development of Web apps now. HTTP is a really simple
protocol, and the stuff we push through it, in particular
HTML and JSON, are pretty simple too. The debugging points
are really easy to trap and trace.
Premature optimization is premature
I'll go back
to the data thing for a moment. I've been known to look at a
particular action or use case and stress about the number of
calls that are made to the database. I'm not suggesting that
it's a bad thing to keep these in mind, but if you worry
about it outside of the context of the actual impact, you're
wasting time. For example, I query the database for last
read times in a forum separately of the user and the list of
forums. The impact on performance barely exists. If I put it
under load, exceeding the kind of load I expect, it still
barely has an impact. Then consider it only counts for
logged in users. The context of this "inefficient" action is
that it doesn't matter. Did I mention I won't be Facebook?
Solve your own problems first
This is another
trap I've fallen into. I've often thought about what other
people might need for some feature or aspect of the
app. In other words, I was willing to make design decisions
based on non-existent data. How stupid is that? When I
decided to truly open source this thing, building for myself
first was a stated design goal. This app has to server the
audiences of
CoasterBuzz, MouseZoom and other sites first. In this development
scenario, you don't have access to mountains of usability
studies or user focus groups. You have to start with what
you know.
I'm sure there are other points I could make too. It has
been a lot of fun to work on, and I look forward to evolving
the UI as time goes on. That's where I hope to see more
magic in the future.