Back in August, I ordered an Ergodox from MassDrop – Cherry MX Blues, an aluminium top plate, and hardware programmable keyboarding was in my future.

It took a long time for it to get here. Plagued by problems in their supplychain, MassDrop finally got all the pieces together around December, and shipped them off to be assembled for those of us who didn’t want to try their hand at sauldering. It finally showed up on my doorstep last week—though I was so excited that I met the UPS guy in my driveway.

I’m typing on it now. But I didn’t at first. The keys were in such radically different positioning that I couldn’t properly strike the keys. For about 48 hours I could barely type at all. I wondered if I’d made the right choice.

I took a bit of time and kept working. Things were getting slightly easier, but I still was below 70% of my former speed. I decided to try to “get work done” on my second day and just go back to my laptop keyboard. Of course, my fingers had already begun to adjust to the new keyboard layout, and so I couldn’t type on that either. It was a serious wakeup call that I’d basically set out to reprogram my own wetware and become dependent on this thing. Here’s hoping that it’s the last keyboard I buy :)

But after a few days I got very proficient. I’m even faster at using this keyboard as an alternative to a mouse because I almost never have to pick my hands up off the home rows. The fact that it has layers and thumb keys made a huge difference.

So I finally settled on a layout.

There are several things about this layout that I absolutely love:

  • The "[", "]", "{", "}" keys are in a similar place, and more reachable. It currently takes a bit longer to think about the fact that I have to “toggle” level 1, but I expect that to go away quickly.
  • The up, down, left, and right navigation keys are on level 1 directly over the H, J, K and L keys. This allows me to use vim-like movement in any program simply by toggingling the layer with my left or right thumb.
  • Having the LGUI / CMD key under my left thumb makes it so that it is used by the same finger, but in a much more accessible spot.
  • I cannot type with backspace in the upper right anymore. Taking your hand off home row to backspace as much as I do is nonsense.
  • The two keys that are above the main thumb keys are pretty useless, but I find them fairly useful for volume and for combining with other keys (I have the alt above the command key so that I can do command-alt easily)
  • I thought I would miss Caps lock being mapped as CTRL, but now, since CTRL is under my thumb, having escape there is great.
  • I use the (mostly worthess for typing) inner keys to navigate through the layers. Cycles fairly nicely.
  • The bottom rows are mostly useless, but I like having a place for seldom-used keys that doesn’t mean a big arm movement.

All in all, so far I’m loving it. I’m back up to about 90% of my previous speed, but my hands are much more comfortable and I do not have any wrist strain or numbness.

Next step is to tent these slightly and to try to figure out the best positioning for my trackpad. Great investment and totally worth it. Try one if you ever get the chance… but know that it will take quite a while to get used to!

Comments

Last weekend I participated in the Global Day of Code Retreat here in Austin. I was impressed at the diveristy of participants, the overall good nature of those there, and what I was able to learn even while pairing with relative beginners.

When I got there, there were 3 women and 3 men in the room. By the end of the day there were about 6 women and 10 men. At least 6 of the participants grew up in foreign countries. It was, for a computer meetup on a Saturday, a fairly diverse crowd. I was impressed.

We started off by pairing on the Conway’s Game of Life problem. Initially we did no tests (intentionally) and just cowboy coded it. We got pretty far, but it was difficult to verify results by hand. We ended up spending a lot of time figuring out how to display the board. We progressed through several exercises: No loops, 5 lines of code limit, tests-first, no objects, and behavior/rules oriented approaches. Every exercise had some level of frustration, but they were all enjoyable and I learned a lot.

By far, the most frustrating part of the day was having to delete your code. I did so, but I was surprised at how attached I became to a set of code in 45 minutes. How much more likely am I to become attached to an implementation I’ve worked on for 3 weeks?

I also learned a lot from doing the “no objects” exercise. It was incredible how fast we were able to implement once constructing objects was out of the way. I was amazed at how much it pointed me toward Functional programming paradigms like filters, etc. And it made it much easier to see what kind of object to create rather than coming up with some idea of what should be before you created it. When I got home I CMD-Z’d my way back to this exercise and examined and refactored it. I know that’s against the spirit, but I really enjoyed it and learned a lot from it.

All in all, a great day. Good food and good fun and good learning. Hope to do a virtual code retreat sometime soon either with coworkers or random pair partners.

Comments

Pairing is hard, but to me, the hardest part about remote pairing is not technology or even logistics, it’s collaboration and problem solving together. To that end, there are multiple pairing styles that are worth looking at when you’re trying to pair with someone knew. Each style facilitates collaboration differently and knowing how they work helps.

Driver / Navigator

Fundamental Idea One partner “drives” at the keyboard, focusing on implementing. The other partner “navigates” verbally, focusing on big ideas, questions, typos, and conventions.

Strengths

  • Great for “unequal” pairing partners / mentoring (let the less experienced ‘drive’)
  • Let’s someone with a highly customized environment work effectively without inhibiting the navigator
  • Great for “thinking through” big problems you’re solving.
  • Easy tech setup, can just use screen share.

Weaknesses

  • Can lend itself toward one partner becoming less engaged (Driver is only copying what is said, Navigator stops talking)
  • Equal partners may desire more “take turns” kind of approach
  • Driver learns less tech, navigator learns less theory/big ideas
  • Weaker on TDD, small problems, repetitive solutions

Trade off / Taking Turns

Fundamental Idea Partners take turns driving and navigating, perhaps with a 15-20 minute timer.

Strengths

  • Both partners get to learn tech and think about big ideas
  • Keeps both partners engaged
  • Great for partners of similar skill levels
  • Still good for thinking through problems
  • Can sync code via git to allow for current driver to use their own environment.

Weaknesses

  • Hard if host environment is unfamiliar for either pair
  • Harder to “mentor”, but still a viable option

Ping-pong

Fundamental Idea Partners take turns by making all tests pass, writing a failing spec and passing control to the other partner.

Strengths

  • Great for exercises
  • Keeps both partners engaged
  • OK for mentoring or more equal pairing

Weaknesses

  • Really difficult in unfamiliar environment
  • Nearly requires a terminal sharing/buffer sharing style of pairing
  • Bad for big problems, communication is most effective through tests, easy to psych yourself out otherwise.

Conclusion

Which pair style you pick will be up to you and your pairing partner, but it’s worth considering what kind of problem you have and what your relationship is with your partner. My general rule of thumb is, for small exercises, do Ping-Pong pairing. For real world problems with unequal skill levels, do Driver-Navigator with the less experienced person driving. For real world problems with equal skill levels, trade off to keep things interesting. YMMV.

Comments

As developers, we have a tension that we almost always deal with, the tension between writing the best possible solution and the fastest possible solution. Usually we end up somewhere between them, sacrificing a bit of quality for speed. I’ve yet to hear of a developer that would say they sacrificed a bit of speed for quality—but isn’t that what we want to do?

For myself, I’ve always struggled with this balance. What we want is to continually improve quality and deliver features quickly and readily. Can we do both?

I think we can, but it still requires discipline. How many times have you been able to begin a project, full of hope in it’s future quality, only to find yourself skipping tests and throwing around bad naming practices just to get something out on time? I know that’s happend countless times for me.

So what discipline does it require? I think we can learn a bit from the construction industry. We often throw about the metaphor of a “foundation” to build upon. Usually we’re refering to the framework or other technologies—our app is the bricks and mortar, wood and drywall. But what you see with each step of building a house is that the “foundation” that is currently in place is allowed time to firm up and be solid before building on top if it. The slab exists and is completely hardened before you add your frame. Your frame is complete before you add drywall or a roof. Your drywall is complete before you paint. There’s plumbing and electric that has to be thrown in all along the way, and then there are finishing touches that need the entire structure to be “complete.”

For us, that means building up and firming up a data model before you allow it to be built on top of. As you build, it still may require small changes, but what we must recognize is that a small change threatens everything built on top of it. The more stable your foundation the more confident you’ll be in building on top of it.

So my idea here is that when you are heading toward quality, focus on firming. When you’re focused on delivering, build on top of what’s firm — if it’s not firm, push back and say “guys, this isn’t firm enough for us to be building features on yet. Let’s spend time letting it firm up.”

Comments

There are lots of skills a developer has to have, but one of the ones you really need to have if you ever want to make a living is being able to interview well. There are lots of things that make interviewing a challenge, but if you interview well you’ll learn something at the least and get a job offer at the most.

Let’s talk about how to interview well.

1. Be Brutally Honest

While I’m sure you can lose job opportunities by being honest, you can’t really lose the right job opportunities by being honest. If you don’t know something, just say it. If you know something you’re not good at, point it out. If you know something you are good at, point that out too, but don’t oversell yourself. Be confident in the fact that you are worth being hired even if you’re far from perfect. They aren’t either.

2. Be Sincerely Humble

If someone asks you how you’d rank yourself in a technology like Javascript on a scale from 1-10, take the number you think you might be at and ratchet it down. Anyone who is interviewing with me and says they are a 9 or a 10 on anything needs to be writing books or conducting classes on the topic. You might be a 9 or a 10, but in all likelihood you’re average or below average in most technologies you work with. Give an honest and humble perspective of yourself—this sets expecations later when they drill you about escoteric things a 9 or a 10 should know.

3. Be Enthusiastic

Come to an interview with lots of enthusiasm. Be yourself—you don’t have to fake it. Just find things you’re excited about and show that through your body language and the way you speak. Listen well, engage people, talk and ask lots of questions. Questions show curiosity and who doesn’t like to be thought of as interesting?

4. This is a Two Way Street

You’re interviewing them as much as they’re interviewing you. You want to know what kind of company they are, what culture they have, and what issues they have as a team. They’re trying to size you up, but you should be sizing up the company too. How do they make decisions? How do they deal with conflict? How do they organize code? How do they work on a day to day basis? What can you expect if you show up on day one? What about day 31? What about day 301?

Sometimes you can’t ask these questions directly because they are hard to answer. If you can ask to come into the office and pair program with someone or sit in on a few meetings, that will give a great bit of insight into how an organization works. You might not be allowed to do these things, but it never hurts to ask. Also, consider what an organization that says “no, you can’t pair program with us before committing” is really saying. Maybe it’s security, but maybe it’s just a lack of transparancy? Consider what an organization says by it’s actions and policies.

5. Try to learn something

From every single interview you’re in, you have an opportunity to learn something. You can learn how another organization manages their code review process or how another developer does some trick in VIM. In this respect interviewing can be beneficial to your current employer. Even interviewing with companies that you don’t have much interest in can give you general information that is hard to obtain otherwise (and I’m not talking about proprietary information). You can get a sense of the technologies some other companies are trying to use and how they use it. You can also get ideas about processes you can take with you to any other employer. How do they do scrum? How does she handle conflict in the team? How do they code review? How have they tried to maintain culture while they’re growing?

6. Interview while you’re employed

This last one is much more circumstancial, so if you’re not employed at the moment, you might not be able to do anything about this. If you are employed, make sure you continue to interview! I try to keep my ear to the ground and interview at least once a quarter with another company. Because I’m always trying to learn something, this usually becomes beneficial to my current employer, but it is almost always beneficial to me.

Beyond that, if you don’t need a job it’s much easier to be very honest and make sure the new gig would really be a good fit. It’s also much easier to negotiate a better situation when you’re already in a good one. Don’t wait until your current job is in bad shape before you start interviewing elsewhere.

Conclusion

Interviewing well is a great skill. The more you practice it the better you’ll become and the more opportunities you’ll have. Remembering that a successful interview does not necessarily mean you get a job makes a big difference. Look at every interview as an exploration of future opportunities. Some doors will open and others will close, but you can learn stuff either way.

Comments

A New Way to Level Up?

A few weeks ago at LSRC, Katrina Owen mentioned exercism.io as a site she set up for people to go learn new things, get feedback and head toward better code.

I was intrigued. I have always loved small, easily finishable exercises that allowed me to think about things OTHER than the exercise itself. I tried a few and quickly became hooked.

But the thing that really surprised me was not just how hooked I was on leveling up on the exercises, but how hooked I was on reading other people’s code and providing feedback on it. It was fascinating to see how many different ways someone else solved the same little problem. Little differences like naming to big differences like Functional vs. OO approaches to problems become easy to evaluate. It also becomes clear where certain solutions shine and where they don’t.

Room for improvement

There are a few little things that it struggles with. This is not meant as a tear down, but rather as a recognition of the limitations of the system and ways it could improve.

It’s easy for the “one true solution” to be cargo culted down. Instead of giving feedback and trying to nudge their solution toward something slightly better, it’s much easier to just try to nudge them toward your solution. There isn’t a great way around this, it seems, since you’re talking about how people work by default.

There’s also the feedback problem. You can give feedback to anyone who has submitted an exercise you’ve already had approved, which means that as you progress, there are fewer and fewer people evaluating your exercise. The point is the feedback more than the solution, so little feedback causes you to disengage from the site over time. This is solvable by getting the experts to focus first on the latest exercises and getting more experts involved overall. It’s still hard, though.

Finally, as the UI expands, it is becoming clear that it’s hard to do UI for programmers. They all want to look at data 1000 different ways but UI is about compromise and saying no most of the time. This is a piddly detail, though in the grand scheme of things.

But filling a void

But it is great at what it does.

  • It gives you direct, real experience on programming languages (that you may or may not know yet) with experts looking at and evaluating your solution.
  • It gives you the ability to look at and evaluate other people’s code. This makes you more open and better at solving problems
  • It gets you thinking about refactoring in a much bigger way. Refactoring in the small leads to refactoring in the large, though it’s still a hard transition.

I am very impressed with the niche that it does fill already. I hope some of the kinks get ironed out and that Exercism is around in a few years as the de facto way to learn a new language, level up in a language you already know, or help newbies out. Can’t wait to see how it pans out.

The other night, I got to pair with @piisalie to learn some Emacs and work through a little exercism.io.

Paul is a relatively new developer, but he’s been studying under the tutelage of @jeg2 and getting ramped up very quickly as a result. It’s neat to see people who are able to absorb so much so quickly.

Setup

  • Google+ Hangouts
  • TMUX + Emacs (Ahhhhhhhhhhh!!)

Paul was pretty familiar with Emacs and did a good job showing me around. We worked on a small exercise and I tried to do as much of the editing as possible as he guided me when I said “how do I move up and down again?”

Takeaways

  • Exercism is a great way to think through a bunch of ways to solve a small problem
  • Emacs is neat in that…
    • it can actually contain a shell within a buffer and that shell is editable.
    • the mnemonics are easier to remember
    • it’s easy to test out config changes in the scratch buffer
    • fuzzy searching is built in
  • Emacs is crazy (mostly in comparison to VIM) in that…
    • nearly every command has a prefix (C-x, C-c), which seems like insanity when you compare moving around/highlighting in VIM with hjkl. It reminds me of TMUX, which is much more tolerable because you’re not switching panes multiple times per second
    • it seems much larger than VIM is
    • The default Emacs on my Mac is version 22, Paul had version 24. VIM is at 7.3 on nearly every system I’m using.
    • it is not VIM and my brain explodes.

All in all, a good session. I’m glad I have a better understanding of Emacs and that I understand some things that I specifically like about VIM and a couple of things that I like about Emacs. Looking forward to pairing with Paul again where we can actually work on something real.

On to the next pairing session…

Comments

Chris Hunt gave a great presentation at LA Ruby Conf about VIM+TMUX. There, he shows you a bunch of cool things you can do with VIM and TMUX.

But he doesn’t tell you how to do them.

So here, I’m going to list each of the things he does and give you the keystrokes/information you need to do what he’s talking about.

TMUX

For these shortcuts, the prefix is mapped to C-b (i.e. Ctrl-b) — though I believe it is much faster and more comfortable to map it to C-a. Chris even maps his to C-j so you use two different hands.

  • 3:51 – List Keyboard Shortcuts – C-b ?
  • 4:06 – Chris Hunt’s TMUX Config
  • 4:30 – Create New Window – C-b c
  • 4:35 – Rename Window – C-b ,
  • 4:39 – Change Windows Absolute – C-b 0|1|2|3|4|5
  • 4:39 – Change Windows Relative – C-b n|p
  • 4:46 – Switching to Last Used window C-b l
  • 4:49 – Split Window vertically into Panes – C-b %
  • 4:52 – Split Window horizontally into Panes – C-b "
  • 6:18 – See List of sessions – C-b w
  • 7:06 – Auto-start iTerm with tmux tmux attach -t hack || tmux new -s hack
  • 11:10 – Detach from session – C-b d
  • 17:50 – Make a new, shared tmux session tmux -S /tmp/pair new -d math && chmod 777 /tmp/pair && tmux -S /tmp/pair attach
  • 19:14 – Attach to a shared tmux session tmux -S /tmp/pair attach

VIM

  • 7:30 – Fuzzy search with CtrlP
    • C-p [search] to find files
  • 8:22 – Profject wide search with Ag
    • :Ag [text] to find text
  • 9:18 – Surround
    • change double quotes to single quotes while within double quotes: cs"'
    • change [ to ( while within square brackets: cs[(
  • 10:39 – Aligning code with Tabular
    • :Tabularize /<regex to match>/
  • 12:18 – Run bundle within vim :!bundle
  • 13:23 – Create new spec file :e spec/math_spec.rb
  • 14:22 – Running tests within VIM – Gary Bernhardt’s RunTests in .vimrc
  • 15:44 – Make a Gist of the current buffer with :Gist (Gist-Vim)
  • 19:56 – Using the Arglist for global search and replace
    • Find all files :args ag -l MyAwesomeApp .
    • View args :args
    • Execute a replace across files (with confirmation) :argdo %s/MyAwesomeApp/ToDoApp/gc | w
  • 21:54 – VIM Macros
    • To start recording Esc q a
    • To stop recording, in command mode, q
    • To execute recording, in command mode, @a
    • To execute multiple times, in command mode 9@a
    • To execute across arg files: :argdo norm @a
Comments

At the Lone Star Ruby Conference, Dave Thomas talked about Elixir to everyone. I found it kindof interesting that there were no loops and the use of if was discouraged. It was neat to see that everything was idempotent and that pattern matching made certain problems incredibly easy to solve with very little code.

So when I found exercism.io and saw that they had an Elixir track, I jumped on it. What I’ve noticed is that solving problems in a functional way changes the way that I code in an OO language. It doesn’t mean I want everything to be a function and never have state, but I want each method on an object to have no side effects and to require an absolute minimum of internal state to function.

Let’s look at some examples from the Exercism Elixir track.

Pattern Matching

The Fibonacci sequence is an oft-asked puzzle question since it requires knowledge of recursion and proper branching conditions. In Elixir, it breaks down very simply because of pattern matching.

fib.exs
1
2
3
4
5
defmodule Fib do
  def fib(0), do: 0
  def fib(1), do: 1
  def fib(n), do: fib(n-1) + fib(n-2)
end

Since Elixir looks for the first match when a function is called, Fib.fib(1) matches line 3, and Fib.fib(2) matches line 4, which calls fib(1) + fib(0) which then match lines 2 and 3. Impressive, no?

Guards

Guards allow you to pattern match based on a property of the values being passed to the function. This lets you test the types without having to have branches inside your function. There are only a few expressions that can be used as guards.

dna.exs
1
2
3
4
5
6
7
8
9
defmodule DNA do
  def to_rna(strand) when is_binary(strand) do
    String.replace(strand, "T", "U")
  end

  def to_rna(strand) when is_list(strand) do
    to_rna(list_to_binary(strand)) |> to_char_list
  end
end

This allows you to have a single interface for Lists, Binarys, Bitstrings and Tuples, even if the logic for each one is quite different. Since they’re all separated, it becomes very easy to maintain..

Cond

Cond is an interesting construct, similar to case, but without an initial argument. It is more like saying case true …. As a result, it’s very easy to pattern match on anything.

bob.exs
1
2
3
4
5
6
7
8
9
10
11
12
def hey(string) do
  cond do
    is_silent?(string) ->
      "Fine. Be that way."
    is_asking?(string) ->
      "Sure."
    is_shouting?(string) ->
      "Woah, chill out!"
    true ->
      "Whatever."
  end
end

Pipelining

Since it’s really common to work on the result of one function in another function, but you don’t have objects which keep internal state, Elixir and Erlang have the idea of pipelining.

word-count.exs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
defmodule Words do
  def count(sentence) do
    sentence |> normalize |> find_words |> count_words
  end

  defp count_words(words) do
    Enum.reduce(words, HashDict.new, fn(word, dict) ->
      HashDict.update(dict, word, 1, &1 + 1)
    end)
  end

  defp find_words(sentence) do
    Regex.scan(%r/\w+/, sentence)
  end

  defp normalize(string) do
    String.downcase(string)
  end
end

Pipelining is really just a shorthand for passing the result of one function in as the first argument for the next function. As you can see on line 3, this makes it very easy to read the order in which you would think of things. “Take a sentence, normalize it, find the words in it, count the words you found.”. The other way to write this would be count_words(find_words(normalize(sentence))). It works, but it’s harder to read and you end up with lots of right-parens.

While there’s nothing super special about this, I have found it very useful for readability, and that’s a huge part of programming.

Binarys, Strings and Lists – Oh My.

One of the most confusing things about Elixir (and Erlang) when I started off is that 'abc' != "abc" because one is a list of characters (i.e. [A?, B?, C?]) and one is a UTF8 binary (i.e. <<65, 66, 67>>).

You can convert one into the other, though, if you are trying to work that way:

convert.exs
1
2
3
4
5
# 'ABC' to "ABC"
list_to_binary('ABC') # => "ABC"

# "ABC" to 'ABC'
to_char_list("ABC") # => 'ABC'

But the best thing to do is to think of them as two very separate things. If you’re working with Strings, you’re really working with UTF8 encoded binaries. If there are valid UTF8 codes contained inside the binary, you’ll get a string returned. If not, you’ll get a generic binary. Understanding this difference is crucial for working with Strings in Elixir, especially when coming from another language like Ruby.

The Documentation

Lastly, I learned how to find things in the documentation. Understanding how the standard library works is key to being effective in any language, and the available docs are okay. They’re not great though. Lots of holes and sometimes it’s difficult to understand exactly what an argument does.

Concurrency

This is the key part of Elixir and I have to admit that I know very little about it. I intend to explore it more as I go forward and hopefully write another post outlinging what I’ve learned.

Going forward

Elixir is a neat langauge. I think it will do more to influence developers in other languages than it will become a production ready system, but either way, it has taught me a handful of ideas that make me consider what advantages functional programming has and how I can incorporate them into my day to day work. Looking foward to diving in more.

Comments

I’ve followed the Pomodoro Technique for a few years now. I’ve tried several different tools to get it where I want, but in the last few months I’ve begun using AppleScript to automate things that I want done in my environment every time I start/finish a Pomodoro.

I use Things as well to keep track of my tasks. I think GTD and the Pomodoro Technique are a wonderful marriage where GTD gets to keep track of the What and the Pomodoro Technique motivates to to actually make progress. It’s all too easy to feel like you’re making progress by simply moving tasks around and “getting organized.”

So when I combined these two techniques, I used Pomodoro.app — which is no longer available on the App Store, but you can easily download it and compile it with XCode.

I have 4 scripts that I use for managing the link:

Start
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
tell application "System Events" to if exists process "Things" then
  tell application "Things"
    set pomoName to "$pomodoroName"
    set createToDo to true
    repeat with todayToDo in to dos of list "Today"
      set toDoName to name of todayToDo
      if toDoName starts with pomoName then
        set createToDo to false
      end if
    end repeat

    if createToDo is true then
      set newToDo to make new to do with properties {name:pomoName} at end of list "Today"
    end if
  end tell
end if

do shell script "cp /etc/hosts ~/.old-hosts; sudo echo '127.0.0.1 facebook.com www.facebook.com netflix.com movies.netflix.com twitter.com youtube.com www.youtube.com' >> /etc/hosts; dscacheutil -flushcache" with administrator privileges

This script finds a TODO with the appropriate name and creates it. Pomodoro.app tries to do this, but it doesn’t work when you add [X] to the title to indicate the number of pomos.

It also blocks facebook, netflix, twitter, and youtube so you can reduce your distractions automatically during your pomo.

Interrupt
1
2
3
4
5
6
7
8
9
10
tell application "System Events" to if exists process "Things" then
  tell application "Things"
    repeat with possibleToDo in to dos of list "Today"
      if name of possibleToDo starts with "$pomodoroName" then
        set currentName to name of possibleToDo
        set name of possibleToDo to currentName & " [']"
      end if
    end repeat
  end tell
end if

During an interruption, this marks a small [‘] on your task. This lets you see which kinds of tasks get you interrupted the easiest when looking over your day.

Reset
1
do shell script "sudo mv ~/.old-hosts /etc/hosts; dscacheutil -flushcache" with administrator privileges

When you reset your pomo, this unblocks all the websites that you originally blocked.

End
1
2
3
4
5
6
7
8
9
10
11
12
tell application "System Events" to if exists process "Things" then
  tell application "Things"
    repeat with possibleToDo in to dos of list "Today"
      if name of possibleToDo starts with "$pomodoroName" then
        set currentName to name of possibleToDo
        set name of possibleToDo to currentName & " [X]"
      end if
    end repeat
  end tell
end if

do shell script "sudo mv ~/.old-hosts /etc/hosts; dscacheutil -flushcache" with administrator privileges

After a successful pomodoro, this script finds the task you were working on in Things and adds a [X] to the end of the title so you can see how many pomos you actually spent on it.

It also unblocks the blocked websites.

All this together makes for easy to prep, easy to review, and relatively distraction-free work.