01 Jun 2010

Four Things You Should Know About Ruby Methods

Just wanted to jot down some of the really cool things I’ve learned aout the way you can call methods in ruby. I may end up expanding this post into four separate posts with more info if need be, but for now I’ll try to keep this short.

1. Default values

When defining a method with parameters, inevitably you’ll find that it can prove useful to have some of the params revert to a default value if no value is passed. Other languages like python and php give you similar conventions when providing the parameter list to a method.

To use default values, simply use an equals sign after the parameter name, followed by the default parameter you wish to use. Note however, that while not all params need have a default value assigned, all params that do have defaults must go at the end of the parameter list.

  # Invalid method definition. Either from_date must be at the end of the method list, or to_date must have a default value
  def back_to_the_future(from_date=1985, to_date)
    puts "From Date: #{from_date}"
    puts "To Date: #{to_date}"
  end

  # Valid method definition
  def back_to_the_future(from_date=1985, to_date=1955)
    puts "From Date: #{from_date}"
    puts "To Date: #{to_date}"
  end

  back_to_the_future
  # => 1985
  # => 1955

  back_to_the_future 2010
  # => 2010
  # => 1955

  back_to_the_future 2010, 2000
  # => 2010
  # => 2000

Pretty simple, but hey, maybe you didn’t know.

2. “Named Parameters” using the special hash parameter

Python, Objective-C, and various other languages have an interesting syntax for method arguments where you can name an argument beyond the scope in which the method is defined. These named parameters give you the ability to assign values to method arguments in an arbitrary order, since you are assigning a value to a specific parameter by that parameters name.

While ruby doesn’t have Named Parameter syntax built in, there is one way to gain something very similar, and it has to do with Ruby Hashes. Ruby’s hash syntax has a very simple, minimalist style that I really like, especially in Ruby 1.9. The interesting thing about using the hash parameter as a “named parameter” or “variable-length” argument, is that there is no syntactic sugar needed when defining the method. All the interesting work goes on while calling the method.

  def back_to_the_future(options)
    puts "From #{options[:from]} to #{options[:to]}"
  end

  back_to_the_future :from => 1985, :to => 1955
  # => From 1985 to 1955

  back_to_the_future :to => 1985, :from => 1955
  # => From 1955 to 1985

  back_to_the_future :with_doc => false
  # => From to

Notice here that we didn’t have to include the open and close curly braces usually present in a hash definition. You can put them in if you’d like, but sometimes it’s more confusing to see it that way (what with block syntax using curly braces or the do...end syntax).

You can still have regularly defined parameters with or without defaults in the parameter list, just make sure they come before the expected hash collection.

  def back_to_the_future(from_date, to_date, options) ... end

  def back_to_the_future(from_date, to_date=1955, options) ... end

  def back_to_the_future(from_date, to_date=1955, options={}) ... end

You’ve probably noticed by now that rails does this all over the place.

3. Variable-length arguments using the special array parameter

While named-parameters is nice for passing a list of configuration options to a method, sometimes you just want a method to accept any number of arguments, such as a logger method that can take any number of log messages and log them independent of each other. Ruby has another parameter condensing technique where all parameters passed that do not map to pre-defined arguments get collected into their own special array parameter, that is, if you ask for it. Defining a method in this way, you simply place a parameter at the end of the parameter list with an asterisk ( * ) preceding the parameter name.

  def back_to_the_future(from_date, to_date, *people)
    puts "Who's coming?"
    people.each {|person| puts person }
  end

  back_to_the_future 1985, 1955, 'Marty', 'Doc', 'Biff'

  # => Who's Coming?
  # => Marty
  # => Doc
  # => Biff

Also worth noting is that the parameters collected do not need to be of one type like Java forces you to be. One could be a string, the next a number, the next a boolean. Whether or not that is a good design for your method is another story.

This style of parameter definition can be mixed with all the styles we’ve discussed so far, just remember the order things go: Regular params, Regular params with defaults, a Hash-collected param (if any), and finally the Array-collected params (where the param is preceded with an asterisk).

  def back_to_the_future(from_date, to_date=1955, delorean_options={}, *people)
    # ...
  end

  back_to_the_future 1985, :use_flux_capacitor => true, :bring_back_george => false, 'Marty', 'Doc'

4. Saving the best for last: Blocks!

Arguably the most powerful feature that Ruby boasts is the ability to send an anonymous function to a method to be executed by the method in whatever way it was designed. Ruby calls these anonymous code blocks just that, blocks. In other contexts you might hear them called lambda’s, procs, or simply anonymous function. You’ve probably already used blocks a ton in your ruby code, but what exactly are they for, and how can you use them in your own code?

Virtually every class in ruby’s core make use of blocks to basically extend the language’s abilities without having to add more syntactic sugar. Take for instance iterating over an array, the conventional way with a for loop, and ruby’s more idiomatic way, with the each and it’s associated block.

  people = ['Marty', 'Doc', 'Biff']

  for person in people
    puts person
  end

  people.each do |person|
    puts person
  end

The first example uses ruby’s syntax sugar to run the loop, printing out each entry in the people array. The second calls the each method on the people array, passing it a block. Array#each can and likely will run it’s own code before or after invoking the block. As a developer outside looking in, it doesn’t really matter to me what each does, so long a it calls my block for each element in the array. If we were to write a simplification of what ruby is doing in the background, it’d probably look something like this:

  def each
    for e in self
      yield e
    end
  end

But wait a minute, isn’t that what we wrote in our first example without the block? Indeed, it’s very similar. Where our block example differs is that we have the ability to pass an anonymous block of code to the each method. When each is ready to call our block, it invokes yield, passing the argument applicable, in this case the e variable. In other words, each is handling the iteration for us, allowing us to focus on what matters more, the code being run for each iteration.

Syntactically, the big things to jot down with defining your methods to accept blocks are as follows:

  • All methods implicitly may receive a block as an argument.
  • If you want to name this argument, for whatever reason, it must be last in the argument list, and preceded by an ampersand & .
  • Just as all methods implicitly may receive a block, you can always check in a given method if a block was given, by calling block_given? .
  • TO invoke a block, simply call the yield method, passing any paramters your block may be expecting
  • Alternatively, if you have named the block, say &func , treat it as a lambda or proc that is passed to you (because that’s what was passed), using the built-in call method available to procs: func.call(some_param) .
  def back_to_the_future(*people, &cool_block_name)
    puts "We're going back to the future with..."
    people.each do |person|
      cool_block_name.call(person)
    end
  end

  back_to_the_future 'Marty', 'Doc', 'Biff' do |person|
    puts person
  end

  # => We're going back to the future with...
  # => Marty
  # => Doc
  # => Biff

All of these examples are obviously contrived, but I hope it sheds some light on some really cool things you can do in ruby with simple method definitions. I’ll likely be doing more posts with blocks, procs, and lambda’s in the future, since they are definitely the most powerful tools in the shed (as far as methods go), so look for those sometime in the near future.

Please let me know if you find any omissions or errors in the above examples and explanations. Happy Coding!

27 May 2010

Ruby Dailies

Back in January (a whopping 5 months ago!) I started at a new position for an up and coming startup company in Utah. I left my previous employer who had treated me extremely well, given me great opportunities to learn and grow, and ultimately put me in a great position to yet again catapult into even bigger and better things.

One of the biggest draws for coming to the new company was the opportunity I was given to choose the language and platform for an entirely new product, one I’d be driving the development of while running my own team. The majority of the team was leaning towards Python, but during the interview process I made it quite clear that it was my goal to do the thing in Ruby. Previous to this opportunity, I’d done a lot of ruby on the side for clients and my own projects, but it hadn’t quite cracked into the full-time gig. Here was my chance.

It took a week or so to nail everyone down to the decision to move forward with Ruby and Sinatra, but it’s been an awesome decision for us. I honestly am so happy each day solving problems in the unbelievably friendly language that is Ruby. I’ve learned an enormous amount, and feel like I’m at the point where I can start sharing a lot of the ruby tidbits I come across each day. I’m going to call this article series the Ruby Dailies, and the plan is to post a few articles a week showing off some neat things.

Naturally, being a somewhat late newcomer to the ruby party, so much of what I have learned so far allows me to stand on the shoulders of (ruby) giants: Matz, _why, Ezra, Yehuda, DHH, Wanstrath, and tons of others. Obviously I’ll give credit where credit is due when posting these tidbits. Stay tuned!

05 Feb 2010

Bundler 0.9.1 With Capistrano

On my current project at work we’re building a Sinatra app. More specifically, we used the Monk generator/glue meta-framework which is built atop Sinatra. When you generate a Monk app it automagically gives you a dependency/gem management system known as, fittingly, dependencies. This article isn’t meant to knock dependencies (which I believe is written by the CitrusByte guys, the creators of monk), but through some continuing issues with it we decided to find something else to handle that problem. That something we found was Yehuda’s Bundler.

Bundler is really cool because it allows you to make all your gem management across all your development, testing, and production systems easy to handle. You define a Gemfile which references all the gems required to make your app go boom (in a good way). Once the file is defined simply run bundle install to ensure your system has all the necessary dependencies to run your app.

I created my bundler Gemfile 4 or 5 days ago, installed the dependencies, and then sort of left it alone for a while. Yesterday I wanted to deploy my app to production and so I went into my capistrano deploy.rb to update my recipe to handle the bundler stuff. Naturally, I needed bundler on the server, so I went and installed the gem. Little did I realize that in those few days Yehuda and Carl had updated the gemspec to a new version for bundler, moving from 0.8.x to 0.9.1. When you install the 0.9.x version it asks you to remove any pre-0.9 installations of bundler. If you have an existing Bundler installation and want to upgrade, delete the old install before you install the new. Otherwise, your gem command will be broken. A lot of my headaches would have been alleviated had I just done that.

I found a few blog posts and gists that have bundler specific tasks for cap recipes, so I forked and modified them for your benefit. In order to get the magic of bundler for your app, use the following in your cap recipe:

# ...

namespace :bundler do
  task :create_symlink, :roles => :app do
    shared_dir = File.join(shared_path, 'bundle')
    release_dir = File.join(current_release, '.bundle')
    run("mkdir -p #{shared_dir} && ln -s #{shared_dir} #{release_dir}")
  end

  task :bundle_new_release, :roles => :app do
    bundler.create_symlink
    run "cd #{release_path} && bundle install --without test"
  end

  task :lock, :roles => :app do
    run "cd #{current_release} && bundle lock;"
  end

  task :unlock, :roles => :app do
    run "cd #{current_release} && bundle unlock;"
  end
end

# HOOKS
after "deploy:update_code" do
  bundler.bundle_new_release
  # ...
end

Two points to notice:

  1. We setup a hook to run after the deploy:update_code task which will run the bundle install command to get any bundle updates. Bundler 0.9.1 comes with a nifty feature where you can lock your gem versions so that any calls to bundle install won’t actually update anything.
  2. We’re also symlinking the .bundle directory that bundler creates for us into the shared folder. This is just a nicety so that bundler doesn’t have to recreate that directory and it’s environment.rb file everytime you release your code.

I hope this helps anyone out there who has upgraded their bundler versions. Happy bundling with capistrano. :)

12 Nov 2009

Are You a Problem Solver or a Tool?

I’m at a point in my career as a Software Developer where I feel like things are opening up quite a bit for me. I’m not talking about getting a new job or something, I just mean that I think I’m finally understanding Software Development for what it is. I’ve been writing software since the beginning of 2003, so I guess I’m a little late coming to the game in this understanding? Oh well, it’s not the destination, it’s the journey, right? Right.

The Journey

My journey began as a craftsman. I got lucky because I learned how to program from a friend I worked with who was just helping me in his little spare time at work. My knowledge of PHP scripting started out super small, but I took rather well to it and essentially launched into a career when I had no idea I wanted one.

Through the following months and years I gained an incredible amount of knowledge by simply working with really bright people. It just seemed that each new job I got I came in contact with someone who helped me in a different way than before:

  1. From Nathan, I learned the very basics of programming: control flow, variables, functions, mysql, etc.
  2. From Rainer I learned a ton about OO programming and CSS-based designs, as well as semantic markup that validates and conforms to standards. He also taught me to love the complex Join Query, and love it I do.
  3. Ben showed me a new way to use objects I hadn’t really seen before (closer to framework programming), and also got me a job at a great little startup where we were given a great opportunity to run the show. At that company, I gained absolutely invaluable experience managing, developing, and deploying large applications. We even got the chance to write our own web framework, which was a huge learning experience.
  4. Ryan showed me what it takes to really get things done. He’s also a fine purveyor of knives and guns (which, admittedly has nothing to do with this post at all, it’s just cool).
  5. From Eric and Kevin I gained the opportunity to take all my knowledge and apply it with a different toolset. I also learned a lot more about enterprise-level systems.

All of these people and experiences has made me the developer I am today. I believe that whatever the road you take, eventually you come to be a developer who solves problems, which is really what software development is all about.

The Destination

So what is the relationship between solving problems and the programming languages or frameworks we use to do so? It’s quite simple:

Languages are tools, and we use tools to solve problems.

Much the same way a carpenter uses a hammer to put in a nail and a screwdriver to put in a screw, developers should choose their tools based on the problem at hand, not based on programming ideology. Just because you know Java considerably well doesn’t mean that Java should be used in all situations, like website scraping. Ruby or Perl would be much better suited to handle the retrieval and parsing of webpages, due to the better Regular Expression integration.

Scraping websites is just one example of a trillion different scenarios. I’ve run into this quite a bit lately, where a developer choose a language or framework due to ideology, and it’s been driving me crazy. Use the right tool for the job, and move on with it. My career and more importantly my abilities are not defined by the tools I use, but by my ability to solve the problem. Just as a carpenter is not defined in skill by whether he uses Dewalt or Craftsman, but by the experience he’s had building staircases or handcrafting beautiful pieces of furniture.

So, as a rule of thumb, write this down:

Your usefulness is defined by your experiences and ability to solve problems, not necessarily by the tools you use along the way.

This will always make you better when you apply this knowledge. Pick the right tool for the job, and ignore the detractors who say that Java is better than Ruby because it has compile-time checking and IDE support.

What good are tools then?

I’m glad you asked. Tools are simply meant to increase productivity and ease manual labor. Simple machines like the lever and pulley were undoubtedly created to alleviate the difficulties of certain types of manual labor, like raising heavy objects up to a higher plane. In other words, some caveman decided to solve a problem in a more convenient way: push the rock up the hill rather than try to heave it up a cliff.

In a similar vein, programming languages and frameworks are created to solve specific problems, which in turn makes them great tools for getting things done. There are thousands of languages out there to use, each of them created to solve a specific need that the creator couldn’t solve effectively with other tools. They found the need, so they created the tool, and now we all can use the tool to solve the given problem again and again.

So please don’t confuse yourself into thinking that the tools you use are what makes you great. The tools you use today will be outdated in five years or less, guaranteed. Your ability to solve problems with the proper tool is what makes you great.

19 Oct 2009

Fighting the Cubicle Uprising

Mind you, that’s cubicle, not cubical, just so we’re all clear.

Technically speaking, the cubicle uprising occurred probably somewhere in the late 70’s (don’t check my sources on that though). I’m not talking about when cubicle’s gained souls and thrust their way from poverty into national prominence, that technically hasn’t happened yet.

I’m talking about the time when Corporate America was born and decided that it was cheaper to put people in boxes to cloud their thinking and judgement. So it’s probably a futile attempt to overthrow the archetypal mind-prison for everybody. That’s why I’m just fighting my own fight. You can come too, if you want.

I can see the violence inherent in the system! Can’t you?

Today at work we had a discussion about how many more programmers we could fit into the programmers office. Our office is a 25’x20’ rectangle. We currently have 5 programmers working in this office, but we’ve had 6 before. My thought is that we could get 2 more than our old max, pushing us to 8. Now, that means we could have 8 programmers in our room comfortably.

Oh, and none of us are in cubicles… yet. I intend to keep it that way.

Fight back you coward!

When I was hired on, we had these kind of faux-wood heavy desks with hutches. Technically we still have some of those, a few of our guys are still in them. Ben and I got snooty though and decided to buy our own from IKEA. It was the best idea, still love that we did it. The company even paid us back for them, which was even cooler.

No, the back of his desk is not an appealing view. Hence the need for diffuse lighting.

The reason I was snooty and wanted a fancy desk is two-fold: 1) I didn’t really like the big desk with the hutch and stuff, it was WAY more desk than I needed; 2) I’d like to think that the cleaner lines of the IKEA desk are simply more pleasing to my design-centric eye, so I just enjoy being at my desk that much more. And why shouldn’t I? On average we spend roughly two-thousand hours sitting at our work desk each year. Why not have it be a cool desk you like, with a glow lamp in the corner and a cool green bamboo plant growing nearby. Feng-shui baby.

Back to the story, the one I was telling before my snooty tangent, the one about the programming room. The other strategy was to get as many programmers (i.e. cubicles) into the room as we could. Scratch that, apparently they are called Work Spaces now. Bah! And a Ford Focus is an M5. You might as well sprinkle sugar on a turd and call it delicious. It ain’t adding up. Calling it one thing doesn’t make it something other than what it is. Call the pot black. It’s a cubicle: a box constructed of cheap material for managers and investors to save some coin at the expense of employees hating their environment every day. “But it only has 3 sides, it can’t be a cubicle!”, you stammer. Believe me my friend, it’s just a cubicle. The same awful open-box with closed-thinking built right in!

The programmers were luke warm to the cubicle idea, but it scared the crap out of me. I thought my cube days were over, solitary confinement in the gray dungeon a thing of the past. So I spoke up, and denounced that my days of cube-sitting were gone with the days of Tech Deck skating and “¿Gracias por llamar a Morinda, como le puedo ayudarle?”.

My assertion was enough to sway the powers-that-be, so let us pray that if/when we hire those additional code monkeys we’ll be getting them some nice IKEA desks instead of the beige-cage.

What have you stood up for today?

Update: Apparently Robert Propst, the designer of the Action Office (what the cubicle originated from), called the cubicle a “monolithic insanity”. I couldn’t agree more.