Posts

Showing posts from 2008

Sprinkle Some Integration Tests into a Mock Heavy Test Suite

I like mocks and stubs and I use them liberally in my tests. This practice, however, is not without danger: If my models, views, and controllers are all tested in isolation then how will I know if a model change busts a controller or a view? Here's something I like to drop in at the end of every controller spec:


1
2
3
4
5
6
7
8
9
10
11
12

describe JerkStoreController, "with views integrated and real objects"do
integrate_views

it "should render the page without blowing up"do
store = JerkStore.create!(:name => "Costanza's house of bargins")
store.products << Jerk.create!(:name => "Puddy") <<
Jerk.create!(:name => "Newman") <<
Jerk.create!(:name => "Steinbrenner")

post :show, :id => store.id
end
end
Not a mock or a stub as far as the eye can see and I'm even integrating views. Normally RSpec doesn't render the view in a controller spec, but if you include "integrate_views&quo…

Rails Rumble, Apprenticeship, and a Running Website

Image
Apprenticeship is a big part of Obtiva (the consultancy where I work) so I introduced my friend Leah to Obtiva, they hit it off, and now she's an apprentice in the studio. Now apprenticeship at Obtiva is a paid, billable position. She's pairing everyday on a medium sized Rails business skill development project and learning a lot, but what just blew me away was the development of the "Run. Track. Run." project.

Leah is a runner and for years she's been talking about how she'd like to create a decent running website that could import Gamin GPS data and produce useful graphs for runners. Apparently all the sites out there plot every single point of data returned from the GPS device, with little-to-no smoothing, and so the graphs are extremely noisy and hard to read. Wouldn't it be great if an actual marathon runner designed a website for runners? At which point I would usually say: "Yeah, that's a great idea -- we should do that someday."…

If you use Mocha and RSpec then read this

I like RSpec, but I'm not a huge fan of it's built in mocking framework. So, when I have the choice, I swap it out for Mocha. However, I really miss mock_model. If you haven't used it, mock_model is an RSpec method where you pass in an ActiveRecord object and it stubs out a whole bunch AR magic so you don't have to. This is crazy useful when testing controllers because when you controller has a line like this:
redirect_to(@model)

I don't want to dig through a ton of Rails code to figure out what I need to stub on this model, I just want it to work. But I just found out that Mislav Marohnić has written a plugin that implements mock_model for Mocha -- so now I can get the best of both worlds. You can find it here:
http://github.com/mislav/rspec-rails-mocha

Thanks Mislav.

Naked Hashes are Trouble

So I had this form in a Rails view that needed some changes so, amongst other things, I changed this:
form_tag(:action => 'search')

to this:
form_tag(:action => 'show', :method => :get)

I had noticed that the show and search methods essentially did the same thing (and had the same views) -- which I why I refactored. However, when I made the change I got a 500. I was using restful routes and this form needed to be a get -- which I thought I had indicated. But I had not -- what should have put in the view was this:

form_tag({:action => 'show'}, {:method => :get})

There's this idiom in Ruby where we don't put curly braces around hashes if we don't need to, but I've consistently lost a bunch of time to mistakes like the one above. So I'm thinking about explicitly denoting hashes with curly braces in my future Ruby code just to improve intentionality.

Photos from Ruby Conf 2008

Image
The Omni Resort was beautiful -- this was our view during lunch:







I liked the Hotel but everything was very expensive. Breakfast buffet? 20 bucks. Awesome (really good bacon) but still 20 bucks. Dinner? 40-50 bucks. Cab ride there from the airport? 80 bucks.

There was a tanning bed convention being held right next door. They got a security guard in front of their door while we did not.


The next 2 pics are of the lazy river. I did a couple of laps (assisted by the current) and it was very nice.




A fountain and one of the many pools.


During the Matz Q&A my friend and fellow ObtivanAndy Maleh got up and asked some questions.

Ruby Conf 2008 Last Day

A wonderful, awful idea: ruby in the browser (and oh by the way it actually works!) by Christopher Nelson

Chris thinks that while Javascript is an excellent programming language, he likes choices so why not provide people with the option to run Ruby in the browser? Also, while programming rich web apps he found that oftentimes he ended up with business objects in Javascript and in duplicate objects in Ruby. Not very DRY. He wanted to be able to use his Ruby logic server-side and in the browser.

Two ideas that didn't work out:
JRuby - the java security manager stopped him from doing just about anything
Silverlight wasn't available for his operating system when he started the project

Rubyjs is what he ended up using. Rubyjs is a ruby compiler that uses ParseTree to produce javascript.
http://github.com/superchris/rubyjs

The translation is, of course, not without some changes:
Strings become Immutable strings
Procs become Functions
Hashes becomes custom hash object


Chris then showed us …

Ruby Conf 2008 Second Afternoon/Evening

What Every Rubyist Should Know About Threads by Jim Weirich

Concurrency is becoming bigger as computers get more cores. If you look at a graph of clock speed they flattened out in 2003.
Past performance gains:
clock speed (not so much anymore) execution optimize cache results
So if clock speed is not going up at a rapid pace anymore, now what?:
hyperthreading multicore (the new saviour) caching
Applications will need to be concurrent to exploit multicore machines. 100 CPU machines are on the horizon. Race conditions are trouble:

If thread one has this:
shared_variable += 1

And thread two wants to do the same thing:
shared_variable += 1

What if the first thread looks up the shared_variable and find that it's 25 but before it can change it the second thread reads the value (still 25 because it hasn't changed). Now the first thread will add one (shared_variable becomes 26) and write the result back to memory, then the second thread will add one to the stale number (25…

Ruby Conf 2008 Second Morning

Aristotle and the art of software development by Jonathan Dahl

How do you identify a good programmer? Jon says Ethics. Ethics is about how you live your entire life. He thinks the what makes a good software developer and what makes a good person have parallels in their answers.

Kant -- Only act on principles that you would like to become universal law. Kant would have loved Haskel.

There are principles in software, but sometimes they conflict such as DRY vs write understandable code. DRYing something up can make it hard to read.

John Stuart Mill
Utilitarianism -- what matters is the effect of the action. The ends justify the means. However, It's hard to know whether the effects will be good ahead of time. The Pragmatic Programmer is a good outcome of Utilitarianism. But Utilitarianism may lead to sloppy code and processes. Or the Cowboy coder.

Aristotle - ethics as virtue. The person is the important part. For Aristotle:
ethics == a life well lived == happiness == virtue

each …

Ruby Conf 2008 First Evening

Better Hacking With Training Wheels by Joe Martinez

"We all have a stake in each other" -- we use each other's code in many, many libraries.

What automatically checks the quality of our code? Joe wants to encode rules in a standard way (called wheels) so that you could drop it into Training Wheels and it would enforce your rules on the code. People who write new libraries could include a wheels directory in their library which would offer suggestions.

Interesting idea -- on my current project we've be having problems with people calling destroy_all on an ActiveRecord class for no good reason. We could define a rule that shoots out a warning every time you do that.

http://github.com/capitalist/training-wheels


NeverBlock, trivial non-blocking IO for Ruby by W. Idris Yasser

"Neverblock enables concurrent DB and network access without thew need to change the program flow" Which is awesome.

Idris said that the Evented model is good but you must adjust your code whi…

Ruby Conf 2008 First Afternoon

Image
I was thinking today that most people design their talk to last 50-55 minutes but I've noticed that conferences have shorter and shorter times slots. 40 minutes + 5 for questions is becoming the standard. So the end slides tend to go by pretty fast.

Another thought: Print the ID badge for the conference on both sides. Exactly the same information on both sides. Fully 50% of the people at Ruby Conf have their badges turned around to the white side and when I can't remember their names (even though we were just introduced) I can't cheat because all I see is a stupid white rectangle. Somehow GLSEC managed to figure this out, why can't other conferences?


JRuby: What, Why, How...Try It Now by Tom Enebo and Charlie Nutter

Why JRuby? Well the JVM is awesome. 15 quadriliion man years of work or something. 15 quadriliion Sun man years can't be wrong, right?

They have declared that Ruby 1.8 is "done" (again) and 1.9 mode can be triggered with a flag. Full 1.9…

Ruby Conf 2008 First Morning

Woke up 15 seconds before my alarm went off again today. Perhaps I'm a little keyed up?

Keynote - Matz "Reasons behind Ruby"

Matz's presentation started out with the question: Why Ruby? He asked why even though Ruby has lots of problems, like all languages, why do we love it? Which is interesting. I've seen Matz talk a few time now and he always talks about the love of languages. The idea of loving what you do is never far from his mind. When Matz was young, his first computer was a pocket computer in 1980 -- only 1400 steps allowed. Only 150 memory places. And the Language was BASIC.

Later he found Lisp and it was the opposite of everything in Basic -- total freedom to do just about anything. And he loved it. That was, however, before he started using Lisp. When he started using Lisp in practice, he wasn't having a good time.

Basically Matz felt that Basic took all the power from him, but Lisp gave too much back. He wanted to have a framework to gui…

Great Lakes Software Excellence Conference

What a nice conference! Emphasis on nice. First Joel Adams, chair of Computer science at Calvin College, got up and welcomed us. Calvin College is where GLSEC was held and it looks so shiny and new I wondered if it had just been constructed. I stayed in a room the was about 200 feet from where I gave my talk.

Then the mayor of Grand Rapids, George Heartwell, gave us software dudes a nice little welcome speech. He implored us to see downtown Grand Rapids and then talked a lot about jobs and growth. I know Michigan has had hard times, but from the looks of the airport and Calvin College (which is about as scientific a survey as it gets) Grand Rapids must be a city on the grooooow.

The opening Keynote was given by Michael Cloran who is the the CEO of Interactions.

He started off with a live demo of the "Service Factory." He spoke, through his phone, to a computer and it parsed his voice and answered his questions. It was scary impressive. Typical line from the extended dia…

Here I am in Grand Rapids, MI

Flew in on election night for the Great Lakes Software Excellence Conference. I'll be giving my metrics talk tomorrow and then I'm off to Orlando, FL to give that talk at Ruby Conf. GLSEC is more of an XP/Agile/Process conference and I'm excited to be attending. The last time I was at a similar conference was XP/AU (Extreme Programming/Agile Universe) in 2004 when I was an apprentice at Object Mentor. I was just about to go back to my job as a high school physics teacher, but I did have an application in at ThoughtWorks. Ah, memories.

Metric Fu's Churn Now Supports Git

I just released version 0.8.0 of MetricFu. New in this release:
Source Control Churn now supports Git (thanks to Erik St Martin)Flog Results are sorted by highest Flog ScoreFix for a bunch of 'already initialized constant' warnings that metric_fu causedThe flog reporter can now handle methods with digits in their name (thanks to Andy Gregorowicz)Internal Rake task now allows metric_fu to flog/churn itselfTo use the Churn task to find files that change a lot with Git, put this in your Rakefile:
MetricFu::CHURN_OPTIONS = {:scm => :git}MetricFu is a Ruby Gem that gives you a fist full of code metrics. Find out more at the home page.

Subversion Binary Image Conflict Solution

Today it was my turn to merge in some bug fixes and updates into the current branch. And we had a conflict on an image file. What to do? Well, if you want to keep the incoming change then use 'svn resolved' or if you like the old one then 'svn revert' Yep, I totally knew that and didn't spend an hour looking around the internet only to find a solution that only applied to svn 1.5 which doesn't work with svn 1.4

Merging sure is fun.

Nail the Small Stuff

I was talking to a friend of mine the other day and he mentioned that his wife had been turned down for some dentistry that she needed performed. It turned out he had been paying for family dental coverage but his company had only signed him up for single. Once the mistake was realized, his company corrected the error. He might have to re-fill out some forms, and her surgery will be delayed, but all will be put right.

I mean it was a simple mistake, how could he possibly hold it against them?

You can spend lots of dollars on big gestures, perks, and what-not but it can all be wiped away by a bit of faltering on the basics. People need to know that the ground beneath their feet is solid -- That they can trust the people who employee them to take care of certain details. When that trust is shaken they start asking themselves questions about other things.

It reminds me of Maslow's hierarchy of needs:

Maslow's hierarchy of needs is often depicted as a pyramid consisting of five l…

Sunday Nights

I used to be a High School physics teacher and so people often ask me why I left teaching and to become a programmer. You'll get a different answer from me every day you ask that question, but today's answer is Sunday nights.

When you find yourself picking fights with your wife, kicking the cat, and generally needing a few drinks every Sunday night it's because you know there's a week of pain coming. This pain may or may not materialize but there's a fair percentage that it will. Once, when I was a teacher, I had a 6'3'' football player in my class who would sometimes take to getting up and screaming at me. One time, after an altercation about talking in class had turned into a huge blow up, he pushed past me on his way out of the room. Now getting knocked aside by someone who could probably kill me in a fight wasn't a daily occurrence in teaching, but that's not the point. The point is that after that day it was always a possibility in my …

Different Ways of Installing Metric Fu

Something I didn't mention when I announced the re-launch of metric_fu as a gem is that now, because it's a gem, you have more options when installing it in your project.

First option:
Vendor Everything. Lots of people are big fans of unpacking gems into the vendor directory of their Rails project (or a similar folder in a non-Rails project) so that everyone who checks out the code gets the right version of the gem. You can then require it in your Rakefile like this:
require 'vendor/gems/jscruggs-metric_fu-0.7.6/lib/metric_fu'
However...

Second option:
Conditionally require the gem. When I announced metric_fu back in April, a lot of commentors bemoaned the fact that they would have to install something into their production code that wasn't really necessary for production. I don't really mind doing this as metric_fu does not modify any classes: It's mostly just a bunch of Rake tasks (and some report building code). However, I see their point. So if you don…

Stop your Mac from going to Sleep with Caffeine

I recently discovered Caffeine for the Mac and it's pretty cool. When I'm giving presentations, listening to streaming audio, or performing some operation where I don't want my mac laptop going to sleep I could mess with the system preferences... Or I could click on a friendly little coffee cup to tell my computer to stay awake. When the coffee cup is full, my computer won't go to sleep or activate the screen saver. Empty coffee cup means my normal preferences are in control. Nice!

Many thanks to Todd Webb, for pointing this out to me.

Windy City Rails Part Two

Yesterday, I talked about the first half of the first ever Windy City Rails conference that happened on Saturday at IIT. Tonight, I'll pick up where I left off with my summary of the presentations I attended.


Virtualization and Elastic Servers -- Yan Pritzker of CohesiveFT

The gist of this talk is that the Rails stack is not well known so why not let CohesiveFT handle deployment for you. It's a virtualization factory, that lets you put together a custom Rails stack and they can deploy and maintain it for you for as little as 10-15 bucks a month. Also, he pointed out that virtualization is a solution for your front end guys getting a working version. Which, having tried to get many a design person's computer up and running, I think is a pretty cool idea.


Ten Things I Hate About Web Apps by Micah Martin

Short list of things Micah hates about Web Apps:
You need to know css, html, js, and the actual programing language just to get started.Html -- only 3 fonts to chose fromCss i…

Windy City Rails Part One

This weekend was the first ever Windy City Rails Conference and I was lucky enough to not only attend but also to speak. I thought I'd sum up the talks I attended in case anyone was interested.

After Ray Hightower, lead organizer of the conference, welcomed everyone Ryan Platte gave the first talk of the day: "Outside the sweet spot"

Ryan's talk was about getting Ruby and or Rails into a large organization which is committed to things like: Windows, Oracle, etc. I.E. not the typical Rails stack.

In Ryan's experience, Rails makes it's way into such an organization the following way: Some guy picks up a Rails book and says "Hey, this is way better than the excel spreadsheet we've been using." Then he talks one boss into the project, and maybe they hire some consultants to help. However the rest of the organization has issues with Rails (it's slow, not compatible with their stack).

Ryan's advice is:
Do top quality work quickly -- get out…

Metric Fu is Now a Gem

Image
I just released version 0.7.6 of metric_fu and there's all sorts of new stuff:

First, MetricFu is now a Ruby gem on GitHub at:
http://github.com/jscruggs/metric_fu

Also, the Flog task can now flog any set of directories you like. Just put this into your Rakefile:

MetricFu::DIRECTORIES_TO_FLOG = ['cms/app', 'cms/lib']

And, the Flog reports are much nicer:


The Flog report generator now looks at a MD5 hash of the files its examining to determine if they files need to be re-Flogged -- which saves time.

The Saikuro report generator can also look at custom directories like so:

MetricFu::SAIKURO_OPTIONS = {"--input_directory" => '"cms/app | cms/lib"'}


MetricFu started its life as a Rails Plugin, but I'm trying to turn it into a flexible gem that can be used in any Ruby application (but still have defaults that enable easy use in a Rails project). Eventually I'd like to create something that could tell you about methods that have high compl…

Lone Star Ruby Conf Second Day (morning edition)

While checking out at the hotel I ran into Coby from confreaks.com They are recording the conference so you'll be able to see the talks online sometime soon. They're not cheap, but their videos are very good (they capture the output of the presenters computer and display it side by side with video of the presentation -- you seriously need to check out their site), and they offer a discount if the conference is willing to CreativeCommons license the talks.

Starting off the morning was "Ruby: A Year of Innovation" with Gregg Pollack & Jason Seifer. They had a lot to cover so it went pretty fast. I tried to keep up as best I could.

Jason Seifer was up first:
HPricot - awesome for scraping websitesJuggernaut - server push with rails -- keeps a connection openAmbition - write your SQL statements in RubyPrawn - Ruby based PDF generationCapistrano Ruby VMsroo - spreadsheets Excel, google docsDtrace and Ruby -- memory stack liveSkynet - map reduce for RubyData Fabric - …

Lone Star Ruby Conf First Day

(or the second day if you count the tutorials)

To start things off Jim Freeze got up and announced that there are 282 attendees and seats for 280 -- So make friends. The the first talk of the day was "The Next Ruby" by Bruce Williams and he (of course) discussed the difference between Ruby 1.8.6 and 1.9

Bruce recommended a good test suite if you're planning to move to 1.9 and I have to agree. Tests are good for lots of reasons (including design) but they pay for themselves 100 times over when you need to do a big tech migration.

Because of changes to string, anything string heavy (such as parsers) is gonna need some love. On the plus side:
"ruby"[0] => 114 in Ruby 1.8.6
"ruby"[0] => "r" in Ruby 1.9
Yep, I've been burned by that and I'm glad to see sanity carry the day.

In other news:
Hash.select now returns a hashHashes will maintain order:this === "this" #true Because of Multinationalization Strings now have each_chr or …

Training Day at Lone Star Ruby Conf

First, I'd to extend a big thanks to Joe and Jim for giving me a ride to the conference today.

The two tutorials I decided to attend today were:
"The Advanced ActiveRecord Workshop" with Gregg Pollack & Jason Seifer (the Rails Envy Guys) and "The Ins and Outs of Ruby I/O" with James Edward Gray II and Gregory Brown. Both of which were excellent.

The Advanced ActiveRecord Workshop covered:
Loading large data sets (the 'ar-extensions' gem helps lots).A gentle reminder to properly index your freakin' database.How Rails optimizes multiple :includes in finds and how that goes to hell if you combine lots of :includes with :conditionsThe super awesome Named Scopes (which you need to look up right now, if you haven't already because it's not just about defining custom finders -- it's about defining custom finders that you can chain together and get optimized queries)Polymorphic Associations, Single Table Inheritance, Dirty Fields, Association P…

I'll be Presenting at Windy City Rails

If you're going to be in the Chicago area on or about Saturday, September 20th, you can see me give my "Using Metrics to take a Hard Look at Your Code" talk at the Windy City Rails Conference. David Heinemeier Hansson, David Chelimsky, and Noel Rappin have been announced as speakers and I'll be joining them for a interesting day of Rails related goodness.

Here's the abstract:

It's an interesting fact of human nature that you can't do something every day and not secretly suspect that you're good at it. Which goes a long way toward explaining why everyone thinks they write fine code. To combat this self-delusion you can use metrics to take a hard look at your application. This talk will discuss the ways in which you can measure how good your Rails project really is. And how to fix the bad parts.

Using a daily metrics build (run every day by CruiseControl.rb) you can compile a 'hit-list' of the worst methods in your application. Then your team can …

I'm Thinking of Putting View Logic into a Model

As I am clearly crazy, but hear me out. Say there's a Car object that uses single table inheritance and all the objects that descended from it are routed through the car method in the CarController. The CarController looks like this:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

classCarController < ApplicationController
defcar
layout = nil
@scripts = []
@stylesheets = []
@car = Car.find(params[:id])
if@car.is_a?(Toyota)
layout = 'two_column'
@stylesheets << 'two_column_layout.css'
@stylesheets << 'two_column_theme.css'
elsif@car.is_a?(Hyundai)
layout = 'three_column'
@stylesheets << 'three_column_layout.css'
@stylesheets << 'three_column_theme.css'
@stylesheets << 'hyundai_theme.css'
@scripts << 'discount.js'
elsif@car.is_a?(Ford)
layout = 'ford'
@stylesheets << 'ford_layout.css'
@stylesheets << 'ford_theme.css'
@scripts <<…