make better_mistakes

When Have You Tested Enough?

@cwgem recently asked: ‘Curiously throwing this out there. For test driven development, what do you consider to be “enough testing”?’

To which I respond:

Yesterday I tweeted, “I only test the code I want to work. I trust my code the least, then my team’s, then libraries.”

Not sure I really answered your original question tho. In TDD the idea of ‘enough’ tests may be missing the point. I don’t claim to TDD all the time, or to do it perfectly when I do, but one of the things that has been an apparent focus of TDD to me is the focus on tests driving design.

More to the point, the purpose of TDD as I understand it is to express expectations as test code, which unlike documentation needs to stay in sync with the changing codebase. By driving out our object from tests we create simpler and more focused methods.

In example, last year I was working on calculator code for a client which had some wonky business logic. I drove out the code using tests, and came up with what I thought was an elegant design (a bunch of single-line methods) in a pretty quick cycle. However, I had misunderstood the requirements when I wrote the tests, and the client wasn’t happy.

I quickly found out how the requirements I had written down in tests differed from reality, changed the tests, then made each failing example go green. If I had designed this without tests behind it, I would have likely written some dense conditional logic, and when it failed to meet expectations it would have been faster to throw it away and try again than to refactor it. The design that tests encourage was better for dealing with change.

I have when writing tests for unfamiliar languages written tests for things like setting variables. It was the simplest thing that I could think to test and writing that test gave me the confidence and familiarity to be able to soldier bravely onward. However, I wouldn’t keep a test of that sort in the codebase. There is nothing too small to write a test for at least once, so that you can prove to yourself that your expectations match the reality of the execution of code. There are, however, tests too trivial to commit to version control. The tests that I want in my test suite are ones which prove that the business logic of my application works, not that the language or libraries work.

Or more to the point, I only test the code I want to work. I want code which I trust the least to work the most, and I trust new code less than old code, changed code less than old code, my code less than my team’s code, and my team’s code less than library or framework code.

Can You Develop With an iPad and a VPS?

I’ve been playing around with connecting to a remote server using my iPad in the last few days. I’m curious if I can develop without a laptop. It’s an interesting constraint to work within. Other accounts of using an iPad and a remote server to develop, like I swapped my laptop for an iPad+Linode, sold me on the possibility of developing on the iPad ages ago. This weekend I thought I’d try it out.

My friend @zspencer recommended Digital Ocean* as a quick to setup VPS, and Prompt and iSSH as iPad apps that give me an ssh terminal. Yesterday I set up a Droplet, Digital Ocean’s name for a remote server. Basically, I gave them a credit card number, clicked a button, and a minute later I had a remote Ubuntu box reserved for me, an IP address, and a root password.

Since then I’ve played around with working on that machine just through the iPad. I cheated once, last night when I wanted to add my remote box’s SSH key to github and I couldn’t figure out how to copy the key from the command line into my iPad’s clipboard.

My web development toolkit on a computer requires me to use a shell, a browser, and a text editor. From the iPad I’ve got the shell. I can use vi for text editing, but it’s not something I’ve got practice with, yet. The trickiest thing is getting a browser going while I’m in the development environ. One route would be to treat the remote server as a staging server. I could write code in vi, administer in the shell, then load the site up in a browser on the iPad. Unfortunately, I don’t want mid-commit work to be staged, I just want to be able to view it.

What I want is to be able to go from the Ubuntu terminal to a GUI environ and look at the site in a browser running on the server. iSSH has a VPN option, but I couldn’t figure out how to get it working this afternoon. In fact I remembered something about X, the linux GUI, and thought I needed to start up xterm. Looking at it now I realize I need to start X not xterm which is a terminal program.

The experience reminds me a bit of the first time I worked with Linux. I ended up installing Red Hat on a Compaq box my family had stopped using. I got the terminal running, but I couldn’t ever figure out how to get a GUI running, despite skimming over a thousand page how to use Linux tome I’d ordered from Powell’s. I don’t think I touched Linux again for another six or eight years.

Anyhow, getting a GUI running in iSSH is clearly my next step, but I also need to figure out if this is the time to level up my vim-fu or figure out how to use Sublime Text in a remote version of Ubuntu. Neither is a particularly terrible option.

One other thing I need to figure out sooner rather than later is how to create a non-root user with the correct permissions to create files, install programs, and make things go. I’ve done a little remote server administration, but most of it has been following recipes written by other developers, and I can’t remember what needs a chmod.

Have you used a remote system to develop? How did you level up? What resources were useful for you? (And how do I get my GUI running? Work with an account other than root?)


* Digital Ocean is just one of many VPS providers. Others include Linode, Amazon VPS, and Slicehost. I don’t have any strong opinions about any of these providers, they all give you access to a server you can administer remotely for about the same price as a cup or two of fancy coffee a month.

Blogging Is Hard

Hello Internet,

I started this blog about a year and a half ago, when I was just starting to pursue a career in development. I’ve done an alright job with it, but let’s be honest, I haven’t posted much lately and this thing is getting a little moss growing on the North side from a lack of forward movement.

I’m no stranger to sharing my writing on the Internet, after all, I had a livejournal back in the day. However, blogging hasn’t been holding my attention, because for a small blog like mine it’s not holding anyone else’s attention. When I write, I want to write for an audience, and even though people read this, it doesn’t feel like enough.

On Saturday, as my technical book club was wrapping up, I said something funny, and Zee indicated interest in subscribing to my newsletter. “Hrmm,” I thought, “maybe a newsletter is what I need to write to write again.”

And but so, I am starting a newsletter called Open Source and Feelings. I expect it to be more conversational and scattershot than my blog posts, and I’ll be putting out the first one near the end of May. Expect excerpts and responses to online articles and a bit of editorial on my part. It’s a letter from me to you, a place to start conversations.

Make Better Mistakes isn’t going away, but posts will continue to be infrequent, and I will post to the blog when I have a one thing to say on a topic.

Cheers!

Your Pal from the Internet,

    Strand

postscript Sign up below! (I am excited.)

Open Source and Feelings

Open Source and Feelings is a fortnightly newsletter.

What’s it about? The day I wrote this I said: empathy, open source, community, Ruby, social systems, language, and relationships. Topics are liable to change quickly, your mileage may vary. I am not a doctor or lawyer.

powered by TinyLetter

The work is never done

As I left Ruby on Ales a few weeks ago I was sad, sad that I didn’t hug a few colleagues, sad that we only got a few words in with each other. I was sad that our time together was so short.

For me conferences are like family reunions. I get to touch base with people I haven’t seen in a while, and see how life is treating them. Many of my conference friends bring their partners along; many conference goers’ partners are doing the same work they are.

We are a close knit tribe. When a day of talks is over at a conference, we go to dinner, we share drinks, we talk about what we are working on for work and what we are working on for fun. We stay up too late drinking in each others company.

So I get really upset when death and rape threats are made against someone telling Twitter they felt uncomfortable at a conference. I get angry when someone is doxed. And I get sad when someone loses their job because… ?

This isn’t what my corner of the tech world is, even on the bad days. The people I choose to work with make safe space for all. Maybe I’m naïve, but I believe our conferences and our companies should be safe places for everyone. For women, for people of color, for transfolk, for queers, sometimes they feel really unsafe. I’m glad that Codes of Conduct are becoming standard issue, and that conferences are focusing on increasing attendance for marginalized groups.

This work isn’t done. The work is never done. We can do better.

Hold ⌘Q to Quit

One of Chrome’s features that I really love is the “Warn Before Quitting” option under the Chrome menu, which prevents the program from quitting with a message saying “Hold ⌘Q to quit.” displaying for a second or two before the browser closes.

Unfortunately, that feature only exists in chrome, and I have fat fingers everywhere. So last night I asked on Twitter, “Lazyweb: Any way to make Google Chrome’s “Hold ⌘Q to quit” (Google blog post explaining the feature) the default across OSX?”

My friend @perisaccadic responded that KeyRemap4MacBook has that feature. I looked at the documentation last night, and KeyRemap4MacBook has a lot of key remapping features. Setting it to prevent quitting on accidental keypresses isn’t hard, but it isn’t obvious either. Here’s how you do it.

  1. Install KeyRemap4MacBook and restart your computer.
  2. Go to “System Preferences…” under the Apple menu, and select KeyRemap4MacBook.
  3. Under “Custom Shortcuts” select “Hold Command+Q to Quit Application.” There are a lot of menus under the “Change Key” tab, and I recommend using search box at top and just searching for “quit.”
  4. Select the Key Repeat tab and adjust the “[Holding Key to Key] Holding Threshold”, which has a default of 200ms. I set this to 2000ms, as I want to have half a breath before I close my programs, your mileage may vary. This option is the third from the bottom.

Then system-wide you’ll have to hold down ⌘Q, rather than bumping it by accident and losing whatever you were working on.

Hold ⌘Q to Quit

One of Chrome’s features that I really love is the “Warn Before Quitting” option under the Chrome menu, which prevents the program from quitting with a message saying “Hold ⌘Q to quit.” displaying for a second or two before the browser closes.

Unfortunately, that feature only exists in chrome, and I have fat fingers everywhere. So last night I asked on Twitter, “Lazyweb: Any way to make Google Chrome’s “Hold ⌘Q to quit” (Google blog post explaining the feature) the default across OSX?”

My friend @perisaccadic responded that KeyRemap4MacBook has that feature. I looked at the documentation last night, and KeyRemap4MacBook has a lot of key remapping features. Setting it to prevent quitting on accidental keypresses isn’t hard, but it isn’t obvious either. Here’s how you do it.

  1. Install KeyRemap4MacBook and restart your computer.
  2. Go to “System Preferences…” under the Apple menu, and select KeyRemap4MacBook.
  3. Under “Custom Shortcuts” select “Hold Command+Q to Quit Application.” There are a lot of menus under the “Change Key” tab, and I recommend using search box at top and just searching for “quit.”
  4. Select the Key Repeat tab and adjust the “[Holding Key to Key] Holding Threshold”, which has a default of 200ms. I set this to 2000ms, as I want to have half a breath before I close my programs, your mileage may vary. This option is the third from the bottom.

Then system-wide you’ll have to hold down ⌘Q, rather than bumping it by accident and losing whatever you were working on.

Triangles, Man

Yesterday I was working on building out some arrows to bring attention to content. The request was to have a box with some content with an arrow from the top that makes it look like a speech bubble.

I came up with this:

speech bubble arrow Based on CSS Arrows and Shapes Without Markup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Colors
$white:             #ffffff
$greya:             #aaaaaa

.bubble
  background:       $white
  border:           1px solid $greya
  padding:          10px
  font-weight:      bold
  position:         relative

.bubble.arrow
  &:before, &:after
    content:        ' '
    height:         0
    width:          0
    position:       absolute
  &:before
    top:            -10px
    left:           87px
    border-left:    10px solid transparent
    border-right:   10px solid transparent
    border-bottom:  10px solid $white
  &:after
    z-index:        -1
    top:            -12px
    left:           85px
    border-left:    12px solid transparent
    border-right:   12px solid transparent
    border-bottom:  12px solid $greya

The effect has a diagonal border that follows the arrow as it juts out, and this is done by faking a border, a triangle with a z-index of -1 is placed below the initial triangle. The :before pseudo-element generates a 10px white triangle, while the :after pseudo element generates a background 12px grey triangle.

Not bad, but it’s pretty repetitive. Moreover, it’s hard to tell from the code that the video bubble’s arrow is on the top.

We can express this more clearly and succinctly. First we abstract out the arrow:

Rewrite step one - note that the values of the existing arrow are used as defaults while structure is set in place.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
@mixin arrow($size: 10px, $shadow: 1px, $position: 85px)
  $shadow-size:     $size + ($shadow * 2)
  &:before, &:after
    content:        ' '
    height:         0
    width:          0
    position:       absolute
  &:before
    top:            -$size
    left:           $position + ($shadow * 2)
    border-left:    $size solid transparent
    border-right:   $size solid transparent
    border-bottom:  $size solid $white
  &:after
    z-index:        -1
    top:            -$shadow-size
    left:           $position
    border-left:    $shadow-size solid transparent
    border-right:   $shadow-size solid transparent
    border-bottom:  $shadow-size solid $greyc
...
.bubble.arrow
  @include arrow

Nothing fancy is going on here, but taking a moment to get the structure in place and check that our math is clear make the next step easier.

It becomes a bit apparent at this point that we’re re-using a triangle pattern for both the arrow and it’s border. We can shake that out too:

Bring triangles out of the arrow
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
@mixin triangle($color, $size, $offset)
  top:              -$size
  left:             $offset
  border-left:      $size solid transparent
  border-right:     $size solid transparent
  border-bottom:    $size solid $color

@mixin arrow($size: 10px, $shadow: 1px, $position: 85px)
  $shadow-size:     $size + ($shadow * 2)
  &:before, &:after
    content:        ' '
    height:         0
    width:          0
    position:       absolute
  &:before
    @include triangle($white, $size, $offset + ($shadow * 2))
  &:after
    z-index:        -1
    @include triangle($greyc, $size + ($shadow * 2), $offset)
...

It looks pretty good, and then we get another request… Can we make it so the the arrow comes out of the left side in some contexts, too.

First we put in the structure to accommodate a fourth argument, $position:

Bring triangles out of the arrow
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
@mixin triangle($color, $size, $offset, $position: top)
  @if $position == top
    top:            -$size
    left:           $offset
    border-left:    $size solid transparent
    border-right:   $size solid transparent
    border-bottom:  $size solid $color

@mixin arrow($size, $shadow, $offset, $position)
  &:before, &:after
    content:        ' '
    height:         0
    width:          0
    position:       absolute
  &:before
    @include triangle($white, $size, $offset + ($shadow * 2), $position)
  &:after
    z-index:        -1
    @include triangle($greyc, $size + ($shadow * 2), $offset, $position)

.bubble.arrow
  @include arrow(10px, 1px, 85px, top)

Then we can add another conditional for the left arrow, and voila a modular arrow giving our dialog boxes a speech bubble playfulness.

The finished product
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@mixin triangle($color, $size, $offset, $position)
  @if $position == top
    top:            -$size
    left:           $offset
    border-left:    $size solid transparent
    border-right:   $size solid transparent
    border-bottom:  $size solid $color
  @if $position == left
    left:           -$size
    top:            $offset
    border-top:     $size solid transparent
    border-bottom:  $size solid transparent
    border-right:   $size solid $color

@mixin arrow($size, $shadow, $offset, $position)
  &:before, &:after
    content:        ' '
    height:         0
    width:          0
    position:       absolute
  &:before
    @include triangle($white, $size, $offset + ($shadow * 2), $position)
  &:after
    z-index:        -1
    @include triangle($greyc, $size + ($shadow * 2), $offset, $position)

.bubble
  background:       $white
  border:           1px solid $greya
  padding:          10px
  font-weight:      bold
  position:         relative

.bubble.top_arrow
  @include arrow(10px, 1px, 85px, top)

.bubble.left_arrow
  @include arrow(10px, 1px, 12px, left)

This technique can easily extend to the right and bottom sides of the box, and shows how the flexibility of Sass speeds up development, especially if you can break down your styles into small, reusable parts.

Apprenticeships as a Competitive Advantage

A business that chooses to train knowledge workers in whatever domain is in demand is likely to find that at the end of the day they have a competitive advantage. I think that you could start a small business today based solely on this principle and be a leader in your field within five years.

I recently read Why Good People Can’t Get Jobs a short book by Peter Cappelli, and found his argument incredibly compelling.1 For a variety of risk-averse reasons companies today make a practice of not filling job openings unless they have the perfect candidate. In the past, to fill a position which required special knowledge some companies would train promising candidates, but the nature of the jobs marketplace in the last few decades has made them overly-cautious of investing in training programs as they fear their employees will walk away after getting training.

For instance, a business that chooses to hire non-programmers and teach them to program will have a competitive advantage in their field. For this reason, based solely on the fact that LivingSocial started an apprenticeship program, I would place money on LivingSocial doing better than GroupOn in the next few years. LivingSocial recognized that without an influx of developers they wouldn’t be able to reach future business goals, and that it is cheaper to train devs than to (continually) recruit them.

I wonder if a web development consultancy cooperative could be formed based off of this insight. If you had a group of half experienced devs and half less experienced but dedicated trainees pairing together, you might find diamonds in the rough rather than paying market rates for diamonds. Of course, this sort of idea could be applied to any sort of business rooted in knowledge work, which is all of them.


  1. That’s an Amazon Affiliate link. The book was short, but this interview with the author is shorter and covers the key points.

Birthday

On my twenty-ninth birthday I got let go from the job I had been on for less than two months. I was hired on at a low rate to move files between servers, and I decided to write a PowerShell script to speed up the process. I improved productivity by an order of magnitude. As in, my project manager told me “the guy who was doing this before you would do in a day what you’re doing in an hour!” They were really excited to have me working so efficiently that they gave me a raise, and I was glad to be tweaking a shell script to do this. (Incidentally, if you’re in a Windows environment, don’t use your own shell script to do this, run robocopy.)

I’d been unemployed for a long while, and I was just glad to be working again. And on top of that I got to program a bit–sure Windows PowerShell wasn’t my preferred environment–but it was great to fix a problem with some code.

And then they gave me the call. I was working from home the day before my birthday, and I had ended up taking a long late lunch with my partner. I had a shell script running at home. I was on the bus home when one of the recruiters at the consultancy called me and let me know that this was my last day. I brought in my equipment the next day, and that was that.

The only jobs I’ve ever been let go from were ones I didn’t like that much in the first place. In this case I accelerated my departure from the project by doing the work very effectively.

“[Developers’] principal work is human communication to organize the users’ expressions of their needs into formal procedure. That work will be necessary no matter how we change the life cycle. And it’s not likely to be automated.”Peopleware, Tom DeMarco and Timothy Lister

About a month ago, I started working as a web developer for Contour. This is the job that I wanted a year ago. This is the job I was hoping for while I was teaching myself Rails while visiting my family in Guangzhou.

I’m really glad to be working where I am, I like the company and my coworkers and I find the work challenging. I’m planning to take the steps I need to really level up in this role, including taking a nine-month night course on Ruby and Rails at UW. I’m finding it difficult to find the time outside my forty-hour work week to focus on self-teaching, let alone finding the time to contribute to open source. (My apologies to Ryan Bigg, I haven’t been able to review much of Rails 3 in Action at all yet.)

This struggle between work and life balance, it’s to be expected, especially when you actually have a life outside of work.

This weekend I turned thirty, and celebrated with barbecuing, beer, backyard reading, blueberry scones, and a new backpack. I’m beginning to figure out what I want to do with the one life I’ve been given, and I’m really glad to be working a job that I like. The weekends go by so quickly, and the workweek seems to move even faster. I’m blocking the time I can to learning what I can. And I’m really happy that I convinced myself I could teach myself to code well enough to be a professional, I think that it’s going to be a really satisfying career.

How to Create a Local Sandbox Facebook App

Note: this walkthrough only handles UNIX-y environments, like Linux and MacOS.

Facebook makes it easy to get started developing an app that integrates with their service, but I ran into a snag that confused me when I was trying to test my app locally. Here’s what I did to resolve the error below, which is thrown when you first try to log in on the Facebook Ruby-based app on localhost:

{
“error”: {
“message”: “Invalid redirect_uri: Given URL is not allowed by the Application configuration.”,
“type”: “OAuthException”,
“code”: 191
}
}

To get started login to https://developers.facebook.com/ with your Facebook account and click Get Started. Under Create a Facebook App, click on Developer App and Create New App, Name it (“Brony Finder”), Give it a Namespace (“og_brony”) and click the ticky-box for Heroku web hosting. I grumbled at having to provide a mobile telephone or credit card, and then moved on.

Select your environment and the email address you would like this Heroku app to be associated with, in my case, Ruby and strand@bettermistak.es. Your new app lives at https://thing-stuff-1234.herokuapp.com/. Mine was https://electric-robot-2715.herokuapp.com/.

Login to Heroku and head to ”My Apps” Click on general info and copy the git address under Git Repo. Go to the command line and in the directory you want the code to live in enter the following

git clone git@heroku.com:electric-robot-2715.git # Clone your app.
cd electric-robot-2715/ # Move into the app directory.
echo FACEBOOK_APP_ID=12345 >> .env # Add your App ID to the local environment.
echo FACEBOOK_SECRET=abcde >> .env # Add your secret to the local environment.
bundle install # Install gem dependencies.
gem install foreman # Install Foreman.
foreman start # Start Foreman.

Navigate to localhost:5000 in your browser and click “Log In.” Oh no! you get OAuthException 191! This had me stuck for a few hours, and all I found were a few confusing Stack Overflow posts about it.

Facebook verifies that all requests for your app are coming from the right domain–they don’t allow requests from localhost or 127.0.0.1–and this info can be updated in your apps settings under Hosting URL. Add “local.herokuapp.com” to your Hosting URLs and save this setting. Then edit your /etc/hosts file so that local content is under the domain local.herokuapp.com. This file is hidden, so from the command line enter sudo vi /etc/hosts. (Substitute your favorite editor for vi.) We need to use sudo, because this file is locked. Add the line “127.0.0.1 local.herokuapp.com” below “127.0.0.1 localhost” and save and quit your text editor.

Hit control-c and run foreman start again. Now test your app at http://local.herokuapp.com:5000/.

Happy Hacking!