How do you objectively measure the progress of a software engineering team from iteration to iteration when they are so many variables (human and otherwise)?
Continue reading ...
Heisenberg’s Key Performance Indicators
Boxed primitives and ==
One part of programming culture at OPOWER is to program defensively, providing useful information when contracts are violated. What does this have to do with boxed primitives? Getting an assertion message of “Person 1001’s customer id 109032 didn’t match the passed-in customer’s id of 109032″ seemed logically impossible, but was somehow true.
But first, let’s talk about defensive coding and how we do it. For example:
/**
* frobs the bar and baz.
* @param bar the bar to frob; may not be null
* @param baz the baz to from; must be positive
*/
public String frob(String bar, int baz) {
if (bar.length() > baz) {
return bar.substring(baz);
}
else {
return bar;
}
}
The Standing Desk
Dave, My OPOWER colleague switched from a normal office desk & chair situation to a standing desk more than a year ago and ever since, I’d been considering doing the sa
me. For my entire programming career, I’ve had terrible posture in my chair and tended to do “the maxell pose” where my wrists are resting at a severe angle on the lip of my desk.
There have been a couple articles recently about the effects of sitting in a chair all day that pushed me to action. This article from business week was particularly eye opening.
OPOWER is super cool about empowering developers to be more productive/comfortable/happy/etc so getting approval for expensing some generic Ikea furniture…
Continue reading ...
Cinco de Failure
If you’ve ever seen Yoni or Jeff K, you would know that I have absolutely no chance of competing in a facial-hair competition with them on raw natural talent. Thus, for the 2010 Cinco de Mustache event, I felt compelled to compete on ingenuity and engineering.
To the disgust of myself and my wife, I collected shavings for approximately 4 months in a plastic cream cheese jar labeled “Not Cream Cheese.”
This last weekend, I took a trip to AC Moore Arts & Crafts and bought some clay. I fashioned a mold into that clay of a mustache that would dominate all other mustaches.
Into that mold, I poured elmer’s glue, hair shavings, 14 gauge electrical copper wiring, more hair, more glue, more hair…
Continue reading ...
Dave’s Talk at ScalaDays 2010
OPOWER graciously sent me to Switzerland this year for ScalaDays 2010. I was lucky enough to be asked to present on “Sneaking Scala into the Enterprise”. OPOWER sponsored the videography. My talk, on starting to use Scala in your organization (based on my experience at OPOWER), is linked below; all the talks are online here.
Alfresco 3.3 Lunch & Learn
OPOWER attended the Reston, VA “Alfresco 3.3 lunch & learn” seminar this week, hosted by the generous folks over at SiteWorx. Alfresco 3.3 looks support the CMIS 1.0 spec and head further into the ECM space.
Continue reading ...
Tie Tuesday – more fun that it sounds
The developers have an informal “Tie Tuesday” each work. It’s exactly what it sounds like. And, since you asked, yes, it is more fun to wear a tie when you don’t have to. Not everyone does it every week, but this week, we had the best participation yet:
Riley Dawg participates in tie tuesday
Locking screens on Macs with the keyboard
Desktop security is a big issue when you have access to massive amounts of data. As far as plain old terminal security, locking your computer while you’re away is a pretty basic rule.
We have lots of OSes around the office here – Ubuntu, Windows, and OSX. Of those, Ubuntu and Windows natively provide a way to lock your desktop with a keystroke (Win+L or Ctrl+Alt+Del, Enter on Windows and Ctrl+Alt+L on Ubuntu). Strangely, Mac gives no easy way to lock your desktop.
We’ve been using HotCorners for the screen saver, but who wants to touch the mouse if you don’t have to (especially when you’re racing to grab a free lunch)?
Enter Quicksilver, everyone’s favorite application interface. (There are all sorts of things you can…
Continue reading ...
When adding more threads makes it all slower
I’ve been working on a new feature that requires analysis of each individual’s entire energy-use history. In other words, I have a process that will touch every single bit of data in our database. This should be a rare thing, so if it takes a while, it’s not that big of a deal. My initial implementation was on track to complete in…11 days.
My first thought was: there’s lots of blocking reading and writing from the database, so adding some threads should speed things up. While one thread was analyzing Bob’s energy data, another could be fetching Mary’s, while another could be updating Joe’s meta-data with the results. Or so I thought.
The more threads I added, the slower the entire thing became. It turned out that the
Maven-izing Google’s Data Client Java Library
OPOWER’s first Innovation Day was a lot of fun. I was waiting about 30 minutes for my primary project (building an AWS machine image for our hudson slave) to complete and I got sucked in to a different project involving automatically downloading google analytics for all the traffic on all the websites we host for our clients.
Clicking around google’s well-documented “get started” guides, it looked like they haven’t made their client JARs available in any MVN repos anywhere. There is a (not-google-sponsored) source forge project that points to a sonatype repo, but instead of adding another 3rd party repo to our small but growing list, I figured it’d be easier for small proof of concept purposes to just manually install the google JARs in OPOWER’s repo (thereby making them accessible to all our developer’s boxes).
It quickly became clear that the number of JARs google ships with makes it faster and less error prone to script the mvn repo installation than doing manual command line copy & pasting. Lo, my gift to the world:
#!/usr/bin/perl -w my @jars = `ls *.jar`; chomp(@jars); foreach my $jar (@jars) { if($jar =~ /(.*)-(\d\.\d)\.jar/) { my $cmd = "./install.pl --artifactId $1 --version $2 --jar $jar"; open(CMD, "$cmd|") or die "Could not execute $cmd $!"; while(<CMD>) { print $_; } close(CMD); } }#!/usr/bin/perl -w use strict; use warnings; use Getopt::Long; sub usage(); my $artifactId; my $version; my $jar; GetOptions('artifactId=s' => \$artifactId , 'version=s' => \$version, 'jar' => \$jar); die usage() unless ($artifactId && $version && $jar); my $cmd = "mvn deploy:deploy-file " . "-DgroupId=com.google.gdata " . "-DartifactId=$artifactId " . "-Dversion=$version " . "-Dfile=$jar " . "-Dpackaging=jar " . "-DgeneratePom=true " . "-Durl=file:///opt/mvn_repo " . <--- change this for your env "-Drepository=opower_local"; <--- change this for your env print "executing command = $cmd\n"; $cmd = "date"; open(CMD, "$cmd|") or die "Could not exec $cmd $!"; while(<CMD>) { print $_; } close(CMD); sub usage() { print "Usage: ./install.pl [--artifactId artifactId] [--version version] [--jar jarfile]\n"; print "Example: ./install.pl --artifactId gdata-webmastertools --version 1.0 --jar gdata-webmastertools-1.0.jar\n"; exit 1; }That assumes the “mvn” executable was in your path and that you run the scripts from within the same directory as all the JARs, but it’s easily modified for whatever your situation may be.
Note that relative to ./lib there are 2 jars in ../deps/ that you should also install in your repo because the google JARs to avoid ClassNotFoundExceptions in some runtime code paths.
Once in, you should be able to boot strap a mvn client project against a Google Data source with a pom not too dissimilar from:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>foo</artifactId> <packaging>jar</packaging> <version>1.0.0-SNAPSHOT</version> <name>Google Client Example</name> <scm> <developerConnection>foo</developerConnection> </scm> <dependencies> <dependency> <groupId>com.google.gdata</groupId> <artifactId>gdata-core</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>com.google.gdata</groupId> <artifactId>gdata-analytics</artifactId> <version>2.1</version> </dependency> <dependency> <groupId>com.google.gdata</groupId> <artifactId>gdata-client</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>com.google</groupId> <artifactId>google-collect</artifactId> <version>1.0-rc1</version> </dependency> </dependencies> </project>