make better_mistakes

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!

FizzBuzz in Ruby

As a quick followup to this week’s earlier post demonstrating FizzBuzz in CoffeeScript, I give you FizzBuzz in Ruby.

FizzBuzz in CoffeeScript

This afternoon I had an interview which I arrived twenty minutes early for. I wondered if they might have me do a demonstration of coding skills, and remembered that @kerrizor is sometimes asked to use FizzBuzz to demonstrate competency in interviews.

So while I was waiting in the lobby, I decided to generate FizzBuzz in CoffeeScript. This is what I came up with: