Tuesday, August 20, 2013

Minimalism, KISS, elegance

This essay is just some exploratory thought sparked by http://www.zedshaw.com/essays/master_and_expert.html. It's worthwhile reading for anyone. You should read it.

I'm guessing you probably didn't read it anyway, so here's the summary: Masters of any subject know how to use the minimum amount of resources to accomplish goals. Experts like to build complexity where it doesn't exist to show off their prowess at handling their created complexity. For every time someone makes some computer function ridiculously simple, there are 10 companies putting buttons and knobs and whistles and levers onto something as basic as email.

What do I have to add? Well, the first things that come to mind are how this idea can be used in practice: When looking for places of employment, do the coworkers add complexity or remove it in their day-to-day activities? Do you find people engaged in discussions about arcane lingo that was internally invented to discuss invented complexity or are the discussing the underlying problems?

People who are good examples of this that spring to mind are John Maeda and Donald Knuth.

One of the reasons I love squash is that it is such a ridiculously demanding physical sport that to play at an advanced level you must remove any wasted movement; Ceteris Paribus, anything but the minimal path around the court means you lose.

In short, I'll end this rambling with a simple reminder: For those of us in technology, always ask yourself: "Am I making my users' life easier by removing complexity or more difficult by adding complexity?"

Friday, August 16, 2013

Rails Callbacks: Being a Good Neighbor

Using callbacks like before_save, after_destroy, etc. in your rails models is a very important way to ensure that the things you assume about your data are actually enforced.

If you return false, and halt the callback chain, be sure to include error messages via errors.add("..."), so the caller knows why it failed.

Class User < ActiveRecord::Base

  before_save :update_other_subsystem

  def update_other_subsystem
    success = some_other_subsystem.send("new user!")
    unless success
     errors.add("couldn't update the subsystem")
     return false

This is a pretty contrived example, but you get the idea.

Friday, July 12, 2013

Making Rubymine Play Well With Others

I use RubyMine, but my colleagues don't. This can cause lots of problems when RubyMine needs specific gems for debugger integration:

    gem 'ruby-debug-base19x'
    gem 'ruby-debug-ide'

Crucially, it's incompatible with the debugger gem, which everybody else needsHere's how I got it working:

1) Don't require the 'debugger' gem if rubymine is present:

In your gemfile:
# rubymine needs some specific gemfiles that conflict with debugger. Rubymine puts an .idea folder
# in the git root, so that's how we detect its presence
is_rubymine_present = Pathname.new("#{File.absolute_path(File.dirname(__FILE__))}/.idea").exist?
# include the debugger gem, but don't require it if rubymine is present. This will load the gem,
# so we don't get Gemfile.lock changes, but it won't be require'd and rubymine will function.
gem 'debugger', (is_rubymine_present ? { :require => false } : {})

2) Let RubyMine install debug gems it needs outside bundler
If you try to debug your server (Run -> Debug...), RubyMine will prompt you to install some gems. Click Ok.  This installs the gems via gem install, which doesn't modify your Gemfile and screw up your teammates bundles.

3) Don't put ruby-debug-ide, ruby-debug-base19x, or any other gem that rubymine needs into your Gemfile.
If you do, you'll break debugging for everyone who doesn't use rubymine.

This reminds me why I often get frustrated with Configuration Driven Development: You're not building stuff, you're just googling around and twisting arcane nobs on someone else's work until your rube-goldberg machine finally works.

Friday, March 22, 2013

Some good recruiting guidelines

   1. Tell me about the 3 biggest things you must accomplish.
   2. Tell me why you must accomplish them.
   3. Tell me when you must accomplish them by.
   4. Tell me how you intend to accomplish them.
   5. Tell me what you're already doing to accomplish them.
   6. Tell me the role you envision me playing in accomplishing them.
   7. Tell me what you expect from me.
   8. Put me with some of the key people already working on them.
   9. Tell me what you'll do when things change or go wrong.
  10. Take me to coffee.

Courtesy edw519

These apply better to larger companies, of course, as early-stage startups tend to have quite a bit more unknowns.

Friday, December 16, 2011

Work Smart. Seldomly Work Hard.

I know many, many people out here in Silicon Valley who, despite being extremely bright in some areas, are ignorant when it comes to being productive. Young, single males with ambition are incredibly likely to pull long hours that hurt them in the long run. 

The basic rule of thumb is that If you are pulling >40 hour weeks for more than a couple of months you're being less productive. "Not me", you say, " I was the smartest kid in my class and I have incredible mental endurance!"

Nope, everybody makes bad decisions after working long hours for a few months. For all the coders out there, think about it like this: How many genious decisions have you made at 3am after working for 15 hours? Now think about how many egregious hacks you wrote at 3am to get something out the door. Compare the two.

Software Analogies

Nearly all software is buggy, but anyone who's ever written a modicum of software is not in the least bit surprised by this. The layman does not share this understanding, to put it mildly. Since the process of programming, debugging, and shipping is not a readily understandable topic if you've never thought about logical implications to the 4th or 5th degree, one needs a good analogy. Here's mine:

Imagine most everyone has a robot in their home that takes blueprints for any object (a toy, a piano, a house, etc.), can build said object really quickly, but can't make any intuitive decisions. That is, the robot follows the designs on the blueprint exactly, for better or worse.

Most of the time objects come out of the robot just fine, but what if whoever wrote the blueprints didn't think about how his toy design would work when covered in baby slobber? What if the house the robot built was designed for 3 people but 7 people are trying to live in it? What if the blueprints for the desk the robot built didn't account for handicapped people?

Writing software is tantamount to making blueprints for builder robots that people end up making in their own home. When you're writing the blueprints you don't really know how people are going to use your stuff. You might not properly get the Feng Shui right in your house blueprints and people across the country using your blueprints get depressed. You never intend all of this stuff.

The blueprints are the code. The builder robot is your personal computer. The door that doesn't quite close is a bug.

Keep it Simple.

A useful truth about programming is that it always takes more effort to debug a piece of code than it does to write it. If, at first pass, you make a piece of code as clever as possible then you're not smart enough to fix it.

Most people hear that insight and think "I'm fine, I can still debug my code", but that's only the first piece of the puzzle. Unless you are actively trying to make work for yourself and others, write all code as simply as possible. If you ever do something clever, ask yourself if it is truly necessary. Odds are it isn't and you're just making more work to be finished later.