Posts from Jason Watkins...
Should deployment be viral?
Reading about Storm recently, I had no idea how big it got before it’s decay. Estimates for how many hosts were in Storm at peak vary, but they’re all in the millions. I was really struck by how sophisticated command and control for botnets has become, moving from simple IRC servers to peer to peer overlays. [...]AnswerLinks
We’ve added a feature today that makes it easy for you to link words in your posts to definition pages on Answers.com. For example let’s say you mentioned someone like Artie Shaw or something like Turmeric in a post. If you click the AnswerLink “A” in your editor: AnswerLinks will find words in your post that [...]Category to Tag Converter
Since launching tags the other week we’ve had a fair number of people who wanted to redo their categories as tags, probably because you have a bunch of categories you’ve only used once or twice. Now under Manage > Import there’s a Category to Tag converter, which shows you how many times you’ve used each category [...]Tags! And Categories
Not long after WordPress.com began we started calling categories “tags” in some places, most notably our global tags system. However while our interface made it easy to add categories on the fly, many people were vocal in telling us that categories and tags were not the same thing, and eventually we figured out they were right. [...]Theme Monday: Digg 3 Column
Here’s a shiny new theme to brighten up your Monday: a three-column, Digg-inspired layout by Small Potato. It features two (count ‘em!) sidebars with widgets, a customizable header image with an overlaid border, and nifty green tabs at the top for your Pages. You’ll find it listed on the Presentation tab of your dashboard, under D for [...]August Wrap-up
There were three big features in August: The new News departments. Theme Previews. Being able to see stats. There was a lot of action going on behind the scenes, but most of that will be revealed later. How about some stats? 154 thousand blogs were created. 176 thousand new users joined. 1.14 million file uploads. 2.2 million posts and 851 thousand new pages. 3 million [...]Eighty-seven
How many words must one person type before they enter a state of deep rooted paranoia as a result of their inability to judge whether their post is too long? Too short? I have no idea, but we can all find out together with WordPress.com’s latest feature: Word Count. Below the post text box, [...]Posting Source Code
Here at Automattic we’re allllll about sharing source code. We’re easy, we give it away. Tragically, though, using WordPress.com it is really, really hard to post source code. You have to know about HTML encoding, pre and code tags, and if you want any slick highlighting you have to convert it before you post it. You [...]Good charts come in threes
We have been accumulating stats data for about twenty months and it’s a pretty massive amount of data. (Just ask Barry.) Today we present you with two new ways to look at your historical stats data. I proudly give you Weeks and Months! You will find three new links above the main stats chart: Days, Weeks, [...]2nd Birthday
You know, if I keep forgetting WordPress.com’s birthday she’s going to stop returning my calls. Has it really been a year since I almost missed our birthday last time? How time flies. Next thing you know it’s a million blogs later. It’s overwhelming to even begin to chronicle everything that has happened, but a year ago we [...]Why We’re Blocked in Turkey: Adnan Oktar
There’s been quite a discussion going on in my personal blog about the fact that all of WordPress.com has been blocked by Turkey. Lots of people, including us, are confused and indignant about this wholesale censorship. Last night we received a letter from the person claiming to be responsible for the block, which in the interest [...]How I learned Ruby
Only because this guy and then that guy asked.
What was your technical background before you started learning Ruby/Rails?
I remember playing with Basic as a kid. My brother had these great choose your own adventure style books where you had to type in basic listings to get to the next part of the story. I typed them in to my parent’s Apple IIgs (we had the Woz signature, yeah bay-be!). I thought it was quite cool, but didn’t really go anywhere with it.
My brother was great. Even though I only had a passing interest in software as a kid, he exposed me to a lot of great ideas just by talking, in particular functional programming.
In my more teenage years I played with OO Pascal in delphi. I did some TCL to script IRC. I liked to learn about programing, but didn’t really do much with it. I read a book on c, and picked up the basics of the c abstract machine.
I developed an interest in game development. I read Foley and van Dam and loved it. I skimmed the web of research literature, starting from Siggraph proceedings, Hughes Hoppe, Seth Teller, Larry Gritz and others. I enjoyed thinking about algorithms quite a bit, but didn’t do much to apply them.
I did some contract art and design for games, and got exposed to some minor in game scripting.
I worked for a CRM VAR for a bit and got exposed to web development with asp. I also played with the early betas of .NET.
I did a little PHP on the side, and hated it.
I worked a non-technical job for a couple years. Around this time I discovered citeseer. I skimmed thousands of papers, and printed hundreds to read in more depth. I don’t exaggerate. I filled my two filing drawers and covered my desk with tall piles of printed papers, only to dump it all in the recycling bin. This repeated 4 times.
I wish I’d kept notes, because I haven’t retained that much detail, but I do find it satisfying to have a sense of the geography of CS.
I read Hennessy and Patterson, loved it, and read a couple compiler books too. I highly recommend this.
How long ago did you start?
I learned the basics of Ruby circa 2001 at the CRM VAR. I had a small scripting task: generating some human friendly temporary password tokens. Perl is what you use for that, right? I’ll learn that, let’s go take a look at it. Bleh. Hrm, maybe there’s some Perl alternatives. Oh hey, this Ruby looks cool. Wait, that’s what I can use to do… and 15 minutes later it worked.
I was hooked.
I kept a passing interest in Ruby after I tired of technical work, and occasionally attended the local users group.
What were the two most useful resources to you in the learning process (not counting the Agile Book or the Pickaxe Book, which we’ll assume everyone knows)?
1. Community.
The blogs, the local users group, irc… they’ve all been invaluable in helping me learn. In particular I want to single out Jeremy Voorhis for teaching me a staggering amount while I was at PA, and being willing to debate topics I found interesting.
2. The Source.
Consistently, the source is the best place for me to answer the tricker questions about rails. Looking at other people’s source is how I’ve learned the most useful ruby. If you’re new to Ruby, this may be a bit daunting. I certainly find portions of the Rails source intimidating. But dig in there, it’s totally worth it.
Tell us the story of how you came to learn Rails:
In late 2004, someone in the portland ruby group mentioned Rails. I’d tried to play with mod_ruby, and found the experience mostly dissatisfying. I checked out Rails. I liked it. I kept an eye on the early blogs, the heiraki and the trac (until it got insanely busy).
In spring 2005 Lucas Carlson gave an intro to Rails talk for the Portland Ruby Group and the portland perl mongers. It was a good talk, and way more people than the ruby group had ever attracted before that time. More than when Matz came for OSCON a few years prior (sorry Matz). I got the feeling that I was one of only a couple people in the room who’d gotten into rails farther than the screencast, but still, the response was thought provoking.
In late 2005, rails really started to hit. I realized I could do this for a living. I hadn’t been interested in a technical job for a while. The chance to work with small, smart, early adopter companies, and to do with with Ruby was way to good to pass up. I started freelancing. In December, 2005, I started working with PLANET ARGON. I learned an amazing amount in my time there.
Three Ruby bloggers to whom you’re passing the baton:
CRUD is rich
Coda Hale made a blog post that started some controversy and interesting debate some time back that I had missed. I started a comment which became lengthy enough to post here instead:
I think the root difference of this debate is that you have a very narrow interpretation of CRUD, coda, and by proxy, REST.
Most people would agree rdbms’s can be described as CRUD systems, yet their behavior is quite rich. Even just the R encompasses projection, generalized selection by arbitrary propositions, products (joins), etc. The key insight of Cobb’s relational database is that the basis of operators provided by relational algebra are sufficient for a huge domain of applications. Meanwhile the uniform interface allows a wide variety of client applications.
Likewise, in the REST thesis the concept of resource is quite rich, including resources that have behavior (ie the code on demand constraint). The CRUD part only applies to the uniform interface which is used between client and server to exchange representations. The domain of ‘RESTful’ applications is similarly large, as is the flexibility in clients.
On to specific responses:
How do you crop an image with CRUD?
Couple options:
- Download an editor resource that can generate a preview and post/put the selected parameters.
- Update an image model object via a request and return a server side generated image.
The interesting thing about case 1 is that the uniform interface constraint of REST implies that you could implement option 2, then implement option 1 to have client side preview calculation, but PUT/POST to the same URI as option 1 to store the finally selected crop parameters. I’m sure you can start thinking about how that might enable simple html, js and flash based editors to talk to the same server endpoint, and how this general principle is useful for eliminating code duplication.
ActiveResouce is likely to take this a step further and allow us to use the same sort uniform interface within our server side code, factoring out a single monolithic application into a cluster of cooperating services.
How do you browse a hierarchical set of categories?
Resources are typically structured in collections. Nothing says collections can’t be nested. Or more formally, our URI can represent a directed walk starting from any acceptable root of the data graph.
How do you retrieve all non-published articles? All articles which have the approval of the desk editor, but not the section editor, which haven’t been flagged for review, with all their associated images, all the while checking that these actions are permissable according to the appropriate ACL with CRUD?
This is why we have query strings on collection resources (or matrix urls). Your very narrow view of CRUD seems to miss the concept of index, or that it might be predicated in some manner. Again this is similar to stating that databases aren’t CRUD because you can retrieve relations that match arbitrary criteria. Obviously databases can handle the above. Are we to decide databases aren’t CRUD?
At some point you’ll be looking at your controller’s actions, each of which is 80 lines long and contains nested case statements inside conditionals, each with an average of 10 different return paths, and you’ll wonder where the hell all that simplicity went.
This was DHH’s key point. When this happens, the message is not “CRUD failed me”, but “My models need to be re-factored”.
There certainly are exceptions, but I think this perspective is quite useful in practice.
Are nouns better than verbs?
From Jim Greer’s interesting blog post, Don’t say CRUD, say FUC’D :
Of course you don’t just want to delete a trouble ticket. You want to know more. And that’s a sign that the operation shouldn’t have been on the TroubleTicket in the first place. You want to have a “TicketClosure”. Then you’ll realize that you want to store a resolution as well as the person who closed it and the date. Now you’ve got a very useful part of your domain model – the hint was that you were writing some thing that wasn’t CRUD – you needed a new noun instead of a non-standard verb.
Something really clicked for me here. Domain models are about storing and manipulating information that represents the world. Typically we do this with objects. There’s a tired metaphor that objects are the nouns, and their methods are the verbs. But maybe that perspective is missing something interesting. What if we start thinking purely in terms of nouns?
What if our domain modeling is just about accumulating history over time? What if it’s all just about the existence of facts and relationships? What if all we do is add nouns using standardized verbs, rather than having a vocabulary of verbs?
There’s something about this I like a great deal. Instead of having methods that let us ask about and manipulate an object’s hidden state, we enrich the relationship modeling to encode the history of events as facts directly.
What do we gain?
We have knowledge not just of “what is”, right now, but also a detailed history of “what was”, back then. We can query across this history in a standardized way, and compose novel ad hoc views of the information with standard operators.
What do we lose?
Perhaps simplicity. Sometimes it’s just simpler to say ticket.close! than to create a new TicketClosure object with the appropriate relations.
How do we balance this tradeoff?
I find it an interesting perspective that I hope to leverage in future work: looking for opportunities to turn a verb into creating an instance of a noun.
So long, and thanks for all the fish
I’m leaving the core team at PLANET ARGON.
It’s with a bittersweet feeling that I go. Working there has been intensely rewarding, and I’ve enjoyed the last half year, but it’s time we took different paths. I wish them well, and look forward to seeing what they’ll achieve.
Where does my path go?
I’ll be exploring in more detail some small ventures I’ve wanted to pursue for some time, and some additional opportunities I need to do due diligence on.
I’ll also have some availability for contract work, giving priority to projects that will provide an opportunity to show a strong initial ROI to my client or expand Rail’s capabilities.
Think your project may fit? Drop me a line and let’s talk.
Also, this blog will most likely be changing as I dedicate more time to contributing back to the Rails community which has been so generous to me.
Every line of code is a liability
Code is a static promise made against changing requirements in a dynamic world.
Every line is a liability. This implies you should both minimize how much code you write, but also be supremely thoughtful in what you do write.
My point today is that, if we wish to count lines of code, we should not regard them as “lines produced” but as “lines spent”: the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger.
Trends: less complexity
I went book shopping today and noticed something. Sometimes a picture says it all:

A more declarative rspec?
I’ve been intrigued with rspec since seeing the steady trickle of blog posts from folks like obie
Looking at this example some thoughts occurred to me.
- How can I easily see what context a given behavior applies to?
- If I want to understand a specific behavior, how do I know which places to look in the spec without scanning the whole file?
- How could we make this more DRY so that there’s less temptation to copy-past behaviors between contexts?
- rake like dependent contexts
- behaviors apply to context groups
require 'a_more_declarative_rspec'
context "empty" do
@stack = Stack.new :limit => 10
end
context "one item" => "empty" do
@stack.push 10
end
context "almost full" => "empty" do
(2..10).each{ |i| @stack.push i }
end
context "full" => "empty" do
(1..10).each{ |i| @stack.push i }
end
context_group "not empty" => [ "one item", "almost full", "full" ]
context_group "not full" => [ "empty", "one item", "almost full" ]
behavior "should accept an item when sent push" => "not full" do
lambda{ @stack.push Object.new }.should.not.raise
end
behavior "should complain when sent top" => "empty" do
lambda{ @stack.top }.should.raise StackUnderflowError
end
behavior "should complain when sent pop" => "empty" do
lambda{ @stack.pop }.should.raise StackUnderflowError
end
behavior "should return top when sent top" => "not empty" do
@stack.top.should.be 10
end
behavior "should not remove top when sent top" => "not empty" do
@stack.top.should.be 10
@stack.top.should.be 10
end
behavior "should return top when sent pop" => "not empty" do
@stack.pop.should.be 10
end
behavior "should remove top when sent pop" => "not empty" do
@stack.pop.should.be 10
contexts "almost full", "full" do
@stack.top.should.be 9
end
contexts "one item" do
lambda{ @stack.top }.should.raise StackUnderflowError
end
end
behavior "should remove top when sent pop" => "one item" do
@stack.pop.should.be 10
end
behavior "should complain on push" => "full" do
lambda{ @stack.push Object.new }.should.raise StackOverflowError
end- one place to look for a given behavior
- more dry
- should reduce bloat when we’re forced to deal with things that have very wrinkly behavior
- it’s far more cluttered and complex than the original
- it can require some creativity to structure contexts such that an expectation can apply verbatim across them all (example: make sure 10 is top of all the non empty stacks)
What do you think? A step in a promising direction, or simply a step to far?
It's going to be a good year
I don’t make a big deal out of holidays, so I was a bit surprised when I showed up to the office today.
All I can say is that a year ago, I would have never predicted I’d be getting paid to do Ruby with such a cool group of people.
We’re growing fast at PLANET ARGON and I’m really happy that everyone here rocks.