Larry Price

And The Endless Cup Of Coffee

Waltzing With Bears

| Comments

When you challenge your subordinates to pull out the stops and bring your project home on time (even though the schedule is ludicrous), you need to understand that you are staffing your key positions with NASCAR racers. They will take every chance, ignoring every imaginable downside, in order to preserve – at least for the longest time possible – any thin, little chance of winning.

The Gist

If you aren’t on board with software risk management by now, your company may be living 20+ years in the past. DeMarco and Lister discuss the importance of risk management and methods to convince others in your company that risk management is important in Waltzing with Bears.

My Opinion

This is an important book. Written during a pivotal moment in the IT industry prior to the Dot-Com Bubble, it is incredible to think that any software product can be built while ignoring any risks. I’m grateful to be a member of an organization that not only thinks about risk, but puts an emphasis on risks, especially before project work begins. I’ve yet to hear many companies who do a good job of thinking about risk in the middle of a project (pre-implosion), but DeMarco and Lister are desparate to convince me to think about risks all the time. Fortunately, I’m not a manager.

The authors hit hard on the fact that some projects fail: from their research, one out of seven projects will not see the light of the day. This is a huge figure, but even I’ve experienced a discontinued project in my short career as a software engineer. The authors don’t tell us how to mourn the death of a project, but simply warn us that it’s always a possibility.

We can adapt to most risks - this dropdown widget has poor performance so we’ll swap it for a simpler widget, UX doesn’t like the way this looks so we’ll revisit it, the vendor stopped responding to emails so we’ll roll our own - but there are other risks which are much more difficult to recover from. Have you added in the risk of your lead developer leaving the company? What happens if your office’s landlord suddenly ends your lease? How can you deal with a client project which takes up 30% of your company coming to an end? Although the authors don’t tell us how to deal with these problems, they encourage us to always keep them in mind when planning.

It seems that the Agile Invasion has come to save us from some of these problems. We plan our work iteratively so we can embrace change (as long as it happens outside fo sprint boundaries). We estimate stories or tasks to enhance our wild guesses about how long our work will take. Our lead developers pair with young padawans to spread knowledge throughout the team. Although Agile methodologies are more ubiquitous these days, it’s clear that this book was written before the adoption of these ideas.

Waltzing is all about managing risk: emphasis on the managing. As a software developer, my role seems to be a bit more fuzzy. The authors encourage the development team to express their concerns, but there isn’t much else to do afterwards. The rest seems to lie in the hands of managers conveying these concerns to the stakeholders and deciding which risks are worth accounting for. The authors also mention using tools to perform Monte Carlo simulations to add risk into project estimations - a tactic useful for managers pre-product-kickoff, but not so useful once you’re in the trenches trying to build a product.

Who Would Like This

Mostly managers or those who want to know things managers need to consider. As an engineer, there seems to be little I can do except to express concerns. I still enjoyed reading this book to get a manager’s perspecitve on software development. These are the same guys who co-authored Peopleware, which is a must-read for anyone in the software world, so it’s certainly worth at least reading the back cover of Waltzing.

I Am an Artist Now: CSS3 Transitions

| Comments

I just discovered CSS3 Animation and I am quickly becoming obsessed.

CSS3 makes DOM animations really easy. I can move things around, shrink or enlarge text and images, make buttons and links “pop” on hover, and help the user focus on the most relevant information. This can all be done through CSS3.

DISCLAIMER: Contrary to the title of this article, I am less of a Picasso and more of a dog making “art” all over your brand new rug.

Animation

Do you see that ball up there? If you can’t, go check out the jsfiddle. The concepts are so simple an embedded programmer could do it. Let’s look at the animation- tags on the ball first:

1
2
3
4
5
6
.ball {
  /* ... */
  animation-duration: 10s;
  animation-name: rollout;
  animation-iteration-count: infinite;
}
  • animation-duration
    • The length of time the animation will take to complete.
    • Example: 10s
  • animation-name
    • A unique name for the animation we want to use. If you write good animations, you might be able to reuse them later.
    • Example: rollout
  • animation-iteration-count
    • The number of times the animation should run. Default 1.
    • Example: infinite

Note that there are several other animation- attributes to give you more control, but we only need a few in this case. For a more in-depth look at these attributes and their constituents, I advise you to check out this MDN article. Also, note that at this point Google’s Chrome browser still requires -webkit- prefixes on animation objects. Hopefully they join the rest of the modern world soon.

The animation- attributes let us configure our usage of an animation, but the real guts of the animation come from the definition inside a @keyframes tag.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.ball { /* ... */ }

@keyframes rollout {
  25% {
    margin-left: 47%;
  }
  50% {
    margin-left: 94%;
  }
  75% {
    margin-left: 47%;
  }
  100% {
    margin-left: 0%;
  }
}

Note the name rollout is the same as the animation-name attribute we set on .ball previously. This is the definition of our animation at different timeframes. What this says:

  1. 25% of the way through the animation, the object should have margin-left of 47%, putting it in the middle of the page.
  2. 50% of the way through the animation, the object should have margin-left of 94%, putting it at the far right of the page.
  3. 75% of the way through the animation, the object should have margin-left of 47%, putting it in the middle of the page again.
  4. 100% of the way through the animation, the object should have margin-left of 0%, putting it back where it started.

This is easy and relatively readable. I can see exactly what is supposed to be going on and when.

Transition

Although the animation- attributes give you a lot of control over animations, there are several other tools available. CSS Transitions are animations that are performed between two distinct states. This is especially helpful when you want to run an animation after some event happens. When I click this button, I add a class to my ball to make it move to the right. I click it again and the ball moves to the left. You can see the fiddle below or view it on jsfiddle.

The important CSS here is transition and the margin-left:

1
2
3
4
5
6
7
8
9
10
.ball {
  /* ... */

  transition: margin-left 3s;
  margin-left: 0%;
}

.rollout {
  margin-left: 94%;
}

When my DOM object has the ball class, a transition will begin to set the margin-left to 0% over a period of 3 seconds. When the rollout class is applied, a transition begins which brings the margin-left to 94% over another 3 seconds. The transition knows to apply the given CSS attribute as found in the last-applicable style definition.

Transitions are really great for single page applications - as I switch contexts in my application, I move my DOM elements around or I gradually hide them from view. When I get time to release my next homemade application, expect to see lots of little animations. Probably way more animations than necessary - just bear with me.

There are many other CSS animation topics, but I don’t quite have the experience to elaborate. Transforms give you really easy ways to rotate, skew, and translate objects, even allowing for the creation of 3-dimensional CSS objects. The to and from shorthand in @keyframes elements can make reading animations even easier. I may be a little late to the party, but the world created by CSS3 and HTML5 is a much better one for programmers and (hopefully) for end-users.

A Quick Guide to Using Docker-compose (Previously Fig)

| Comments

Have you used Docker yet? Docker is awesome! Docker is a tool for managing isolated system environments. I have started using Docker for everything. This is not the first time I’ve written about this delightful tool.

Though the ideas and implementation behind Docker are really cool, the command line syntax is extremely cumbersome. There used to be this great third-party tool to address this problem called fig. But, as of yesterday, it looks like Docker is maintaining fig and have renamed it to docker-compose. The impact of this change is minimal on developers - rename fig.yml files to docker-compose.yml, use docker-compose up instead of fig up. Some great features have been added that I’ve been sorely missing, including the ability to use environment files and only grabbing the latest tagged images from the hub.

Let’s learn you some docker-compose.

Installation

Two ways: pip install docker-compose (if you’re into that kind of thing) or through a questionable bash script:

1
2
$ curl -L https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose

You probably want bash completion while you’re at it:

1
$ curl -L https://raw.githubusercontent.com/docker/compose/1.1.0/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose

Compose, World

Let’s say I have a simple Go application which only prints the obligatory “Hello, World”:

simple-golang-app/main.go
1
2
3
4
5
6
7
package main

import "fmt"

func main() {
  fmt.Println("Hello, World")
}

I want to run this with docker-compose, so I create the following file:

docker-compose.yml
1
2
3
4
5
6
app:
  image: golang:1.4
  working_dir: /go/src/simple-golang-app
  command: go run main.go
  volumes:
    - ./simple-golang-app:/go/src/simple-golang-app

This file specifies using the golang:1.4 image as the base image. It maps the our code directory to a directory in the $GOPATH in the container. It then specifies running the command go run main.go from the working directory of /go/src/simple-golang-app. So let’s run it:

1
2
3
4
5
6
$ docker-compose up
Creating dockercomposeexample_app_1...
Attaching to dockercomposeexample_app_1
app_1 | Hello, World
dockercomposeexample_app_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)

Composing a Database Connection

Now let’s say I want to connect to a database and find some information. The following example connects to a Mongo database, inserts a record, and spits out all the existing records:

database-golang-app/main.go
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
package main

import (
  "fmt"
  "gopkg.in/mgo.v2"
  "gopkg.in/mgo.v2/bson"
  "os"
  "time"
)

type Ping struct {
  Id   bson.ObjectId `bson:"_id"`
  Time time.Time     `bson:"time"`
}

func main() {
  // get the session using information from environment, ignore errors
  session, _ := mgo.Dial(os.Getenv("DATABASE_PORT_27017_TCP_ADDR"))
  db := session.DB(os.Getenv("DB_NAME"))
  defer session.Close()

  // insert new record
  ping := Ping{
    Id:   bson.NewObjectId(),
    Time: time.Now(),
  }
  db.C("pings").Insert(ping)

  // get all records
  pings := []Ping{}
  db.C("pings").Find(nil).All(&pings)

  fmt.Println(pings)
}

This application has an external dependency on mgo, which means I’ll need to have that dependency installed somehow. I’ll make a Dockerfile to live alongside this example:

database-golang-app/Dockerfile
1
2
3
FROM golang:1.4

RUN go get gopkg.in/mgo.v2

Now I’ll construct a yaml file for docker-compose to consume. This time, we need to build the main app from our Dockerfile, add in a second container for the database, add a link between our application and the database, and specify an environment variable.

docker-compose.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
advanced:
  build: ./database-golang-app
  working_dir: /go/src/database-golang-app
  command: go run main.go
  volumes:
    - ./database-golang-app:/go/src/database-golang-app
  links:
    - database
  environment:
    - DB_NAME=advanced-golang-db
database:
  image: mongo:3.0
  command: mongod --smallfiles --quiet --logpath=/dev/null

Since mongod has a tendency to spit up a big boilerplate on initialization, I redirect its output to /dev/null for this example. Let’s see what happens when we compose:

1
2
3
4
5
6
7
8
$ docker-compose up
Creating dockercomposeexample_database_1...
Creating dockercomposeexample_advanced_1...
Attaching to dockercomposeexample_database_1, dockercomposeexample_advanced_1
advanced_1 | [{ObjectIdHex("54efd8f889120d000d000001") 2015-02-27 02:39:52.53 +0000 UTC}]
dockercomposeexample_advanced_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
Stopping dockercomposeexample_database_1...

If you squint, you can see the output next to the advanced_1 tag. We printed out one item from our database - the one we just added. What if we run it again?

1
2
3
4
$ docker-compose up
...
advanced_1 | [{ObjectIdHex("54efd8f889120d000d000001") 2015-02-27 02:39:52.53 +0000 UTC} {ObjectIdHex("54efdbb936cc3f000e000001") 2015-02-27 02:51:37.879 +0000 UTC}]
...

This output proves that we’re fetching from the database each time in addition to adding new records. Since the Mongo Dockerfile we used to build the image creates a volume, we get to see the data persisted.

To achieve the same goal with the Docker CLI, I would need to do this:

1
2
3
4
5
$ docker run -d --name database mongo:3.0
$ docker build -t database-golang-app ./database-golang-app
$ docker run --link database:database -e DB_NAME=advanced-golang-db \
    -v /home/lrp/Projects/2015/docker-compose-example/database-golang-app:/go/src/database-golang-app \
     database-golang-app go run /go/src/database-golang-app/main.go

Keeping that much information at your fingertips all at once absolutely hurts. Making that line reproducible means copy/pasting it into/out of a README somewhere, or running some “single-line script” which only the one guy on the team is allowed to touch. docker-compose fixes these issues and makes docker a joy to use.

You can find all of the source code for this blog post on Github: https://github.com/larryprice/docker-compose-example.

Peopleware

| Comments

Visual supervision is a joke for development workers. Visual supervision is for prisoners.

The Gist

Peopleware, originally published in 1987, is the most relevant book ever written for managing software teams and organizations. DeMarco and Lister give a light-hearted take on all the wrong ways to manage IT projects and give helpful shoves towards some better alternatives.

My Opinion

I knew this book would be a good fit for me, but I had no idea just how much I would like it. This book connects a lot of pain points I’ve had so far in my (relatively) short career, so much so that I cannot believe we still have these problems nearly thirty years since its inception.

In particular, I found the first half of this book life-affirming. The second half is more about managing people/teams, which is harder for me to get a grasp on as a developer, though now I’ll be quietly (or loudly) judging my managers based on what I read. Let me go into details about all my favorite parts of this book.

Quality – If Time Permits. Sacrificing quality for the sake of time and/or money is an extremely common theme in our industry. Not only does a low-quality product hurt the bottom line, but software builders base thier self-esteem on the quality of their code and releasing bad code makes us feel bad. Morale is guaranteed to hit rock-bottom when we are not given enough time to determine edge cases and iron out bugs before releasing a product.

Parkinson’s Law is complete gibberish. Parkinson’s Law states that work expands to fill the time allocated. I’ve heard this phrase thrown around pretty persistently in my professional life, especially when we talk about estimating story points. I shouldn’t need to go into why this is a terrible thing to tell a dev team. It’s insulting; do we truly believe that our development team does not want to get the work done as efficiently as possible?

The Office Environment. This part of the book hit a little too close to home for me. I recently moved desks and have been having unforeseen interruption and distraction issues. I sat right next to the door entering Main Engineering. Hundreds of times a day, I would hear the beep! of a badge swipe, the clunk! of the door unlocking, the crunch! of the handle being pushed in while the door swings open, and finally the ker-chunk! of the door closing and locking. Each of these times, my head would naturally bounce up towards the doorway to see who’s entered. In the most unfortunate of cases, I would make eye contact with the intruder, prompting them to come and chat for a brief moment. Time and time again, my concentration would be broken. I finally realized this a few days ago and moved my desk back into a little corner, which alleviated a big part of this problem.

You Never Get Anything Done Around Here Between 9 and 5. I have become somewhat infamous in the office for being the first one to work. I currently arrive around 7am, although I’ve been known to show up anywhere between 5:30am and 7:30am depending on what I’m working on. I do this because the open office plan that software culture is currently infatuated with drives me insane. I had begun to think I was the only one in the industry who would prefer a shared private office to an open cube farm, but fortunately this book has reassured me of my sanity. Knowledge work requires quiet time without distractions or interruptions, which often means it requires walls and a door.

You Never… also discusses space issues. The authors are famous for conducting “coding war games,” where individuals from different companies compete in a programming challenge while timing themselves and writing down every disruption that affected their time. In these studies, they found that those with a greater amount of personal space tended to do better than those with less. The top quartile had 78 square feet on average, while the bottom had 46 square feet. My estimate puts my current space at around 40 square feet.

Somewhere in The Office Environment, the authors discuss windows (the transparent kind), which I wanted to breifly touch on. Our current facilities are window-rich, but window-seat poor due to the design of the building. Fortunately, we have a Commons area that is “Oops! All Windows” at our disposal, but I would love to be able to glance out a window from my desk. My eyes get tired throughout the long day of staring at my computer; the authors prescribe desks with at least 8 feet of space between the developer and the wall such that the developer can let his or her eyes rest from time to time. This is a difficult problem to solve with cubicles. Windows also help with this.

There is also a lot of content in this book about managing people, especially those in software. You should read it. There are good discussions about not forcing teams to do overtime, keeping players who work well together on the same teams, and letting underlings make decisions.

All in all, this book was incredibly useful for me and made me feel a little less alien. I read the second edition of this book, though I have come to learn there has recently been a third edition released.

Who Would Like This

Software developers and anyone who thinks they have direct control over software developers should stop whatever they are doing right now and read this book. Did you read this book twenty years ago? Read it again.

Ollert Is Now Open Source

| Comments

Ollert, the Trello data analytics tool, has been open sourced under GNU Affero GPL v3.0. The source code can be found on Github and I’ve already accepted several pull requests.

Why?

I’ve been working towards this for a few months now. Although Ollert was a lot of fun to create and has helped quite a few people learn more about their Trello boards, I’ve been having trouble finding the time to write new features in between my other pursuits. Although SEP has given me resources in the past, it’s not always easy to find people off-project who have the right experience, determination, and time to grok the codebase and start churning out new features.

An interesting pattern started to appear: With every other feature request I received for Ollert, the requestor would add in some other loaded question: Where is the source code? Is there a Github repo so I can add issues? Do you accept pull requests?

Random strangers on the internet wanted to help. These are people with the drive to work with me even though I couldn’t give them anything in return. These are people with fresh perspectives on Trello usage which I had never imagined. These are the developers whose help I sorely wanted.

Feature requests?

I am still accepting feature requests. Feature requests are now dealt with through our issues page.

Contributing?

  • Write tests
  • Run tests
  • Seriously, the travis-ci build had better be green.
  • Follow the currently in-place patterns. If you don’t like them, let me know your idea before you work for a week and I deny your changes.
  • Create issues for whatever you’re working on.
  • We do things by pull requests. Make a fork, make a branch, let Github do the rest.

And so, it continues…

This does not mean I am abandoning Ollert. Internally we’ll still be discussing how to increase traffic and improve user experience. Hopefully, open sourcing Ollert will give us invaluable feedback on the code and fresh perspectives on features. I’m looking forward to the future of Ollert.