Highway Speeds

This morning on the way to work, a driver next to me switched lanes unpredictably. Marking that car as dangerous, I wanted to be either in front of them or behind them. If in front, they can see me. If behind, I can see them. It’s clear whose responsibility it is to watch out for whom. Driving next to other cars requires a situational awareness, and a trust between them. I didn’t trust that driver, so I chose not to be next to them. It is like on a team. If there’s a clear hierarchy, then everyone only has to watch the people in front of them. In self-organized teams, every team member needs an awareness of every other team member. We have to be careful not to run them over or let them fall behind. This takes trust, communication, attention and caring. Self-organized teams take more conscientiousness, more balance. Yet, how much faster cars can go next to each other than in a line!

Traditional team:

Self-organizing team:

Team without balance and situation awareness:

Work to Rule

There’s a particular kind of almost-strike called “work-to-rule.” It’s when workers in a factory “adhere strictly to all the working rules laid down by their employers, with the deliberate intention of reducing the rate of working.” Doing exactly what they’re told, and nothing else, means production grinds to a halt. Every formal system in life “is parasitic on an informal system.”[2] We count on people to notice problems, to adjust and improvise in small ways. 

The perfect example of work-to-rule is: every program ever. The computer always does exactly what it’s told, nothing less or more. This is incredibly hard to get right! Every human endeavor so far, we rely on people with local awareness. Your blueprint may be lovely, but it’s a construction worker who’s going to notice when the materials aren’t quite right and the walls aren’t fitting, and react to it. A person on the manufacturing line will see when the product is out of whack and correct it. They learned what “out of whack” means from someone else. There’s an informal system underneath.

In the program, there is no person on the ground when decisions are made at runtime. All of that awareness, everything that could go wrong and should be noticed, it all must be programmed in up front. That pushes all of the human context up a level: it’s the developers who supply all of it. We need to understand the program’s environment, the business context, the data, everything. Which problems matter? What can we fix, and what should halt the whole operation? What clues can tell it “this is out of whack?” How will our program react to surprise?

This means all the creativity and conscientiousness and context of all the runtimes is crammed into the development at code-time. The team communication, the adjustment, the humanity: maximize this on the development team. Because we need every ounce of this we can get of this going into the code. It’s all we have to lean on.

We’ve seen from the waterfall process what happens when we try to create a program based on a written set of requirements. Create a development process with a bunch of rules and regulations, emphasizing vertical (in the org chart) communication, and what will you get? That program is already work-to-rule. When the people coding it are also working-to-rule, to any degree, then the code is brittle and unresponsive, just like the production output of a plant whose workers are on this almost-strike.

Be careful about the rules we impose on development. Communication YES, knowledge sharing YES. But let the rules be the ones the work itself imposes. Blind adherence to standards, that’s what the computers are for.

———————-

[1] http://www.thefreedictionary.com/work-to-rule

[2] Seeing Like a State, James C Scott. Introduction.

Tools

There are these wineglasses that my partner likes. They’re pretty, but they’re so tall they only fit in the cupboard above the fridge. He can reach that cupboard, but I have to fetch a stool to get in there. He uses these glasses all the time, while I always choose the squattier glasses that I can reach unaided. It’s free (in time costs) for him to use the pretty glasses, expensive for me.

At work, what tools do you reach for that your coworkers don’t? Or do some of them have tools that you ask them to use for you, because they understand them and you’d have to look stuff up?

When something is free, we use it all the time. Once we do that, we get benefits never thought possible. Branching in git is like that. Autocomplete as a way of exploring an API. Some of us use grep and cut to explore log files, because we know these tools well enough that it’s just as easy as opening the file and searching inside. At a previous job, I was the fastest at production support because I built up a library of SQL joins that tracked down the useful data.

When we take the time to learn a new tool, it’s like we get taller. We can bring down answers and build solutions that were out of reach before. That’s not an option for me with the wine glasses, but it is with Chef and Jenkins, Graphite and the Typesafe Console, Kleisli and Liebniz (strange scalaz types).

Learning a new tool might feel like yak-shaving. Learn it well enough that it’s free (no cognitive load), and you just gained a few inches on everyone else.

Weakness and Vulnerability

In computers and in people, weakness and vulnerability are different. Separate the concerns: [1]

Vulnerability is an openness to being wounded.

Weakness is inability to live through wounds.

In D&D terms: vulnerability is a low armor class, weakness is low hit points. Armor class determines how hard it is for an enemy to hit you, and hit points determine how many hits you can take. So you have a choice: prevent hits, or endure more hits.

If you try to make your software perfect, so that it never experiences a failure, that’s a high armor class. That’s aiming for invulnerability.

Thing is, in D&D, no matter how high your armor class, if the enemy makes a perfect roll (a 20 on a d20, a twenty-sided die), that’s a critical hit and it strikes you. Even if your software is bug-free, hardware goes down or misbehaves.

If you’ve spent all your energy on armor class and little on hit points, that single hit can kill you.

Embracing failure is about letting go of ideal invulnerability, and thinking about recovery instead. I could implement signal handlers, and maintain them, and this is a huge pain and makes my code ugly. Or I could implement a separate cleanup mechanism for crashed processes. That’s a separation of concerns, and it’s more robust: signal handlers don’t help when the app is out of memory, a separate recovery does.

In relationships, vulnerability lets us form connections.[2] When emotional defenses are high, deep communication doesn’t happen. If we leave ourselves open to hurt, if we take that risk, there are payoffs. If we build a network of honest, compassionate friendships, those friends become our recovery mechanism for when we do get hurt. Friends who hug you and say “You are good. I love you.” Fall in love, get burned, cry to my people and be comforted.

In the software I currently work on, I take the strategy of building safety nets at the application, process, subsystem, and module levels, as feasible.[3] Then while I try to get my code right, I don’t convolute my code looking for hardware and network failures, bad data and every error I can conceive. There are always going to be errors I don’t conceive. Fail gracefully, and pick up the pieces. 

——-

[1] Someone tweeted a quote from some book on this, on the difference between weakness and vulnerability, a few weeks ago and it clicked with me. I can’t find the tweet or the quote anymore. Anyone recognize this?

[2] Brené Brown on Vulnerability. Twenty minutes that can change you or affirm you.

[3] The actor model (Akka in my case) helps with recovery. It implements “Have you restarted your computer?” at the small scale.

——-

I’m going to post a condensed version on my real blog.

Unreachable Stars

Something I love about agile and iterative development: acknowledgement that software is never done. It’s never the best it could be — even if it were, “best” changes quickly. A typical project is “done” by decision, not by any inherent completeness. We could always improve.

There’s a beauty in that, an embracing of imperfection and balance. And there’s a dichotomy of striving that defies traditional goals. Within any iteration and any one day, there’s a victory condition of completing a feature or small set of changes. Small victory conditions, achieved all the time. At the same time there’s a larger direction: a striving for software that delights people who use it. This is the Unreachable Star of an agile project, the target that is always in the distance, always moving away from us.

At the same time, within the team, there’s work toward becoming better as developers individually and collectively. Each retrospective has its victory conditions of the week, and we always find more ways to improve. The Unreachable Star is perfect communication, productivity, creativity. We aim for it, yet if we ever think we’ve achieved it, we stop growing and instantly fail.

Contrast with waterfall projects, which define “success” as a particular featureset by a particular date. Work really hard for a long time! Hit the milestone (if you’re really lucky), put up a banner, and then miss the real target. Software developed in isolation never delights people who use it. And then what? Athletes who work their whole lives and finally win gold - then what? Victory is fleeting, so keep it small and frequent. The big-milestone strategy lacks the vision of the Unreachable Star and the daily satisfaction of meeting victory conditions.

This works for me in life. Every day I have small victories, like writing this post, tweeting something that is meaningful to me, completing a task, hearing my daughter laugh. In the larger scale, I don’t have “goals” that I work toward blindly only because I set them for myself. Instead I have Unreachable Stars: as a developer, to keep learning higher levels of abstraction and to share it with others; as a partner, to be completely honest with my connections; as a mother, that my children know I love them and can grow in directions of their choosing.

There are many paths toward my Unreachable Stars, sometimes too many (property-based testing! scalaz-streams! clojure!). It isn’t important which I follow, nor is it important that I head straight there. Any small step in the general direction is a victory. If I define a milestone of some sort (“speak at conferences”) and then achieve that, it’s another victory for the day. If I don’t achieve it, there are many other paths to the Star. No milestone, achieved or missed, can end the quest.

Big milestones (what most people call “goals”) are valuable in defining a strategy toward the Star. They give us something to break down into our daily victory conditions. That’s all. They’re not the real objective, and they can distract us if we’re not careful. It is the mission, the quest, the target-that-is-only-aimed-for-never-reached, that inspires me.

I’ve been looking for a word for this, for the target that sets my direction with no expectation of hitting it. The song from Man of La Mancha, sung by Don Quixote, expresses it. Even in his delusion he has no expectation of fixing the world. Yet he finds happiness in every small move he can make toward rightness. Others are inspired by him, and start to move the world in their small ways. He spread hope, and so became larger than one person.

"And the world will be better for this, that one man, scorned and covered with scars, still strove with his last ounce of courage to reach the Unreachable Star." 

https://www.youtube.com/watch?v=-Mfd4E7kpvc

Personal interfaces

jessitron:

this has me thinking about: when do other people need knowledge of my inner workings to interact with me? when do I broadcast enough information to be discoverable?

Where is the Nanny?

- this is a direct parody of @unclebobmartin’s post, “Where is the Foreman?” -

The nanny in a household is the lady who is responsible for making sure all the kids do things right. She’s the lady with the tape-measure that goes around making sure all the clothes fit properly. She’s the lady who examines all the hair, teeth, and floors to make sure they are clean, and don’t have any significant food particles. She’s the lady who counts the buttons on the jackets to make sure they won’t gap open when they’re worn. She’s the lady — the lady who takes responsibility — the lady who makes sure everything is done right.

Where is the nanny on our software projects? Where’s the lady who makes sure all the tests are written. Where’s the lady who makes sure that all the exceptions are caught. Where’s the lady who makes sure all the errors are checked, and that references can’t be null, and that variables are thread-safe? Where’s the lady who makes sure that the programmers are pairing enough, talking enough, planning enough? Where’s the lady who keeps the food off the floor?

Without a good nanny, a nursery would fall apart into chaos. The children wouldn’t line up. The jackets would hang askew. The pants would be on backwards, and the underwear on the outside. Without a good nanny the diapers and the cups would both leak, and the whining of babies would be heard in the drawing room. Without a good nanny the children would get to school very late, with a huge mess left behind them, and have abysmal outfits.

Without a nanny, the floors would be covered in food.

What would the nanny do on software project? She’d do the same thing she does in a household nursery. She’d make sure everything was done, done right, and done on time. She’d be the only one with commit rights. Everybody else would send her pull requests. She’d review each request in turn and reject those that didn’t have sufficient test coverage, or that had dirty code, or bad variable names, or functions that were too long. She’d reject those that, in her opinion, did not meet the level of quality she demands for the project.

I imagine that many programmers recoil in horror from the idea that someone else would have the power to judge their code and reject their commits. After all, how can you get done on time if the code has to be right? How can you possibly meet your schedule if you have to write all those tests? I mean, if there’s a lady who’s actually going to look at the code, then there’s no way to make yourself look good by saying that the code is done when it’s not. It’d be awful.

Awful or not, it’s what most industries do. If you want to get a project done, done right, and done on time, you need a nanny. And that nanny has to be so technically astute that she can check the work of all the workers. She has to have the authority to reject any work she considers sub-standard. And she also has to have the power to say “No” to the unreasonable demands of the customers and managers.

Where is the nanny on our software projects? Where is the lady with the commit rights? Where is the lady who makes sure all the tests are written, and all the concerns are separated, and all the right dependencies are inverted?

Why don’t we have this lady?

Is it any wonder that our floors smell like breakfast?

——————————-

Gendered language matters. It matters to who feels like they belong, who feels like they should be in charge. If you are skeptical of this, please please read (or at least skim) this satirical piece by Douglas Hofstadter:

http://www.cs.virginia.edu/~evans/cs655/readings/purity.html

Libraries and Frameworks

"Politics and culture often function as ‘prisonhouses’ of knowledge… yet they can and often do function as ‘toolboxes,’ enabling new perpectives."[1]

Imagine if you’d only ever used JavaScript with Bootstrap. If all you’d ever worked with were Bootstrap sites, you might think that .button(‘toggle’) is a native method. Someone else, coming from a different framework, might ask why you organize your files just so, and you’d be like, “What do you mean? That’s where they go. They have to.”

A framework places restrictions on what we do. It makes decisions for us. This makes our lives easier. And it’s OK, when we choose the framework, and we consciously accept those limitations. Libraries, on the other hand, only support us in our decisions. Sometimes that’s all we need.

Each of us lives in a cultural framework. We didn’t choose it, we just grew up in it. It’s the way we know, the “obvious” way things are. Yet, there are people around us whose circumstances aren’t the same. People of a different class, race, gender, or background. They grew up in a different cultural framework. They know some things we don’t. If we recognize this, we can learn those things. Like using pieces of Angular within your Bootstrap site. You can’t switch frameworks, but once you realize that other frameworks exist, you can use bits of them like libraries.

————-

[1] The Feminist Standpoint Theory Reader, Sandra Harding. Introduction.

"Why?"

Children ask “Why?” and when you answer, they say “Why?”

It’s “Why” all the way down with them, sometimes. There is no end.

As an adult, we ask “Why?” now and then, and pretty quickly we get to “In my observation, it has already worked this way.” This isn’t a reason, but it is a heuristic that works, and it lets us get stuff done.

This happens in programming, too. When pairing, a curious beginner asks, “Why do we do it this way?” and the senior programmer says, “YAGNI.” and the beginner asks, “Why?” A philosophical discussion ensues, and the senior programmer is bored and frustrated. She wants to write some code!

In her observation, you ain’t gonna need it, so code it the simple way and move on. The beginner wants to investigate the concepts and learn. They’re both right. Both are good uses of time… but maybe not this time right now. Adults get stuff done, curious beginners (such as children) learn.

In a board game the other day, my partner went for the direct route of “How can I get points?” while I went the indirect route of “How can I give myself more options for later?” I won that game.

Those of us who continue to question will win in the long term. Yet, as adults can know when it’s time to go on experience. The best of both is to reflect on our work later, question our assumptions and dig into the “Why?” and the “Is there a better way?”

Conferences are great for this. Step back and reflect, learn new viewpoints, and discuss. We are grownups most of the time at work. Go to development conferences, and be a kid. Play! Expand your options and connections and keep asking “Why?”

Narratives

In real life, people struggle to hear, categorize, and remember stories that don’t fit one of the traditional narratives. A story of an open marriage that didn’t work out, where complete honesty wasn’t enough to bring acceptance for romantic love in the plural, where love died gradually until by the time the danger was recognized it was too late

becomes “he cheated and chose his girlfriend over his marriage.” Not the truth, but it fits the pattern, people can classify that and talk about that. Simple models, we like simple models, who cares about accuracy if it’s a nice simple model?

There are accepted narratives in software, too. The web application. The algorithm. The formal scrum iteration or the mostly-waterfall model. The agony of Release Week. When a project or framework or (what can we even call it when there are no clear application boundaries?) breaks out of established modes of computation, when User Acceptance Testing no longer makes sense, how do you even explain that to people?

"I don’t see how this could work. This doesn’t make sense. Stop it." If we can’t see the reasons for something, there must not be a reason. That person is stopped in the middle of the parking lot because they’re an idiot! There is no other explanation in my simple model!

I grow beyond myself when I am small in the world. Everything happens for a million reasons, and I might know a few, but usually I’m wrong. New ways to see, new ways to think, new ways to learn things I could not conceive before, this is the goal. In relationships and in computing.