Write once, copy once, refactor once.

This post is about effectively using your time. It is not a defence of taking on huge technical debt to make your life easier for a single day, and you are hopefully smart enough to avoid doing that. It’s just a simple approach to growing a system you’re working on while avoiding duplication of effort and over-engineering.

Write once.

The first time you have to do it, just get it done. You’ll be in the best position to improve your solution once it actually exists, by knowing real things about how well it solves your problem. Plus, at that point, it’s already solving your problem.

You may be tempted to figure out the best solution before writing anything, which in my experience is a huge waste of time. If you haven’t written it yet, figuring out which bells and whistles to add is time-consuming and error-prone.

Copy once.

You got it done, a week passes, and a new problem comes up that feels almost the same. Assuming you can’t just use the thing you wrote before, you can:

  1. Refactor your code to make the original useable in both spots.
  2. Copy your code to the new spot.

Most people want to refactor now, but I think you should copy. Why?

It is very hard to determine patterns from just two examples.

With two instances, statements about the group as a whole are wild guesses. A simple illustration — consider these two numbers: 1, 2, …

The next number might be 4, 3, 1, 57, or anything else. No clear pattern shows up, because two data points only have one relationship, and patterns are formed from the relationships between things. Try three numbers: 1, 2, 3, …

4 is next, and I’m sure you saw it coming. This example is admittedly a little weak, but it clearly illustrates that patterns can leap out at 3 things, while being unclear at 2. With three things, you can have up to three relationships, and similarities between multiple relationships are way easier to be think about than similarities between … one.

Refactoring after two instances

Let’s say you chose to refactor. You put the shared code somewhere ideal for the two cases you know, and rewrite the tests.

Two weeks later, the problem shows up elsewhere. Is the code useable right away in this new spot? If you’re like me, you gave your abstraction the smallest scope necessary, and you’ll probably have to move it again. You parameterized the minimum amount required, and you may have to add new controls. That was all wasted time and effort.

So just copy it!

Almost no effort needed. You’ll probably have to refactor in two weeks, but you didn’t waste the time today.

Objections to copying things:

“I might forget to update a copy later!”

“Copying and pasting leads to typos!”

These are both valid points. In the first case, making synchronized changes might lead you to refactor (after all, you’ve already written once and copied once), and in the second case, the risks aren’t as big they seem. The second case has a nastier form:

“That’s not DRY!”

Not repeating yourself is a well known rule, and endless repetition is obviously bad, but I caution readers to ensure that they aren’t following DRY blindly. You should consider things like the following:

  • will your code be easier to read with a copy, or with a new abstraction?
  • will the abstraction that makes sense today last beyond tomorrow?
  • will a bad abstraction be harder to remove than repetition is?

As for copies and typos, most people are intelligent and careful enough to deal with a single copy well. The real horror stories occur when you make several copies (3+) of something and they’re all just a little bit different. Don’t make three or more copies: just copy once.

Refactor once.

Back to that choice from earlier: say you’d copied it instead of refactoring. Now it’s two weeks later and you hit a third instance of the problem.

As a quick aside, the “third instance” may just be a need to change your code in both copies. This is a sufficient condition to refactor. Two distant, identical pieces of code needing similar non-trivial changes is a great way to create a bug by messing up minor differences of context. After you’ve written once and copied once, the next step in this approach is always to refactor once.

With three instances, you have a good chance of finding patterns. A quick refactor here is going to yield even better code than a slow, thoughtful one would have with just two instances of the problem. Context rules.

Before we move on, what exactly does “having three instances of the problem” and “the next step is refactoring it” mean? There are two paths upon discovering you need the code a third time:

  1. Make a third copy just to see how it fits and that it works, then refactor.
  2. Jump straight to refactoring the first two, and just apply the solution.

The first choice takes longer, but is safer: your code never leaves a working state. This is a little bit like long-division. In complex situations, or when you’re less experienced, it’s best to write everything down. You’ll know which feels right when you’re in this position.

The Fourth Instance

What if two weeks after your refactor step, you hit the problem yet again, and for some reason you can’t just use your past work? Why not write once, refactor twice? Or write once, copy twice, refactor once?

In my experience, the fourth-instance-that-doesn’t-fit-the-pattern is surprisingly rare. Refactoring at the third instance is usually good enough for a long time, so doing it then minimizes the odds that you’ll have to refactor the same thing twice in a short period.

As for copying twice and refactoring at the fourth instance… this gets back into that “three copies or more” zone, where it gets hard to keep minor differences between your solutions straight. Feel free to try, but I bet you’ll find it to be a serious, bug-causing hassle.

Write once, copy once, refactor once.

  1. It’s faster.
  2. It’s only slightly more error prone, if at all.
  3. It will probably yield better code in the end.

So do what the title says.

google should do this

“Okay google, would it be faster to take the subway or walk to the nearest UPS store?”

I asked my phone that today and really thought it might spit back a useful response. That’s the level of magic we’ve come to expect form our phones. It didn’t answer the question, and my response was mild disappointment instead of thinking “man wouldn’t it be cool if my phone could do THAT” — I feel reasonably sure that someday soon, it will.

65 Possible questions for a future study — what would you ask?

I spent this morning at Union Station in Toronto, Ontario, standing in a space that allowed me to see the transition space between the Subway concourse and Union Station proper. For a little over an hour and a half, I stood, taking notes on possible questions to ask or variables to measure in a possible upcoming study. The requirements for a good question or variable are that it must be visually discernable from 50 meters away, and that it be discretely answerable either with a chosen collection of qualitative descriptors, a quantity, or as a yes/no response.

Many of the questions that I wrote must assume a context, like “count the people who are exhibiting a property at a given moment”, or “measure this across time” or in correlation with another variable.

I would love to hear other ideas for questions, or what questions anyone who might read this think sound interesting. I’m currently in the process of contacting the correct people to gain permission to perform this study by placing a camera or accessing their CCTV system.

Here they are:

  1. Are people moving in an intentional direction, or passively with the crowd?
  2. Given particular visual information about stairway / corridors, what do people choose (e.g. avoid a full stairway, how full, etc.)
  3. Flow rate of people in/out of doors, onto/off-of, on stairs, and on flat areas per unit time
  4. Colour of clothing — both in aggregate, and broken down by gender, time, fullness of platform
  5. Fullness of platform, broken down by time, maybe in 30 second increments?
  6. Door choice for entry/exit (total counts, counts per time range)
  7. Apparent ethnicity, compared to time and to cohort’s apparent ethnicity
  8. People following other people or navigating on their own or noticeably separately from the person in front of them
  9. Distinctive religious symbols (crosses, turbans, burqas, payots, etc.)
  10. Angles — 90 degree turns vs diagonal navigation, especially in relation to intentional vs passive motion
  11. Average time spent in the system per person, at various points in time
  12. Time of year, also weather: temperature, humidity, cloud cover, brightness
  13. Suits, Casual wear, Tie-colour, jackets/no jackets, long sleeves vs t-shirts, pants v. shorts, dresses vs. skirts,
  14. wearing headphones
  15. reading books, reading newspapers, reading phones
  16. origin <-> destination map over time, e.g. subway to Union, Union to ground level
  17. number of trips, collisions, falls, sudden changes of direction, especially in correlation with weather, following, angles, speed, and fullness
  18. backpacks, purses, laptop bags, suitcases, rolling luggage, packages
  19. shoe type: running shoe, dress shoe, sandals, flats, heels
  20. apparent hair colour, by time and by cohort and overall
  21. apparent age, by time and by cohort and overall
  22. apparent gender, by time and by cohort and overall
  23. ‘footedness’ — which foot do people step onto the stairs with first & last, up and down? by gender?
  24. handedness — which hand to people hold doors with versus footedness
  25. location, timing, and duration of stay for buskers and beggars
  26. strollers, pregnant women
  27. canes, crutches, walkers, wheelchairs, seeing eye dogs
  28. facial expressions, by time, by gender, by following/intentional, by footedness
  29. directional facing at given instants, over time
  30. pidgeon count and location, pidgeon-collectors
  31. gum chewing and spitting
  32. where are people looking — up, down, in front of them, sideways
  33. eye colour (certainly infeasible to collect)
  34. # runners, per time and overall
  35. glasses-wearers, sunglasses-wearers, google-glass-wearers
  36. #steps at a time, by gender, by time of day
  37. haircut styles, hair length
  38. loiterers
  39. food — are people eating or carrying it, and their speed, following vs intentional, gender, age, time of day, etc.
  40. train arrival and departure times
  41. skateboards and bikes
  42. apparent weight of people at given times & given behaviours
  43. people whistling (probably not collectable)
  44. garbage bin use, litterers
  45. people asking other people questions
  46. people in pairs, in groups, actively discussing things, effects on themselves and people around them
  47. lanyards worn
  48. people talking on phones
  49. people who hold the rail or do not
  50. hat wearing and styles, over time, in total, by weather
  51. umbrellas by weather, gender, at given times
  52. security personnel, cleaning staff, construction workers, by location and time
  53. smokers, by location and behaviour, gender, time, weather
  54. day of the week
  55. coffee, thermos, other drinks, actively drinking, carrying multiple
  56. obstruction by flow — trying to get through a crowd going against you
  57. “clever” people who take a long or unusual route, perhaps confidently
  58. “confused” people who stop and look around helplessly or move very slowly while taking in their surroundings
  59. Stride length and tempo, limps, speed-adjustments (high and low speed per person for example) in given situations, at given times, etc
  60. Where do people put their hands? In pockets, at sides, behind back, on backpack, etc.
  61. Tendency of groups to clump vs tendency to expand and keep distance, over time and by gender / ethnicity maybe
  62. musical instruments
  63. footstep style (stompy, light, jogging, half-step at a time)
  64. manifestation of fears (as a pidgeon flew by, one woman suddenly cowered and crouched looking scared, then realized everything was fine, stood up and moved along)
  65. hunches / postures

Anyway, that’s about all I’ve got for now. Please tell me about other possible things to watch / checkout that may be informative for the usefulness and efficiency of the space, or suggest that topics I’ve already put up are stupid or good ideas, to help decide what I actually measure.

Ludum Dare 30.

I wrote my award-winning* thought process up in a post on the actual ludum dare crowd blog thing, and will maybe link to everything I write there from here. That may not be much. Look forward to a timelapse video of my failure, though! And maybe a half-playable game!

  1. Took a long time to settle on an idea
  2. Framework chosen: Phaser
  3. Sleep Time!
  4. First Screenshot of The Traveller
  5. Now Comes the Hard Part

* not a fact

Late, half-baked crap

Recently, I had a reminder that overall, a lot of things just don’t get done.

It’s rarely a conspicuous lack of a thing getting done that reminds me — instead, it’s the surprised, positive reaction from people when things do get done. We simply couldn’t muster such shock and joy if most things just… got finished.

It’s easy to assume that other people get stuff done. Certainly people finish stuff at work, do taxes, and fill out medical forms. But outside that — keeping up with friends and colleagues, participating in clubs and sports, or working on side projects — it’s tough to tell. You see each of your own failures, and mostly hear about other people’s successes. So it’s easy to imagine that you’re worse than average at doing stuff.

But we all forget to send emails and to look things up. We all fail to keep in touch with friends who we meant to stay connected with. It may seem too late to send a greeting, or to finish something you said you’d get done. It may seem like you just haven’t done enough yet. At any rate, it would feel embarrassing to send it now.

Fortunately though, these rare reminders about how bad we all are can teach us a powerful lesson, which is that late, half-baked crap is more than people expect.

All you need to do is beat the world’s low expectations

The easy way out of these situations is to not do anything. Just put it down and don’t think about it. As long as it’s not work, taxes, or health stuff, the problem will usually just go away. So that’s what most of us do. Nothing. And that’s most of us expect, too. Nothing.

But nothing is only what it looks like. Most people actually do get started. We do take the first steps toward finishing stuff. Maybe just a bit late, or something makes us put it aside incomplete. Then life happens, time passes, and embarrassment keeps us silent. So it looks like nothing got done at all.

So no one expects anything of you. Which is great news!

Because you probably have a pile of late, half-baked crap lying around. Stuff you meant to do a long time ago, or that just needs a little more work. You occasionally remember it and cringe, thinking it’s too late now. False. It’s time to send it off — just apologise if you’ve gotta. Set aside the prideful embarrassment for a moment and think about this:

They aren’t expecting anything from you — or anyone

If it’s so late that you feel embarrassed about sending it, the person has probably forgotten about it, or moved on. They’re not expecting anything now, so this is unexpected gravy. You may just make their day. They won’t be angry that you’re late, or didn’t do enough, they’ll be glad that you did something. The vast majority of people can’t manage that. Your late, half-baked crap may even amaze them.

No matter what, it’s better than nothing.