Canonical Voices

What Larry Price talks about

Snappy Libertine

Libertine is software suite for runnin X11 apps in non-X11 environments and installing deb-based applications on a system without dpkg. Snappy is a package management system to confine applications from one another. Wouldn’t it be cool to run libertine as a snap?

Yes. Yes it would.

snapd

The first thing to install is snapd itself. You can find installation instructions for many Linux distros at snapcraft.io, but here’s the simple command if you’re on a debian-based operating system:

1
$ sudo apt install snapd

Ubuntu users may be surprised to find that snapd is already installed on their systems. snapd is the daemon for handling all things snappy: installing, removing, handling interface connections, etc.

lxd

We use lxd as our container backend for libertine in the snap. lxd is essentially a layer on top of lxc to give a better user experience. Fortunately for us, lxd has a snap all ready to go. Unfortunately, the snap version of lxd is incompatible with the deb-based version, so you’ll need to completely remove that before continuing. Skip this step if you never installed lxd:

1
2
3
4
$ sudo apt remove --purge lxd lxd-client
$ sudo zpool destroy lxd                 # if you use zfs
$ sudo ip link set lxdbr0 down           # take down the bridge (lxdbr0 is the default)
$ sudo brctl delbr lxdbr0                # delete the bridge

For installing, in-depth instructions can be found in this blog post by one of the lxd devs. In short, we’re going to create a new group called lxd, add ourselves to it, and then add our own user ID and group ID to map to root within the container.

1
2
3
4
5
6
$ sudo groupadd --system lxd                      # Create the group on your system
$ sudo usermod -G lxd -a $USER                    # Add the current user
$ newgrp lxd                                      # update current session with new group
$ echo root:`id --user ${USER}`:1 >> /etc/subuid  # Setup subuid to map correctly
$ echo root:`id --group ${USER}`:1 >> /etc/subgid # Setup subgid to map correctly
$ sudo snap install lxd                           # actually install the snap!

We also need to initialize lxd manually. For me, the defaults all work great. The important pieces here are setting up a new network bridge and a new filestore for lxd to use. You can optionally use zfs if you have it installed (zfsutils-linux should do it on Ubuntu). Generally, I just hit “return” as fast as the questions show up and everything turns out alright. If anything goes wrong, you may need to manually delete zpools, network bridges, or reinstall the lxd snap. No warranties here.

1
2
3
4
5
6
7
8
9
10
11
$ sudo lxd init
Do you want to configure a new storage pool (yes/no) [default=yes]?
Name of the new storage pool [default=default]:
Name of the storage backend to use (dir or zfs) [default=zfs]:
Create a new ZFS pool (yes/no) [default=yes]?
Would you like to use an existing block device (yes/no) [default=no]?
Would you like LXD to be available over the network (yes/no) [default=no]?
Would you like stale cached images to be updated automatically (yes/no) [default=yes]?
Would you like to create a new network bridge (yes/no) [default=yes]?
What should the new bridge be called [default=lxdbr0]?
What IPv4 address should be used (CIDR subnet notation, “auto” or “none”) [default=auto]?

You should now be able to run lxd.lxc list without errors. It may warn you about running lxd init, but don’t worry about that if your initialization succeeded.

libertine

Now we’re onto the easy part. libertine is only available from edge channels in the app store, but we’re fairly close to having a version that we could push into more stable channels. For the latest and greatest libertine:

1
2
$ sudo snap install --edge libertine
$ sudo snap connect libertine:libertined-client libertine:libertined

If we want libertine to work fully, we need to jump through a couple of hoops. For starters, dbus-activation is not fully functional at this time for snaps. Lucky for us, we can fake this by either running the d-bus service manually (/snap/bin/libertined), or by adding this file to /usr/share/dbus-1/services/com.canonical.libertine.Service.service

/usr/share/dbus-1/services/com.canonical.libertine.Service.service
1
2
3
[D-BUS Service]
Name=com.canonical.libertine.Service
Exec=/snap/bin/libertine.libertined --cache-output

Personally, I always create the file, which will allow libertined to start automatically on the session bus whenever a user calls it. Hopefully d-bus activation will be fixed sooner rather than later, but this works fine for now.

Another issue is that existing deb-based libertine binaries may conflict with the snap binaries. We can fix this by adjusting PATH in our .bashrc file:

$HOME/.bashrc
1
2
# ...
export PATH=/snap/bin:$PATH

This will give higher priority to snap binaries (which should be the default, IMO). One more thing to fix before running full-force is to add an environment variable to /etc/environment such that the correct libertine binary is picked up in Unity 8:

/etc/environment
1
2
# ...
UBUNTU_APP_LAUNCH_LIBERTINE_LAUNCH=/snap/bin/libertine-launch

OK! Now we’re finally ready to start creating containers and installing packages:

1
2
3
4
$ libertine-container-manager create -i my-container
# ... (this could take a few minutes)
$ libertine-container-manager install-package -i my-container -p xterm
# ... (and any other packages you may want)

If you want to launch your apps in Unity 7 (why not?):

1
2
$ libertine-launch -i my-container xterm
# ... (lots of ourput, hopefully an open window!)

When running Unity 8, your apps should show up in the app drawer with all the other applications. This will all depend on libertined running, so make sure that it runs at startup!

I’ve been making a lot of improvements on the snap lately, especially as the ecosystem continues to mature. One day we plan for a much smoother experience, but this current setup will let us work out some of the kinks and find issues. If you want to switch back the deb-based libertine, you can just install it through apt and remove the change to /etc/environment.

Read more

2016 Retrospective

This has been a unique year for me, and I wanted to quickly lay out what I’ve accomplished and where I think I’m going for the coming year. This is now officially a tradition at three posts (see: 2014 and 2015).

Revisiting 2016’s Goals

These are the goals I set for myself at the start of the year and how I met or missed them:

  • Spend Money
    • I wanted to become less of a miser and spend more money. Note that this is not for bragging purposes, just that I am naturally very frugal and hesitant to spend money. I think we did a pretty good job, though! For starters, I swapped out my commuter car for a tech-heavy crossover. We stayed in a really cool art-hotel in downtown Cincinnati in the Spring, drove across the country for a big Yellowstone trip in early Summer, stayed at the Indiana Dunes for a few days in the Fall, and took a brief trip to Madison, WI, shortly thereafter. I bought a nice sitting/standing desk and chair for my home office. I paid the entry fee to go to GenCon for a day. Our fridge, dishwasher, and furnace all died one weekend, and it ended with me buying upgraded, modern appliances. I’ve also been keeping the post office busy with plenty of orders off Amazon, and I’ve been trying to Kickstart more games that I think deserve attention. I also found a new hobby in homebrewing which has been a great use of fun-money.
  • Back Into Web
    • At the start of 2016, I though I really wanted to do more web work. Turns out I’ve done a 180 on this one, and I now work on primarily desktop/mobile with minimal web work, and I wouldn’t have it any other way for the time being.
  • Work With Others
    • In 2015, I worked alone a lot. In 2016, I joined a new company where I work remotely. Although I don’t necessarily see my coworkers every day, I am working on projects with multiple developers and communicating constantly with my teammates (and others) through chat. Working with others again has helped me grow socially and become a better engineer.
  • Become Part of an Open-Source Community
    • I really wanted to better integrate FLOSS into my life and my career, and I believe I’ve hit the jackpot. My job is to build popular open-source operating system Ubuntu, where all the code I write is public and generally GPLv3. My job is to write open-source software, and to interact with the community. I use my own software and report/fix bugs that affect me all the time.
  • Good Vibes
    • I was feeling a bit down at the end of 2015, and I wanted to be a more positive person in 2016. Although there were some depressing things going on worldwide in 2016, I am generally happier with my personal and professional life on a micro-level.

Surprise Victories

  • New Job
    • The big one! After almost four years at SEP, I transitioned to a new role at Canonical. I get to work on Ubuntu, one of my favorite open-source projects, as my full-time job. This also means I get to work remotely, dropping my commute from 30 miles in 2012 to 3 miles in 2014 to 50 feet in 2016. I’ve been having a great time working on software that’s in the public spotlight, working with the community, and traveling every few months to see my coworkers. With this new job, I’ve also had the opportunity to visit Europe for the first time this year.
  • Less Own-Time Work
    • Although I’ve hit pretty hard in the past that developers should do some learning outside of work, this year likely contained the least own-time work I’ve ever done. I’ve been finding joys in non-software hobbies and home maintenance, and working on Ubuntu as my full-time job has made me less needy for doing open-source work in my off-hours. I tend to respond to bugs and Github PRs at any hour, and I follow more technical people on social media than I used to. I think this stems from a satisfaction from the learning I do throughout the day, and the difficulty of separating work-life and home-life when one works at home.
  • FOSDEM
    • Yesterday, I learned that I’ll be giving a talk at FOSDEM. I’m very excited (and nervous) to give my first-ever conference talk in Brussels this February.
  • Homebrewing
    • I picked up homebrewing beer at the start of 2016, and I love it. I started with simple pre-made extract kits, but have worked my way up to creating my own all-grain recipes and labels. Brewing is a fun, tasty hobby giving me some creative, manual labor to break the mold of always doing computer work.
  • Books
  • Spotify
    • Spotify is very good for listening to whatever music I want anytime, especially now that I work at home. If you really like a band, you should still buy their music or merch through their website to make sure they get paid to keep existing.

2017 Goals

  • Local
    • I’d like to make sure I stay involved locally, especially as I continue to work from home. I’ve let my Golang group dwindle over the past few months, and I’d like to see us back up to our numbers at the start of 2016. If possible, I’d also like to attend other meetups and meet more local devs.
  • Linux Greybeard
    • This is a slow process, but I want to get better at using Linux in general. I’ve been surprised at how much I’ve learned about the low-level workings of Ubuntu over the past 9 months. I’m excited to see what I can learn over the next year, especially as I’ll likely move into a different codebase at some point this year.
  • More talking
    • I’m very excited to be giving a talk at FOSDEM this year, but I would enjoy doing such things more regularly. It doesn’t necessarily have to be at conferences, as I could do meetups much more easily. I need to try to get back into blogging more regularly. Additionally, I’ve recently been kicking around ideas for a discussion-based podcast on the worst parts of software development, although that may have already been done to death. Contact if interested.
  • Transition Web Tooling
    • I would like to switch over my analytics systems to use a personal Piwik instance, and I would love to replace the (hopefully unobtrusive) ads on this site with some kind of tip jar system. I would also like to update this blog to use a Let’s Encrypt certificate, as well as Ollert once I’ve been given full control.
  • Kegging
    • In my homebrewing, I’ve been bottling my beers. This is generally ok, but I think the beer would be consumed faster if I kegged it and could fill growlers for my friends and family. Getting started with kegging is expensive, requiring the purchase of kegs, tanks, parts, and some sort of refrigeration unit. By the end of the year, I intend to have a kegerator-style setup with the ability to stow and distribute from two kegs.
  • Moving
    • My wife is looking into graduate schools for Fall 2017, and has already been accepted by one. I’m currently assuming a big part of my life this Spring/Summer will be finding and adjusting to a new home.
  • Active Activism
    • I’ve complained a lot about our government and the way the world works on social media, at the “water cooler”, and privately to my wife, but it’s become obvious that passive activism isn’t good enough. Signing petitions and pledges are nice gestures, but are more meaningful when backed up by real action. I’d like to do something, though I’m not sure what at the moment. By the end of 2017, I would like to, at minimum, have a plan to donate, join, create, or generally be more involved.

Adieu, 2016

Major changes in my life, career, and the world at large have made 2016 a memorable year for me. I highly encourage you to reflect on the year you’ve had and think about what you can do to make 2017 great. Happy new year!

Read more

Looking for the code? Look no further: https://github.com/larryprice/pingus-snap

In my last post, I demonstrated creating a snap package for an application available in the archive. I left that application unconfined, which is taboo in the long run if we want our system to be secure. In a few steps, we can add the necessary components to confine our pingus snap.

For reference, this is the original snapcraft.yaml file for creating a pingus snap, except that we’ve updated the confinement property to strict:

snapcraft.yaml
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
name: pingus
version: '0.1'
summary: Free Lemmings(TM) clone
description: |
    Pingus is a free clone of the popular Lemmings game.
    |
    Your goal is to guide a horde of penguins through a world full of obstacles
    and penguin traps to safety. Although penguins (unlike lemmings) are rather
    smart, they sometimes lack the necessary overview and now rely on you to
    save them.

grade: devel
confinement: strict

parts:
  archives:
    plugin: nil
    stage-packages:
      - pingus
  env:
    plugin: dump
    organize:
      pingus.wrapper: usr/bin/pingus

apps:
  pingus:
    command: pingus

If you’re feeling bold, you can build and install the snap from here, but be warned that this led me into an ncurses nightmare that I had to forcibly kill. That’s largely because pingus depends on X11, which is not available out-of-the-box once we’ve confined our snap. If we want to use X11, we’re going to need to connect to it using the snap-land concept of interfaces. Interfaces allow us to access shared resources and connections provided by the system or other snaps. There’s some terminology to grapple with here, but the bottom line is that a “slot” provides an interface which a “plug” connects to. You can see a big list of available interfaces with descriptions on the wiki. Our pingus app will “plug” into the X11 interface’s “slot”:

snapcraft.yaml
1
2
3
4
5
6
# ...
apps:
  pingus:
    command: pingus
    plugs:
      - x11

You can build and install the new snap with the --dangerous flag for your local confined snap. After that, you can verify the interface connection with the snap interfaces command:

1
2
3
4
5
6
7
8
9
$ snapcraft
$ sudo snap install --dangerous pingus_0.1_amd64.snap
pingus 0.1 installed
$ snap interfaces
Slot                     Plug
:alsa                    -
# ...
:upower-observe          -
:x11                     pingus

Now, when we run pingus… it works! Well, video works. If you want sound, we’ll also need the pulseaudio interface:

snapcraft.yaml
1
2
3
4
5
6
7
# ...
apps:
  pingus:
    command: pingus
    plugs:
      - x11
      - pulseaudio

Once again: build, install, and run… et voilà! Is it just me, or was that surprisingly painless? Of course, not all applications live such isolated lives. Make note that the x11 interface is supposed to be a transitional interface, meaning that we would rather our app fully transition to Mir or some alternative. To go a step further with this snap, we could create a snapcraft.yaml to build from source to get the absolute latest version of our app. At this point, we can change our grade property to stable and feel good about something that we could push to the store for review.

Any code you see here is free software. Find the project here: https://github.com/larryprice/pingus-snap

Read more

If you haven’t heard, snaps are a new, modern packaging format made by the guys at Ubuntu. Snaps give every app a confined environment to live in, making desktops more secure and dependencies less of a hassle. One common way to create a snap is to simply use existing packages from the Ubuntu archives.

Let’s try to create a snap for the game pingus. pingus is a great little Lemmings clone that we can easily convert to a snap. We’ll start by installing the necessary dependencies for snap building (see the snapcraft website for more):

1
$ sudo apt install snapcraft

Now we can initialize a project directory with snapcraft:

1
2
$ mkdir -p pingus-snap && cd pingus-snap
$ snapcraft init

snapcraft init creates the following sample file to give us an idea of what we’ll need to provide.

snapcraft.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
name: my-snap-name # you probably want to 'snapcraft register <name>'
version: '0.1' # just for humans, typically '1.2+git' or '1.3.2'
summary: Single-line elevator pitch for your amazing snap # 79 char long summary
description: |
  This is my-snap's description. You have a paragraph or two to tell the
  most important story about your snap. Keep it under 100 words though,
  we live in tweetspace and your description wants to look good in the snap
  store.

grade: devel # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots

parts:
  my-part:
    # See 'snapcraft plugins'
    plugin: nil

Most of these values for our pingus snap should be obvious. The interesting markup here is in parts, which is where we’ll describe how to build our snap. We’ll start by taking advantage of the nil plugin to simply unpack the pingus deb from the archive. We define our list of debs to install in a list called stage-packages. We’ll also define another section, apps, to tell snapcraft what binaries we want to be able to execute. In our case, this will just be the pingus command. Here’s what my first draft looks like:

snapcraft.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
name: pingus
version: '0.1'
summary: Free Lemmings(TM) clone
description: |
    Pingus is a free clone of the popular Lemmings game.
    |
    Your goal is to guide a horde of penguins through a world full of obstacles
    and penguin traps to safety. Although penguins (unlike lemmings) are rather
    smart, they sometimes lack the necessary overview and now rely on you to
    save them.

grade: devel
confinement: devmode

parts:
  archives:
    plugin: nil
    stage-packages:
      - pingus

apps:
  pingus:
    command: usr/games/pingus

Nice, right? Building and installing our snap is easy:

1
2
3
$ snapcraft
$ sudo snap install --devmode pingus_0.1_amd64.snap
pingus 0.1 installed

We used devmode here because our app will be running unconfined (a topic for another blog post). Now, for the moment of truth! The snap tools automatically put our new app in PATH, so we can just run pingus:

1
2
$ pingus
/snap/pingus/x2/usr/games/pingus: 2: exec: /usr/lib/games/pingus/pingus: not found

¡Ay, caramba! We’ve run into a fairly common issue while snapping legacy software: hardcoded paths. Fortunately, the corresponding pingus executable is very simple. It’s trying to execute a command living in /usr/lib/games/pingus, which is not in our snap’s PATH. The easiest way to fix this is to fix the pingus executable. Since we don’t want to spend time modifying the upstream to use a relative path, we can create our own version of the pingus wrapper locally and copy it into our snap. The only change to this new wrapper will be prepending the snap’s install path $SNAP to the absolute paths:

pingus.wrapper
1
2
#!/bin/sh
exec $SNAP/usr/lib/games/pingus/pingus --datadir $SNAP/usr/share/games/pingus/data $@

Now we can update our yaml file with a new part called env which will use the dump plugin to copy our wrapper file into the snap. We’ll also update our command to call the wrapper:

snapcraft.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ...

parts:
  archives:
    plugin: nil
    stage-packages:
      - pingus
  env:
    plugin: dump
    organize:
      pingus.wrapper: usr/bin/pingus

apps:
  pingus:
    command: pingus

When you run snapcraft this time, the env part will be built. After performing another install, you can run pingus, and you should be greeted with one of the best Lemmings clones available! Because we’re running unconfined in devmode, this all just works without any issues. I intend to write another blog post in the near future with the details on confining pingus, so look out for that soon. I may also go into detail on building more complex cases, such as building snaps from source and building custom plugins, or reviewing a case study such as the libertine snap.

For much, much more on snaps, be sure to visit snapcraft.io. If you’re looking for a published version of pingus as a snap, you can try sudo snap install --devmode --beta pingus-game, and you can run the game with pingus-game.pingus.

Source code available at https://github.com/larryprice/pingus-snap.

Read more

Whether I’m adding dependencies, updating package names, or creating new package spins, I always have issues testing my debian packages. Something will work locally, only to fail on jenkins under a clean environment. Fortunately, there’s a nifty tool called pbuilder that exists to help out in these situations. pbuilder uses a chroot to set up a clean environment to build packages, and can even be used to build packages for systems with architectures different from your own.

Note: All code samples were originally written from a machine running Ubuntu 16.10 64-bit. Your mileage may vary.

Clean builds for current distro

Given a typical debian-packaged project with a debian directory (control, rules, .install), you can use debuild to build a package from your local environment:

1
2
3
4
5
$ cd my-project
$ debuild
...
$ ls ../*.deb
my-project.deb

This works pretty well for sanity checks, but sometimes knowing your sane just isn’t quite enough. My development environment is filled with libraries and files installed in all kinds of weird ways and in all kinds of strange places, so there’s a good chance packages built successfully on my machine may not work on everyone’s machine. To solve this, I can install pbuilder and set up my first chroot:

1
2
3
4
$ # install pbuilder and its dependencies
$ sudo apt-get install pbuilder debootstrap devscripts
$ # create a chroot for your current distro with build-essential pre-installed
$ sudo pbuilder create --debootstrapopts --variant=buildd

Since I use debuild pretty frequently, I also rely on pdebuild which performs debuild inside of the clean chroot environment, temporarily installing the needed dependencies listed in the control file.

1
2
3
4
$ cd my-project
$ pdebuild
$ ls /var/cache/pbuilder/result/*.deb
my-project.deb

Alternatively, I could create the .dsc file and then use pbuilder to create the package from there:

1
2
3
4
5
6
7
8
$ # generate a dsc file however you like
$ cd my-project
$ bzr-builddeb -- -us -uc
$ cd ..
$ # use pbuilder to create package
$ sudo pbuilder build my-project.dsc
$ ls /var/cache/pbuilder/result/*.deb
my-project.deb

Clean cross builds

Let’s say that you need to build for an older distribution of Ubuntu on a weird architecture. For this example, let’s say vivid with armhf. We can use pbuilder-dist to verify and build our packages for other distros and architectures:

1
2
3
4
5
6
7
$ # create the chroot, once again with build-essential pre-installed
$ pbuilder-dist vivid armhf create --debootstrapopts --variant=buildd
$ # the above command could take a while, but once it's finished
$ # we can attempt to build our package using a .dsc file
$ pbuilder-dist vivid armhf build my-project-dsc
$ ls ~/pbuilder/vivid-armhf_result/*.deb
my-project.deb

Custom, persistent chroot changes

In some cases, you may need to enable other archives or install custom software in your chroot. In the case of our vivid-armhf chroot, let’s add the stable-overlay ppa which updates the outdated vivid with some more modern versions of packages.

1
2
3
4
5
6
7
8
9
$ # login to our vivid-armhf chroot, and save state when we're finished
$ # if --save-after-login is omitted, a throwaway chroot will be used
$ pbuilder vivid armhf login --save-after-login
(chroot) $ # install the package container add-apt-repository for convenience
(chroot) $ apt install software-properties-common
(chroot) $ add-apt-repository ppa:ci-train-ppa-service/stable-phone-overlay
(chroot) $ exit
$ # update packages in the chroot
$ pbuilder-dist vivid armhf update

pbuilder and chroots are powerful tools in the world of packaging and beyond. There are scripting utilities, as well as pre- and post-build hooks which can customize your builds. There are ways to speed up clean builds using local caches or other “cheats”. You could use the throwaway terminal abilities to create and destroy tiny worlds as you please. All of this is very similar to the utility which comes from using docker and lxc, though the underlying “container” is quite a bit different. Using pbuilder seems to have a much lower threshold for setup, so I prefer it over docker for clean build environments, but I believe docker/lxc to be the better tool for managing the creation of consistent virtual environments.

Further reading:

Pbuilder HowTo on the Ubuntu wiki Pbuilder tricks from the debian wiki

Read more

I currently write a lot of python and C++. Although I religiously unit test my C++ code, I’m a bit ashamed to say that I haven’t had much experience with python unit testing until recently. You know how it is - python is one of those interpreted languages, you mostly use it to do quick hacks, it doesn’t need tests. Until you’ve written your entire D-Bus service using python, and every time you make a code change a literal python appears on the screen to crash your computer. So I’ve started writing a bunch of tests and found (as expected) a tangled mess of dependencies and system calls.

In many C-like languages, you can fix most of your dependency problems with The Big Three: mocks, fakes, and stubs. A fake is an actual implementation of an interface used for non-production environments, a stub is an implementation of an interface returning a pre-conceived result, and a mock is a wrapper around an interface allowing a programmer to accurately map what actions were performed on the object. In C-like languages, you use dependency injection to give our classes fakes, mocks, or stubs instead of real objects during testing.

The good news is that we can also use dependency injection in python! However, I found that relying solely on dependency injection would pile on more dependencies than I wanted and was not going to work to cover all my system calls. But python is a dynamic language. In python, you can literally change the definition of a class inside of another class. We call this operation patch and you can use it extensively in testing to do some pretty cool stuff.

Code Under Test

Let’s define some code to test. For all of these examples, I’ll be using python3.5.2 with the unittest and unittest.mock libs on Ubuntu 16.10. You can the final versions of these code samples on github.

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
39
from random import randint

class WorkerStrikeException(Exception):
    pass

class Worker(object):
    """
    A Worker will work a full 40 hour week and then go on strike. Each time
    a Worker works, they work a random amount of time between 1 and 40.
    """
    def __init__(self):
        self.hours_worked = 0

    def work(self):
        timesheet = randint(1, 40)
        self.hours_worked += timesheet
        if self.hours_worked > 40:
            raise WorkerStrikeException("This worker is picketing")

        return timesheet

class Boss(object):
    """
    A Boss makes profit using workers. Bosses squeeze 1000 monies out of a
    Worker for each hour worked. Workers on strike are instantly replaced.
    """
    def __init__(self, worker):
        self.worker = worker
        self.profit = 0

    def make_profit(self):
        try:
            self.profit += self.worker.work()*1000
        except WorkerStrikeException as e:
            print("%s" % e)
            self.worker = Worker()
            self.profit += self.worker.work()*1000
        finally:
            return self.profit

These are two simple classes (and a custom Exception) that we’ll use to demonstrate unit testing in python. The first class, Worker, will work a maximum of 40 hours per week before picketing it’s corporation. Each time work is called, the Worker will work a random number of hours. The Boss class takes in a Worker object, which it uses as it performs make_profit. The profit is determined by the number of hours worked multiplied by 1000. When the worker starts picketing, the Boss will hire a new Worker to take their place. So it goes.

Mocking the Worker Class

Our goal is to fully test the Boss class. We’ve left ourselves a dependency to inject in the __init__ method, so we could start there. We’ll mock the Worker and pass it into the Boss initializer. We’ll then set up the Worker.work method to always return a known number so we can test the functionality of make_profit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import unittest.mock
from unittest import TestCase

from corp import work  # your impl file

class BossTest(TestCase):
    def test_profit_adds_up(self):
        worker = unittest.mock.create_autospec(work.Worker)
        worker.work.return_value = 8
        boss = work.Boss(worker)
        self.assertEqual(boss.make_profit(), 8000)
        self.assertEqual(boss.make_profit(), 16000)
        worker.work.return_value = 10
        self.assertEqual(boss.make_profit(), 26000)

        worker.work.assert_has_calls([
            unittest.mock.call(),
            unittest.mock.call(),
            unittest.mock.call()
        ])

if __name__ == '__main__':
    unittest.main()

To run this test, use the command python3 -m testtools.run test, where test is the name of your test file without the .py.

One curiosity here is unittest.mock.create_autospec. Python will also let you directly create a Mock, which will absorb all attribute calls regardless of whether they are defined, and MagicMock, which is like Mock except it also mocks magic methods. create_autospec will create a mock with all of the defined attributes of the given class (in our case work.Worker), and raise an Exception when the attribute is not defined on the specced class. This is really handy, and eliminates the possibility of tests “accidentally passing” because they are calling default attributes defined by the generic Mock or MagicMock initializers.

We set the return value of the work function with return_value, and we can change it on a whim if we so desire. We then use assertEqual to verify the numbers are crunching as expected. One further thing I’ve shown here is assert_has_calls, a mock assertion to verify that work was called 3 times on our mock method.

You may also note that we subclassed TestCase to enable running this class as part of our unit testing framework with the special __main__ method definition at the bottom of the file.

Patching the Worker Class

Although our first test demonstrates how to make_profit with a happy worker, we also need to verify how the Boss handles workers on strike. Unforunately, the Boss class creates his own Worker internally after learning they can’t trust the Worker we gave them in the initializer. We want to create consistent tests, so we can’t rely on the random numbers generated by randint in Worker.work. This means we can’t just depend on dependency injection to make these tests pass!

At this point we have two options: we can patch the Worker class or we can patch the randint function. Why not both! As luck would have it, there are a few ways to use patch, and we can explore a couple of these ways in our two example tests.

We’ll patch the randint function using a method decorator. Our intent is to make randint return a static number every time, and then verify that profits keep booming even as we push workers past their limit.

1
2
3
4
5
6
7
8
9
10
11
12
@unittest.mock.patch('corp.work.randint', return_value=20)
def test_profit_adds_up_despite_turnover(self, randint):
    boss = work.Boss(work.Worker())
    self.assertEqual(boss.make_profit(), 20000)
    self.assertEqual(boss.make_profit(), 40000)
    self.assertEqual(boss.make_profit(), 60000)
    self.assertEqual(boss.make_profit(), 80000)

    randint.assert_has_calls([
        unittest.mock.call(1, 40), unittest.mock.call(1, 40),
        unittest.mock.call(1, 40), unittest.mock.call(1, 40)
    ])

When calling patch, you must describe the namespace relative to the module you’re importing. In our case, we’re using randint in the corp.work module, so we use corp.work.randint. We define the return_value of randint to simply be 20. A fine number of hours per day to work an employee, according to the Boss. patch will inject a parameter into the test representing an automatically created mock that will be used in the patch, and we use that to assert that our calls were all made the way we expected.

Since we know the inner workings of the Worker class, we know that this test exercised our code by surpassing a 40-hour work week for our poor Worker and causing the WorkerStrikeException to be raised. In doing so, we’re depending on the Worker/Boss implementation to stay in-sync, which is a dangerous assumption. Let’s explore patching the Worker class instead.

To spice things up, we’ll use the ContextManager syntax when we patch the Worker class. We’ll create one mock Worker outside of the context to use for dependency injection, and we’ll use this mock to raise the WorkerStrikeException as a side effect of work being called too many times. Then we’ll patch the Worker class for newly created instances to return a known timesheet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def test_profit_adds_up_despite_strikes(self):
    worker = unittest.mock.create_autospec(work.Worker)
    worker.work.return_value = 12
    boss = work.Boss(worker)

    with unittest.mock.patch('corp.work.Worker') as MockWorker:
        scrub = MockWorker.return_value
        scrub.work.return_value = 4

        self.assertEqual(boss.make_profit(), 12000)
        self.assertEqual(boss.make_profit(), 24000)

        worker.work.side_effect = work.WorkerStrikeException('Faking a strike!')
        self.assertEqual(boss.make_profit(), 28000)
        self.assertEqual(boss.make_profit(), 32000)

        worker.work.assert_has_calls([
            unittest.mock.call(), unittest.mock.call(), unittest.mock.call()
        ])
        scrub.work.assert_has_calls([
            unittest.mock.call(), unittest.mock.call()
        ])

After the first Worker throws a WorkerStrikeException, the second Worker (scrub) comes in to replace them. In patching the Worker, we are able to more accurately describe the behavior of Boss regardless of the implementation details behind Worker.

A Non-Political Conclusion

I’m not saying this is the best way to go about unit testing in python, but it is an option that should help you get started unit testing legacy code. There are certainly those who see this level of micromanaging mocks and objects as tedious, but there is be benefit to defining the way a class acts under exact circumstances. This was a contrived example, and your code may be a little bit harder to wrap with tests.

Now you can go get Hooked on Pythonics!

Read more

The release of Ubuntu 16.10 Yakkety Yak in the coming months will bring about the public release of Unity 8 as a pre-installed desktop session (though not as the default session). It’s been a long time coming, and there’s a lot of new features which will break older applications. Canonical has unveiled snappy as the preferred packaging system for Unity 8, but what about all those old deb packages?

There have been a few other good posts about X applications on Unity 8 including this one on dogfooding, this one on Ubuntu Touch, and this one on how it works under the covers. This blog post is explicitly about Unity 8 on desktop using the Libertine CLI, though can be applied to most devices running Ubuntu Touch.

Disclaimer: I work for Canonical on one of the teams making all of this fancy stuff work.

A (Very) Brief Explanation

The toolchain we’ll be relying on is called libertine, and it’s essentially a wrapper around unprivileged LXC and chroot-based containers. We prefer to use LXC containers on newer OSes, but we must continue supporting chroot containers on many devices due to kernel limitations.

What You’ll Need

For desktop Unity 8, you’ll need the packages for libertine, libertine-tools, and lxc to get started. This will install a CLI and GUI for maintaining Libertine containers and applications.

If you’re running Wily or newer, you can just run the following in your terminal:

1
$ sudo apt install libertine

Otherwise, you’ll need to add the stable overlay PPA first:

1
2
3
$ sudo add-apt-repository ppa:ci-train-ppa-service/stable-phone-overlay
$ sudo apt-get update
$ sudo apt-get install libertine

The GUI

At this point, if you’re on desktop you can open up the GUI which will guide you through creating a new container and installing applications. Search the Dash (or Apps scope) for libertine and, given that we haven’t pushed a buggy version recently, you’ll be presented with a Qt application for maintaining containers. I highly recommend using the GUI, because then you are guaranteed not to be following out-of-date console commands.

…But maybe you prefer the terminal. Or maybe you’re secretly SSH’d into the target machine or Ubuntu Touch device and need to use the terminal. If so…

The CLI

The CLI we’ll be using is libertine-container-manager. It has a manpage, a --help option, and autocomplete to help you out in a jam.

The first thing you’ll want to do is create a container. There are a lot of options, but to create an optimal container for your current machine you only need to specify the id and name parameters:

1
$ libertine-container-manager create --id desktopapps --name "Desktop Applications"

A couple of things to note here: Your id must be unique and conform to the simple click name regex - this is what will identify your container on a system level. The name should be human-readable so you can easily identify what might be inside your container. If you don’t specify a name, your id will be used. The CLI will likely ask you for a password to use in the container in case you ever need it. You can leave this blank if you’re not concerned with that kind of thing.

At this point, a bunch of things should be happening in your terminal. This will pull a container image for your current distro and install all the requirements to get started maintaining and running X apps. This could take anywhere from a few minutes to the next hour depending on your network and disk speeds. Once you’re done, you can use the list subcommand to list all installed containers (note you probably just have one at this point). If you ever want to delete your container, you can run libertine-container-manager destroy -i desktopapps.

Once that’s finished, we can start installing apps. To find apps available, you can use the search-cache subcommand:

1
$ libertine-container-manager search-cache --id desktopapps --search-string "office"

This will return a few strings from the apt-cache of the container with id “desktopapps” that match “office”. Now, if you want to install “libreoffice”:

1
$ libertine-container-manager install-package --id desktopapps --package libreoffice

This will install the full libreoffice suite. Nice! Similarly, you can use the remove-package subcommand to remove applications. Don’t remember what apps you’ve installed? Use the list-apps command:

1
$ libertine-container-manager list-apps --id desktopapps

Maybe you’re an avid Steam for Linux gamer and want to try to get some games working. Since Steam still only comes in a 32-bit binary, you’ll need to enable the multiarch repos, and then you can just install Steam like any other app:

1
2
3
$ libertine-container-manager configure --id desktopapps --multiarch enable
...
$ libertine-container-manager install-package --id desktopapps --package steam

Steam will ask you to agree to their user agreement from the command line, which you should be able to do easily. If you need to use the readline frontend for dpkg, you can append --readline to the install-package command to enable it.

There are many other commands to explore to maintain your container, but for now I’ll let you check the manpage or open the GUI to explore further.

Running Apps

Now that you’ve installed some apps, you probably want to run them. You can install the Libertine Scope, which will allow you to peruse your installed apps in a Unity 8 session. You can either install it from the App Store on a device (search for “Desktop Apps Scope”) or through apt on desktop with:

1
$ sudo apt install libertine-scope

In a Unity 8 session, you can now find the scope and click on apps to run them. Note that there are many apps which still don’t work, such as those requiring a terminal or sudo; consider these a work in progress.

The Future

I’ve been toiling away the past few weeks getting a scope ready which can be used explicitly to install/remove X apps in Unity 8, like the current Ubuntu Software Center (or app store on Touch devices). This scope should be available anywhere the libertine scope is available, meaning that it will alleviate a lot of the pain associated with installing/removing apps for a large chunk of users. Using the Libertine GUI or Libertine CLI will still allow for much more customization, but those tools are largely designed with power users in mind.

Are you able to get libertine working on your system? Can you launch X applications to your heart’s content? Let me know in the comments!

Read more

This is the third in a series of blog posts detailing my experience acclimating to a fully remote work experience. You may also enjoy my original posts detailing my first week and my first month.

Has it really been 4 months since I started riding the raging river of remote work? After my first month, I felt pretty good about my daily schedule and work/life balance. Since the last post, I’ve met many of my co-workers IRL, learned to find my own work, and figured out how to shake things up when I get in a rut.

But First, Did I Handle My Action Items?

During my first month, I struggled to figure out what to work on after finishing a task. At this point, it’s extremely rare that I don’t have a dozen things in the queue like a pile of papers in an In Box about to topple over. I am happily busy all the time, either pulling things off the top of the stack, plucking things from the middle, or coming up with some new feature that I need to add.

I feel a lot more comfortable on chat. Our IRC channels are a bit daunting at first, especially when there’s a lot of action going on. I’ve learned some good ways to interject or reach out to the people that I need to talk to.

Oh, and I still haven’t gotten a new floormat. Yes, this one’s still broken. For some reason, it just doesn’t annoy me as much as it used to. It’s almost endearing: like a three-legged puppy that I roll my chair across and stand on top of for 8 hours a day.

Meeting IRL

Why would you guys actually meet IRL? - Elliot, Mr Robot

I know a bunch of my coworkers by IRC nicks, and I see a few of their faces in a Google Hangout for our daily standup. This has been sufficient for me, but we did something truly magical in June. We met IRL.

The team I’m on (~10 people) and our sibling team (~10 people) met in Montréal, Québec, Canada, for about a week, and it was unlike any meeting-of-the-minds I’ve ever been to. The engineers were largely from the US and Europe. We all stayed in the hotel downtown and used a small conference room to hang out and work all day, every day. We woke up and ate breakfast together, met in the conference room at 9, had snacks and coffee, ate lunch together, stopped working precisely at 6, and met back in the lobby a few minutes later to go out on the town until 11 or midnight. It’s a truly intense social experience, especially for a group of people who spend most of their days only interacting with other humans through IRC, especially for a group of people who only meet twice a year or so.

This coming together allowed us to hash out a lot of our plans for the coming months, but I believe the true victory in this type of event is the camaraderie it creates. It’s nice to be able to put faces to nicks, think about the inflection in a person’s voice coming out in the way they type, and know exactly who I need to ping on IRC to accomplish certain tasks. It’s fun to hang out with people from all over the world, and it’s fun to go drinking with your coworkers, a thing I had temporarily forgotten.

I’ll note that we also happened to be in Montréal during the 23rd annual Mondial de la Biere, a huge international beer festival that lasted several days. I’ll also note that it was fun to try to speak little bits of French in Montréal, and I’m really looking forward to wherever the next sprint abroad may take us (most likely Europe in October).

Finding Work

With a decentralized company, the issue of finding things to work on for new employees can be tough. Do you give them something small and easy and possibly belittling? Do you give them something massive that will leave them scratching their heads for weeks and completely out of touch with the rest of the company? How can you find a good middle ground here?

I’d say I was “eased in” with smaller tasks into my current project. After the first few tasks were completed, it was often unclear to me where I should go next. There was always a list of bugs - was I the right person to work on them? Was there any other impending feature or unlisted bug that I should start looking into instead? These are hard questions for someone who hasn’t been around for very long.

Over time, I gained more and more responsibilities. I needed a bug fixed pronto in another project, so I did it myself and submitted an MP. Oh, you understand this codebase? You can be a maintainer now! Oh, I think I remember from your resume that you have some golang experience. We need this fixed ASAP, using SD cards is completely broken without it!

It’s all a slippery slope to having a bottomless bucket of super-interesting things to choose from to do work, perform code reviews, and answer community questions. Yet somehow it’s all happened in a way that is not overwhelming, but freeing. When I get stuck on a problem or need a short break from my current project, there’s plenty of other work to go around. Which leads me to…

Shaking Things Up

Routine can be helpful, but it can also be terrible. For the parts of May and June that I wasn’t traveling, I was largely waking up at the same time, making the same lunch, listening to the same music every day, petting the same cats, and picking up the same kinds of tasks from the backlog. None of this was bad per se, but I found myself getting a tad sluggish. It would be harder to work on menial tasks, and easier to come up with elaborate solutions to simple problems. So what did I do?

I started varying my sleep schedule. Some days I get out of bed at 7, other days I get out of bed at 8:45. Because I work from home, I don’t have to worry about fighting traffic or skipping breakfast.

I started varying my lunches. I was making some fun rissotto recipes, but since it’s summer I’ve been mixing up a bunch of different vegetables into a menagerie of salads: sauteed green tomatoes, onions, and zucchini; cukes and onions; pineapple, succotash, and eggs.

As I’ve gained more responsibilities for various projects, I’ve been able to branch into different kinds of tasks. After finishing up a big rework of one codebase, I can start jumping into bugs somewhere else. I can dig deep somewhere, and pivot when I’m ready to go back. There’s always something interesting to work on, and I can see the way different tasks help us towards our end goal. Not to mention I can always do bug hunts.

Remote Life 4-eva

It’s not just working remotely that makes this possible - it’s the people, the culture, and the fun and interesting products we’re creating. Maybe I’ll start blogging more about those things in the future. I don’t have much in this area that I’m looking to improve on, so this could be the last post in the series. Maybe I’ll do one at the 1-year mark to note any new tricks I’ve learned. Until then, keep looking our for other non-diary-entry blog posts.

Looking for advice on working remotely? Not sure if you’d like it? Do you have a strong disagreement with me as a person or my lifestyle choices? Hit me up and we can chat!

Read more

Thinking about writing an Ubuntu application that will work in Unity 8? You’ll be writing a “convergent” app, which is an application that can respond to touch or mouse, and will adapt appropriately to a phone, tablet, or desktop screen. It will even be able to update its display on-the-fly if, say, you plug your phone into a monitor or bluetooth keyboard.

There are lots of ways to write a convergent application with the Ubuntu SDK. You can build apps in pure QML, C++ with QML, QtQuick, pure HTML5/Javascript, or even Golang with QML. We’ll be focusing on go apps for the rest of this post.

Go is a young language, and the recent release of go 1.6 has introduced some nasty changes particularly involving cgo. It has also introduced vendoring by default, which is a welcome change.

I’m using go 1.6.2. For me, the current project template provided by the Ubuntu SDK feels quite broken. I can’t get things to build locally, and furthermore I see no options for pushing an ARM build to my device.

Fortunately, I found this ubuntu-go-qml-template which is a template to enable running/building a go/qml application locally while also supporting building/installing onto an arm device. The kicker? This tool was designed to work for go 1.3.3. Sigh! Since I’m unwilling to compromise and use old technology, I forked the project and updated it to fit my more modern needs.

Because our go template will depend on QML, we depend on the go-qml project to create the necessary C bindings to allow us to use QML. However, with the update to go 1.6, the current version (revision 2ee7e5f) of go-qml will give a runtime error from cgo with the wonderfully helpful panic: runtime error: cgo argument has Go pointer to Go pointer. Another thorn in our side. Fortunately, this issue is in previously tread-upon ground and there is a fork of go-qml with enough of the cgo issues fixed to run our application with no problems. In the ubuntu-go-qml-template I forked above, I’ve gone ahead and vendored this fork of go-qml. It all works because of the default vendoring available in go 1.6.

With that background out of the way, let’s run through getting a project started:

1
2
3
4
5
6
7
8
9
10
11
$ sudo apt-get install golang g++ qtdeclarative5-dev qtbase5-private-dev \
                       qtdeclarative5-private-dev libqt5opengl5-dev \
                                           qtdeclarative5-qtquick2-plugin
# installing dependencies...
$ git clone https://github.com/larryprice/ubuntu-go-qml-template.git your-project-name
# cloning repo...
$ cd your-project-name
$ chroot-scripts/setup-chroot.sh
# building a chroot for ubuntu-sdk-15.04
# distro=vivid, arch=arm
# with go 1.6.2 with armhf compilation support

You may need to have other dependencies including click or phablet-tools. The above commands installed dependencies, cloned the repo, and built and/or updated a chroot for building our source for arm.

Next you’ll want to setup the project for your own needs. The original template creator included a nifty setup script to get this done:

1
2
$ ruby setup.rb -v -n your-project-name -a "Your Name" -e "your.email@example.com" \
                   -d "your-developer-namespace"

This will do some fancy gsub and file renaming to make the template your own.

If you check src/, you’ll find a main.go file ready for your use. You’ll also find a main.qml file in share/qml/. You can vendor all of your dependencies in vendor/, where you’ll already find the qml package.

As far as getting your application to work, there are more scripts available:

1
2
3
4
$ ./build.sh
# this will build your project locally
$ ./run.sh
# this will build your project locally and then run it on the desktop

The best part about this template is the ability to build for arm and load your applications onto a device:

1
2
3
4
5
$ ./build-in-chroot.sh
# builds the package using the vivid+armhf chroot we set up previously
$ ./install-on-device.sh
# builds for vivid+armhf and installs the click directly on
# the first USB-connected Ubuntu Touch device

Now you can run and install go/qml applications on desktop or on devices. Time to go build something cool!

Disclaimer: In the future, this template will likely need to be updated for new go versions or new default versions of the Ubuntu SDK. Don’t be afraid to make a comment below or submit a PR.

Read more

The Gist

How can one man give the world so much? Scott Meyers transformed my understanding of C++ with Effective C++, a book which not only teaches good C++ practices and principles, but also explains what’s going on behind the scenes to make those efforts so effectual. Effective Modern C++ is the same book aimed at a different audience. The audience of Effective C++ was the developer who could use C++ to build a humble home of straw or wood, but didn’t know that C++ was born to create homes of brick and mortar. Effective Modern C++ is for the seasoned developer who knows the brick home they built with C++98 can stand tall, but is bewildered by the plethora of modern amenities available in the top-floor penthouse that is C++11.

Takeaways

Even when first introduced to the language, it seemed the mentality around C++ was that it was simple, baremetal, and robust. It didn’t need garbage collection. It didn’t need decent threading (fork that). Lambdas? Type deduction? Go talk to a language specification who cares!

But here we are. C++11 can now act a little bit more like its cousins C# and Java, but run fast like its pappy C. I have been on a number of projects where C++11 is king for the last 3 months. The last time I had been on a C++ project, we seemed to be stuck in the ice age. As I first started reading this book, I would read one of the items and apply it directly to the code I was working on literally the following morning. This new C++ is downright luxurious compared to the old one.

C++11 gives us the auto pointer for type deduction, similar to var in C#. Some examples:

1
2
3
auto x = 1;                 // x is int
auto y = new Thing();       // y is Thing*
const auto z = "the thing"; // z is a const char*

C++11 also has new loop syntax for iterators:

1
2
3
4
5
6
7
8
std::vector<int> v{4, 6, 0, 3, 3};

for (const auto& value: v)
{
  std::cout << value;
}
std::cout << std::endl
// prints 46033

You may notice in the above code the use of curly braces to initalize the std::vector. Braced initialization allows us to use a std::initalizer_list to initalize STL objects, but it also allows basic construction.

There are now lambdas: function handles defined dynamically which can capture other variables (called a closure).

1
2
3
4
5
6
7
auto x = 5;
auto my_func = [&x](int y) {return x+y;};

my_func(5); // 10
my_func(3); // 8
x = 11;
my_func(5); // 16

In the above example, x is captured by reference. You could also copy-capture x by excluding the &.

You like garbage collection? We got you covered. There’s std::unique_ptr to represent one-shot memory that should be deleted when the pointer goes out of scope, and there’s std::shared_ptr which is reference counted and will be deleted when all references to the shared_ptr go out of scope. These language enhancements are essential, and anyone well-versed in the usage of boost::scoped_ptr and boost::shared_ptr will have no trouble getting the hang of these.

The concurrency API is pretty neat, though I haven’t had much chance to play with it. std::atomic allows you to create objects which are guaranteed to be read/write thread-safely. std::future allows you to fire off a command in another thread and continue after it’s completion.

Looking to override a method? You can indicate an intentional override with the override keyword to tell the reader and the compiler you’re intending to override a parent method. Comes in handy.

Another nice construct is nullptr. In C++, NULL is actually just 0. Because of this you might even see your fellow developers comparing pointers to 0 while you try to determine their intent. We can now compare and set our NULL pointers to nullptr: an improvement soft in functionality, but noticeable in readability.

Although I loved reading about C++ in bite-sized chunks throughout this book, there were a few things that went over my head (not just the first time). A major point of friction between myself and the author were universal references (&&) and the move operator. These concepts were new to me and difficult to grasp the first few times they were brought up in this book. It may have been the order they were presented, or it may have been my lack of contact with them in the real world, but I would recommend having some level of understanding for universal references before reading those parts of this book.

The move operation moves the contents of memory from one object into another, as opposed to a copy operation which will duplicate that memory. A universal reference is, in some sense, a way to allow either a copy or move to be called based on whether an lvalue or an rvalue is being passed in. There are lots of rules involved, and sometimes move is faster than copy but other times it isn’t. For me (and I assume many others), this confusion will lead me to largely ignore this feature for now.

There is also quite a bit of discussion early in the book about using type deduction in templates with auto and decltype, but this discussion made my head hurt and made me glad I don’t do much template metaprogramming.

On top of all this goodness (and more I didn’t mention), C++14 includes a lot of bonus features that make C++ even a little sweeter. Here’s a shortlist. (Looking for a list of C++11 features? Here you go.)

Action Items

Read more

If you weren’t paying close attention, you may not have noticed that Github has recently removed Streaks from profile pages along with a few other changes.

For the uninitiated, Github tracked each user’s commit history every day and displayed this information prominently on the user’s profile for the past 365 days. When committing multiple days in succession, a “streak” is started. Your streak resets the next solar day you don’t commit to Github.

What was the purpose of the streak?

The streak encouraged developers to contribute public open-source code as frequently as possible. This is a very good thing! Maybe it even influenced some people to contribute to open-source projects that desperately needed help. Maybe it helped some developers explore new codebases and languages they never dreamt of exploring previously.

However, any good feelings that came from the streak are instantly dashed when you take a day off. All those good-feels you get after working hard to get a 10-day streak? Crushed in an instant. Now you need to start over, but you don’t bother because every time you feel a streak coming on it’s dashed away. This is a painful reminder that life is short, and you’ll only be rewarded in the short-term for any effort you put in.

So if the good-feels wasn’t the purpose, how about notoriety? Surely someone with a long streak is a good person and a noble developer!

Except for gists like this which will help you generate a 100-year streak. Or the fact that you could make empty commits to personal repos and manipulate the streak. Or you could be making minor documentation/newline changes every day. Not only that, but not all developers use Github as their primary source control platform. Developers could be making contributions to Bitbucket as well as Github and not have that reflected in their streak at all.

My theory is that streaks, though well-intended, served no purpose.

They were ripe for abuse and not a very good “reward” for contributing code on the side, nor a good indicator of how grey a developer’s beard is. Not all good developers make commits every day, and encouraging a commit-a-day is getting people trapped in the Silicon Valley bad-habit of never not working. For the time being, good riddance.

At Canonical, we use Launchpad to host most of our source code. Launchpad has this concept of “Karma” which tracks your commits, code reviews, bug reports, branch merges, etc on Launchpad. Karma decays over time but not immediately, which means that you can take days off and maintain Karma. From this number, you can usually tell if a user is new to the system, highly active recently, or has turned into a manager. For reference, mine is a little over 3000 as of this blog post. Although I mostly like the way Karma works, I don’t think it’s the epitome of source code gamification.

As far as I know, sites like Bitbucket and GitLab don’t have such a concept of rewarding heavy coders or giving some indication of recent activity outside of a news feed. Maybe a news feed style is enough?

The good people at Github want you to code socially, and I’m excited to see if they can come up with a fun and light way to gamify open-source software while avoiding some of the unfun aspects of streaks and the blaisé concept of news feeds.

What do you think? Do you miss streaks? Did streaks motivate you to contribute more frequently? Any ideas for a new system? Tell me in the comments!

Read more

This is the second in a series of blog posts detailing my experience migrating from a culture based on co-location to a fully remote environment. You may also enjoy my original post detailing my first week. Look out for another post in the fall.

I’ve spent an entire month working remotely. Whereas I spent much of my first week working remotely getting my home office in a working state, the rest of the month was largely spent acclimating to a culture of complete autonomy, getting comfortable with my peers, and finding my way around.

Attacking My Action Items

One of my action items from the week 1 post involved personalizing my workspace. I brought three posters from our second-floor study and planted them on the walls of my new office area downstairs. It makes my new office feel a lot more like my own space and a lot less like the formerly-unused living room. I have a 1994 Ren&Stimpy calendar hanging on the bookshelf as well as a few stickers and other various nerdy hangables. I’m fairly happy with the current state of my office.

I’ve made a point of exercising more during the work day. I work my biceps and triceps with my handheld weight, as many nose-to-the-ground push-ups as I can, and really hard bicycles until my abs tell me to stop. I’ve also been walking outside in the early afternoon to check on the state of my hop garden. Not to mention I’m still making significant use of my sit-stand desk.

As far as extracurricular activities go, I think I’m keeping steady. I’ve been going to my local Code&Coffee, and I just had a monthly meeting of Indy Golang. I’ve been reading a bunch of blogs and eating up modern C++ material. I’d like to make sure I get to IndySA every now and then, but I usually just whiff the date. I haven’t been doing much coding outside of work, but that hasn’t been high on my priority list recently. Since I currently work for an open-source company, I am embedded in the world of code all day, and I usually end the day very satisified.

I did not buy a better floormat. Still on the list.

Acclimation Station

Although my first week was a success, I’ll admit it was still a little awkward. However, I’ve found myself significantly more comfortable at the end of my first month.

In this position, there is a level of autonomy unlike any I have ever experienced. No one tells me what to work on next. I figure out what I’ll be doing almost entirely based on incoming bug reports, community rumblings, nebulous plans, or simply things that interest and/or annoy me about a project. Priorities are in the eye of the beholder, and it’s in my best interest to pick up work that is meaningful and relevant. I complete the task, get it into review, and make sure everybody’s happy. Since everyone has a shared goal, it’s unusual for developers to be especially nit-picky during reviews, and thus reviews become more focused on correctness, education, and mysterious edge cases.

Talking to people on IRC can be a little daunting because so many of my coworkers are just so good at it. At first, talking to the right people seemed impossible. Eventually, I’ve learned to become efficient with my IRC usage and I have certain channels relevant to my current tasks where I hang out. Although I describe our communications as “efficient”, that’s not to say we don’t joke around and have a good time. There are people I interact with every day who I consider work-friends even though we’ve never spoken face-to-face.

Over the past several weeks we’ve held two company-wide events. The first was a remote open forum with our CEO. During the remote forum, the CEO discussed how the company was doing and then she opened the floor for questions. Someone would ask a question in chat, people would vote for those questions, and then we would get an answer. It was done quite well and felt like a great introduction to the CEO and her vision for our company’s future. This week was a three-day conference spanning the entire organization. Presenters would share their faces and slides using Hangouts on Air, while attendees watched live and chatted together in a relevant channel. I learned a lot about the wider scope and relevance of my project, and I also got to hear about all the other interesting things going on around the company. I got to hear the founder do a Q&A, which gave rise to many great questions with humble, honest answers which gave me a good idea of what we are all about as an organization. Attendance was optional, so irrelevant presentations could be ignored as easily as closing a tab.

For the first couple weeks, I couldn’t figure out how some of my peers could be so busy all the time. Now I understand. I found myself working on projects several dependencies away from my own, adding features and fixing bugs such that our project could integrate with the dependency and we could get features shipped. Due to the nature of everything being open-source, I’m constantly working with my peers to figure out where a bug might be stemming from or the appropriate level to inject a feature or even just who to talk to about how things work. You fix a bug in one project and accidentally become a contributor while the project is in desperate need of many code reviews, which you then do and become an even more relevant member to the team.

Oftentimes, traditional office workers will say things to me like, “I don’t know how you work from home; I’d just be distracted all day and wouldn’t be able to get anything done.” I’ve found that to be completely untrue. There are many days where I have trouble not working in the evening. I’ll read up on some modern C++ techniques or read some misguided blog post about our projects, and I’ll think about jumping on the computer at 9pm just to take a peek. It takes a lot of self-restraint, but I’ve thus far been pretty good about not working after work. Hopefully I can keep that up.

In a few weeks, my team is meeting in Montreal to hang out and do code for a week. I’m excited for the opportunity to see everyone (not to mention to be in Montreal), and I’m certain that it will help me feel even more acclimated to this new environment.

Some New Action Items

  • Better floormat. Standing on my plastic mat right now, my feet do start to hurt. I need to run to an office supply store and find some rubber padding.
  • IRC Champion. Although I’m more comfortable on IRC, I know I could be better about reaching out at the right times to the right people.
  • Automaton. I still grope around for work when I’m not sure what to do next. I’d like to come up with a process to determine what should be next on the agenda without too much synchronous assistance.

Read more

Interviews suck, amirite? Recently, there’s been a rise in posts discussing how harmful whiteboard problems are. Let’s chat about how the internet works, and then we’ll discuss where I land on this issue.

You’ve got one group of people who love whiteboarding. Whiteboarding allows interviewers to see how a candidate thinks. Whiteboarding gives the illusion of programming without the fear of compiler errors. Solving a problem algorithmically on a whiteboard is the same as programming.

And you’ve got the people who think whiteboarding during interviews is just as terrible as waterboarding a candidate. Whiteboard problems cause interviewers to become smug, sexist, and xenophobic. Candidates are forced to sweat bullets at a whiteboard while a death panel of interviewers silently judge them. Whiteboarding a programming problem is entirely different from computer programming.

Between you and me, I don’t believe it’s all so black and white. Like most things in this world, whiteboarding falls into a somewhat uncomfortable grey area. There are certainly things which can be gained by whiteboarding, but it’s also in no way indicative of programming strength or culture fit. There are literally classes teaching people how to be pro at whiteboarding.

One of the main problems is that this is not how you work in real life. You don’t put together code on a whiteboard while a group of strangers stares intently waiting for you to screw up so they can mark points off your score. Your day is largely spent reading other people’s code to figure out how you can force whatever new feature or bug fix you need to implement into their code as easily, quickly, and cleanly as possible, and then you’re usually put into a position where you have to sacrifice the easy, quick, or clean part of that plan. Along the way, you usually get to fight the compiler or search the internet for any relevant APIs, StackOverflow questions, or existing libraries. You’re probably also a member of a team with varying experience levels in the current codebase, so you’ll spend another big part of your day asking/answering questions on group chat and gatekeeping the codebase from code that is unreadable, unchangeable, or just plain questionable via code reviews.

But if this is the way we do our jobs, why do we ask candidates to reimplement underscore’s debounce function, create all the possible words from a telephone number, or generate roman numerals from an integer?

Some organizations have moved to systems of making the candidate solve a multi-hour problem in their free time, or come into the office and spend a day (or more) pairing with their future teammates. Although I think these ideas are founded on a solid base of logic, they are terrible. A large number of worthy candidates already have full-time jobs to deal with, and many of them have other commitments during the evening hours. The perfect candidate may have recently found themself with a new child, and every non-9-5 hour is no longer available to create a reverse binary tree. Adding more work and stress to an interview is not the right way to go.

How could we possibly find the perfect candidate without stressing them out and giving them standardized tests?

Let’s make them work like we do, but only for a reasonable amount of time. Come up with a medium-difficulty coding problem and write it yourself. But don’t make it clean. Make it sloppy. Make a ripe mess of that code. Add an obvious bug or two.

Now, when you bring in an interviewer or talk to them on a video call, show them this code. Can they figure out what it does? Can they find the bugs? Ask them to code review it. Do they see all the terrible things you’ve done? Can they tell you how to make it better? Can they do it without being condescending (news flash: most full-time programmers cannot do this)? This should all be a back-and-forth, with the (lone) interviewer working with the candidate to discuss any issues. If you have time, ask them to actually correct and refactor some of the code. If you’re into that kind of thing, work with them to write some test cases for the bugs you’ve fixed. If for some reason you still don’t know whether or not you like this person, have them add some functionality to the codebase. Then code review their code and see how they handle your suggestions. You should limit this exercise to an hour, maybe two if you’re a sadist. Do not make this an all day thing.

Think about how much you could get out of this exercise. You’ll determine whether the candidate knows what code looks like, knows how to read code, knows how to communicate about code, and knows how to fix bad code. You’ll also get a bit of their personality based on how mean they are during the code review sections. Hopefully, you were able to have a real discussion about design decisions and coding during the interview. The candidate will have done very little programming, just like you and me on a normal day. Best of all, you’ll only have spent an hour of each other’s time trying to figure out if the candidate is competent. Leave time for questions at the end and be done with it.

Of course, I don’t currently run a tech company or do much with the interview process. But everyone’s been giving their two cents on that issue, and I like to type words on the computer. What do you think? Is whiteboarding during an interview integral to your interview process? Do you need it? Do you hate it? Do you have any alternatives? Let me know in the comments.

Read more

I would like for this to be the first in a series of blog posts detailing my experience migrating from a culture based on co-location to a fully remote environment. Look out for another post at about the 1-month mark.

I’ve spent an entire week working remotely. How did it go? I’m not going to go into my current job here (if you’re curious: I love it), but I’m going to try to focus on the aspects of setting up a pleasant environment for working from home and how I coped during my first week.

But first: some background

I’ve never worked remotely as a professional software engineer for more than one day at a time until now. I’ve been a part of an office with traditional cube farms and an office with more modern team spaces. I haven’t worked in a Silicon Valley Sweat Shop, and I’ve never had a private office with walls, windows, and that holy grail of office furniture: a door. My past organizations have been nested in a culture of co-location which is, of course, very normal. However, I’ve very recently moved to a position at a new organization with cultural values borrowed from the open-source community. About 70% of the 700 employees are full remote.

When I use the term “working remotely,” I mean that a given employee works from wherever they want. For the majority of people it’s their home or apartment, but it could also be a coffee shop, a co-working space, a public park, or anywhere with an internet connection and a nearby power source.

Setting Up My (Physical) Environment

Also known as Things I Had to Buy to Make This Work.

To prepare for this new work environment, I did what anyone would do: I started buying things. I bought a cool wireless mouse that I could connect to my laptop through it’s built-in bluetooth. I bought a chair with a name from IKEA and one of those cheap plastic carpet protectors. I started looking into motorized sit/stand desks, but didn’t purchase one immediately (a mistake I quickly recovered from). I moved a second lamp into my home office and figured I was set up for success.

My first day, poor Markus (the chair) cracked the floor protector in several places, and my carpet is so thick that the chair couldn’t roll on its own. I painfully used my laptop’s keyboard for about 15 minutes before finding another mechanical keyboard to use instead which arrived that afternoon. The height of my old desk made sitting for hours super uncomfortable, so I quickly put in an order for a sit/stand desk that I could use downstairs where the carpet is thinner.

The next day, my new mechanical keyboard refused to let me type Shift+RightAlt without thinking it was a Meta key, causing all my keyboard shortcuts to be busted. I swapped it out with my old mechanical keyboard that worked just as well, but with a functioning Shift+RightAlt. It was around this time I noticed my WiFi connection was becoming flaky. I cursed my ISP and decided it was fine for the time being.

At some point during the week, the sit/stand desk arrived. Because of the thick carpet and uneven floors upstairs, I decided to start creating my new office downstairs. Unfortunately, my house is extremely poorly lit, so at the end of the day I had to run out to Target to buy a new lamp (and some cream cheese! classic combo!).

By this time it was Friday. My network connection was not just bad, but worse than it ever had been. I started sniffing around the internets and found that my wireless card (a bluetooth/WiFi dual card) was notoriously bad at handling bluetooth and WiFi at the same time on Linux, but sometimes updating the kernel and getting the latest iwlwifi drivers fixed the problem. So I updated to 4.3. No luck, so I updated to 4.4. Still no luck. By the end of things, I had the 4.4.6 kernel and I honestly thought things were a little better. A few hours and a dropped Hangouts call later, I realized I was wrong. However, booting off of a USB with fresh Ubuntu gave me a consistent and fast network connection. After piddling around a bit, I dramatically smacked my forehead. I flipped off the bluetooth connection on my laptop, and my network connection was fast and stable. I had been thwarted by my beautiful bluetooth mouse which, fortunately for me, also came with the usual wireless USB dongle.

At the end of the week, I finally felt like my setup was fine. Network still a little slower than expected, but I fixed that recently by moving the router to higher ground.

Let me count the ways…

OK, so I had some issues getting my home office in working order. But I love working from home.

I don’t feel rushed when I get out of bed in the morning. I shave, shower, make coffee in the french press, and perfectly toast/cheese my bagel; and I get to enjoy every minute of getting ready for the day. I start when I want, but when I want is a normal time. I’m at my desk ready to do my job sometime between 7:30am and 8:30am. The only way I need to let people know I’m in the office is by signing into chat.

My house is almost silent except for the noises I make and the infrequent meow of a cat wanting attention. I can focus on what I’m doing without being distracted by peers or normal office noises. I don’t need to put on headphones when I want solitude, which means I’m not distracted by whatever noise is coming out of the headphones. Achieving flow seems to be much easier when there are fewer distractions.

Speaking of cats… I know this will seem silly, but it’s quite nice to have my feline companions hanging out with me all day. Usually they’re taking naps nearby so I can say “d'awwwwwwww”, or they’re waiting in the kitchen for me to get up so they can get pets. Go adopt a cat now.

I can make a healthy meal really easily at lunch. I love being able to pull some frozen veggies out of the freezer, throw them in the skillet with some sauce ingredients, add some protein, and feel like I’m eating well in the middle of the day.

All of my communication comes through chat, email, and infrequent Hangouts. We mostly just use Hangouts for our daily standup, and it’s a great way to see everyone’s faces and feel like a team. Email is pretty much only used for mailing lists, such as new merge proposals, bug reports, and company news; so I only glance at my email a couple times a day, and mark whatever I don’t care about as Done. We use Google services to do this, which means I’m using Inbox to achieve zero-inbox. Chat is our primary means of communication. Being a remote group, the chat is extremely efficient. There are no graphic memes, and chats never end with “let’s get a conference room to hash this out.” Information is constantly being exchanged through the chat, and I rarely feel dissatisfied with the outcome. It’s also interesting to note that when you leave the chat, you do not get to know what happened in your absence. However, this does not seem to be a hindrance to anyone, but almost more of a relief. You don’t need to be in-the-know 24/7 to know what’s going on.

Near-Future Goals

  • Exercise more. Although my eating habits feel a little better, my exercise habits have been much worse. I used to meander the office every hour or two to get 10-15 minutes of exercise, or go outside to walk around. I have my sit/stand desk set up now, and I shuffle back and forth based on what I’m doing and how my butt feels, but that doesn’t count as exercise. I plan to lift my 10lb weights more frequently, and I’d like to work out my core with push-ups and bicycles. It would also be great to walk around the neighborhood in the summer.
  • Extracurricular. It’s been a while since I’ve worked on something meaningful in the evenings, and it’s been tough to get started on something since my work office (and computer) is now also my play office. In the next few weeks, I’d like to build an Atom.io package to integrate with bzr.
  • Personalize workspace. Since I’ve taken over the living room, the decor is mostly a big, decorative clock. I have some wicked posters I’d like to put up, but I need to convince my housemate that they won’t look too tacky in such a guest-visible area.
  • Find a better floormat. Like I said, this cheap IKEA floormat cracked on the first day. I’d like to find something vinyl or closer to rubber that will be more resilient but also more comfortable when I morph into standing mode.

Read more

The Gist

Have you ever tried to buy airline tickets in a hurry? Have you ever had to find directions to the ER on the hospital website during an actual emergency? Have you ever wondered why you have to give a bug tracker your “title,” “gender,” or “address”? Design for Real Life written by Eric Meyer and Sara Wachter-Boettcher explores the pitfalls of designing for the perfect user and the dangers of asking unnecessary or inappropriate questions.

By the way, the means by which I found out this great book existed is by following Sara on Twitter: you should too!

Takeaways

We spend a lot of time designing our websites for the perfect persona. Right this minute, you probably have Sam the Salesperson, Hermoine the HR Rep, and Monica the Manager all smiling down upon you from their painter’s tape thrones on the wall next to your cubicle. You meet these caricatures at their best: bellies full of coffee, heads full of false worries, plenty of time, and a healthy dose of get-up-and-go in their web browsing digits. These idealized characters are a great way to make a best-case-scenario product, really nailing that “90%"of users everyone wants to find.

What about the other 10% of users? At the start of a long and miserable day full of meetings, can someone short on time and patience create yet another calendar event in the few short minutes they have available? Thirty seconds before Polly the Procrastinator’s timesheet is due, can she quickly add in her time without filling in meaningless fields? Instead of focusing on the ideal case, we might be better-served using this kind of time-crunched, ambivalent user as one of our personae. By designing for the streamlined user, we’ll likely find that we’ve also satisfied the needs of our “ideal” users.

We ask for too much information. Think about how many times you’ve just filled in junk information in forms to get through them as fast as possible. It’s not shameful; it just wasn’t worth your time to fill our information that you knew the application wouldn’t use or could potentially use against you. On another note, think about how many times you’ve given up filling out a form for a website because it was just too long. Asking for too much information causes user fatigue, and you are guaranteed to lose users when you start asking them for too much. If your website doesn’t need to take location, title, or city of birth to get its job done, stop asking for them. If you have a tough time removing these fields, then write some user-visible text explaining why you need this information.

Some questions could cause an unintended emotional response from users. If you’re going through a tough time in your marriage or a recent divorce, filling out “title” or “marital status” could cause unwanted emotional duress. A “gender” dropdown with two options is non-inclusive to users with a non-binary gender identity, and may cause users going through a transition to wince at such a question. Someone who has just suffered the loss of a parent, child, or sibling could feel great emotional pain when you, a complete stranger, bring up family members for no reason but to feed to your bottomless data pit. Once again, the first question you ask yourself should be whether or not you absolutely need that information. Again, if you really want it, consider making more fields optional and explaining how this information will help your application.

Do more user interviews before implementing newly-designed features. We can’t assume that everyone will use the app the way we think they will, and we’ll always be better off for getting more information.

Your app probably doesn’t need to be funny. We litter our error messages with “Whoopsie!” and our log out messages with “Sayonara, sucker!”, but this is an absolute waste. When errors occur, there’s a chance you’ve just angered your user. You know what makes them angrier? That error message you wrote that you found funny at the time. Be informative and supportive in your messaging, and your users will be better off for it.

Action Items

  • Stop trying to be funny in the copy. It’s only funny when developing. Maybe we should have some sort of i18n setting that shows funny messages during development and English in production.
  • Don’t ask so many questions.
  • More form fields should be open-answerable. Also more form fields should be optional. Also see previous bullet.
  • Streamline the hard stuff. It may not be the most-used feature, but if it’s important to a user in emergency mode you can bet it’ll be appreciated.

Read more

Last weekend was the 2016 SEP Startup Weekend, a bi-annual hackathon where a few of the engineers get together for 48 hours to build things. As far as most people know, we transform massive quantities of beer, coffee, and unhealthy food into cohesive piles of code. Although that about sums it up, I thought it might be nice to chronicle my team’s experience of this season’s event. Enjoy!

The Pitch

In my first startup weekend since Ollert, I pitched an idea for an instant runoff voting platform called RePoll. RePoll would allow users to create polls, rank candidates, and view results in a login-less system via a web portal, Android, and iOS app. To make it all interesting, I wanted to do all of the coding in javascript by using React for the web frontend and React Native for the iOS and Android apps.

Friday

I somehow convinced 3 of my coworkers to help me on Friday night, who I’ll refer to as H, G, and K, forming teams by combining the letters.

After sending around a few images and documents with my proposed architecture, I had GH start working together to build the Android app in React Native. Unfortunately, we hit a few snags in getting React Native to run an Android app on actual hardware, but late into the evening everything was up and running on a genymotion simulator. By the end of the night, GH had a good portion of the React Native opening tutorial completed.

In the meantime, K and myself were hard at work building a core web API in NodeJS for all apps to use. We decided to use Mongo so we didn’t have to worry about updating schema and initializing databases, and we used Postman to test our API calls. I may have overarchitected the session/token-based authorization system, but we got over 50% of the way done with the API. In my initial estimates, I wanted to have the API 100% completed by Friday night, but we were all tired and decided to break for the night around 10p.

Although everyone else headed out the door, the garage was packed with cars leaving a fancy-pants event held near our office. I stayed behind for about an hour setting up our API to run on heroku with a MongoDB instance, and then configuring DNS for the domain I had already purchased.

Saturday

I arrived early and laid down some sweet jams. I continued working on the API alone and had K start working on the iOS app. We added a new teammate, dubbed A, who started work on the web frontend. The API neared completion by the end of the afternoon, and the mobile apps were beginning to hook into the publicly accessible API. During this time, several bugs were found in the initial API code and were fixed. The iOS app was making quick UI progress, but having issues connecting to the API. I started floating between dev teams as I got drowsy, but eventually got a second wind and started helping with the web frontend. The Android and web applications were both able to create polls before everyone went home. A started using a web React datetime component to set start and end dates, while the Android team was figuring out how to use the native calendar and clock to select dates and times.

To store data, the mobile teams started using the Async Storage library which allows for OS-agnostic storage of data in iOS and Android. On the web frontend, we used local storage to keep around any information we might need.

Near the end of the night as I started working on the poll results page on the web frontend, I started finding system-crashing bugs in my interpretation of instant runoff voting, and eventually found that the results weren’t always correct.

One item slowing us down Saturday when writing React Native code was its insistence on using syntax defined in ES2015. Our team was largely unfamiliar with this new syntax, so this tripped us up a bit more than expected. All in all, it was a great learning experience to see this cutting edge specification in action.

Sunday

Early again, I created a heroku app for our web frontend and set up the DNS appropriately. As the rest of the team started to pile in (and the smells of bacon arose from the Commons), I transitioned to trying to fix the incorrect ballot-counting logic in the API. I ended up rewriting the code several times, but finally found an algorithm that worked correctly. At this point I was kicking myself for not writing tests to verify we were writing good code.

The Android team caught a second wind, finishing the create poll page and started tackling poll lookup. The original plans called for a typeahead, which ended up being tougher to implement than expected, so the Android app instead supplied a simple textbox to attempt to match an existing poll. In doing this, the Android team successfully created an authentication token in the API and was able to display poll candidates in the app before running out of time.

The iOS team continued to have issues with the API, but successfully mocked out most of the rest of the app right before the demos.

Due to familiarity with the tech, the web team was able to get most of the way to a completed layout. I hastily fashioned a dual-list system for seeing candidates and ballot selection, while A transformed that system into a drag and droppable component. We were able to submit updated ballots to the server and fetch previous ballots for our poll tokens. With the updated API, the results page started working and it became possible to view the steps involved in eliminating candidates during the runoff process.

During demos, we presented all three apps and everyone was quite impressed at our javascripting.

Action Items

  • General Things
    • Learn more about React Native. I was largely shielded from the pain as I was working on the API and React web parts of our project, but from what I’ve seen and heard React Native is an incredible framework for getting things done and sharing code and code paradigms.
    • Start using ES2015. Tools like Babel allow us to start using next-generation javascript standards to write code now even if the browser support is unavailable.
    • Do more with webpack or browserify. I want to be able to use these tools to optimize pre-rendering on our site, but we were in such a rush we primarily used webpack to enable us to use several NodeJS dependencies. Still cool, but there’s so much else to explore.
  • Startup Weekend
    • Estimate better. I drastically underestimated the amount of work needed to get this project completed in a weekend. We would have had a better chance had I pre-built the API. I think doing some pre-work in this case would have been okay, but I also could have asked for more help. Next time I would like to do a better job of figuring out how much work there is and how much time it will take.
    • Be an expert. About half the work we did this weekend was in unknown territory for me. I should have studied further on getting React Native working before the event, and I should have known a little bit more about ES2015 as well. Although the lack of expertise slowed us down a bit, my teammates were extremely adaptive and loved learning the new tech.
    • Create and prep the team beforehand. I had enlisted one engineer before the pitches Friday night, and I ran my presentation through that engineer to verify it all made sense. I should have also run some of my architecture ideas past that engineer to get buy-in. I also wouldn’t mind having the team mostly formed before we start, but that’s a big commitment to ask of people.
    • Take more frequent, shorter breaks. We hit the Monon Saturday afternoon and walked for 30-40 minutes which ended up making me drowsy. However, the fresh air did us some good and was revitalizing for the project in general. It would be great to have more frequent, 10-15 minute walks, but it’s really difficult to find a time when the team is ready to take a group break in such a fast-paced environment.

Read more

Drive

Have you ever seen a six-month-old or a three-year-old who’s not curious and self-directed? I haven’t. That’s how we are out of the box.
– Dan Pink

The Gist

Daniel Pink’s Drive explores how to motivate modern humans. Today’s offices still employ business practices created to meet the needs of late 19th and early 20th century workers performing monotonous tasks, but many modern workers spend their days doing creative work which is ill-suited for stick-and-carrot management. Pink posits that today’s workforce crave autonomy, mastery, and purpose to lead a satisfying life and produce better, maybe even faster, results.

Takeaways

“Stick and carrot” refers to the technique of “if you do this, then you’ll get that” motivation. Work overtime this week and I’ll buy you bagels on Friday. Read a book and you’ll get a free personal pan pizza. Sit, good boy, here’s a treat. Alternatively, “now that” rewards are ok from time to time. “Now that” the team has worked well together for a few weeks, I decided to bring in some donuts. “Now that” we handed off the code to the client, let’s go get lunch. Note that “now that” rewards should not become predictable, lest they become “if then” rewards.

The concepts in this book are not new. Researchers have discovered this kind of interesting behavior since the ‘60s, and each time they are essentially ignored by the general population. Over the last few years, I have read several books on this topic and assumed we were only just starting to realize that sticks and carrots were bad for creative work, but it seems to have taken some time for these concepts to enter the public view.

“Flow” is the optimal state of working, where the work is challenging enough to keep one engaged but familiar enough to allow mental connections to be made. It doesn’t mean working on something so easy one can get it done fast, because such trivial exercises are boring and non-enriching. Alternatively, it doesn’t mean working on something so difficult that one is “head down” for several days accomplishing nothing, because this type of task is exhausting. You’ll know when flow has struck when you glance up at the clock and suddenly an hour has gone by and you feel good about what you’ve already accomplished and you can see what you’ll be accomplishing in the next hour.

Although money is a poor way to motivate workers, all workers should still be given a fair base pay and benefits package. Everyone needs to live, and unfortunately we don’t live in a Roddenberry socialist utopia where everyone works together to build a functioning world where everyone is paid in the love of one’s career. In fact, Pink prescribes that organizations should try to pay employees slightly above average, which should essentially take the money issue off the table during recruiting and retention.

The best motivation in the modern workplace is the encouragement of autonomy, mastery, and purpose.

Autonomy is the ability to make decisions for oneself, and cause a meaningful impact on the work being done. The craving of the modern human for autonomy can be explicitly seen in the rise of agile software development, remote working, Etsy retailers, startups, farmer’s markets, and freelancing over the past 20 years. When people are allowed to make decisions without the intervention of big brother, they feel more ownership over the work they do, and they feel more freedom to be creative.

Mastery is continual improvement. A 5K runner achieves her goal of finishing in 20 minutes and sets a new goal for 19 minutes, then 18 minutes, and so on. She never stops to say “20 minutes was good enough, I think I’ll stop now.” Mastery is usually something that can never 100% achieved, but the quest for mastery is something that drives us to be better than we were yesterday.

When we think about purpose, we think about leaving our mark on the world. For some organizations, this may involve redistributing part (or all) of the annual revenue to charity. It could also mean building a better medical device for diabetics. Not all purposes are created equal. Improved quarterly sales, more working hours, higher profit margins, happier stockholders are all invalid purposes that do not drive workers to be happier.

Schools suffer substantially from our system of numbers-based achievements. Better grades and better test results have become the primary indicator of success, quelling the curiosity of our children and destroying the happiness of our teachers. Getting away from numbers-based learning will be an extremely difficult task, but there are already schools working towards this goal.

Action Items

  • Recognize when I’ve been in flow and write it down.
  • Recognize when someone is offering me an “if-then” reward, and try to determine a better way to think about it.
  • Recognize when I offer someone an “if-then”, and think about the consequences. Did they perform better or worse than I expected? How could I have created an opportunity for the other person to improve themselves instead?

Read more

At the end of 2015, I published a video course on getting started with web development in Go. For the next two weeks, you can get it for 50% off using this link: http://bit.ly/1PEubnd. With over 2 hours of content for just over $20, it’s a great deal. The sale runs from 21 Jan until 4 Feb 2016.

The video takes the student through every step of creating a personal library web application from scratch, covering concepts such as routing, database access, and authentication. It’s a great introduction to go, and an excellent primer to starting your own go-based web project.

All this comes with the added benefit of supporting me: your local developer. :)

Read more

2015 Retrospective

Another year gone.

What I Wanted from 2015

I set some arbitrary goals for myself at the end of 2014, and I sort of accomplished most of them. Here’s a short list:

  • Contribute meaningful code to several open source projects not created by me
  • Read at least 1 book per month
    • I read 8 books professionally, started getting into graphic novels, and read a couple of silly books by celebrities. I’ll count this as a win.
  • Attend more meetups
    • I hosted quite a few Golang meetups and attended a few ISA meetups, but I’m not sure I actually went to more meetups.
  • >3000 sessions/month on this blog (currently ~1400)
    • By the end of the year, I was doing a little over 4000 sessions/month. I had a few popular posts on Go and Docker which I believe contributed to this.
  • Improve social skills
    • Eh. Unfortunately, this year I largely worked on solo projects in the office which didn’t give me many opportunities to improve my social skills.
  • Work remotely more and better
    • I started off the year doing this well and I was working 2 days a week from home. After one of my projects got canceled, I never managed to get back into the swing of working remotely.
  • Obtain more technical leadership roles on projects
    • Technically, I accomplished this. Again, this feels like somewhat of a weak victory as I only had the opportunities to lead myself.

Surprise Victories of 2015

Not everything can be planned.

  • Got paid to build a video course on writing web applications in Go.
    • I was approached via email by Packt Publishing after they recognized all of my work on my blog and Github in Go. I agreed to create a multi-video course on creating a modern web application in Go from scratch. This was a lot of fun, but also a lot of work. Since I love to teach, I may be looking for more opportunities like this.
  • SEP Professional Development Revamp
    • I am a part of a continued effort to overhaul the Professional Development system at SEP. We are moving away from monetary rewards and towards shared experiences. The first iteration received positive feedback, and we are days away from launching our second attempt.
  • Guides Program
    • In late October, I was asked to be a “guide” for a new employee at SEP. I jumped at the opportunity and have been lucky to help guide an all-around good guy through his first few months at SEP.
  • Open Sourcing Ollert
    • We even got a few pull requests. See the repo.
  • Cats
    • We got two cats, Juniper and Jelly Bean. I didn’t even know I wanted cats until I got them, but they’ve been an important addition to my little family.

Things I Worked On Professionally

I’ll keep this brief.

  • Reporting tool for school administrators in Go
  • Critical web bugs in a traffic radar system, primarily Javascript work
  • iOS app for sending results from a medical device to client servers
  • Bugs and minor features for previous client building an e-commerce website in C# ASP.NET both WebForms and MVC

What I Want From 2016

  • Spend Money
    • My parents raised me to be cheap, and we always seemed to be just scraping by. These teachings served me very well in college and for the year or two after, but now I’m lucky enough to have a great job, house, wife, American dream, etc, and I’ve found myself becoming somewhat of a miser. We finally bit the bullet this weekend and bought a fancy new mattress, but I want this to be the year of me buying new stuff that I’ve always wanted but been too hesitant to purchase.
  • Back Into Web
    • I got really deep into web in 2014 and the first half of 2015, and it’s a platform that I really like to work in. If I can’t find web work in the office, I’ll be making open-source web work a priority.
  • Work With Others
    • This has been the year of solo projects for me, and to be quite honest I’ve found myself feeling downright lonely the past couple months. It’s frustrating to have no one to share with, to fight with, and to laugh with on a project. I intend to rail hard against any project assignment where I am the only engineer.
  • Become Part of an Open-Source Community
    • I have a tendency to build my own side-projects or submit individual pull requests and never be heard from again. This year, I want to find a project where I can be a part of something bigger than just me.
  • Good Vibes
    • I want to have a positive influence. I’m not 100% sure how people view me now, but I understand that I complain a lot and probably come off as a bit negative. I know that I have the power to make waves when given the chance, but I want to make sure that those waves don’t leave the surfers with a sour taste in their mouths.

So Long, 2015

A year where I didn’t accomplish as much of what I set out to, but I managed to find a few surprise wins along the way. If you catch me going against any of my resolutions in 2016, I encourage you to deride me and set me back on track; I’ll be happy to do the same for you.

Read more

Go for Web Development

I have published a video series on building web applications in Go called Go for Web Development.

These videos will guide you through the entire process of creating a web application in Go, all the way from spinning up a basic web server to multi-user authentication. In the end, you’ll learn how to vendor dependencies and deploy the application to heroku. Throughout the course, you’ll learn to utilize many of the most popular go packages including gorilla/mux, negroni, gorp, ace, and bcrypt. You’ll learn about making asynchronous requests from the browser back to the web server, and you’ll learn to access external REST APIs from your web server. You’ll use go’s struct tags to parse both XML and JSON, and you’ll use struct tags to access database entities with gorp.

I spent many late nights creating this course, and I’ve learned a lot of lessons about creating screencasts along the way. I was also able to solidify much of my base understanding of the go language and learn about many features I don’t often utilize. The videos are published by Packt Publishing, and they were a great help along the way. The most valuable lesson I learned from doing these screencasts is that a quality microphone makes a huge difference, and I would have saved myself a lot of trouble had I used my Rock Band microphone from the beginning. In the end everything turned out great. I’m relieved to be finished and excited to have an official ISBN connected to my name.

The video is currently only $5 for the holidays, but the regular retail price is set to $75 (which is still a bargain considering all the content).

Link: https://www.packtpub.com/web-development/go-web-development-video.

Read more