The Parameter Object Pattern

Posted on January 4th, 2012 by | No Comments »

I have been paying more attention to software design patterns recently. It all started with my noticing the Null Object pattern and the Ruby Rogues talking about Smalltalk Best Practice Patterns. My most recent discovery is of the Parameter Object pattern. Thanks, by the way, to @timtyrrell for telling me the name of it.

As I’ve mentioned before, I’ve been spending some time at work with a search engine. It works sort of like NewEgg’s search in that you might type a string in (“desktop ram”) and then narrow your search by clicking on links in a side bar (DDR3 or Corsair). The search engine in question powers a product called SubjectLin.es (it’s in beta; you can sign up for a free account to try it out, if you like) where you can search for words that appear in an email subject and then further limit by, say, who sent it (“sender”), what kind of email it is (like coupon or receipt, we call it a “tag”) or what business the sender was in (“market”).

To date, I’ve rewritten the search engine a few times and refactored it a few times. It and one other area of the code base are, by far, the most complex bits of the application, so it has gotten it’s fair share of attention. And it’s gotten more recently when an exception brought our attention to something: We don’t have one search engine… we have four. It’s just that they’re all in one class. Finding the email subjects that a user is interested in is not really related to finding the senders who sent them except that the user’s parameters are the same. So I thought what we’d do is factor out our current search object into 4 smaller ones (subject, sender, tag and market) that each centers around the object it’s pulling out of the DB. Besides code clarity, there are some other benefits we get from this modularity, but I don’t want to get into that in this post.

So now we’re faced with the fact that we’ll have 4 objects we want to create that all depend on the same parameters to build themselves. Add to that the fact that we do some fancy Google-style keyword parsing (you can type “some key words sender:Company” and we pull out the company name) and the fact that if the user is interested in limiting by sender, we want to display things differently than if they aren’t. Now, I thought, it looked as if we should have an object just about the user’s search parameters and that each of our search engines should take only that as an argument.

This way, our view (or presenter… whatever) can ask the search parameter object if the user limited based on sender or not. We can build the one object and then pass it to each of the four engines. We can put all the keyword parsing logic into the search parameter object, too. When I had it, it seemed like such a good idea that it had to have been thought of before. And, lo, it is called the Parameter Object pattern. Or, anyway, I think this is a case of that pattern.

What do you think? Is this Parameter Object? Is it something else? Does my example make any sense at all (I honestly have no idea, since I’m so deep in the system; I tried to balance high-level with need-to-know)? Note: as of this writing, none of this is implemented yet. This is all just design work with @marcosacosta, so far. If anything interesting crops up while we’re writing it, I’ll try to remember to update this post.

Release: twitter_atm 1.0

Posted on January 14th, 2011 by | No Comments »

Holy crap. Did I really start this blog in December 2008? That would make it more than 2 years old. Wow. Well, good on me, I guess. That feels sort of absurd. Anyway…

An Itch…

The other day at work, I had to get the OAuth credentials for a twitter account that our application would use to send programmatic tweets to. For those of you not familiar with OAuth, a brief description: The usual way you OAuth with Twitter is that you have a web page where a user clicks something indicating they’d like to OAuth you to their account. You then send your consumer key and secret off to Twitter to get a request token and, using that, you send the user off to a url over on twitter.com.

Once there, they sign in (or are already signed in) and click “Allow”. Twitter then hits your callback url with some more tokens, which you use to make a final reply and then they respond with the access token and secret you’ll need to do whatever it is you’re doing with the user’s account. If the user changes username or password, you’re still authorized and if they want to revoke your access, they can without changing their username or password. Great! (If you’re thinking, “What?!? Not great! That made no sense!” then maybe the image in this article will help).

However, when your program is a desktop client or when you’ve only got one account you’ll ever be tweeting from (or maybe a small handful), it’s not really practical to build a web interface and a callback url to hit so that you can do the whole dance and get the tokens. So Twitter has an alternate path that replaces the redirects in the middle of the dance. Instead of redirecting users over to twitter.com, you show them the URL and they go there manually. When they click “Allow”, they’re given a PIN, which they then give back to you and you can then finish off the dance as if the PIN were the callback.

…Scratched

So at work, I hacked around in the console for a bit and eventually figured out how to work the PIN-based method, ran it for the account I wanted and then got the access token and secret for our account. But, I thought, I shouldn’t have to hunt all around to figure out how it works (the documentation is almost all focused on the callback path). Heck, if I know my consumer key and secret and I own the account, I shouldn’t need to know how it works at all. So, having figured out how it works already, I decided I’d write a little command to do it for me and publish it as a gem. Thus was born twitter_atm.

The Tool

As the README states, it’s pretty simple. You invoke twitter_atm get_creds with your consumer key and secret as arguments, then it interactively gives you directions on how to finish out the process and spits out the access token and secret at the end. I do want to note, about the name, it’s not about cash. It’s about inputting a PIN and getting something in return. It’s not very exciting to use, so I won’t talk about it much. I’d rather move on to…

An Old God of Asgard

This was the first time I’d written a program with a command line interface, so I asked around a little about gems that were good at that and Jonathan Otto (of Dealzon) pointed me at thor. In short, thor seems awesome. It’s got a nice DSL for describing the various subcommands of your application and it looks deep enough to handle something more complex than my purposes with twitter_atm.

As a brief example, consider git pull --rebase origin master. If you were writing something that would support this syntax in thor, it would look something like this (I made up the git commands inside off the top of my head, so it’s a bit naive):

1
2
3
4
5
6
7
8
9
10
11
12
13
class Git < Thor
  desc "git pull", "Fetches and merges stuff into the current branch."
  method_options :rebase => :boolean
  def pull(remote, branch)
    `git fetch #{remote}`
 
    if options[:rebase]
      `git rebase #{remote}/#{branch}`
    else
      `git merge #{remote}/#{branch}`
    end
  end
end

You can also declare different types of options, default values, etc. Have a look at the fairly extensive readme and look at how I used it in twitter_atm if that helps. I quite recommend the gem and already have another project I’d like to use it on.

bundle gem twitter_atm

There’s this little project–I don’t know if you’ve heard of it–called bundler. It was started by a couple of up-and-coming young programmers who really might go somewhere some day. Bundler is great for managing gems in a big project and it does this really impressive dependency resolution thing. But there’s a lesser known command that I’ve fallen in love with: bundle gem <gem_name>. It just makes a skeleton for a gem project for you. Unlike Jeweler, it only gives you the bare minimum and really just gets out of your way. You manage your own version number and write your own gemspec (gasp!).

It has three handy rake tasks with obvious functions: rake build, rake install and rake release. Each of those for the most part just issue various gem commands. I basically like it because it builds you a little foundation and then doesn’t really manage anything else for you. One thing that’s important to note: The current version of bundler doesn’t add Gemfile.lock to the .gitignore that it generates (but future versions will), and it is important that you do so. Yehuda has a blog post explaining why.

So, based on this experience, here’s what I took away: Thor is good to use for making a CLI, bundle gem is good to use for making a gem and sometimes you can make something small and cool for yourself in one sitting which gives you a good feeling and is a well invested 5 hours.

OtherInbox Is For Email From Computers

Posted on December 23rd, 2008 by | No Comments »

So I use this great thing called OtherInbox. They’re in closed beta just now, but if you follow them on Twitter you’re likely to see when they hand out another round of invites (which they recently tweeted would be coming early in January, if I remember right). Let me tell you a bit about OI before I go into my rant. Hopefully it will segue nicely.

OtherInbox is an email, uh… application. Like Gmail or Hotmail, sort of. When you sign up for OI, though, you don’t get _username_@otherinbox.com, you get a whole subdomain and infinite email addresses at it. So, _whateveryouwant_@_username_.otherinbox.com. Then, when you login to your account, you’re presented with folders based on the email address that the email came to. It’s sort of like filters in other email clients, except you don’t have to set them up, you just hand out a new email address. So if I sign up for a new site, I hand it _sitename_@_username_.otherinbox.com and when they send me email, it automatically goes to a folder in my OI named after that site. So I have an Amazon folder and a Twitter folder, etc. etc.

You can also have a vanity URL and edit your MX records on the host so that email gets routed to OI’s servers, so that you don’t have to use the long _username_.otherinbox.com in your emails. So I have benhamill.com set up that way. Very, very nice feature, that.

Okay, so why might you want this service? Well, spam, firstly. If I’ve only ever given a certain email address away to amazon.com and I start getting spam to that address, I know who the culprit is. Also, if I want to sign up for something that I expect to get spam from, I can do so without fear. After getting that confirmation email, I can just hit the “Block All” button and OI will just not show me those messages. I don’t have to worry about it ever again.

Another use case which I’m loving is when you sign up for what’s called bacn; stuff you want, but not, you know, right now. I use OI to sign up for email lists and such that I don’t want cluttering up my inbox. Stuff I might want to read, but over the weekend or whatever; stuff that’s not time-sensitive.

Which leads me to my rant. If you’re not an OtherInbox user, the following might not make a lot of sense, so you might want to skip it until you are. And I highly recommend you become one. I found that the more I used it, the more I liked it. So, rant on…

OtherInbox is not your primary inbox. It’s right there in the name. I was confused about this at first, too, but it should be obvious. You don’t ditch gmail for OI. You use them both. How you divide it up is something people do differently, but here’s my rule of thumb: If it is sent by a computer (as opposed to a human), it goes to OI. What this does (ideally, since I haven’t finished converting all my accounts over to OI addresses) is makes it such that the only emails that show up in my gmail account are ones that are actually to me.

I mean–how many emails do you get from computers? If you’re like me then a lot. I get email every time someone follows me on Twitter and every time someone sends me a message in my online Diplomacy game and every month when Rock Band sends out their “zine”. Why not have a computer help me deal with it all? It’s not going to read it for me, of course, but it _will_ help me process them. If I know I ordered something from Amazon, then I will look at new emails to my amazon address when they show up. Otherwise, I’ll probably ignore it.

However, OI is pretty bad at displaying conversations. I mean–that’s not a fault, that’s not part of their core mission. They’ve been talking about adding a feature like that since it makes sense for mailing lists, but for personal email, gmail is still king. Tags and search and conversation view, etc. That’s what gmail is good at. OI is good at sorting spam and bacn.

People who talk about having their friends each email an OI address based on their name just confuse me. Your friends aren’t going to sell your email address to spammers or send you stuff you don’t want to read (or, if they are, get new friends… elderly relatives, on the other hand, who will send you random jokes might warrant an OI address), so there’s no need to hide you *real* email address. If you want, you can set up auto-forwarding for an OI address, but just hand that out to real people like you would your real address.

It can get sort of heady, making up any old address to give to people, but if you’re handing out OI addresses to real people, you’re sort of defeating the purpose of OtherInbox. Either you’re using OI’s interface, which is optimized for dealing with emails en mass, or you’re having to set up a bunch of auto-forwards to your primary inbox (with the nice interface for dealing with individual emails). OI is supposed to make it so you don’t have to set up filters or auto-forwards all the time.

I really love OtherInbox. If you’re not a user (and you didn’t skip the rant), really go follow them on Twitter and get an invite code. Or find someone who’s in the beta now and see if they have any invites left (I have a single one as of this writing). I didn’t think I was really an awesome candidate for an OI user, but that’s only because I didn’t realize how much email I get from computers. It’s really freeing to be able to click “Yes, send me updates” on everything. If you never get anything from them that’s worth your time, you never waste any time on it. Throwing away that email address it completely trivial. The real trick to having OtherInbox improve your life is not swimming against the stream, though. So remember my rant when you sign up.