Peter Christensen

  • Presentations
  • Contact Me

Learning iOS, Swift Part 1

August 25, 2015 by Peter Leave a Comment

I’m about a week into learning iOS and Swift 2.0 and I am pleased and impressed. For reference, I’m using this course (currently $59 on StackSocial).

This week, I went through the basic Swift language sections and lessons about creating a basic app to demonstrate controls, outlets, and actions. I am pleased at how Swift looks so natural and unsurprising – I have to admit that I looked iOS a couple years ago and a page of Objective-C was enough to make me turn around and leave.

For background, I programmed in Pascal as a kid, then C and C++ in college (which I hated), then C# for my first 5 years of work (which I loved), then Ruby/Rails/JS/web for the next 5 years (which I currently love), with Common Lisp and Clojure sprinkled over the last several years for fun. Ruby is my goto language for getting things done, but Clojure is inspiring for its clarity of design and how it guides you to do the right thing. Swift has nice, comforting C-style syntax while providing a lot of the guidance, protection, and convenience that I like about Clojure. For instance:

  • the way you have to opt into nil using Optional types
  • the way you can save some boilerplate where possible using the forcible unwrap operator
  • using guard instead of if to emphasize your main logic
  • the flexibility around parameters – binding a local variable with the param name, explicit inout params when you need to change them, variadic parameters

I tend to program defensively and I get the feeling Swift will make that very natural.

I had more fun using the Storyboard, view controllers, and control library than I’ve had in a long time. My first work as a programmer was building Windows Forms in .Net 1.1, and it was so fast and productive for such a rich app experience. I love the web, but no web programming I’ve ever done (even now in 2015) has that same rush of creating results as fast as you can click and type as I got from using Visual Studio way back when. But building a silly toy app that lets you click buttons to change background colors and show/hide controls when you toggle a switch was every bit as good. I know there’s so much more to iOS than the control library, but if the rest of the platform is a well developed and simple to code against as that, then I’m in for a real treat!

Next up are an Ad Libs app and an RGB app.

 

Filed Under: iOS, Programming

Finding Things Fast in Emacs

August 17, 2015 by Peter Leave a Comment

I use emacs, and it is super powerful, but out of the box, it has some rough edges. Finding files in stock emacs isn’t great.

I used to use a plugin called find-things-fast (https://github.com/eglaysher/find-things-fast), but a previous employer had a codebase too big that made it grind to a halt. (Hint: different projects should be in different repos.) I grew out of the habit of using it, but when I upgraded and tried using it again, I got no results. Turns out the new version has a file extension whitelist, and the author sets it to his type of project, the Chromium project with lots of C++ file extensions. I wanted to use the file extensions for my projects, but rather than guess and make an ad-hoc list, I decided to roll up my command line sleeves and figure it out for real.

Find all files in Git repo:

git ls-files

Run a regex to strip out the ending file extension:

git ls-files | perl -ne 'while(/\.[^\.\/]+$/g) {print "$&";}'

Sort the lines, and filter down to unique extensions:

git ls-files | perl -ne 'while(/\.[^\.\/]+$/g) {print "$&";}' | sort | uniq

Append this to a file:

git ls-files | perl -ne 'while(/\.[^\.\/]+$/g) {print "$&";}' | sort | uniq >> ~/src/file_extensions.txt

Run this command in each project.

Create a sorted unique list from all projects:

sort ~/src/file_extensions.txt | uniq > ~/src/sorted_file_extensions.txt

The I used an emacs editor macro to make an elisp list of wildcard strings, that looked like this:

'("*.asd" "*.bash" "*.bowerrc" "*.clj" "*.cljs" "*.coffee" "*.conf" "*.css" "*.csv" "*.editorconfig" "*.el" "*.eot" "*.erb" "*.example" "*.gif" "*.gitattributes" "*.gitconfig" "*.gitignore" "*.gitkeep" "*.gitmodules" "*.goo" "*.haml" "*.htm" "*.html" "*.info" "*.irbrc" "*.jade" "*.jpg" "*.js" "*.jshintrc" "*.json" "*.k" "*.lisp" "*.lock" "*.lua" "*.md" "*.nrepl-port" "*.nvmrc" "*.orig" "*.png" "*.rake" "*.rb" "*.rdoc" "*.rspec" "*.ru" "*.ruby-gemset" "*.ruby-version" "*.scm" "*.scss" "*.sh" "*.sml" "*.ss" "*.swf" "*.texi" "*.text" "*.ttf" "*.txt" "*.woff" "*.xml" "*.yml" "*.zsh")

I customized the variable ftf-filetypes, restarted emacs, and now if works like a dream again. Thanks Elliot!

Filed Under: Emacs, Programming

Starting to Learn iOS, Swift

August 16, 2015 by Peter Leave a Comment

I have a project idea that has been bugging me for years, and I finally feel like it’s time to work on it. It’s an app, with a server-side back end. In the past I had been focused on startups and making a business, but I realized that at this point in my life and career, I’d rather stretch and expand my technical skills. Admitting that lets me focus on it as a cool technology project, and demands that I learn new things, as opposed to starting a company, which would require me to use what I could be most productive with right away.

I’ve been a Clojure fan for years but was never had more than intermediate mastery of it, and never used any of the amazing cutting edge libraries from that community. But the combination of ClojureScript, various React wrappers (Om, Reagent, etc), React Native wrappers, and Datomic is such a compelling stack that it has kicked me into action. This talk from David Nolen is a great summary of the state of advanced Clojure:

As much as I would love to lean on the Clojure stuff, I have been burned in the past when I didn’t know the stack underlying a cool library. So over the next few months, I’m going to learn Swift and iOS, and then React. For Swift, I’m using this course on iOS 9 and Swift Mastery. Several iOS developers recommended the Stanford iOS course from iTunes U, but I wanted a course that covered the newest version of Swift, because of the big recent changes.

I plan on writing up my experience learning Swift, and downloading Xcode 7 (3.6 GB) gave me plenty of time to write this!

Filed Under: iOS, Programming

Faking an ActiveRecord Attribute

June 12, 2015 by Peter Leave a Comment

Recently, I had a problem in Rails that took some extra research to solve. In the process, I read numerous StackOverflow posts, mailing list posts dating back to 2008, and tried, like, a million things before coming to a fairly clean solution. The solution is either clever or genius, and either way, future me will need present me’s help to understand it, which is why I’m writing it down.

The problem was that I had a Rails ActiveRecord model User, that had an attribute named phone. We switched our associations so that a User could have multiple PhoneNumber objects, but we wanted to preserve the user.phone and user.phone= interface.

The classes look something like this:

  class User < ActiveRecord::Base
    has_many :phone_numbers, as: :phoneable, dependent: :destroy
  end
 
  class PhoneNumber < ActiveRecord::Base
    belongs_to :phoneable, polymorphic: true
  end

All the rest of the code is in the User class.

In order to ensure that the accessor methods were operating on the same object, I wrote a wrapper method for accessing the same object:

  def phone_number_obj
    phone_numbers.find_by_primary(true)
  end

The getter looked like this:

  def phone_number
    self.phone_number_obj.try(:number) 
    # PhoneNumber objects have a string field named number
  end

The setter was a little more complicated, because it had to either create or update a PhoneNumber object:

  def phone_number=(new_phone_number)
    if p = self.phone_number_obj # Number already exists
      if p.number != new_phone_number # Only update if number changes
        p.update_attributes(number: new_phone_number)
      end
    else
      phone_numbers.create({primary: true, number: new_phone_number})
    end
  end

All this worked lovely and wonderfully for objects that already existed, but it caused a number of problems when creating objects. ActiveRecord uses attribute setters when creating and initializing objects, but phone_number= requires that the User must already be persisted in order to create a PhoneNumber object in its phone_numbers association. I needed to strip out the phone_number attribute when creating a new User, save that value, and then create the PhoneNumber object once the User was saved.

The second part, creating the PhoneNumber object was saved, was easy. ActiveRecord callbacks (http://guides.rubyonrails.org/active_record_callbacks.html#available-callbacks) include after_create:

  after_create :assign_phone_number
  def assign_phone_number
    if @phone_number
      self.phone_number = @phone_number
    end
    @phone_number = nil
  end

The first part, stripping out the incoming attributes when creating a new object, that was not so easy. Lots of painful searches (most of which told me to not do what I was trying to do) and experiments later, I learned some things about Ruby and Rails and came up with something that worked.

  • The earliest AR callback, after_initialize, was too late for what I needed to do. When it runs, all of the attributes have already been assigned.
  • I thought of them interchangeably, but new is a class method on the model, and initialize is an instance method (this was a good explanation: http://stackoverflow.com/a/10383786/1895697). Model.new creates an object (allocates memory, connects functions, language implementation stuff), and the it calls initialize on the new object, which sets values for attributes. I tried overriding new (based on the implementation in http://api.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-create), on the model, and it worked as expected in console but it failed in every rspec test, with the very unhelpful error:
    • Failure/Error: Unable to find matching line from backtrace
      ArgumentError:
      wrong number of arguments (2 for 0..1)
  • super is a helpful keyword when using inheritance. You can call it with specific parameters
    • super(a, b)
    • or if you call it with no parans or arguments, it passes the same parameters in the same order as the containing function.

Once I figured that out, the implementation was pretty straightforward:

  def initialize(attributes = nil, options = {})
    phone_number = nil
    if attributes.is_a?(Hash)
      phone_number = attributes.delete(:phone_number)
    end
    new_user = super
    phone_number && new_user.instance_variable_set(:@phone_number, phone_number)
    new_user
  end

This lets me:

  • strip out the phone_number attribute so the setter is not called during initialization
  • use super to assign all the remaining attributes with ActiveRecord::Base.initialize
  • Save the phone_number you stripped into an instance variable so the after_create hook can use it
  • Return the user object as expected

Since it preserves all the behavior of initialize, ActiveRecord association methods that create Users still work.

Caveats

  • This is a usable but not perfect copy of the AR interface. For instance, you can’t put phone_number in a .where query or dynamic finder.
  • This does a lot more database queries. It could be reduced by caching the phone number in an instance variable but for now I’m going for correctness.
  • The setter (phone=) uses update_attributes on the PhoneNumber record, so there’s no way to assign a new phone number and save later.
  • This doesn’t play nicely with new, build, etc – the User has to be persisted before the PhoneNumber can be assigned to it. Lots of our tests and factories used build instead of create to save time, but those had to be changed from:
    • let(:user) { build(:user, phone_number: “555-555-5555”) }
    • to
    • let (:user) do
      u = create(:user)
      u.phone_number = “555-555-5555”
      u
      end

Conclusion

In retrospect, it probably would have been easier to break the .phone interface rather than hop through these hoops. This code is sort of a land mine that looks like one thing but behaves slightly differently. Use at your own risk, but it’s here in case you have this specific need.

Filed Under: Programming, Rails

#sfcljs August Meetup – Om vs Reagent vs Quiescent, Converting to Om

August 25, 2014 by Peter Leave a Comment

[UPDATE: Added links to slides for some of the talks]

ClojureScript is my new toy, so I was glad to see the San Francisco ClojureScript Meetup plan a new event, and all of the talks were about Om, which made it even better. It was a great event at Etsy’s SF office. Thanks to Melissa and Sean Grove for organizing it!

Here are my notes:

  • http://www.meetup.com/SF-Clojurescript-Meetup/events/201007552/
  • Official Meetup Hashtag: #sfcljs – https://twitter.com/search?q=%23sfcljs
  • Etsy (host) is hiring: https://www.etsy.com/careers/
  • Diogo
    • Slides: http://htmlpreview.github.io/?https://github.com/diogo149/om-no/blob/master/notes.html
    • Project: Social network with data mining, in stealth
      • switched from Om to Reagent
      • hit a wall after 5k+ LOC, months
    • What was good about Om
      • Global undo – really easy, but didn’t apply to the app
      • One atom to contain global app state
    • The Bad
      • reify and build/build-all was error prone – you have to keep straight which fns return reified functions and which are normal
      • API is verbose
        • he built syntactic sugar for it, but that shows weakness with API
      • Too slow – much slower than Angular JS
      • No anonymous fns as components
        • didn’t throw error messages, just re-mounted and caused site to flicker
      • Can’t compose components, because components track their parent
      • Cursors – pointers into app state
        • async transact! can change the value or order of the app state, making the cursor point to the wrong data
      • Local state mixed with global state
        • you can’t wholesale replace new app state, b/c you don’t know where it’s mixed with local state that you would lose
      • cursors behave like maps
        • you can pass maps like cursors, except for when you want to transact!
      • Need to Know principle
        • In React, components work best when they know as little as possible, so they don’t re-render for unnecessary changes
        • In Om, app state is a tree, so you need knowledge of lowest common ancestor
        • same data in multiple places
      • hard to be both consistent and performant
    • Reagent
      • principle of least surprise
      • more Clojure-y – lazy components, normal functions,
      • data model works better with React.js
      • easier to work with data as a direct acyclic graph
      • We were able to teach a new employee the codebase without knowledge of app or Reagent – testament of a good API
      • Simpler for small apps, more scaleable for large apps
    • Reagent – https://github.com/holmsand/reagent
  • Anton – http://textik.com/
    • Slides: http://www.slideshare.net/AntonAstashov/textik
    • ASCII diagram generator
    • Pet project, so he needed something he could build in an hour a day
    • Normal design of front-end web apps
      • observe changes in view models by any other observer models, sometimes cascading
      • Works well, but hard to figure out what happened in exception
      • Many inputs, many code paths
    • Prefer one-way flow of events → data → rendering → events
      • One global code path
      • Full state of the app when exceptions happen
    • Like React for fast view layer, use Quiescent for cljs
      • lightweight, ~200 LOC
      • Simple
      • Opinionless
    • Cons
      • slowly developing – few recent commits, pending pull requests
      • you have to maintain your own fork for e.g. animations
      • Has bugs that are fixed in Om
    • Lifecycle
      • Init – call Render
      • View – render, register event handlers that send payload to core.async channel
        • core.async used b/c you can’t have circular dependencies on namespaces, since view would require dispatch and vice versa
      • Dispatch – listen to channel, call mutators, call render
      • Mutators – change data (only layer where data is changed)
      • Data → return to Dispatch
    • Code – https://github.com/astashov/tixi
    • Minimal app using Quiescent, this architecture – https://github.com/astashov/mintik
    • Quiescent – https://github.com/levand/quiescent
  • Danny from CircleCI – Om From a Designer’s Point of View
    • Does not like writing Om, but likes how everything is in one language, so it’s easier to reason about (vs HAML, CoffeeScript, CSS, etc)
    • Can be harder to find where the data is coming from
    • Only sort of gets the lifecycle, design of components
      • Learning is coming faster than expected
    • Workflow + tools are the same except for a ~10sec delay when making changes
      • Using production data, and has to use the whitespace compiler to produce a single Javascript file
      • Sublime, Chrome Dev tools, etc
    • This is not a natural tool for a designer – most would need someone to help with the more programmery/Clojure-y stuff
    • Syntax for Hiccup etc isn’t a big change from HTML/CSS
    • Could use a more applicable cheat sheet for designers
    • Uses CSS or SVG animations
    • Surprised by React making assumptions/transformations on markup – e.g. moving an anchor to be a sibling of inline tag, from inside of it
    • Design process would be easier if he ran a local dev environment, but that’s a big new dependency that requires maintenance
  • Daniel from CircleCI – Converting a Site from Knockout to Om
    • Can now use CircleCI for open source projects – free container, public build pages
    • Open sourced front-end code: https://github.com/circleci/frontend
      • You connect to your own CircleCI backend data, so you can push changes/fixes to be merged into the main, public repo, while protecting your data
      • Still working out details of the open source workflow
    • (this was more showing code than presentation)
    • Old site used Knockout.js, 2-way data binding
      • data binding in JS, HAML-coffee templates in CoffeeScript, etc, so there were language mismatches, string interpolation
    • Converter from HAML-coffee to Hiccup – not perfect, but close enough
      • Difference between whitespace automatically included vs required
    • Event handlers put messages into core.async channels
    • Took about 2.5 months full time development to convert
    • How it works
      • All state is serializable in a single Atom
      • Build messages – something we know about the build that we want to tell you (~100 messages)
        • Gave a representative sample of serialized state to designer
      • In theory you can store and replay messages to rebuild state
      • core.async – e.g. Stripe checkout – complete/cancel puts message into channel, and the page blocks on that
    • Problems with Om
      • haven’t figured out testing, still just using webdriver tests
      • Rendering too much to the virtual DOM – parents have to know about child data, even if they don’t need it
        • hasn’t been too big a problem yet
      • Slow enough that you can drop characters on input, because of how much rendering goes on when everything is in global app state
        • More of a problem in tests
        • Needed to pull input data out of app state and into local component state

Filed Under: Clojure, Programming

Notes on Core.Async Webinar

August 23, 2014 by Peter Leave a Comment

Recently, David Nolen of Cognitect held a webinar about “Designing Front End Applications Using core.async”. I’m a huge fan of David’s teaching style (see his tutorials on Enlive, LightTable+ClojureScript, Om Basic and Om Intermediate) so I cleared my calendar. I’m very excited about Clojure’s front-end stack, with ClojureScript, core.async, and Transit, and after this webinar, I have a much clearer idea of how core.async fits in.

UPDATE: The recording is now live: http://go.cognitect.com/core_async_webinar_recording

Here are my notes

  • EXAMPLES – https://github.com/cognitect/async-webinar
  • Problems with Asynchronous programming
    • nesting callbacks is hard to maintain, read
    • JS is single-threaded
    • JS promises
      • better looking code, somewhat easier to read, but still a lot of callbacks. Chaining, not as nested
    • JS ES6 generators – extremely low level – core.async delivers the same benefits, but with a much higher level abstraction
  • ClojureScript
    • Cognitect – write the same types of apps, but simpler. Embrace and enhance the host
    • Immutability
    • ClojureScript – good interop with JS runtimes + libraries, with Clojure language platform
  • Why ClojureScript?
    • ClojureScript – good interop with JS runtimes + libraries, with Clojure language platform
    • Leverage Google Closure Compiler/Library
      • JS has many methods of packaging and delivery; Cljs only uses Closure
      • Superior minification + compression
        • dead code elimintation – include whatever you want, with no code bloat
      • Battle-tested standard library – support back to IE6
  • Core.Async
    • based on CSP (communicating sequential processes) – naturally captures one-off async tasks AND async streams/queues (e.g. mouse movements, etc)
    • Go blocks are a source transform that give the illusion of blocking, even in single-threaded context (i.e. JS hosts)
  • Terminology
    • Channels – conduit between different processes – put values in, take values out
      • Buffers – channels use them to configure backpressure, handle bursts of events; you can customize semantics
      • Transducers (new!) – efficient way to control how values enter and exit channel, e.g. map/filter
    • Go blocks – async blocks of execution with the illusion of blocking operations
  • Core Operations
    • putting values onto a channel
    • taking values off a channel
    • selecting over multiple channels (puts & takes)
  • 10 short examples
    • good enough first principles
    • repo available – https://github.com/cognitect/async-webinar – build, launch, follow along in browser
    • helpers
      • includes examples of JS interop
      • events→chan – listen for events, put them into the channel
        • use core.async to deal with events, instead of callbacks
      • mouse-loc→vec – turn events into vector
    • Example1
      • create a channel of clicks, block, and add a note
      • <! – blocking read inside of go blocks
    • Example 2 – same, but wait for 2 clicks
    • Example 3 – 2 channels, wait for one from each channel
    • Example 4 – shows how writing to a channel blocks that program until some other go block takes from the channel
    • Example 5 – separate go block to consume the channel
      • go blocks are like forking a process
      • looks like 2 separate processes running together and communicating over channels
    • Example 6 – stream processing
      • use transducer to convert events before they come into the channel
      • looks like an infinite loop – but getting a message off the click channel ends it
      • alts! – select over multiple channels – non-deterministically read from whichever channel has data first
        • line 140 – pattern matching on the channel
      • transducers let you work at a higher level of abstraction and data like you like it
    • Example 7 – more transducers
      • discard events unless the y is divisible by 5
      • loops can use the loop var bindings to record state
    • Example 8 – use loop vars to store state
    • Example 9 – more like real web
      • next/prev buttons to loop through a list
      • listen on prev/next channels to change vals, enable/disable prev/next
    • Example 10 – bigger example, broken out into helpers
      • more transducers – take all key presses, map the keyCode, filter by the set #{37 39}, and map them to :prev/:next
        • efficient because all those transformations happen in one function, inside the channel
      • click start, construct the keys channel
        • async/merge – take any number of channels, merge them into one channel (e.g. prev, next, keys) → a single channel that spits out :prev/:next
        • you can add more channels (e.g. left/right swipe on a tablet) and convert them to the same channels
  • Code is easier to manage and reason about new sources of events
  • Resources & Next Steps
    • original announcement – http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html
    • Tim Baldrige Clojure/conj 2013 core.async talk (40 min vid) – http://www.youtube.com/watch?v=enwIIGzhahw
      • server-side work
      • portability between Clojure and ClojureScript
    • Facebook React – http://facebook.github.io/react
      • Works well with immutable data structures for UI
      • ClojureScript libs – Om, Reagent, Quiescent, Reacl
  • Q&A
    • How do you compose small pieces into a large front-end application?
      • Think about the abstract event types and handling, not concrete event sources
      • Core.async lets you write little distributed elements inside your UI
      • Components are independent and share a message language for coordination
    • Chan function – up to 3 args
      • int that sets buffer size or properties
        • more useful in server context than UI
      • on front end, best is to use size 1 and a transducer to transform the stream
    • Complex data?
      • All pre-built React components can work with any ClojureScript React library
    • Buffer size is 1 event – with data of arbitrary value
    • If you’re already running JVM, it makes more sense to use Nashorn JS on JVM lib instead of Node
    • You cannot monitor channels – they are purposely opaque

Filed Under: Clojure, Programming

Running Windows Programs on OSX Using VMWare Fusion

August 12, 2014 by Peter Leave a Comment

I recently needed to run a Windows application (TurboTax Business) on my Macbook. I know about Parallels, dual boots, etc but those either cost money or seemed like too much work. Based on my experience with the incredible pain of getting a modern Rails stack to run on OSX, I decided to try using a VM, and it worked really well. Can’t recommend it enough.

Step 1: VMWare Fusion

I’m not often wowed by software, but VMWare Fusion is effectively magic. You can do the normal VM experience of having a computer in a window, but you can also run Windows programs separately and they behave like normal Mac apps. The 30 day free trial was plenty for me.

  • Downloads: http://www.vmware.com/go/tryfusion
  • Info: http://www.vmware.com/products/fusion/

Step 2: Windows ISO Images

I thought I was either going to have to buy a copy of Windows or do something shady. At the time, Microsoft has stopped selling Windows 7, but it was not how well supported my program was on Windows 8. I haven’t used Windows regularly since Vista, and I did not want this to suck up a bunch of time.

UPDATE: Microsoft shut down the Digital River links. I was able to find a Windows 8 ISO here: http://getintopc.com/softwares/operating-systems/download-windows-8-pro/

Luckily, you can legally download ISO images of Windows that come with a trial period, and you buy an activation key when the license runs out. I found a link to all the different variations of Windows 7 here: http://www.w7forums.com/threads/official-windows-7-sp1-iso-image-downloads.12325/. I chose Windows 7 Home Premium x64 English: http://msft.digitalrivercontent.net/win/X17-24209.iso (big file).

Step 3: Interacting with VM

From that point, it was easy to create a new VM, using the ISO as the disk. A shared disk folder, networking, etc all work with no additional setup. I downloaded and installed my program, and everything worked.

Bonus links

Discussion threads I read while figuring this out

  • https://blogs.vmware.com/teamfusion/2013/10/vmware-fusion-6-and-os-x-mavericks-the-perfect-combo.html
  • http://www.makeuseof.com/tag/vmware-fusion-6-opens-windows-on-your-mac/
  • http://www.macprovideo.com/hub/mac-osx/using-windows-8-under-vmware-fusion-part-1-installation

Filed Under: Programming

Fast Rails Tests Through Behavior Verification

May 17, 2014 by Peter Leave a Comment

[This was originally posted on Manilla’s tech blog, which is no longer up. RIP Manilla]

Most Rails developers have a love/hate relationship with their tests.  We love testing, we love writing tests, we love the confidence that a robust test suite provides when refactoring or adding new features.  But sometimes, especially with a large test suite, running the tests takes a disruptive and discouraging amount of time.

At Manilla, it takes about 20 minutes to run the complete test suite.  This is not terrible, but it’s far too much to run during development.  So we usually only run the spec file for the code file we’re working on, then we’re done developing, we run the whole suite before committing to our master branch.

My previous employer was a much larger company with many times more tests.  It was basically impossible to run the test suite on a developer machine so we had a massive parallelized CI-farm that everyone used every time they were committing code.  So while the situation at Manilla is still tolerable, I know what the future holds.

(most of what I’m about to say is paraphrased from Corey Haines’ excellent talk on Fast Rails Tests)

There are two approaches to making your test suite run faster.

The first is to improve your test infrastructure.  There are lots of strategies for this, like using fixtures instead of factories, using fixture_builder to ease the pain of maintaining fixtures, running spork to speed up running individual tests, etc.  These are attractive because let you continue writing tests in the way most people already do, but they require occasional bursts of non-development work to keep running.

The second approach is what Corey simply calls “changing the design of your code”.  He shows a lot of examples and benefits, but he glossed over the philosophical difference that underlies his approach.  I didn’t really get his talk until I grasped this distinction.

State Verification vs Behavior Verification

The best description of this is in Martin Fowler’s essay Mocks Aren’t Stubs.  Here’s a quick example for those of you who didn’t read that essay like I just told you to.  Imagine you’re writing a class for an ATM, and you want to test the deposit function.

Here’s your function:

## atm.rb
def deposit(account, amount)
  account.create_transaction(amount)
end

With state verification, your test code looks like this:

## atm_spec.rb
it "#deposit - should increase the Account balance" do
  account = Account.new(:balance => 100)
  Atm.new.deposit(account, 100)
  account.balance.should == 200
end

The test ends up being a mini-integration test that not only does your Atm.deposit work, but the Account.deposit works too.

With behavior verification testing, the test code looks like this:

## atm_spec.rb
class FakeAccount
end
it "#deposit - should tell Account to create a transaction" do
  account = FakeAccount.new
  account.should_receive(:create_transaction).with(100)
  Atm.new.deposit(account, 100)
end

In this case, you’re not testing that the balance of the account actually increased, you’re just verifying that you called the account object the way you expect to be calling it.  With behavior verification testing, you treat any class outside the class you’re currently testing as an API.  Most developers already do this with things like email, geocoding, batch processing, etc.

There are two huge implications of behavior verification testing.

Your unit tests for one class or module can’t be broken by code changes in other model.  This is a good thing because a change in one class won’t break hundreds of dependent tests across the entire suite.  But it also makes your integration tests that much more important.  If the interface to a class changes, your behavior verification tests won’t break even though the code no longer works.  State verification tests do test integration as deep as the coupling between the classes, but still need to be backed by real end-to-end integration tests.

The other point, relevant to test speed, is that you don’t need to load any resources that aren’t used by the class or module you’re testing.  So just like you don’t need to actually send emails when you run your email tests, you don’t need to load external classes to make sure you’re calling them correctly.

In the context of Rails, this means that through some slight restructuring of your code, you can avoid calling one big huge heavy API: Rails itself.  Loading any ActiveRecord class requires loading Rails, which takes several to many seconds, and including spec_helper takes many more seconds.

But how do avoid using Rails and ActiveRecord?

Strategies for Writing Fast Tests in Rails

Don’t get me wrong – ActiveRecord is a wonderful thing.  Rails is great.  If lines of code were pollutants, Rails would be the love-child of Al Gore and Captain Planet.  But it has a tendency to take over and get into all of your code.  Rails calls your code, rather than you calling Rails code.  Here’s how to slightly change your code to isolate your business logic from Rails and greatly speed up your test execution:

First, continue using ActiveRecord for persistence, validation, relationships, etc.  It’s wonderful for that.

For class Foo, create a module called FooBehavior (or some more targeted subset, like FooDepositBehavior) and include that in your class.

Move your business logic methods to that module and change them so they do not assume internal knowledge of the class.  For instance, change this:

## account.rb
def approve_loan_request?(withdrawal_amount)
  self.balance > withdrawal_amount
end

to this:

## account_bahavior.rb
def approve_loan_request?(withdrawal_amount, current_balance)
  current_balance > withdrawal_amount
end

The code looks almost identical, but in the first version, the innocent looking ‘self.balance’ requires the whole infrastructure of Rails to be in memory, it might make a database call unless it has already loaded the object, etc.  The second version is just about the easiest line of Ruby code ever written.

Here are some tips to write fast behavoir verification testable code:

  • Extract business logic code into its own module where appropriate
  • In business logic methods, pass all arguments and compute based on those (this also makes your tests more meaningful because they’re not dependent on outside state – see Functional Programming For the Rest of Us for more details)
  • When you need to lookup data using ActiveRecord’s API, use scopes or create your own methods that only contain AR queries and only return results.  This makes stubbing much easier.

And in your tests:

  • Require only the specific file(s) you’re testing
  • Put a dummy class at the top of your file for any external resources you’re calling
  • Use doubles or mocks, not factories or fixtures.  If you’ve separated your business logic from your AR classes, then your code and tests don’t need to know the difference between a full ActiveRecord object and a mock.
  • Put your “fast tests” in a separate directory (e.g. spec/fast/).  This makes them easier to run all at once.
  • Write a script (not a rake task, rake loads Rails) to run all your fast tests.  If you write tests like this, it’s faster to run the whole fast test suite than it is to autocomplete the filename that you’re working on. Ours looks like this:
#!/usr/bin/ruby
def test_files(dir)
 Dir["#{dir}**/*_spec.rb"].join " "
end
exec "rspec #{test_files('spec/fast/')}"

Results

We just started down this road so right now there’s only one file of fast tests, but there’s a look at the difference it makes:

Without Spork running:

$ time rspec spec/models/interstitial_announcement_spec.rb 
…
  11/11:       100% |==========================================| Time: 00:00:03

Finished in 3.47 seconds
11 examples, 0 failures
real    1m40.845s
user    1m29.785s
sys     0m4.165s

With Spork running:

$ time rspec spec/models/interstitial_announcement_spec.rb 
...
  11/11:       100% |==========================================| Time: 00:00:02

Finished in 2.57 seconds
11 examples, 0 failures 
real    0m10.528s
user    0m2.269s
sys     0m0.196s

After converted to fast tests:

$ time fast_tests
…
  12/12:       100% |==========================================| Time: 00:00:00

Finished in 0.07578 seconds
12 examples, 0 failures 
real    0m2.834s
user    0m2.519s
sys     0m0.246s

Summary:

Without Spork 1:40.8

With Spork 0:10.5

Fast Style 0:02.8

Conclusion

If you’re still reading, then you have an amazing attention span.  This journey felt a lot like tracking down an odd bug, where one symptom leads to a whole different root cause and solution.  I did not expect to end up studying testing philosophies when I was grumbling bad thoughts while waiting for my tests to run.  But even without the side benefit of faster tests, I’m grateful I learned a new way to look at testing.

Like so many things in programming, state verification vs behavior verification is “it depends”, not “right or wrong”.  There is some code that just works better with state verification.  Also, I bet most of your tests are already state verification, and there’s no reason to do a big-bang rewrite of everything at once.  Just convert the appropriate parts of a class to use behavior verification testing as you’re working on that class, over time, 5%, 20%, 50% of your test suite will be fast.

The real benefit is only partly to your full suite execution time.  A fast test suite can run thousands of tests per second, so instead of running only the test file you’re working on while you develop, you can run a big fraction of all your test suite. Every. Time. You. Write. Code.  Then, testing can be something you do while you develop instead of after it.

 

Filed Under: Programming

Software Talks for the Ages

May 8, 2014 by Peter Leave a Comment

Sturgeon’s law applies to talks. Despite the best efforts of conference organizers and speakers, most talks about software are too narrow, to vague, too detailed, too specific to the time when they were given. (Don’t anyone take offense, I’ve given some of those!)

But the best talks, oh, the best talks ring in your mind like a crystal glass, bearing fruitful ideas for years to come and on viewing after viewing.

I was at RailsConf 2014 and while I enjoyed DHH’s talk about Writing Software, several of my co-workers were very moved by it. His background as a computer nerd but not a programmer, his life outside of tech hubs, his non-Computer Science background, all spoke to them in a way that few talks by people with more formal and academic backgrounds did not.

I realized that in addition to programming for almost 25 years, I’ve been watching and listening to talks about software for almost 10 years, and some of those talks are as vivid as the day I first watched them. When I mentioned some of them, and my coworkers hadn’t heard of them, I felt a wonderful opportunity to share awesome stuff.

Here are some of the software talks that have made an impact on me.

Growing a Language by Guy Steele

This message unfolds in such a subtle and effective way that I won’t spoil the surprise. But both the words and format of the talk are a masterpiece.

50 in 50

This talk opened my eyes to the creativity and playfulness of programming language design, and made it sink into this thick analytical head that expressing an idea can be its own reward.

  • MP3: http://www.oopsla.org/oopsla2007/podcasts/invited-talks/keynote0104-50-in-50.mp3
  • Video: http://vimeo.com/25958308

YOW! 2010 50 in 50 Keynote Guy Steele and Richard Gabriel from YOW! 2010 on Vimeo.

OOPSLA 2007

I don’t know what magic happened at this conference, but I was blown away by talk after talk after talk. I still remember these talks 7 years after listening to them as a podcast. Two in particular stood out:

  • Fred Brooks – http://www.oopsla.org/podcasts/Keynote_FrederickBrooks.mp3
  • Kathy Sierra – http://www.oopsla.org/oopsla2007/podcasts/invited-talks/keynote0102-kathy-sierra.mp3

Rich Hickey

Rich Hickey, the creator of the Clojure programming language, has unorthodox but appealing and unassailably logical views on software development. These are 3 of his best talks.

  • Hammock Driven Development – the best software comes from the best designs, and the best designs take time. Time thinking, time away from firefighting and away from hacking.
  • Simple Made Easy – Simple is a unit of software that does one thing. Easy is the thing that takes the least up-front effort. Confuse them at your peril.
  • The Value of Values – Immutable data facts better represent the real world, and there are many benefits to inferring state from facts rather than continuous mutation of state.

You and Your Research

This talk by mathematician Richard Hamming covers work habits, producing impactful work, and prioritizing excellence.

  • Transcript: http://www.paulgraham.com/hamming.html
  • Video: https://www.youtube.com/watch?v=a1zDuOPkMSw
  • A lecture series that this talk came from: https://www.youtube.com/playlist?list=PL2FF649D0C4407B30

Randy Pausch – Last Lecture

Before he died, professor Randy Pausch gave this talk about Achieving Your Childhood Dreams

End of Fun by Sarah Mei

A deeply useful talk about the difference between work and play, creativity and process, and open and closed thinking.

  • Slides: https://speakerdeck.com/sarahmei/the-end-of-fun-lone-star-ruby

Structure and Interpretation of Computer Programs

The classic MIT textbook and lecture series. The textbook is amazing in the graceful way it builds up topics in computation while still seeming simple. The 20 part video lecture series from 1986 is so, so great. It’s tempting to dismiss it because of the old fashion and the sloooow Scheme interpreter they use on an overhead projector, but Abelson and Sussman are such clear teachers and so playfully confident that you can’t help but love it. This is time well, well spent.

  • Lecture series: https://www.youtube.com/playlist?list=PLB63C06FAF154F047

Part 1A

Conclusion

These are only some of the great talks that have been given. They are some of the great treasures of programming education and culture

Please, let me know which ones I’m missing!

Filed Under: Clojure, Programming

Why Aren’t More Programs Written in Powerful Languages?

December 23, 2013 by Peter Leave a Comment

http://coffeeghost.net/2008/03/19/your-ignorance-does-not-make-a-programming-language-suck/

Fans of obscure but powerful languages like Lisp, Haskell, Scala, and OCaml can sometimes get overzealous about how much great their language is, especially compared to those (holding nose) “common” languages like Java, C++, or C. Not only is this really annoying, but it sets them up for one the easiest comebacks in all of trash talking: “SCOREBOARD!” (For those not familiar, when fans of one sports team is losing to another team but still talking trash, all the fans of the winning team have to say is “SCOREBOARD” to indicate that, despite all you guys have to say, you’re losing the game). The nerd equivalent of this is “If X is so great (for any powerful value of X), how come there aren’t any programs written in it?” Indeed, people writing trillions of dollars worth of software in C, C++, C#, and Java, it is a valid rebuttal.

To those of you that have ever been hit with this rebuttal, take heart. Although you probably understand that it’s not a completely valid point, allow me to offer a theory. The start for this theory comes from a gem of a quote from Paul Graham, tucked away in a footnote of one of his articles: “Never attribute to malice what can be explained by math.” So please permit me to use some crude math.

[Read more…]

Filed Under: Programming

Next Page »

Categories

  • Blog
  • Book Review
  • Business
  • Clojure
  • Education
  • Emacs
  • Fun
  • iOS
  • Lisp
  • Personal Sprints
  • Pictures
  • Polyphasic
  • Presentations
  • Programming
  • Rails
  • Startups
  • Uncategorized

Copyright © 2025 · Minimum Pro Theme on Genesis Framework · WordPress · Log in