We just pushed the latest build of Tekpub - and it's a pretty substantial upgrade. I bounced between frameworks during this rewrite, eventually settling with Rails 3. A few people have asked why. Here's why.
Upgrading Tekpub with Rails 3
To get this out of the way first: because as your business grows, you need to adapt and change. Eventually you will run up against the edges of your architecture - where it takes long enough to make a change that it gives you pause. At that point you need to take a few steps back and adjust a bit deeper - or toss stuff entirely.
This is where James and I found ourselves a few months back. When you start a business you have 100 different ideas, and usually focus on one or two. If successful, those one or two ideas will lead to 4 or 5 more. Sometimes you know what those are, sometimes you don't.
Just like a tree - you can trim and adjust as it grows; but sometimes you need to prune back a bit to force more growth. We've tried to say as agile as possible - knowing that rebuilding chunks of what we do would come along with growth. Our new site is more about pruning than anything else - we've simplified and dropped a number of architectural approaches (no functionality - nothing you'll notice) - and made everything a little leaner, a little faster.
Originally we built Tekpub using ASP.NET MVC and it worked out pretty well, but soon enough we realized that we couldn't manage the growth needs of our site while simultaneously creating the product if we wanted to stay small (small meaning just James and myself). This is a major focus of ours: staying small. We're a year into it, and it's still just us (which I consider a win).
James and I talked about our decision in an article on InfoQ - so I won't go into that again here. Suffice to say that we moved to Rails six months after we started and it's worked out really well.
It's come time to prune, however, and nothing is safe. Not even Rails.
Those who do nothing are never wrong - Theodore de Bouville.
Iteration 1: Sinatra
With this latest effort I was focused on removing a lot of the "cruft" we didn't need - and with that everything came into question. I wanted small and simple; in short I wanted to do videos and not worry about the damn website.
The first step was to evaluate whether we needed to stay on Rails at all. At the time I didn't think so - Sinatra is so very appealing because of it's lean simplicity and close attention to semantic URLs etc.
So I went with Sinatra. It was wonderful at first, and the overall size of our application shrunk massively. I didn't to an LOC count (I should have) but I would guess it dropped by a good 60 to 70%.
Once I had the core built out, I turned my attention on pressing out the details. I had the design in place, the player and all front-facing pages were firing - all I needed to do was plumb out our backend (where James and manage the site and the people) and... that's when things started to spiral a bit.
There's a lot that we do - and let me just summarize by saying that it quickly became obvious that I'd have to write a lot of the supporting "bits" by hand. I didn't mind this so much - but as I said before: I want to focus on videos, not supporting the web site.
A pessimist is a person who looks both ways before crossing a one way road - L Peters
Iteration 2: Padrino
I'm in love with Sinatra. I crave simplicity and elegance and Sinatra has it in spades. But writing a complex app in Sinatra requires more than a bit of discipline and the time to do things properly. I don't mind getting my hands dirty with deep level code; but I also don't have the damn time, and soon it became apparent I needed a bit more of a framework under me.
Things like creating HTML tags and forms that used CSRF validation tokens by default. Asset-expiration handled by default, along with flash notifications and better session/cookie management.
The good news is that
Padrino is a great set of functionality on top of Sinatra that gives you most of this as well as an admin tool (with page generator). It's an opinionated bit of software that adds some process to the wild-west awesomeness of Sinatra.
I took what I had written in Sinatra and pushed it into Padrino and was very happy. I had to go a little backwards to fit in what I had written - but in general it rolled right in and I was able to customize the admin stuff (sort of) to what I needed.
This is about the time where I began to notice the code files growing as Padrino began to wrap some framework structure around my lean little Sinatra app. As much I like small and simple - Tekpub is busting its britches a bit.
As I looked over the Padrino app I began to wonder: if I have to give in to the framework thing - what do I get with Padrino over Rails? And is the difference something I truly care about?
The answer to that question used to be "less" and "admin site". I can dig "less" - it's a great answer. But sometimes there are things I need in that "less"-ness I'm doing without. To be specific:*As annoying as migrations can be, they work. I ended up carving some code out of ActiveRecord to run my own - which is sort of sad.
*Caching. Yes I know there are plugins that do it for Sinatra/Padrino - but Rails caching/sweeper setup is pretty damn simple and compelling
*Email. One of the things we should have done from the beginning is email to our users. There's Pony and Padrino has a built-in mailer; but Rails 3 ActionMailer is just so simple and straightforward.
*Documentation. I can't even believe I'm saying this - it's the cry of the Tormented Geek. But the Rails docs and examples are pretty damn complete. It's not just that - Rails has been around for sooooo long; there are just a zillion articles and tutorials written on it
*Tooling. There are just some tools that make it really, really compelling to stick with Rails. I'll talk more about that below.I could go on - and we might get into a lovely technical debate but you have to remember it's about "Time On Code" for me - not the tech underneath it. My focus is "in and out - back to the vidoes" and at this point Sinatra and Padrino are losing...
Or I should say, have lost.
Too many decisions about changes are made by people untouched by the change process - Peter Block.
Iteration 3: Rails 3
I kept the core of the logic I wrote and decided I need to take an ax to everything else and build from the ground up - ripping out every "nice to have" or "what if" possible.
I started by changing from a Mongo/MySQL solution to just MySQL. We need a relational system on the backend - and the simplest thing to do by all account was to push everything into the tightest possible relational structure I could.
This reduced a ton of code and our model shrunk considerably. You might be asking "why" - and the short answer is for two reasons: we had duplication in our MySQL system (which is acceptable as it's for reporting) and I threw out Ivory Tower constructs we didn't need.
I know a lot of people will smirk at the move from NoSQL. Again - nothing to do with Mongo or pain of any kind; I only want one system running. That's all.
Rails 3 generators are just ... amazing. I was able to kick up a set of highly-customized generators for jamming out controllers (CRUD and not-so-CRUD) in about 3 hours. I used those to crack out the skeleton of the site. I'm not a fan of scaffolding at all.
Those generators used
Formtastic (which is a form-building gem in Rails) to auto-create the form based on the DB schema. This allowed me to*Build CRUD pages incredibly fast
*Not have to write form code when DB changed
*Customize only what I have toDelayed Job is another one of those "life saver" gems that seem to pop up all over the Rails landscape. This thing makes any method call asynchronous - simply by chaining the word "delay" in. It gets queued in the database and a worker thread picks it up later.
This solved a major issue for us - sending email synchronously with Rails is not a good idea. It takes up a thread and can slow down your entire app.
And finally - deployment. This, right here is the #1 reason that we use Rails over other non-Ruby frameworks: Capistrano. This gem is not Rails-specific, but I love it so much that I just have to mention it. When we went live last week, I was doing a push every 30 minutes - fixing little (and some big) bugs that people found in minutes - sometimes seconds.
We pushed the site this last weekend, and all in all it took me about 3.5 weeks in total - about 90 man-hours in total. I can tell you that the bulk of my time went into look and feel as well as UI experience. There's a lot of tidying to do - but I really don't want you to even notice the site is there.
My design goal is that all you see are the videos and the things you'll learn - nothing more.
This is the
short version. We built Tekpub with
Rails 3 and
MySQL. It's still hosted with
Amazon EC2 where we
stream our content securely behind Adobe Flash Servers hosted with Amazon's
CloudFront Edge Servers.
off of Mongo for no other reason than
tooling support. I like Formtastic, Devise, and a few
other groovy gems.
James and I want to
focus on the business not what it's built on. We have lots of plans and wanted to build a flexible core. This release
allows us to stay two people.