Jester
House of garybernhardt

garybernhardt's hand

The top 100 gists by star count
A
types.markdown974
# This document has moved!

Itclass="_tkStr_1klyn_166">'s now [here](https:class="_tkCom_1klyn_170">//www.destroyallsoftware.com/compendium/types/baf6b67369843fa2), in The Programmer's Compendium.
The content is the same as before, but being part of the compendium means that it's actively maintained.
A
K
gistfile1.md86
# Things that programmers don't know but should

(A book that I might eventually write!)

Gary Bernhardt

I imagine each of these chapters being about class="_tkNum_1klyn_175">2,class="_tkNum_1klyn_175">000 words, making the whole book about the size of a small novel.
For comparison, articles in large papers like the New York Times average about class="_tkNum_1klyn_175">1,class="_tkNum_1klyn_175">200 words.
Each topic gets whatever level of detail I can fit into that space.
For simple topics, that's a lot of space: I can probably walk through a very basic, but working, implementation of the IP protocol.
More subtle topics will get less detail: for RSA, maybe I'd (class="_tkNum_1klyn_175">1) give a rough sketch of the number theory, (class="_tkNum_1klyn_175">2) show that we can treat arbitrarily large byte arrays as numbers, and (class="_tkNum_1klyn_175">3) say class="_tkStr_1klyn_166">"combine them in the obvious way".
K
Q
gistfile1.txt78
(Chapters marked with * are already written. This gets reorganized constantly
and class="_tkNum_1klyn_175">10 or so written chapters that Iclass="_tkStr_1klyn_166">'m on the fence about aren't listed.)

Programmer Epistemology
class=class="_tkStr_1klyn_166">"_tkCom_1klyn_170">  * Dispersed Cost vs. Reduced Cost
class=class="_tkStr_1klyn_166">"_tkCom_1klyn_170">  * Verificationist Fallacy
class=class="_tkStr_1klyn_166">"_tkCom_1klyn_170">  * Mistake Metastasis
  The Overton Window
  Epicycles All The Way Down
  The Hyperspace Gates Were Just There
Software Design
class=class="_tkStr_1klyn_166">"_tkCom_1klyn_170">  * Structured Design: Understanding Graphs
Q
J
selectable_queue.rb24

A queue that you can pass to IO.select.

# A queue that you can pass to IO.select.
#
# NOT THREAD SAFE: Only one thread should write; only one thread should read.
#
# Purpose:
#   Allow easy integration of data-producing threads into event loops.  The
#   queue will be readable from select's perspective as long as there are
#   objects in the queue.
#
# Implementation:
#   The queue maintains a pipe. The pipe contains a number of bytes equal to
#   the queue size.
J
10
gistfile1.sh18
# Has your OS/FS/disk lost your data?

# cd to the directory containing your project repositories and run the command
# below. (It's long; make sure you get it all.) It finds all of your git repos
# and runs paranoid fscks in them to check their integrity.

(set -e && find . -type d -and -iname class="_tkStr_1klyn_166">'.git' | while read p; do (cd class="_tkStr_1klyn_166">"$(dirname "$pclass="_tkStr_1klyn_166">")" && (set -x && git fsck --full --strict)); done) && echo class="_tkStr_1klyn_166">"OK"

# I have class="_tkNum_1klyn_175">81 git repos in my ~/proj directory and had no errors.

# You might get messages about dangling commits, dangling blobs, etc. Those
# aren't errors. If it prints class="_tkStr_1klyn_166">"OK" at the end, your repos are all valid.
10
9
1-description.txt17
This tool is used to compare microbenchmarks across two versions of code. It's
paranoid about nulling out timing error, so the numbers should be meaningful.
It runs the benchmarks many times, scaling the iterations up if the benchmark
is extremely short, and it nulls out its own timing overhead while doing so. It
reports results graphically with a text interface in the terminal.

You first run it with --record, which generates a JSON dotfile with runtimes
for each of your benchmarks. Then you change the code and run again with
--compare, which re-runs and generates comparison plots between your recorded
and current times. In the example output, I did a --record on the master
branch, then switched to my scoring_redesign and did a --compare. In my output,
three of the benchmarks' runtimes look to be unchanged; the other three got
9
8
inline.rb11
#!/usr/bin/env ruby

require class="_tkStr_1klyn_166">'base64'
require class="_tkStr_1klyn_166">'nokogiri'
require class="_tkStr_1klyn_166">'uri'

def main
  html = Nokogiri::HTML($stdin.read)
  inline_all_images(html)
  inline_all_css(html)
  $stdout.write(html.to_s)
end
8
7
build.rb10
require class="_tkStr_1klyn_166">"erb"
require class="_tkStr_1klyn_166">"pathname"

DOT_TEMPLATE=<<-END
digraph {
size=class="_tkStr_1klyn_166">"class="_tkNum_1klyn_175">20,class="_tkNum_1klyn_175">20";
overlap=false;
sep=class="_tkNum_1klyn_175">0.4;
graph [fontname=Helvetica,fontsize=class="_tkNum_1klyn_175">10];
node [fontname=Helvetica,fontsize=class="_tkNum_1klyn_175">10];
edge [fontname=Helvetica,fontsize=class="_tkNum_1klyn_175">10];
rankdir=TB;
7
6
rebuild9
#!/usr/bin/env bash

set -e

if [ -e static ]; then
    rm -r static
fi
mkdir -p static
sass src/sass/main.scss > static/application.css
$(npm bin)/browserify src/js/main.js > static/application.js
cp -r src/html/* static
6
5
gistfile1.rb8
# Goal: put a non-Rails-aware Ruby library using normal class="_tkStr_1klyn_166">`require`s in
# lib/sim. Have it transparently reloaded between requests like Rails app
# code is.
#
# The code here goes inside of your configure block in
# config/environments/development.rb. There are two parts, commented inline.

# Reload code whenever the simulator changes.
config.watchable_dirs[class="_tkStr_1klyn_166">"lib/sim"] = [:rb]
config.watchable_files << class="_tkStr_1klyn_166">"lib/sim.rb"

# Manually unload and reload the simulator before every request. This assumes
5
4
gistfile1.txt8
Turning The Design Clock Back

Object-oriented design principles haven't had the effect we hoped for. The
SOLID principles are excellent design guidelines, but experience shows that
programmers find them difficult to follow. What do we do about this?
Surprisingly, the Structured Design literature of forty years ago contains
compelling solutions to many current design problems. They're simple and easy
to understand, but were lost in the noise as OO rose to popularity. We'll
reinterpret these simple design ideas in a modern context, finding that many of
our most promising new design ideas resemble them. Rapid web application
development, the area of professional programming in most dire need of design
improvements, will serve as an example.
4
3
gistfile1.rb7
# I don't really see any services here. What I see is:
#   - Normal HTTP boundary stuff (params flash, redirect).
#   - Model creation and retrieval.
#   - Warden manipulation, which is an odd done but smells like boundary.
#
# I left all of the HTTP boundary stuff in the controller (and only the
# controller). I moved the model creation/retrieval into simple class methods
# in the models. I moved the warden manipulation stuff into
# ApplicationController (with caveats that I'll discuss inline).
#
# Commentary on each class follows:
3
2
cron.rake5
task :cron => :environment do
  DatabaseBackup.back_up_to_s3!
end
2
A
gistfile1.sh5
find $(manpath | tr class="_tkStr_1klyn_166">':' class="_tkStr_1klyn_166">'\n') -iname class="_tkStr_1klyn_166">'*.class="_tkNum_1klyn_175">1' | xargs cat | (LC_CTYPE=C tr -C class="_tkStr_1klyn_166">'[:alnum:]-_' class="_tkStr_1klyn_166">'\n') | egrep class="_tkStr_1klyn_166">'^--[\-_[:alnum:]]+$' | sort | uniq -c | sort -n
A
K
wrap.rb3

Probably a really bad implementation of word wrapping

class Wrap
  def self.wrap(s, max_length)
    raise ArgumentError.new(class="_tkStr_1klyn_166">"Maximum wrap length can't be class="_tkNum_1klyn_175">0") if max_length == class="_tkNum_1klyn_175">0
    return [class="_tkStr_1klyn_166">""] if s.rstrip.empty?

    # Split into words and whitespace blocks
    blocks = s.split /(\s+|\S+)\b/

    lines = []
    line = class="_tkStr_1klyn_166">""

    until blocks.empty?
K
Q
gistfile1.c3

An excerpt from GCC's reload.c

static int
find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
		      enum reload_type type, int opnum, int dont_share)
{
  rtx in = *p_in;
  int i;
  /* We can't merge two reloads if the output of either one is
     earlyclobbered.  */

  if (earlyclobber_operand_p (out))
    return n_reloads;
Q
J
gistfile1.diff3
diff --git a/app/views/devise/shared/_links.erb b/app/views/devise/shared/_links.erb
dissimilarity index class="_tkNum_1klyn_175">99%
index 414904b..0b0b21d class="_tkNum_1klyn_175">100644
--- a/app/views/devise/shared/_links.erb
+++ b/app/views/devise/shared/_links.erb
@@ -class="_tkNum_1klyn_175">1,class="_tkNum_1klyn_175">19 +class="_tkNum_1klyn_175">1,class="_tkNum_1klyn_175">15 @@
-<%- if controller_name != class="_tkStr_1klyn_166">'sessions' %>
-  <%= link_to class="_tkStr_1klyn_166">"Sign in", new_session_path(resource_name) %><br />
-<% end -%>
-
-<%- if devise_mapping.registerable? && controller_name != class="_tkStr_1klyn_166">'registrations' %>
-  <%= link_to class="_tkStr_1klyn_166">"Sign up", new_registration_path(resource_name) %><br />
J
10
1-shell-session.sh3
find ~/Downloads/Gmail -type f | grep -v class="_tkStr_1klyn_166">'\.git' | ruby -rdate -e class="_tkStr_1klyn_166">'today = Date.today; STDIN.each { |path| content = File.read(path.strip); begin; from = content.grep(/^From:/).fetch(class="_tkNum_1klyn_175">0); date = content.grep(/^Date:/).fetch(class="_tkNum_1klyn_175">0); puts from if Date.parse(date) > today - class="_tkNum_1klyn_175">365; rescue IndexError; end }' | while read line; do echo class="_tkStr_1klyn_166">"$line" | ~/.mutt/add-aliases.sh; done
10
9
run-tests.sh3
#!/usr/bin/env bash

main() {
    if [ ! -p .test-commands ]; then
        mkfifo .test-commands
    fi

    while true; do
        cmd=$(cat .test-commands)
        if [[ $cmd == class="_tkStr_1klyn_166">"" ]]; then
            continue
        else
9
8
gistfile1.txt2
set conf_name to text returned of ¬
	(display dialog ¬
		class="_tkStr_1klyn_166">"Enter conference name:" with title ¬
		class="_tkStr_1klyn_166">"Schedule Conference" default answer ¬
		class="_tkStr_1klyn_166">"" default button class="_tkNum_1klyn_175">2)

tell application class="_tkStr_1klyn_166">"OmniFocus"
	tell default document
		set newProject to make new project with properties {name:conf_name}
		
		tell project conf_name
			make new task with properties {name:class="_tkStr_1klyn_166">"Schedule " & conf_name & class="_tkStr_1klyn_166">" in calendar"}
8
7
gistfile1.sh2
(set -e && ls content/*.markdown | while read p; do DATE=$(echo $p | cut -d class="_tkStr_1klyn_166">'/' -f class="_tkNum_1klyn_175">2 | cut -d class="_tkStr_1klyn_166">'-' -f class="_tkNum_1klyn_175">1-class="_tkNum_1klyn_175">3); TARGET=$(echo $p | sed class="_tkStr_1klyn_166">'s/-/\class="_tkCom_1klyn_170">//' | sed class="_tkStr_1klyn_166">'s/-/\//' | sed -E class="_tkStr_1klyn_166">'s/[class="_tkNum_1klyn_175">0-class="_tkNum_1klyn_175">9]+-//' | perl -pe class="_tkStr_1klyn_166">'s/^(.*\/.*\/.*\/)(.)(.*)$/\class="_tkNum_1klyn_175">1\u\class="_tkNum_1klyn_175">2\class="_tkNum_1klyn_175">3/' | sed -E class="_tkStr_1klyn_166">'s/-|_/ /g'); echo $TARGET; mkdir -p $(dirname $TARGET); echo class="_tkStr_1klyn_166">"<\!-- $DATE -->" > $TARGET; cat $p >> $TARGET; rm $p; done)
7
6
gistfile1.txt1

using the git reflog

# I have a repo with two commits
failbowl:temp(master) grb$ git shortlog
Gary Bernhardt (class="_tkNum_1klyn_175">2):
      commit class="_tkNum_1klyn_175">1
      commit class="_tkNum_1klyn_175">2

# I destroy the second commit
failbowl:temp(master) grb$ git reset --hard HEAD^
HEAD is now at 7454aa7 commit class="_tkNum_1klyn_175">1


# It's gone
6
5
gistfile1.lua1
x = function()
    y = function()
        local table = class="_tkNum_1klyn_175">5
    end
    local old_table = table
    y()
    assert(table == old_table and table ~= class="_tkNum_1klyn_175">5)
end
x()
5
4
gistfile1.txt1
#!/bin/bash

set -e

if [ $# -gt class="_tkNum_1klyn_175">0 ]; then # we have args
    filename=$class="_tkNum_1klyn_175">1
    (set +e; grep -r class="_tkStr_1klyn_166">'spec_helper' $filename) > /dev/null
    if [ $? -eq class="_tkNum_1klyn_175">1 ]; then # no match; we have a stand-alone spec
        standalone_spec=class="_tkNum_1klyn_175">1
    fi
else # we have no args
    filename=class="_tkStr_1klyn_166">'spec'
4
3
gistfile1.txt1
It's a subscription-based screencast site, where I post a new five- to
ten-minute screencast every week. For this, people pay a nominal fee
around $class="_tkNum_1klyn_175">3 per month, giving them access to the full archives and new
screencasts as they happen. The style would be similar to the
screencasts I've posted on my blog: just me and the computer, recorded
in one take, although with much practicing. I'd focus not on new
languages and tools, but on the minute-to-minute mechanics of
effective programming practices, with an obvious bias toward the stack
and practices that I use.
3
2
gistfile1.txt1
Date: Thu, class="_tkNum_1klyn_175">3 Oct class="_tkNum_1klyn_175">2013 class="_tkNum_1klyn_175">17:class="_tkNum_1klyn_175">16:class="_tkNum_1klyn_175">51 -class="_tkNum_1klyn_175">0700
From: Gary Bernhardt <gary.bernhardt@gmail.com>
To: info@wdsearch.com
Subject: Mailing practices

I suspect that you guys know this, but just in case: your emailing
practices have been resulting in... less than good impressions among the
people you aim to recruit. Here are some tweets, none of which were
written by me:

Ugh, Nicholas Meyler. Scummiest Scumbag Recruiter ever.
- https:class=class="_tkStr_1klyn_166">"_tkCom_1klyn_170">//twitter.com/ryanbigg/status/class="_tkNum_1klyn_175">385918215559184384
2
A
inbox_diff.sh1
inbox_blobs() {
  git ls-tree -r master | grep class="_tkStr_1klyn_166">'INBOX' | awk class="_tkStr_1klyn_166">'{print $class="_tkNum_1klyn_175">3}' | sort
}

diff <(cd ../Gmail && inbox_blobs) <(inbox_blobs) | grep class="_tkStr_1klyn_166">'<\|>' | while read marker hash; do
  echo class="_tkStr_1klyn_166">"$marker $(git show $hash | grep -m class="_tkNum_1klyn_175">1 '^Subject:')"
done | sort
A
K
gistfile1.txt1
bench class="_tkStr_1klyn_166">"paths", :without_gc => true, :gc_time => true do
  PATHS[class="_tkNum_1klyn_175">0, class="_tkNum_1klyn_175">1000].each { |choice| Score.score(choice, class="_tkStr_1klyn_166">"x" * class="_tkNum_1klyn_175">16) }
end

Output:

...!.!.!.!..............................................
filtering paths
  Before: |                       --X-----------------------                     |
  After:  |                                   ---------X-------------------------|
          class="_tkNum_1klyn_175">0                                                                   class="_tkNum_1klyn_175">14.1
K
Q
gistfile1.txt1
failbowl:selecta(scoring_redesign) $ ruby ../readygo/readygo.rb --compare benchmark.rb
.!.!.!.!.!.!.!.!..!.!.!.!.!.!.!.!.!.!...!.!.!.!.!.!.!.!.............................................................................................................

filtering non-matching
  Baseline: |                                                      X-----------|
  Current:  |                                X---------                        |
            class="_tkNum_1klyn_175">0                                                           class="_tkNum_1klyn_175">6.848 ms

filtering matching exactly
  Baseline: |                                              X-------------------|
  Current:  | X                                                                |
            class="_tkNum_1klyn_175">0                                                          class="_tkNum_1klyn_175">68.219 ms
Q
J
gistfile1.rb1
module RenderToHTML
  def self.book
    [title, css, body].join(class="_tkStr_1klyn_166">"\n")
  end

  private

  def self.title
    commit_hash = class="_tkStr_1klyn_166">`git log -class="_tkNum_1klyn_175">1 --pretty="format:%H"`
    %{
      <div class=class="_tkStr_1klyn_166">"title">
        <h1>#{TITLE}</h1>
J
10
gistfile1.ml1
open Parser;;
open Stringutil;;

type t = String of string | List of t list

let rec of_module m =
  List (String class="_tkStr_1klyn_166">"module" :: of_definitions m)

and of_definitions ds =
  List.map of_definition ds

and of_definition (FuncDef func_def) =
10
9
test.rb1
# This is a stripped-down example based on Selecta's TTY handling. We store the
# TTY state in class="_tkStr_1klyn_166">`tty_state`, then go into an infinite loop. When the loop is
# terminated by a ^C, we try to restore the TTY state. It's important that this
# work, but it doesnclass="_tkStr_1klyn_166">'t in some subtle situations, and I don't know why.
#
# Save this file as test.rb and run it via this command, where class="_tkStr_1klyn_166">`stty` should
# successfully restore the TTY state:
#   bash -c class="_tkStr_1klyn_166">'echo | ruby test.rb'
#
# Next, run it via this command, where class="_tkStr_1klyn_166">`stty` should fail to restore the TTY
# state:
#   bash -c class="_tkStr_1klyn_166">'echo $(echo | ruby test.rb)'
9
8
twitter_lib.rb1
module TwitterLib
  def self.authenticate
    libs = [Twitter, TweetStream]
    libs.each do |lib|
      lib.configure do |config|
        config.consumer_key = ENV.fetch(class="_tkStr_1klyn_166">"TWITTER_CONSUMER_KEY")
        config.consumer_secret = ENV.fetch(class="_tkStr_1klyn_166">"TWITTER_CONSUMER_SECRET")
        config.oauth_token = ENV.fetch(class="_tkStr_1klyn_166">"TWITTER_OAUTH_TOKEN")
        config.oauth_token_secret = ENV.fetch(class="_tkStr_1klyn_166">"TWITTER_OAUTH_SECRET")
      end
    end
  end
8
7
test.rb1
#!/usr/bin/env ruby

# This script tests par2 recovery when the par2 files themselves are corrupted.
# Process:
#   class="_tkNum_1klyn_175">1. Generate a file containing all class="_tkNum_1klyn_175">256 possible bytes.
#      (More would be better, but it gets slow fast.)
#   class="_tkNum_1klyn_175">2. Generate par2 data for the file.
#   class="_tkNum_1klyn_175">3. Individually corrupt each par2 file at each offset.
#      (Write byte class="_tkNum_1klyn_175">0 unless the offset already contains byte class="_tkNum_1klyn_175">0; then, write byte class="_tkNum_1klyn_175">255.)
#      (Writing each possible byte would be better, but it gets slow fast.)
#   class="_tkNum_1klyn_175">4. After each corruption, verify the par2 data, then reverse the corruption.
#   class="_tkNum_1klyn_175">5. Produce a summary of what the par2 verification commands' output, along with the frequencies of each output string.
7
6
gistfile1.txt1

Automatically fix rubocop errors, with one commit per error

rubocop | egrep class="_tkStr_1klyn_166">' (W|C): ' | cut -d class="_tkStr_1klyn_166">' ' -f class="_tkNum_1klyn_175">3 | sort -u | sed class="_tkStr_1klyn_166">'s/:$class="_tkCom_1klyn_170">//' | while read cop; do
    git checkout .
    rubocop -a --only class="_tkStr_1klyn_166">"$cop"; 
    if [[ $(git diff --stat) != class="_tkStr_1klyn_166">'' ]]; then
        git add --all
        git commit -m class="_tkStr_1klyn_166">"fix rubocop cop $cop"
    fi
done
6
5
fancy_tab_completion.vim0
" Remap the tab key to do snippets, autocompletion or indentation depending on
" the context (cobbled together by Gary Bernhardt; partly based on
" http://www.vim.org/tips/tip.php?tip_id=class="_tkNum_1klyn_175">102)
"
" Because this uses the private class="_tkStr_1klyn_166">'Jumper' function in snippetsEmu, you'll need
" to edit class="_tkStr_1klyn_166">'/.vim/plugin/snippetsEmu.vim' to make it public. To do that, just
" replace all occurrences of class="_tkStr_1klyn_166">'<SID>Jumper' with just class="_tkStr_1klyn_166">'Jumper'. There were only
" two occurrences in my copy.
" 
" The g:snippetsEmu_key variable must be defined, but not to a function key.
class="_tkStr_1klyn_166">" (I have no idea why function keys break it.) "  I recommend something on the
" leader prefix that you don't use.
5
4
gistfile1.py0
class BowlingScorer:
    def __init__(self, rolls):
        rolls = rolls[:]
        self.score = sum(self.score_frame(rolls) for _ in range(class="_tkNum_1klyn_175">10))

    def score_frame(self, rolls_left):
        roll1 = rolls_left.pop(class="_tkNum_1klyn_175">0)
        if roll1 == class="_tkNum_1klyn_175">10:
            return class="_tkNum_1klyn_175">10 + rolls_left[class="_tkNum_1klyn_175">0] + rolls_left[class="_tkNum_1klyn_175">1]

        roll2 = rolls_left.pop(class="_tkNum_1klyn_175">0)
        if roll1 + roll2 == class="_tkNum_1klyn_175">10:
4
3
gistfile1.py0
def santa(people):
    return dict(zip(people, reversed(people)))


def describe_santa():
    bob, george, judy = class="_tkStr_1klyn_166">'bob jones', class="_tkStr_1klyn_166">'george jetson', class="_tkStr_1klyn_166">'judy smith'

    def takes_lists_of_people():
        santa([bob, george])

    def pairs_people_with_eachother():
        pairs = santa([bob, george])
3
2
gistfile1.txt0
# Loop through git revisions, counting lines of Python
# code, unit test code, cucumber code, and media. The
# paths and filenames are specific to my project; if
# you want to use this, you'll have to change them.

reverse() {
  sed class="_tkStr_1klyn_166">'x;class="_tkNum_1klyn_175">1!H;$!d;x'
}
(echo class="_tkStr_1klyn_166">'rev,python code,unit test,cucumber,media' &&
git rev-list HEAD |
reverse |
while read rev; do
2
A
gistfile1.diff0
diff --git a/tests/test_entity.py b/tests/test_entity.py
index c3c4aec..8410b9d class="_tkNum_1klyn_175">100644
--- a/tests/test_entity.py
+++ b/tests/test_entity.py
@@ -class="_tkNum_1klyn_175">209,class="_tkNum_1klyn_175">6 +class="_tkNum_1klyn_175">209,class="_tkNum_1klyn_175">15 @@ class TestMatchesDict(unittest.TestCase):
             creator=[class="_tkStr_1klyn_166">'Matt', class="_tkStr_1klyn_166">'Nobody'],
             tags=[class="_tkStr_1klyn_166">'fun', class="_tkStr_1klyn_166">'boring']) == self.e
 
+    #def test_order_independence_of_query(self):
+    #    assert not self.e.matches_dict(creator=[class="_tkStr_1klyn_166">'Matt'],
+    #                                   title=[class="_tkStr_1klyn_166">'DO NOT MATCH'])
+    #    assert not self.e.matches_dict(creator=[class="_tkStr_1klyn_166">'DO NOT MATCH'],
A
K
gistfile1.htm0
The Limits of TDD
#date class="_tkNum_1klyn_175">2009-class="_tkNum_1klyn_175">11-class="_tkNum_1klyn_175">09 class="_tkNum_1klyn_175">21:class="_tkNum_1klyn_175">47
#tags python,tdd

<p>
    My <a href=class="_tkStr_1klyn_166">"/class="_tkNum_1klyn_175">2009/class="_tkNum_1klyn_175">11/how_i_started_tdd.html">last post</a> about TDD
    generated some great responses, some of which were skeptical. A few common
    complaints about TDD were brought up, and posed with civility, so I'd like
    to address them.
</p>

<h4>Complaint: You weren't stupid enough</h4>
K
Q
gistfile1.txt0
failbowl:repo grb$ cloc .
    class="_tkNum_1klyn_175">1472 text files.
    class="_tkNum_1klyn_175">1061 unique files.                                          
     class="_tkNum_1klyn_175">883 files ignored.

http:class=class="_tkStr_1klyn_166">"_tkCom_1klyn_170">//cloc.sourceforge.net v class="_tkNum_1klyn_175">1.06  T=class="_tkNum_1klyn_175">36.0 s (class="_tkNum_1klyn_175">11.3 files/s, class="_tkNum_1klyn_175">1457.1 lines/s)
--------------------------------------------------------------------------------
Language           files     blank   comment      code    scale   3rd gen. equiv
--------------------------------------------------------------------------------
HTML                 class="_tkNum_1klyn_175">196       class="_tkNum_1klyn_175">818        class="_tkNum_1klyn_175">14     class="_tkNum_1klyn_175">30174 x   class="_tkNum_1klyn_175">1.90 =       class="_tkNum_1klyn_175">57330.60
Python               class="_tkNum_1klyn_175">169      class="_tkNum_1klyn_175">4155      class="_tkNum_1klyn_175">1517     class="_tkNum_1klyn_175">13664 x   class="_tkNum_1klyn_175">4.20 =       class="_tkNum_1klyn_175">57388.80
CSS                   class="_tkNum_1klyn_175">13       class="_tkNum_1klyn_175">120         class="_tkNum_1klyn_175">8       class="_tkNum_1klyn_175">749 x   class="_tkNum_1klyn_175">1.00 =         class="_tkNum_1klyn_175">749.00
Q
J
gistfile1.py0
def live_cell_count(x, y):
    square_coords = [(x-class="_tkNum_1klyn_175">1, y-class="_tkNum_1klyn_175">1),
                     (x+class="_tkNum_1klyn_175">0, y-class="_tkNum_1klyn_175">1),
                     (x+class="_tkNum_1klyn_175">1, y-class="_tkNum_1klyn_175">1),
                     (x-class="_tkNum_1klyn_175">1, y+class="_tkNum_1klyn_175">0),
                     (x+class="_tkNum_1klyn_175">1, y+class="_tkNum_1klyn_175">0),
                     (x-class="_tkNum_1klyn_175">1, y+class="_tkNum_1klyn_175">1),
                     (x+class="_tkNum_1klyn_175">0, y+class="_tkNum_1klyn_175">1),
                     (x+class="_tkNum_1klyn_175">1, y+class="_tkNum_1klyn_175">1)]

    count = sum(class="_tkNum_1klyn_175">1 for x, y in square_coords
                if cell_alive_exists(x, y))
J
10
gistfile1.py0

How would you rather write your tests?

# How would you rather write your tests?
# Tell it to @garybernhardt (or gary.bernhardt@gmail.com)

# class="_tkNum_1klyn_175">1) Hypothetical RSpec-inspired Python library (PSpec?) that does violence to nature
with describe(class="_tkStr_1klyn_166">'my class'):
    with it(class="_tkStr_1klyn_166">'adds numbers'):
        sum = MyClass.add(class="_tkNum_1klyn_175">1, class="_tkNum_1klyn_175">1)
        sum.should == class="_tkNum_1klyn_175">2

# Actually, I think the only acceptable name for the above library would be class="_tkStr_1klyn_166">"withit"

# class="_tkNum_1klyn_175">2) Mote (minimal violence to nature) + Expecter Gadget (violence free)
10
9
gistfile1.txt0
# One extra keyword needed for an RSpec clone. Just sayin.
describe(class="_tkStr_1klyn_166">'integers') do:
    it(class="_tkStr_1klyn_166">'can be added') do:
        expect(class="_tkNum_1klyn_175">1 + class="_tkNum_1klyn_175">1) == class="_tkNum_1klyn_175">2
    it(class="_tkStr_1klyn_166">'can be subtracted') do:
        expect(class="_tkNum_1klyn_175">2 - class="_tkNum_1klyn_175">1) == class="_tkNum_1klyn_175">1
    it(class="_tkStr_1klyn_166">'truncates on division') do:
        expect(class="_tkNum_1klyn_175">3 / class="_tkNum_1klyn_175">2) == class="_tkNum_1klyn_175">1

# Implement blocks with plain old generators:
def describe(description):
    ... set stuff up
9
8
gistfile1.sh0
ls _posts/* | grep -v class="_tkStr_1klyn_166">'[class="_tkNum_1klyn_175">0-class="_tkNum_1klyn_175">9][class="_tkNum_1klyn_175">0-class="_tkNum_1klyn_175">9][class="_tkNum_1klyn_175">0-class="_tkNum_1klyn_175">9][class="_tkNum_1klyn_175">0-class="_tkNum_1klyn_175">9]-[class="_tkNum_1klyn_175">0-class="_tkNum_1klyn_175">9][class="_tkNum_1klyn_175">0-class="_tkNum_1klyn_175">9]-[class="_tkNum_1klyn_175">0-class="_tkNum_1klyn_175">9][class="_tkNum_1klyn_175">0-class="_tkNum_1klyn_175">9]' | while read fn; do day=class="_tkStr_1klyn_166">`grep '#postdate\|#date' $fn | cut -d '-' -f class="_tkNum_1klyn_175">3 | cut -d ' ' -f class="_tkNum_1klyn_175">1`; git mv $fn class="_tkStr_1klyn_166">`echo $fn | sed "s/-\([class="_tkNum_1klyn_175">0-class="_tkNum_1klyn_175">9][class="_tkNum_1klyn_175">0-class="_tkNum_1klyn_175">9]\)-/-\class="_tkNum_1klyn_175">1-$day-/"`; done
8
7
gistfile1.txt0

failbowl:temp $ rm -rf env && pip install -E env dingus && ls -l env/lib/python2.class="_tkNum_1klyn_175">6/site-packages
Creating new virtualenv environment in env
  New python executable in env/bin/python
  Installing setuptools...done.....
Downloading/unpacking dingus
  Downloading dingus-class="_tkNum_1klyn_175">0.2.tar.gz
  Running setup.py egg_info for package dingus
Installing collected packages: dingus
  Running setup.py install for dingus
    warning: build_py: byte-compiling is disabled, skipping.
    warning: install_lib: byte-compiling is disabled, skipping.
7
6
gistfile1.txt0
failbowl:temp $ rm -rf env && pip install -E env dingus && . env/bin/activate && pip update pip 
Creating new virtualenv environment in env
  New python executable in env/bin/python
  Installing setuptools...done.....
Downloading/unpacking dingus
  Downloading dingus-class="_tkNum_1klyn_175">0.2.tar.gz
  Running setup.py egg_info for package dingus
Installing collected packages: dingus
  Running setup.py install for dingus
    warning: build_py: byte-compiling is disabled, skipping.
    warning: install_lib: byte-compiling is disabled, skipping.
Successfully installed dingus
6
5
gistfile1.txt0
failbowl:temp $ deactivate; rm -rf env && pip install -E env dingus && . env/bin/activate && ls -l env/lib/python2.class="_tkNum_1klyn_175">6/site-packages                        
zsh: command not found: deactivate
Creating new virtualenv environment in env
  New python executable in env/bin/python
  Installing setuptools...done.....
    Complete output from command /Users/grb/temp/env/bin/python /Users/grb/temp/env/bin/easy_install /opt/local/Library/Frameworks/...ar.gz:
    Processing pip-class="_tkNum_1klyn_175">0.7.class="_tkNum_1klyn_175">2.tar.gz
Running pip-class="_tkNum_1klyn_175">0.7.class="_tkNum_1klyn_175">2/setup.py -q bdist_egg --dist-dir /var/folders/Vr/Vrnubf6zGE4qOl6GIOQjh++++TI/-Tmp-/easy_install-AFWiid/pip-class="_tkNum_1klyn_175">0.7.class="_tkNum_1klyn_175">2/egg-dist-tmp-72Ag6W
warning: no files found matching class="_tkStr_1klyn_166">'*.html' under directory class="_tkStr_1klyn_166">'docs'
warning: no previously-included files matching class="_tkStr_1klyn_166">'*.txt' found under directory class="_tkStr_1klyn_166">'docs/_build'
no previously-included directories found matching class="_tkStr_1klyn_166">'docs/_build/_sources'
warning: build_py: byte-compiling is disabled, skipping.
5
4
gistfile1.txt0
failbowl:temp $ pip install -U pip
Downloading/unpacking pip
  Downloading pip-class="_tkNum_1klyn_175">0.7.class="_tkNum_1klyn_175">2.tar.gz (68Kb): 68Kb downloaded
  Running setup.py egg_info for package pip
    warning: no files found matching class="_tkStr_1klyn_166">'*.html' under directory class="_tkStr_1klyn_166">'docs'
    warning: no previously-included files matching class="_tkStr_1klyn_166">'*.txt' found under directory class="_tkStr_1klyn_166">'docs/_build'
    no previously-included directories found matching class="_tkStr_1klyn_166">'docs/_build/_sources'
Installing collected packages: pip
  Found existing installation: pip class="_tkNum_1klyn_175">0.7.class="_tkNum_1klyn_175">2
    Uninstalling pip:
Exception:
Traceback (most recent call last):
4
3
gistfile1.sh0

whodoneit: Find who introduced a certain pattern to the code base

# Originally from Jonathan Penn, with modifications by Gary Bernhardt
function whodoneit() {
    (set -e &&
        for x in $(git grep -I --name-only $class="_tkNum_1klyn_175">1); do
            git blame -f -- $x | grep $class="_tkNum_1klyn_175">1;
        done
    )
}
3
2
gistfile1.txt0
# This doesn't work – it calls nil.join (the map seems to return nil?)
puts things.to_a.sort_by(&:id).map do |thing|
  class="_tkStr_1klyn_166">"#{thing.id} #{thing.url}"
end.join(class="_tkStr_1klyn_166">"\n")

# This DOES work (the only difference is that the map uses curlies instead of do/end).
puts things.to_a.sort_by(&:id).map { |thing|
  class="_tkStr_1klyn_166">"#{thing.id} #{thing.url}"
}.join(class="_tkStr_1klyn_166">"\n")
2
A
gistfile1.lua0
function wrap(f)
    return function()
        -- Storing the result of the wrapped function is the source of the
        -- problem.
        result = f()
        return result
    end
end

function f()
    return class="_tkNum_1klyn_175">1, class="_tkNum_1klyn_175">2
end
A
K
gistfile1.sh0
# Setting up the graph; you can skip to the next comment.
$ hg init
$ echo class="_tkNum_1klyn_175">0 > class="_tkNum_1klyn_175">0
$ hg ci -Am class="_tkNum_1klyn_175">0
adding class="_tkNum_1klyn_175">0
$ echo class="_tkNum_1klyn_175">1 > class="_tkNum_1klyn_175">1
$ hg ci -Am class="_tkNum_1klyn_175">1
adding class="_tkNum_1klyn_175">1
$ hg co class="_tkNum_1klyn_175">0
class="_tkNum_1klyn_175">0 files updated, class="_tkNum_1klyn_175">0 files merged, class="_tkNum_1klyn_175">1 files removed, class="_tkNum_1klyn_175">0 files unresolved
$ echo class="_tkNum_1klyn_175">2 > class="_tkNum_1klyn_175">2
$ hg ci -Am class="_tkNum_1klyn_175">2
K
Q
gistfile1.rb0
# Braintree has a cutesy search query API:
class Sweeper
  def self.sweep!
    Braintree::Subscription.search do |s|
      s.status.is Braintree::Subscription::Status::Canceled
    end
  end
end

# Putting expectations on it sucks, but less than I expected:
describe Sweeper do
  it class="_tkStr_1klyn_166">'searches for canceled subscriptions' do
Q
J
gistfile1.txt0
failbowl:destroyallsoftware.com(76m|braintree!?) $ cat Gemfile                                              
source class="_tkStr_1klyn_166">'http:class="_tkCom_1klyn_170">//rubygems.org'

gem class="_tkStr_1klyn_166">'rails', class="_tkStr_1klyn_166">'class="_tkNum_1klyn_175">3.0.class="_tkNum_1klyn_175">3'

# Bundle edge Rails instead:
# gem class="_tkStr_1klyn_166">'rails', :git => class="_tkStr_1klyn_166">'git:class="_tkCom_1klyn_170">//github.com/rails/rails.git'

gem class="_tkStr_1klyn_166">'sqlite3-ruby', :require => class="_tkStr_1klyn_166">'sqlite3'

gem class="_tkStr_1klyn_166">'braintree', class="_tkStr_1klyn_166">'class="_tkNum_1klyn_175">2.7.class="_tkNum_1klyn_175">0'
gem class="_tkStr_1klyn_166">'devise', class="_tkStr_1klyn_166">'class="_tkNum_1klyn_175">1.1.class="_tkNum_1klyn_175">5'
J
10
gistfile1.txt0
# I do this:

module ActiveRecord
  class Base
    @@old_save = instance_method(:save)

    def save *args
      @@old_save.bind(self).call *args
    end
  end
end
10
9
gistfile1.scpt0
set conf_name to text returned of ¬
	(display dialog ¬
		class="_tkStr_1klyn_166">"Enter conference name:" with title ¬
		class="_tkStr_1klyn_166">"Schedule Conference" default answer ¬
		class="_tkStr_1klyn_166">"" default button class="_tkNum_1klyn_175">2)

tell application class="_tkStr_1klyn_166">"Things"
	set newProject to make new project ¬
		with properties {name:conf_name}
end tell

tell application class="_tkStr_1klyn_166">"Things"
9
8
gistfile1.txt0
Disregard this. I'm not a competent programmer.
8
7
gistfile1.sass0
$grid_column_width: 40px
$grid_column_margin: 10px
$grid_columns: class="_tkNum_1klyn_175">12
$grid_width: $grid_columns * ($grid_column_width + $grid_column_margin * class="_tkNum_1klyn_175">2)

=container
  margin-left: auto
  margin-right: auto
  width: $grid_width
	
=alpha
  margin-left: class="_tkNum_1klyn_175">0
7
6
gistfile1.rb0
module Rack
  module Utils
    def parse_nested_query(qs, d = nil)
      params = ActiveSupport::OrderedHash.new

      (qs || class="_tkStr_1klyn_166">'').split(d ? /[#{d}] */n : DEFAULT_SEP).each do |p|
        k, v = unescape(p).split(class="_tkStr_1klyn_166">'=', class="_tkNum_1klyn_175">2)
        normalize_params(params, k, v)
      end

      return params
    end
6
5
model_spec.rb0
  # mock-based (interaction)
  # db independent, but tied to implementation (I can change the AR call without affecting the behavior and this will fail)
  context class="_tkStr_1klyn_166">"data gathering" do
    it class="_tkStr_1klyn_166">"finds all indicators associated with the given sector and includes indicators not associated with any sectors" do
      sector = stub_model(Sector, :id => class="_tkNum_1klyn_175">6)

      Indicator.should_receive(:where).with(class="_tkStr_1klyn_166">"sector_id is null or sector_id = ?", sector.id)

      Indicator.for_sector(sector)
    end
  end
5
4
gistfile1.txt0
CantTouchThis = Class.new do
  def to_s
    class="_tkStr_1klyn_166">'<CantTouchThis>'
  end
end.new

class Stripper
  def self.strip(klass)
    klass.class_eval do
      Stripper::constants_to_remove.each do |c|
        self.const_set c.to_sym, CantTouchThis
      end
4
3
group_steps.rb0
Given /^I'm subscribed as a group host for ([^ ]*) users?$/ do |users|
  users = users.to_i
  steps %Q{
    Given I'm on the account page
    Given I enter valid billing details
  }
  choose(class="_tkStr_1klyn_166">"for_many") # THIS FAILS
  fill_in class="_tkStr_1klyn_166">"people ($class="_tkNum_1klyn_175">9 per month each)", :with => users
  steps(class="_tkStr_1klyn_166">'And I press "Subscribe"')
end
3
2
after.rb0

Before/after let comparison

  class Delegator
    takes :request, :route_path, :resource, :delegate_name

    let(:delegate_method) { @resource.record_class.method(method_name) }
    let(:method_name) { @delegate_name.split(class="_tkStr_1klyn_166">'.').last.to_sym }

    def delegate
      delegate_method.call(*delegate_args)
    end

    def delegate_args
      inference_sources = InferenceSources.new(@request,
2
A
lightning.txt0

PyCodeConf 2011 Lightning Talk Signup

I want to give a lightning talk about: 

class="_tkStr_1klyn_166">"Wat?"

I need the projector: yes / no

Yes
A
K
gistfile1.rb0
require class="_tkStr_1klyn_166">'download_policy'

describe DownloadPolicy do
  let(:screencast) { stub(:free? => false) }
  let(:anonymous_user) { nil }
  let(:user_with_access) { stub(:has_screencast_access? => true) }
  let(:user_without_access) { stub(:has_screencast_access? => false) }

  it class="_tkStr_1klyn_166">"is disallowed for anonymous users" do
    subject.allow_download_for?(screencast, anonymous_user).should be_false
  end
K
Q
gistfile1.rb0
# Make a user that we'll add a book to.
user = User.create!
controller.stub(:current_user) { user }

# This prints []. The book list is empty.
p user.books

# Expect a book to be added to the user. This fails (see below)
expect {
  post :create, :id => asin
}.to change { user.books }.from([]).to([book])
Q
J
gistfile1.txt0
Python array methods:

>>> [m for m in dir([]) if not m.startswith(class="_tkStr_1klyn_166">"_")]
[class="_tkStr_1klyn_166">'append', class="_tkStr_1klyn_166">'count', class="_tkStr_1klyn_166">'extend', class="_tkStr_1klyn_166">'index', class="_tkStr_1klyn_166">'insert', class="_tkStr_1klyn_166">'pop', class="_tkStr_1klyn_166">'remove', class="_tkStr_1klyn_166">'reverse',
class="_tkStr_1klyn_166">'sort']

Ruby array methods:

>> ([].methods - Object.methods).sort
=> [class="_tkStr_1klyn_166">"&", class="_tkStr_1klyn_166">"*", class="_tkStr_1klyn_166">"+", class="_tkStr_1klyn_166">"-", class="_tkStr_1klyn_166">"<<", class="_tkStr_1klyn_166">"[]", class="_tkStr_1klyn_166">"[]=", class="_tkStr_1klyn_166">"all?", class="_tkStr_1klyn_166">"any?", class="_tkStr_1klyn_166">"assoc", class="_tkStr_1klyn_166">"at",
class="_tkStr_1klyn_166">"choice", class="_tkStr_1klyn_166">"clear", class="_tkStr_1klyn_166">"collect", class="_tkStr_1klyn_166">"collect!", class="_tkStr_1klyn_166">"combination", class="_tkStr_1klyn_166">"compact", class="_tkStr_1klyn_166">"compact!",
class="_tkStr_1klyn_166">"concat", class="_tkStr_1klyn_166">"count", class="_tkStr_1klyn_166">"cycle", class="_tkStr_1klyn_166">"delete", class="_tkStr_1klyn_166">"delete_at", class="_tkStr_1klyn_166">"delete_if", class="_tkStr_1klyn_166">"detect",
J
10
gistfile1.rb0
# Rails controller
def create
  @profile = ProfileManager.create(params[:profile])
rescue ProfileManager::CreationFailed => e
  render :new, :errors => e.errors
end

# Raptor route
create :to => class="_tkStr_1klyn_166">"ProfileManager#create", ProfileManager::CreationFailed => render(:new)
10
9
gistfile1.rb0
# Hash form:
{
  :current_user => class="_tkStr_1klyn_166">"CurrentUser.current_user"
}

# Discovery form with inverted app structure:
module Injectables
  def current_user(session)
    User.find(:id => session[class="_tkStr_1klyn_166">'current_user_id'])
  end
end
9
8
gistfile1.txt0
Last login: Mon Jan class="_tkNum_1klyn_175">30 class="_tkNum_1klyn_175">16:class="_tkNum_1klyn_175">54:class="_tkNum_1klyn_175">38 on ttys000
failbowl:~(master!?) $ rvm install ree
Installing Ruby Enterprise Edition from source to: /Users/grb/.rvm/rubies/ree-class="_tkNum_1klyn_175">1.8.class="_tkNum_1klyn_175">7-class="_tkNum_1klyn_175">2011.12
ree-class="_tkNum_1klyn_175">1.8.class="_tkNum_1klyn_175">7-class="_tkNum_1klyn_175">2011.12 - #fetching (ruby-enterprise-class="_tkNum_1klyn_175">1.8.class="_tkNum_1klyn_175">7-class="_tkNum_1klyn_175">2011.12)
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
class="_tkNum_1klyn_175">100 7773k  class="_tkNum_1klyn_175">100 7773k    class="_tkNum_1klyn_175">0     class="_tkNum_1klyn_175">0  2447k      class="_tkNum_1klyn_175">0  class="_tkNum_1klyn_175">0:class="_tkNum_1klyn_175">00:class="_tkNum_1klyn_175">03  class="_tkNum_1klyn_175">0:class="_tkNum_1klyn_175">00:class="_tkNum_1klyn_175">03 --:--:-- 2513k
ree-class="_tkNum_1klyn_175">1.8.class="_tkNum_1klyn_175">7-class="_tkNum_1klyn_175">2011.12 - #extracting ruby-enterprise-class="_tkNum_1klyn_175">1.8.class="_tkNum_1klyn_175">7-class="_tkNum_1klyn_175">2011.12 to /Users/grb/.rvm/src/ree-class="_tkNum_1klyn_175">1.8.class="_tkNum_1klyn_175">7-class="_tkNum_1klyn_175">2011.12
Applying patch class="_tkStr_1klyn_166">'tcmalloc' (located at /Users/grb/.rvm/patches/ree/class="_tkNum_1klyn_175">1.8.class="_tkNum_1klyn_175">7/tcmalloc.patch)
Applying patch class="_tkStr_1klyn_166">'stdout-rouge-fix' (located at /Users/grb/.rvm/patches/ree/class="_tkNum_1klyn_175">1.8.class="_tkNum_1klyn_175">7/stdout-rouge-fix.patch)
Applying patch class="_tkStr_1klyn_166">'no_sslv2' (located at /Users/grb/.rvm/patches/ree/class="_tkNum_1klyn_175">1.8.class="_tkNum_1klyn_175">7/no_sslv2.diff)
Applying patch class="_tkStr_1klyn_166">'lib64' (located at /Users/grb/.rvm/patches/ree/lib64.patch)
8
7
gistfile1.rb0
#!/bin/ruby

guard class="_tkStr_1klyn_166">'spork' do
  watch(%r{^config/.*\.rb$})
  watch(%r{^config/environments/.*\.rb$})
  watch(%r{^config/initializers/.*\.rb$})
  watch(%r{^features/support/.*\.rb$})
  watch(class="_tkStr_1klyn_166">'spec/spec_helper.rb')
end
7
6
gistfile1.txt0
failbowl:temp(master+!?) $ git st
# On branch master
# Changes to be committed:
#   (use class="_tkStr_1klyn_166">"git reset HEAD <file>..." to unstage)
#
#	modified:   a
#	new file:   c
#
# Changes not staged for commit:
#   (use class="_tkStr_1klyn_166">"git add <file>..." to update what will be committed)
#   (use class="_tkStr_1klyn_166">"git checkout -- <file>..." to discard changes in working directory)
#
6
5
gistfile1.rb0
describe class="_tkStr_1klyn_166">'a' do
  it class="_tkStr_1klyn_166">"raises an error when no source is found for an argument" do
    klass = Class.new { def f(unknown_argument); end }
    expect do
      injector.call(klass.new.method(:f))
    end.to raise_error(Syringe::UnknownInjectable)
end
end
5
4
gistfile1.txt0

I asked Comcast to stop leaving me two four-second voice mails every day. This is their response.

Dear Gary,

Thank you for contacting Comcast Email Support. My name is Jean and I
appreciate your time and effort in contacting us. I hope you are having
a great day.

I understand that you would like us to put your name and your number,
xxx-xxx-xxxx, right at this moment. I truly understand how this must
have been frustrating to you and I do apologize for any inconvenience
this has caused you. I can certainly understand how important it is for
you to have this resolved as soon as possible in order for you to not
receive any call. Rest assured that we, at Comcast, are dedicated to
4
3
gistfile1.rb0
def tweet(o)
  match(o) {
    with(o.name == class="_tkStr_1klyn_166">"garybernhardt") { raise TrollError }
    with(Image i) { tweet ShortLink.for_image(i) }
    with(Text t) { actually_tweet_here }
  }
end
3
2
changes.rb0
class Changes < Actor
  out :timeline_tweets_out
  takes :tweets_in, :friends_in

  def before
    @friends = @friends_in.pop
  end

  def pump
    tweet = @tweets_in.pop
    timeline_tweets_out << tweet if @friends.include_user?(tweet.user)
  end
2
A
gistfile1.txt0

Isolation, Data & Dependencies

Isolated unit testing—mocking everything—is a controversial topic. We'll briefly review what it is today, why people like it, and its problems. Then, on to the real goal: a trip through behavior vs. data, mutation vs. immutability, how data shape affords parallelism, transforming interface dependencies into data dependencies, and what it might look like to unify all of these with a slightly tweaked version of OO. Fortunately, Ruby is sufficiently flexible that we can do the whole experiment without leaving it.
A
K
gistfile1.txt0
A Whole New World

Few of us have participated in the creation of our
infrastructure—operating systems, compilers, terminals, editors, etc.,
even though many of us know how to build them in theory. Collectively,
we suffer from a learned helplessness around them: to build new
high-level tools, we'd also have to rebuild some of the
infrastructure, sometimes going all the way down to the kernel. We
can't imagine triggering such a large cultural and technological
shift, so we don't even try to build truly new tools for ourselves.
Iclass="_tkStr_1klyn_166">'ve been working on such a stack-busting tool and, though I won't
spill the beans on it here, Iclass="_tkStr_1klyn_166">'ll say that it's required me to
K
Q
gistfile1.txt0
#define assert_equals(expected, actual)\
    if (expected != actual) {\
        printf(class="_tkStr_1klyn_166">"FAIL: %#Lx != %#Lx\n", (uint64_t)expected, (uint64_t)actual);\
        exit(class="_tkNum_1klyn_175">1); \
    }

#define run_test(name)\
    printf(class="_tkStr_1klyn_166">"%s\n", #name);\
    name();
Q
J
gistfile1.applescript0
tell application class="_tkStr_1klyn_166">"Finder"
  open file ((path to home folder as text) & class="_tkStr_1klyn_166">"Dropbox:notes") using ((path to applications folder as text) & class="_tkStr_1klyn_166">"MacVim.app")
end tell

tell application class="_tkStr_1klyn_166">"MacVim"
	activate
end tell
J
10
gistfile1.txt0
failbowl:~(master!?) $ # Curl with normal user agent; get the correct text back
failbowl:~(master!?) $ curl -s class="_tkStr_1klyn_166">'https:class="_tkCom_1klyn_170">//gist.github.com/raw/class="_tkNum_1klyn_175">4534954/b508396cb255b52a0defbc75c92e69ad5c2937b5/gistfile1.rb' | head -class="_tkNum_1klyn_175">1
# I don't really see any services here. What I see is:

failbowl:~(master!?) $ # Curl as iPhone; get broken text back
failbowl:~(master!?) $ curl -s -A class="_tkStr_1klyn_166">'Mozilla/class="_tkNum_1klyn_175">5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/class="_tkNum_1klyn_175">528.18 (KHTML, like Gecko) Version/class="_tkNum_1klyn_175">4.0 Mobile/7A341 Safari/class="_tkNum_1klyn_175">528.16' class="_tkStr_1klyn_166">'https:class="_tkCom_1klyn_170">//gist.github.com/raw/class="_tkNum_1klyn_175">4534954/b508396cb255b52a0defbc75c92e69ad5c2937b5/gistfile1.rb' | head -class="_tkNum_1klyn_175">1
# I don&#class="_tkNum_1klyn_175">39;t really see any services here. What I see is:
10
9
gistfile1.txt0
failbowl:~(master) $ irb
>> X = class="_tkNum_1klyn_175">1
=> class="_tkNum_1klyn_175">1
>> undef_const :X
NoMethodError: undefined method `undef_const' for main:Object
  from (irb):class="_tkNum_1klyn_175">2
>> const_undef :X
NoMethodError: undefined method `const_undef' for main:Object
	from (irb):class="_tkNum_1klyn_175">3
>> const_delete :X
NoMethodError: undefined method `const_delete' for main:Object
	from (irb):class="_tkNum_1klyn_175">4
9
8
gistfile1.txt0
>> class Foo; attr_accessor :hello; end
>> f = Foo.new
>> f.hello = lambda { puts class="_tkStr_1klyn_166">"why no self?" }
>> f.hello
=> #<Proc:0x0000000102b6e768@(irb):class="_tkNum_1klyn_175">12>
8
7
gistfile1.diff0
--- /Users/grb/.rvm/gems/ruby-class="_tkNum_1klyn_175">1.9.class="_tkNum_1klyn_175">3-p194@investments/gems/values-class="_tkNum_1klyn_175">1.5.class="_tkNum_1klyn_175">0/lib/values.rb	class="_tkNum_1klyn_175">2013-class="_tkNum_1klyn_175">06-class="_tkNum_1klyn_175">17 class="_tkNum_1klyn_175">19:class="_tkNum_1klyn_175">28:class="_tkNum_1klyn_175">23.000000000 -class="_tkNum_1klyn_175">0700
+++ values.rb	class="_tkNum_1klyn_175">2013-class="_tkNum_1klyn_175">06-class="_tkNum_1klyn_175">25 class="_tkNum_1klyn_175">17:class="_tkNum_1klyn_175">28:class="_tkNum_1klyn_175">17.000000000 -class="_tkNum_1klyn_175">0700
@@ -class="_tkNum_1klyn_175">1,class="_tkNum_1klyn_175">7 +class="_tkNum_1klyn_175">1,class="_tkNum_1klyn_175">7 @@
 class Value
   def self.new(*fields)
     Class.new do
-      attr_reader *fields
+      attr_reader :hash, *fields

       define_method(:initialize) do |*values|
         raise ArgumentError.new(class="_tkStr_1klyn_166">"wrong number of arguments, #{values.size} for #{fields.size}") if fields.size != values.size
@@ -class="_tkNum_1klyn_175">10,class="_tkNum_1klyn_175">6 +class="_tkNum_1klyn_175">10,class="_tkNum_1klyn_175">8 @@
7
6
gistfile1.txt0
thelongpoll: Acquiring lock on /Users/grb/.thelongpoll
thelongpoll: - Got it
thelongpoll: Is the mail client running?
thelongpoll:         * ps aux
thelongpoll: - No
thelongpoll: Checking git status
thelongpoll:         * (cd /Users/grb/Downloads/Gmail && git status --short)
thelongpoll: - Clean
thelongpoll: Don't need to commit to git
thelongpoll: Starting sync
thelongpoll:         * offlineimap
OfflineIMAP class="_tkNum_1klyn_175">6.5.class="_tkNum_1klyn_175">4
6
5
gistfile1.txt0
John Carmack on shadow volumes...

I recieved this in email from John on May 23rd, class="_tkNum_1klyn_175">2000.

- Mark Kilgard


I solved this in a way that is so elegant you just won't believe it.  Here
is a description that I posted to a private mailing list:

----------------------------------------------------------
5
4
gistfile1.txt0
$ echo class="_tkStr_1klyn_166">'#!/bin/ls /' > foo
$ ./foo
./foo

/:
bin  boot  dev	etc  home  initrd.img  lib  lib64  lost+found  media  mnt  opt	proc  root  run  sbin  selinux	srv  sys  tmp  usr  var  vmlinuz
$ echo class="_tkStr_1klyn_166">'#!/bin/ls / /' > foo
$ ./foo
/bin/ls: cannot access / /: No such file or directory
4
3
gistfile1.txt0
#!/bin/bash
/usr/bin/env ruby --disable-gems <(cat <<class="_tkStr_1klyn_166">'EOF'
puts class="_tkStr_1klyn_166">"ruby code goes here"
EOF)
3
2
gistfile1.txt0
failbowl:~(master) $ cabal list --installed hunit
class=class="_tkStr_1klyn_166">"_tkCom_1klyn_170">* HUnit
    Synopsis: A unit testing framework for Haskell
    Default available version: class="_tkNum_1klyn_175">1.2.class="_tkNum_1klyn_175">5.2
    Installed versions: class="_tkNum_1klyn_175">1.2.class="_tkNum_1klyn_175">5.2
    Homepage: http:class=class="_tkStr_1klyn_166">"_tkCom_1klyn_170">//hunit.sourceforge.net/
    License:  BSD3

failbowl:~(master) $ echo class="_tkStr_1klyn_166">'import HUnit' | runhaskell

/var/folders/g5/jl_jnwv57nn_rhnvd_v6wpqw0000gn/T/runghcXXXX79850.hs:class="_tkNum_1klyn_175">1:class="_tkNum_1klyn_175">8:
    Could not find module `HUnit'
2
A
gistfile1.txt0
puts class="_tkStr_1klyn_166">"export #{vars.map { |k, v| %{#{k}="#{v}class="_tkStr_1klyn_166">"} }.join(" class="_tkStr_1klyn_166">")}"
A
K
gistfile1.txt0
failbowl:rubies(master) $ git l
class=class="_tkStr_1klyn_166">"_tkCom_1klyn_170">*   65cc7ef  (class="_tkNum_1klyn_175">41 seconds)  <Gary Bernhardt>   (HEAD, master) Merge branch class="_tkStr_1klyn_166">'activate_command_cleanup'
|\
| * f4ced72  (class="_tkNum_1klyn_175">2 minutes)   <Gary Bernhardt>   extract variables
| * f2760be  (class="_tkNum_1klyn_175">3 minutes)   <Gary Bernhardt>   File.join instead of string interpolation
| * 94b8df5  (class="_tkNum_1klyn_175">5 minutes)   <Gary Bernhardt>   activate command's imperative part is in activate!
|/
class=class="_tkStr_1klyn_166">"_tkCom_1klyn_170">*   class="_tkNum_1klyn_175">9291243  (class="_tkNum_1klyn_175">7 minutes)   <Gary Bernhardt>   Merge branch class="_tkStr_1klyn_166">'ruby_info_cleanup'
|\
| * b7cb944  (class="_tkNum_1klyn_175">9 minutes)   <Gary Bernhardt>   indentation
| * a3428c7  (class="_tkNum_1klyn_175">10 minutes)  <Gary Bernhardt>   move RubyInfo field extraction into RubyInfo class
| * dff6a33  (class="_tkNum_1klyn_175">15 minutes)  <Gary Bernhardt>   introduce ruby_info! command method
K
Q
gistfile1.rb0
  it class="_tkStr_1klyn_166">"requires an amount_charged greater than class="_tkNum_1klyn_175">0" do
    order = FactoryGirl.build(:order, :amount_charged => class="_tkNum_1klyn_175">0)
    order.valid?.should == false
    order.errors[:amount_charged].should == [class="_tkStr_1klyn_166">"must be greater than class="_tkNum_1klyn_175">0"]
  end
Q
J
gistfile1.sh0
git diff --name-status head~class="_tkNum_1klyn_175">3000..head | grep class="_tkStr_1klyn_166">'^D' | awk class="_tkStr_1klyn_166">'{print $class="_tkNum_1klyn_175">2}' | while read f; do git log -class="_tkNum_1klyn_175">1 --pretty=class="_tkStr_1klyn_166">"format:%H" -- class="_tkStr_1klyn_166">"$f"; done > temp.txt
J
10
gistfile1.txt0
def adjust(t,h);(class="_tkNum_1klyn_175">3*h)−(class="_tkNum_1klyn_175">4*t*h);end
def adjust(t,h);(class="_tkNum_1klyn_175">3*h)-(class="_tkNum_1klyn_175">4*t*h);end
10
9
gistfile1.txt0
CyBurTaz:	i programed my comps memory to read my 	own lang
RAVERgrl34:	LoL... oh muh god!
CyBurTaz:	FOXXY STFU
RAVERgrl34:	you are a piece of shit!
RAVERgrl34:	ROFL
RAVERgrl34:	LMAO
RAVERgrl34:	oh muh god!
RAVERgrl34:	you are lamest mother fucking i have ever 	seen!
RAVERgrl34:	oh muh god, you are lame.
9
8
gistfile1.txt0
failbowl:~(master) $ curl class="_tkStr_1klyn_166">'http:class="_tkCom_1klyn_170">//maps.google.com/?saddr=St.%20Petersburg%20Shavrova%class="_tkNum_1klyn_175">2015&daddr=St.%20Petersburg%20Sadovaya%class="_tkNum_1klyn_175">2030&dirflg=r&output=json'
<HTML><HEAD><meta http-equiv=class="_tkStr_1klyn_166">"content-type" content=class="_tkStr_1klyn_166">"text/html;charset=utf-class="_tkNum_1klyn_175">8">
<TITLE>class="_tkNum_1klyn_175">302 Moved</TITLE></HEAD><BODY>
<H1>class="_tkNum_1klyn_175">302 Moved</H1>
The document has moved
<A HREF=class="_tkStr_1klyn_166">"http:class="_tkCom_1klyn_170class="_tkStr_1klyn_166">">//maps.google.com/maps?saddr=St.%20Petersburg%20Shavrova%class="_tkNum_1klyn_175">2015&amp;daddr=St.%20Petersburg%20Sadovaya%class="_tkNum_1klyn_175">2030&amp;dirflg=r&amp;output=json">here</A>.
</BODY></HTML>

failbowl:~(master) $ curl class="_tkStr_1klyn_166">'http:class="_tkCom_1klyn_170">//maps.google.com/maps?saddr=St.%20Petersburg%20Shavrova%class="_tkNum_1klyn_175">2015&amp;daddr=St.%20Petersburg%20Sadovaya%class="_tkNum_1klyn_175">2030&amp;dirflg=r&amp;output=json'
<HTML><HEAD><meta http-equiv=class="_tkStr_1klyn_166">"content-type" content=class="_tkStr_1klyn_166">"text/html;charset=utf-class="_tkNum_1klyn_175">8">
<TITLE>class="_tkNum_1klyn_175">302 Moved</TITLE></HEAD><BODY>
<H1>class="_tkNum_1klyn_175">302 Moved</H1>
8
7
gistfile1.txt0
$ heroku pg:backups
Installing Heroku Toolbelt v4... done.
For more information on Toolbelt v4: https:class=class="_tkStr_1klyn_166">"_tkCom_1klyn_170">//github.com/heroku/heroku-cli
Setting up node-v4.class="_tkNum_1klyn_175">1.1... done
Installing core plugins heroku-cli-addons, heroku-apps, heroku-fork, heroku-git, heroku-local, heroku-run, heroku-status...
 ▸
Error reading plugin: heroku-apps. See /Users/grb/.heroku/error.log for more information.
Error reading plugin: heroku-cli-addons. See /Users/grb/.heroku/error.log for more information.
Error reading plugin: heroku-fork. See /Users/grb/.heroku/error.log for more information.
Error reading plugin: heroku-git. See /Users/grb/.heroku/error.log for more information.
Error reading plugin: heroku-local. See /Users/grb/.heroku/error.log for more information.
Error reading plugin: heroku-run. See /Users/grb/.heroku/error.log for more information.
7
6
user.py0
from collections import namedtuple
from datetime import date

# Here's a user defined using the usual class="_tkStr_1klyn_166">"OO" style.
class UserClass:
    def __init__(self, first, last, birthday):
        self.__first = first
        self.__last = last
        self.__birthday = birthday

    def name(self):
        return self.__first + class="_tkStr_1klyn_166">" " + self.__last
6