DevHouseBoston

This past Sunday, I had the pleasure of attending DevHouseBoston.

So what's that you might ask. The way I like describing it is that it's pretty close to a LAN party, except with hacking on cool projects instead of online gaming.

Held near Central Square in Cambridge, MA, people started filtering in around 10am. At 10:20 or so, there were 20-30 people gathered, and a brief introduction was given, and everyone went around the room to introduce themselves and mention a project they would want to work on.

My project was to build a webapp to help you catalog the sights, sounds, etc, etc. My main use case was that I moved recently, and wanted a good way of getting an idea of what type of stuff is right around me as far as resturants, bars, etc go. Certainly, there is yelp, and Google Maps' search, but neither really gave you a good view of exactly how much stuff was in an area (they usually limit the view to 10 or so per page).

As it turned out, two other attendees were interested in hacking on this.

Given that I've been into rails a lot lately, and rails is pretty good for getting something going pretty quickly, it was the obvious choice. And with the awesomeness of Google Maps API, that was a pretty obvious choice.

After a bit of research, I found two plugins which helped us out quite a bit. The first was ym4r_gm. We used this to be able to programatically construct a map in Ruby, and used the helpers in the view to render it.

For example, we had a method that looked like

def build_map
  @map = GMap.new("map_div")
  @map.control_init(:large_map => true,:map_type => true)

  @map.center_zoom_init [@origin[0], @origin[1]], 12

  @markers.each do |marker|
    @map.overlay_init marker
  end
end

In the head, we do:

<%= GMap.header %>
<%= @map.to_html if @map %>

This takes care of adding the appropriate CSS magic, and script includes, and spits out the javascript that actually does the constructing of the map. We are then free to add the map div, and things just work.

The second plugin was geokit. This provides acts_as_mappable, which adds a lot of magic to your model to let you be able to search for objects within a certain distance of an origin. For example:

  @spots = Spot.find :all, :origin => @origin, :conditions => "distance < #{params[:distance]}";

It also provides a facade for using the various geocoders that are available, such as Google, Yahoo, and Geocoder.us.

So, by making use of these, we were able to getting a somewhat functioning prototype working by the end of the day.

We had collected data on a few chains restaurants/eateries (since the data is so easy to grok) that spread across Boston. In the webapp, you select Boston, and it shows all the Spots that we had in the system. You can set a center of the map, and choose how large a radius to search for, and a name search. As I type this, it sounds pretty trivial, but let me assure you, it did take quite a bit of effort to get going :)

One thing we needed was some way of sharing our work through the day. I had seen some projects being hosted by Google Code, so after a few minutes of poking around, I had setup a new project for us, where2go. It sounds like my fellow collaborators are interested to continue hacking at this, so with luck, we will eventually launch something cool and exciting.

All in all, it was a great time, and many thanks to all the organizers and attendees. I am definitely looking forward to the next DevHouseBoston, whenever it may be.

Permalink Edit Destroy

NFJS: Summary and thoughts on the New England Software Symposium

Today marked the concussion of No Fluff, Just Stuff for the Boston Fall 2007 event. To put it simply: it was a truly amazing experience.

If you aren't familiar with NFJS, it was started just over six years ago by Jay Zimmerman out in Denver, Colorado. After many discussions with members of the Boulder Java User's Group, it was decided that there weren't any local conferences that focused on Java and agility, and that were strictly technical. Shortly thereafter, NFJS was born with a three-day symposium format. It was decided to cap the attendance at 250 in order to keep a high level of interaction between speakers and attendees. Each day has five concurrent tracks with a total of eleven 90 minute sessions with top-notch speakers from around the country.

I had the opportunity to speak briefly with Jay, and one thing I had asked was if much had changed over the past years. Apparently it had not. The particular format of the symposium works amazing well, with the small number of attendees, great speakers, and a high level of interactivity. Changing any of these would detract from what makes it so good, and would violate the original intent in which the event was started. Sure venues change, more schwagg is introduced, and technology continues to plow ahead, but at the heart, it's really the same as it has ever been, and that's a good thing.

The Sessions

There were a lot of great talks this year. Here is a list of sessions I had the opportunity to hit up:

  • Friday
    • JavaServer Faces: A Whirlwind Tour by David Geary
    • OSGi: A Well Kept Secret by Venkat Subramaniam
    • 10 Ways to Improve Your Code by Neal Ford
    • Keynote: No, I Won't Tell You Which Web Framework to Use, or The Truth (with Jokes)
  • Saturday
    • Productive Programmer: Acceleration, Focus, and Indirection by Neal Ford
    • Productive Programmer: Automation and Canonicality by Neal Ford
    • The Busy Java Developer's Guide to ClassLoaders by Ted Neward
    • Leveraging Annotations with AOP by Ramnivas Laddad
    • Birds of a Feather: Dynamic Languages with Neal Ford
  • Sunday
    • Software Development Risk Analysis Techniques by Mark Johnson
    • Adding Behavior to Java Annotations by John Heintz
    • Experts Panel with all speakers present
    • REST: The Basics and Not So Basic... by John Heintz
    • Refactoring Ant Builds with Ivy, Groovy, and Good Old Fashion Common Sense by Andrew Glover

If I can find public copies of any of these presentations, I'll update this list with links.

Some future posts...

I found a few of the talks to be particularly fascinating, so I hope to follow up with several posts:

  • Productive Programmer
  • ClassLoaders
  • Annotations + AOP + Behavior
  • A summary of tips, resources, etc from everything

If you don't see something about these in the next week or so, feel free to hassle me a little :)

Pseudo random thoughts, observations, and feelings

  • Things were pretty swagtastic this year
    • A pleather binder that zips close, came in extremely useful
    • A nice backpack, but I won't likely use it...
    • A CD with all the presentations
  • The venue was the Framingham Sheraton
    • Great food
    • Great service and staff
    • Maybe a little overzealous on the AC in a few rooms
  • Being around smart and passionate people definitely rubs off
  • Definitely feeling
  • Each day felt much longer than it was, in a good way
    • Amazing amount of new material
    • Constantly experiencing paradigm shifts
  • All the speakers I spoke with were very approachable
  • A lot of people didn't seem quite as engaged, as much as I was at least
    • Sitting leaning back during talks
    • Not taking notes
    • Not asking questions, or talking to the speaker afterwards
    • Not engaging in conversation with other attendees between sessions or at meals
  • Survey says...
    • Most people are on Java 1.5 now
    • Most of the people still on Java 1.4 are there because of WebSphere
    • WebSphere sucks
    • A majority of people are doing automated testing
    • More people are doing continuous integration
    • More people are using not struts, including JSF, Tapestry, and Spring MVC
    • Most people are pretty psyched about Groovy, JRuby, and Grails
    • Overwhelming majority of people are using Eclipse
    • Most of the speakers are now Mac users
    • Most of the speakers are using IntelliJ IDEA

Advice for potential attendees

The most significant piece of advice I can give is this: be engaged. You have an amazing opportunity to interact with experts in the fields. You are surrounded by feels geeks and hackers who take time off to go to these kinds of things. Talk to them! Take notes! Absorb!

Wrap it up, B

I really can enumerate enough how awesome of an experience it was. I'm feeling pretty pumped up to get back to development to put this new knowledge to use. If NFJS is coming to a city near you, take the plunge; you won't regret it.

Permalink Edit Destroy

Snowocalypse Boston 12-13-2007

If you're in the northeast, I'm sure you're aware that it's snowing just a bit, some places more than others. Boston is getting hit pretty hard right now. Most offices and schools should have closed early by now.

Rush hour was happening at around 2PM, with the accumulating snow further complicating things. I'm fortunate enough to commute on the T, or optionally, to walk. Given the snow, I figured it'd be a nice day to give walking a try :-D

I took photos along the way with my iPhone, so if you've always wondered what it's like walking around Boston in the snow, here's your chance!

Check out the flickr set here.

Some random thoughts/observations from the trek:

  • I immediately regret not bringing gloves today.
  • Only a few other people were crazy enough to walk across the Longfellow bridge in this weather.
  • I don't envy people with stuck in traffic in the snow.
    • You can see a turquoise sedan in several shots. I'm pretty sure I was pacing it most of the ways, except I was stopping to take pictures
  • The iPhone interface isn't particularly fond of the cold, or wet snow
    • At times, I had to try a few times to unlock it. Not sure if this was my hands freezing, the iPhone freezing or being wet.
    • At times, I had to try a few times to take pictures. It would acknowledge I pressed the button, but wouldn't actually take it.

I don't know about anyone else, but I think it's time I get me some eggnog!

Permalink Edit Destroy

Boston.rb Hackfest 4/15 Post Mortem

Last Tuesday, we had a small, but dedicated showing at the Hackfest:

Going in, we didn't really have a something in mind to work.

We thought to pick up the app we started in merb for organizing katas. But when it came down to it, we figured it'd be a lot quicker if we just did it rails.

We actually wanted something a little more general, kind of a one stop shop for Boston Ruby stuff. Here's what we wanted:

  • Keep track of events (meetings, hackfests, and katas)
  • Projects that have come out of above-mentioned meetings
  • Recent commits from these projects

Tools we used:

You can see the code we ended up with in the hackfest repository.

Or, you can see it in action.

For simplicity's sake, we didn't initially bother with users/permissions/etc, so be gentle with it.

Permalink Edit Destroy

Boston.rb Hackfest 4/29 Post Mortem

So, we were just kidding about working on the recommendable plugin. We actually worked on the bostonrb.org website some more.

The crew tonight was:

The significant things we worked on were:

  • Projects have descriptions now
  • Events now have a location
  • Reorganized events page
    • left side has all upcoming events
    • center has next event with google map
    • right side has nothing now, but we're thinking to put a calendar type view

Some articles, resources, that came up while hacking away:

The fruits of our labor have been pushed to http://bostonrb.org, and the source can be found at https://svn.thoughtbot.com/hackfest/boston_rb.

Permalink Edit Destroy

Boston.rb Hackfest 5/07 Post Mortem

By now, I think it's a running joke that we'd work on the recommendable plugin we started a month or so ago.

Instead, we worked on the Factory stuff. This article captures most of the ideas of using factories for testing and reasons for using them instead of fixtures.

The crew tonight:

Overview

As the article mentions, someone did implement a plugin which captures most of these ideas.

There were a few reasons (and some more which I don't remember) why we didn't like this plugin.

  • Plugin, not a gem, so unusable outside of rails
  • Pollutes the namespace of Object
  • No tests

So, the journey for better Factories begins. The basic ideas/goals we settled on is this:

  • Define your factories in test/test_helper.rb
  • Be able to define a factory for a class with default options
  • Be able to define alternate factories for a class, for example, to create an admin user versus a normal user
  • Flexibility for defining default attributes, ie be able to call other methods
  • Choice of making new instance, persisting a new instance, stubbing an instance, or getting valid attributes
  • Flexible API for actually calling the factories

The API

So we started out with a basic API that Dan Croak had outlined:

Factory.define do |factory|
  factory.add :project do |project|
    project.name {"factoryfu"}
    project.homepage_url {"http://factoryfu.rubyforge.org"}
  end

  factory.add :event, :meeting do |event|
    event.event_type {"Meeting"}
    event.date {Time.now}
    event.description {"an sick meeting"}
  end

  factory.add :event, :hackfest do |event|
    event.event_type {"Hackfest"}
    event.date {Time.now}
    event.description {"a cool hackfest"}
  end
end

As for usage of the factories, we had 3 possibilities:

Factory.create :project, :name => 'ambitious_sphinx'
Factory.create_project :name => 'ambitious_sphinx'
create_project :name => 'ambitious_sphinx'

I'm not going to say much about these, aside from the first being the simplest to implement, the second being the most explicit about what you are doing, and the last is the most concise.

Because it seemed like the simplest, we started implementing the first. I believe that the other two syntaxes can actually be emulated using it.

To simulate the second, as we register factories, we can create the appropriate methods, ie create_event, new_event, valid_event_attributes.

To simulate the third, we can build on the second, and probably do some magic to delegate from TestCase to our Factory.

Implementing it

For simplicity's sake, we started with our work from last week's hackfest on bostonrb.org.

We added the snippet for defining factories into our test_helper.rb, made a new model unit test which used the factory methods, and started a Factory class.

We basically ran the test, watched it blow up horribly, and added some code, until eventually the test passed.

You can see the work we ended up in the hackfest repository under 'boston_rb'

Of particular interest are:

So, I'm just go over a few of the more interesting bits of the implementation:

Factory.define

This is the entrance into defining our factories.

The implementation isn't very interesting. We just call the block on Factory. We were originally making new instances of Factory, and passing that to the block, but we then realized that this made it a little trickier to have factory methods be class-level methods.

Factory.add

This is what you use to define how you the factory behaves.

It takes a block which defines how to create new attributes. If you look at the snippet:

event.event_type {"Hackfest"}
event.date {Time.now}

Notice that event.event_type and event.date are actually taking blocks. This allows us to do Time.now, and have this not actually be invoked until object creation.

Factory.add actually passes your block a magical Hash which captures this attribute/attribute creation data. We'll talk about this has in a little bit.

After we get back from the block, we store in @@model_templates, keyed by the model and kind of the factory.

The Factory methods

We provide three factory methods:

  • valid_attributes: a Hash of valid attributes for the object
  • new: a new unpersisted instance, using valid_attributes
  • create: a persisted instance, using new

You invoke them like:

Factory.valid_attributes :project
Factory.new :project, :name => 'factoryfu', :homepage_url => 'http://somewhere.com'
Factory.create :event, :hackfest, :date => 3.days.ago, :description => 'your looking at it'

The way we parse the arguments is a little tricky. Initially, we only supported the first 2 lines. This meant our method signature looked like:

def self.new(model, attributes = {})

When we went to support the 3rd line, we thought to go like:

def self.new(model, kind = 'default', attributes = {})

By doing so, you break the 2nd line, because kind would get set to our attributes.

activesupport provides a solution: Array#extract_options. Basically, it looks at the Array, and pops the last element off the end if it's a Hash. We use it like:

def self.valid_attributes(model, *args)
  kind, attributes = parse_args(*args)
  # ...
end

protected

def self.parse_args(*args)
  attributes = args.extract_options!
  kind = args.first || 'default'
  [kind, attributes]
end

BlockfulHash

We made a subclass of Hash which lets you define keys like:

event.date {Time.now}
event.description {"This is going to be SICK!"}

Such that it's equivalent to:

event[:date] = {Time.now}
event[:description] = {"This is going to be SICK!"}

Here's the implementation:

class BlockfulHash < Hash
  def method_missing(method, *args)    
    # When Proc.new is given no arguments,
    # it returns a Proc for the block passed to the current method
    # Proc.new... yeah, it's officially a hackfest.
    self[method.to_sym] = Proc.new
  end
end

This BlockfulHash is what gets passed to the block given to Factory.add.

What's next

So, we have something workable here:

  • Uses the syntax we laid out for defining factory
  • Supports the first syntax for using factories (Factory.create :event)

As far as what is left to do:

  • Extract it out of the boston_rb code base
  • More tests
  • Gemify
  • Support Factory.create_event syntax
  • ...
  • PROFIT!!!

Addendum

Some links and other ideas tossed around over the course of the night:

Permalink Edit Destroy