Grow to where we’re going

“Plants are movers…. Plants grow to where they’re going.”

Frazier, P. & Jamone, Lorenzo & Althoefer, Kaspar & Calvo, Paco. (2020). Plant Bioinspired Ecological Robotics. Frontiers in Robotics and AI. 7. 10.3389/frobt.2020.00079.

This is a keynote written originally for a private company. I’ll do it at conferences, including YOW! in September 2020.

Short bite:

In software, we want to go fast. We draw a roadmap, so we can move from here to there.

When software is part of a larger system, we want it to go to new places and also support the customers it supports now.

Growth is a better metaphor for software change than movement. When we grow to a new place, we still exist in the old place. We are still there for the systems that integrate with us.

  • The value of software is in its connections to the wider system: in its use.
  • Growth never stops until death; software is “done” when it’s out of production.
  • We don’t grow -in- an environment; we grow -with- an environment. Influence is healthier than control.
  • Teams are like forests. The whole forest is communicating underground through a network of roots and fungi. The essence of a team’s work is out of sight, in the knowledge we exchange with each other and embed into the software.
  • Developers are like trees in a forest. Sometimes management can’t see the “team” for the “resources.”
  • Trees are green because intensity isn’t everything. To go fast is less important than to keep going.

This is about more than software. As a person, I grow to where I’m going. As a culture, we grow to where we’re going. We don’t control our environment, but we do influence it.


Full text:

We like to go fast.

As humans, we like to move. Kids run fast, grownups drive fast cars.

We like to get from here to there.

In software, we like to move. High velocity. Draw a roadmap and move forward.

Moving is not the only way to get to a new place.

We do a lot of moving because we’re animals. Consider plants. plants go places. Plants grow to where they’re going.

You think they hold still, when we look at them they’re not going anywhere. But that’s just cuz we’re too busy moving. You put a time-lapse camera on them, and sure enough, they’re on the move. And not just up, either.

Plants have a couple different movements. There’s tropism, where they move to the light or against gravity. There’s there’s nutation, which is not triggered by light or gravity, it comes from the plant. My favorite is circumnutation.

This is where as the plant is growing, it’s turning. Most plants, in their stems, in the pistils of flowers, as they grow they’re also turning. Round and round, they do this thing. They do it by growing at different paces in different sections. The right is growing, and now the back side, and now the left, and now the front — and this causes this twisting. It’s a kind of exploration.

An extreme example is a vine, because it grows fast — vines are clearly going somewhere — and it’s always looking for new support mechanisms.

i want to show you this YouTube video that’s a time lapse of a vine growing. It makes this tendril, and the tendril whips around (slowly, not that we could see it by staring for our incredibly short attention span) and when it finds a support, boom! it grabs on, it grows around, and then it grow… shorter, by growing twisty like a slinky, and pulls the vine in.

(video. 0:10 – 1:43) 

It goes around like a startup looking for traction, and then whap! it found some. Now it’s checking that out, now it’s pulling in closer, by growing into a slinky shape. Like it’s bringing its business in line with this product-market fit. meanwhile the flower. It changes shape by growing first at the base, then along the length of the leaves. It’s growing in ways you can’t see, too. Until… boom! now that’s a feature release! Look at that UI, I bet it has great documentation too, and such marketing! I want to adopt it!

See, in software, maybe we’re more like plants than animals. We get to new places by growing.

When I talk about software, I mean the important stuff. It’s running in production, other software calls its APIs, people use its interfaces, it’s part of a business, it’s part of an industry.

Because, if we run like an animal or drive like a car, we can get to someplace new but then we’re not where we were. And what if someone was counting on us back there?

What about the previous API format? what about the old screens, and the people who knew where stuff was? There are other systems that depend on our software being where it was.

Our customers matter. Internal customers also matter.

Then when we want to change a feature – if we conceive that change as animal movement, as we-were-there, now-we-are-here, we might have a hard cutover. There used to be a “provider_name” field, now you have to give us a “provider_url” field. Other internal systems have to coordinate their deployments with ours. Starting at 2am on Saturday morning, it’s gonna work this way. We’re all gonna stay up late and have a big rollout.

Ughghg I remember those days, fifteen years ago. It was not pretty. These changes are fragile! because we’re not supporting the system around us.

The alternative is to grow to the new place. Grow to accept provider_url.

To do that, first we want to sense our environment. Plants can feel light, gravity, pressure, bites and cuts, lots of things. Our software can too, if we build the sense organs we need. So make an event for each call to our API, and make that event say whether they supplied provider_name or provider_url.

Then we make it possible for them to send provider_url, we add the optional field. And we notice that no one is sending it. And we notice who is sending provider_name.

And we talk to them. In an external API, this would be marketing, maybe developer relations, advertising to customers about how provider_url is so much faster and more specific and such a great idea.

Internally we do this too, the vine feels its way up the plant as we talk to other teams about the importance of provider_url to the business. We advocate for the change.

And then we see it happen, in the production events. And MAYBE, if this is internal and we have influence over everyone who calls this API, someday no one will use the old provider_name field.

And then we can kill off that old part. We can those leaves die. We can remove provider_name.

Oh my gosh, you might say. This is so many more steps than a clean switchover.

OK, anyone who’s been part of a six-month development cycle, Saturday night release knows: it is not clean. There is nothing easy about that. And those changes were not fast.

Here’s a thing: we think that fewer steps are easier. Wrong. Easier steps are easier.

Design the change to keep every step easy and smooth.

Growing happens in many steps. The stem grows on the right, the stem grows on the back, the stem grows on the left. The outer leaves grow, the inner leaves grow. The shape changes.

Does this sound slow? Surely fewer steps are faster. Wrong. Faster steps are faster.

The change is smooth, there’s nothing to trip over, no one we have to coordinate with.

With growing to new places, with smaller steps and backward compatibility, we get decoupling. Not of functionality — your service might still depend on mine — but of change. They can change at separate times. They can adapt.

The environment adapts to me, and I adapt to the environment.

You have your vine growing around the tree, and I have my vine, and they might twist around each other and support each other. I promise to still be here, and you’re free to grow at your pace. Neither of us needs control over the other. We do have influence.

Influence is healthier than control.

And this is a difference between programming and software development. Programming is part of software development.

Programming is not the same thing as software development.

When we learn to program, we get good at solving puzzles in code. We think, I’ll get a job and solve harder puzzles.

But in software development, we have to formulate the puzzles. And then solve them in code until we figure out they aren’t well-formulated. We find those edge cases and ambiguities hopefully while coding. sometimes in production. We’re always refining the problem.

Software development is so much more than programming.

Software development is system change.

Value is in the relations, in how our piece relates to its environment, in the ways people use it. We preserve that value when we grow to new places.

External change has to be careful. We need very careful API design because whatever we publish, we’re gonna have to support it forever.

Design more than the new feature, how it works inside — design the path to get the larger system sys there.

Marketing, Training, documentation, transition plans, backwards compatibility is never optional, measurement of use and of value. There’s a lot more to software than changing the code.

Because it’s not just about us and whether we closed these JIRA tickets, when it’s about a business or an industry or making the world better, then moving fast is not the goal.

Growing safely is the goal.

System change is slow.

Like plants!

Plants have a different sense of time.

We can’t see them moving because we don’t hold still long enough. It takes a vine a few weeks to take over my rosebush. To a beech tree in its forest, what’s eighty years? Aaah, still a baby.

Trees have electrical signals that move through their bodies. They take 3 seconds to go an inch. Our nervous system is at least 60 times as fast.

We need to program at a higher pace than this.

Decouple the pace of change

So we take extra steps (easy, fast steps) to decouple the change of the outer system from the inner system. Feature flags let the flower grow inside the leaves until we’re ready to show it to the world.

Let the smaller pieces change faster.

We make API-level tests so we can safely deploy. These are boundaries, inside which we are free to move. To formulate and re-formulate those puzzles before we commit to that public release.

Growth is complex

Now, all that code for backwards compatibility, all those stems and leaves behind us — that’s complexity. That makes our code a lot more complicated.

And more valuable. That is essential complexity, that our software makes the world’s life easier by encasing that complexity.

When you see code that’s old, that doesn’t make sense anymore, maybe it exists for some historical reason that a customer’s software was harder to change than ours, appreciate it. That code is beautiful.

Because our code only matters as much as someone uses it. As much it fits into the environment.

It’s our relation to our environment that matters

And that’s another thing about growth. It cares about the local environment, all along the way.

Growth is exploration.

Growth is sensing. Its plan is a direction, and its path is determined by what it sees in the environment. The vine climbing a tree knows it’s going “up” and “around” but it can feel the tree as it goes, and make local decisions. If it encounters a branch — well, the roadmap says to go THROUGH. But maybe we’ll go around. Or maybe, since we noticed it, maybe we’ll send a sprout along the branch and find a whole new space.

Growth succeeds -with- its environment, not fighting it.

In software: maybe we add a new API to return past orders. To keep the rest of the system safe, we put in paging, and a limit on the total requests it will accept. We find early that the total request limit is hit, everybody is asking for the entire history all the time. We can’t let all those requests through. Do we implement per-customer rate limiting? Do we add a whole new subsystem with its own copy of the data to handle demand? Or maybe – maybe the customers would narrow the data request if we ask them what they need to select by and give them that option. Sense the unexpected request volume, and then feel along it to find out what the world needs from us.

We can formulate the puzzles better now.

Growth succeeds -with- its environment. They change together.

and we succeed, as teams and as companies -with- each other.

The value is in our connections, not in competition.

Take these trees. My brother-in-law took this picture down in southern missouri, where he lives. He’s in a pine forest, looking up, and you can see the sky. It outlines the trees. This is called “crown shyness.”

The trees are not all up in each others’ business in the canopy. They give each other space. They share the light.

They’re like, on the same side or something.

Now, the naive version of evolution says it’s about competition. Individual variation in an effectively fixed environment.

That’s not reality with these trees. They’re creating an environment together. The forest where they live and the forest is made of them. If one tree dies, then storms get in, then the cool moist microclimate of the forest is disrupted, and all trees suffer.

So they watch out for each other, and for the forest generally. How do they avoid touching like that? not sure. Maybe they talk about it – trees do talk to each other.

They communicate with chemical and electical signals through their roots. Their roots interconnect, and also they connect through fungi which is all wrapped up in the roots, giving nutrients, getting sugar. The trees are sharing sugar with the fungi, with each other, they help the sick trees. They warn each other about pests. Time to start producing this defensive chemical.

Sometimes they use the air for communication. A particular bug bites the leaf, the tree tastes that saliva and gives off a chemical to trigger the other trees — and other parts of itself, the air is faster than its internal signals — that here’s this pest. Defenses up, summon the wasps that eat this caterpillar.

Those air-based communications can benefit other plants in the forest, too.

Trees share knowledge with each other and the whole forest

In fact, trees off by themselves in a green field, with no “competition” but also no connections to other trees — they aren’t as healthy. They don’t live nearly as long.

It’s almost like the forest is more of a thing than the tree.

This reminds me of our teams.

Cuz the forest is made of trees, the team is made of us and we work in the team. It’s like we collectively form our own habitat.

we share knowledge

We share knowledge with each other. And we put our knowledge into the software.

We put our knowledge into the software, our knowledge of the business and how this needs to work and what should be done in each case, with each provider_url (or whatever). And we put in our knowledge of how computers work together and what people need to know and what we need to know in order to decide where to grow next.

Cesar Hidalgo, statistical physicist, has this book Why Information Grows where he points out that a product is a form of embodied knowledge. Our customers don’t have to know nearly as much about the business as we do.

software embodies our knowledge

That software embodies that knowledge, the knowledge of how to get prescriptions paid for. They can use the knowledge without having all of it.

Like a forest, the team is made of us (and the software).

And on the team we share information with each other, we help each other get work done.

Get work done, hmm.

What work?

Recently some college interns were asking about my job, they wanted to know what I do on a typical day. And I struggled with the question. Like, it doesn’t feel relevant?

Some of us were looking at job descriptions for roles on a product team, and trying to define their responsibilities… what does a product owner DO? What does a designer DO? What does a software engineeer DO?

Uh… typing? and talking to people and each other?

Define our roles by what we know, not what we do

I can’t even describe how the team works together with action words. We may have a backlog and some user stories and we make some code and some tests and you can see commits and artifacts but these are superficial. They’re thin representations of some knowledge.

Cuz this is knowledge work, right? We’re not making physical stuff, we’re generating knowledge and embodying it in software.

I can describe the team and the different roles of the people by what we each know.

Follow this link for what this looks like: Define roles in terms of what we know

We each know how our piece of the system works — on the computer and in the larger system. We each know enough about the others’ focuses to have a conversation and know when to ask. And these focuses don’t mean we know everything, it means we go get that information when the team needs it. (Which is how you become an expert.)

And we grow in different areas. Like, maybe we’re working on a feature right now, but next we’ll work on availability, and then we’re gonna do some security testing and tighten that up, and then we’re going to make this feature perform better — like the plant circumnutating, growing at different rates in different parts, finding a healthy direction to grow. We focus on increasing our own knowledge in different areas, and encoding that into the software.

From this perspective I can derive activities and artifacts. We increase knowledge with reading code, with talking to customers and business experts, with looking at the events that happen in production. We contribute knowledge in discussions around user stories, by typing in code, by improving our build pipeline, by designing careful API changes.

But all of this is surface. The essence of what’s going on in our team’s work is underground, it’s like the fungi in the forest, where all that knowledge is moving between us and our environment and the software.

So teams are like forests that way. And that expression, you can’t see the forest for the trees? Well, sometimes a company can’t see the team for the resources. You can plant a new tree in this forest, but it takes time to grow roots and tap into that network of knowledge. A new person can know Ruby, but they don’t know how this software works yet, or who to talk to about each thing, or where to write a test or how to deploy – this is not quick, no matter how smart that person is. And you can take a person off the team, like cutting a tree down in a forest, but it’s gonna take time for the canopy to close and restore the climate, and we may never recover all the familiarity with the system that lives in those roots, in that fungi network out of sight.

So be careful. Our teams are repositories that generate and embody knowledge. We happen to type some of it in.

But if you get focused on the people as “resources”, and you get focused on “productivity”, you won’t get healthy growth.

In fact, plants have something to say about efficiency.

See this valley? This is my favorite mountain view in Tennessee: it’s off Avdi Grimm’s deck.

What do you see? lots of shades of green? Ya know what that green is?

Waste. Waste! The fattest juiciest light in the sun’s spectrum is green. And those plants, that chlorophyll whose job it is to turn sunlight into energy is reflecting it right back!

so it’s green, not like proper solar power cells which are black, because they absorb all the sunlight, duh!

Trees are green because smooth is better than MOAR.

It turns out, according to some recent research, that reflecting the green light gives the leaf cells a smooth flow of energy.

Plants reflect green light because they are optimizing for consistent flow, rather than most intensity.

See, the tree cells can only turn light into sugar so fast. Excess energy starts ionizing free radicals and is dangerous for the cell. So the leaf does its best work when it gets a fairly consistent flow of energy from sunlight, and then it can absorb it all into sugar.

In the circumstances our plants live in, the red and blue ends of the spectrum hit the leaves more consistently, more smoothly. And somebody did a model and said, if the leaf cells are optimizing for steady flow, then the best thing is to absorb red and blue and reflect green!

More important than going fast is to keep going.

Growth is like this. A plant might grow up and then out and the vine might be moving this way and then oh wait lets send this shoot off over here. Or it’s winter, let’s slow this stuff down. But it never completely stops growing.

As we don’t either. We’re always renewing cells and making fingernails at least.

Moving is done. Growth is never done. (until you’re dead)

And our software is never done. (until it’s out of production)

It can’t be done, because the world around us is still changing. Those puzzles we carefully formulated and solved, somebody found a hole in that formulation.

If it wasn’t our customers, it’s an attacker.

The creativity of security exploits grows every day. Like somebody figured out, in JavaScript on the server, if you can send some data that sets a property on any object’s __proto__, you’ve set it for all objects. And then you can set it to code, and templating frameworks let you put JavaScript code in the HTML templates, and so they eval that code, and boom, an outside person can run anything on your server.

(It’s like the plants in Chernobyl. When people stop paying attention, life finds a way.)

Now, how would they figure out what data to send in order to do this? Some of it’s trial and error, generating random input until you see a different error message, but it’s also based on open source frameworks and libraries. These give clever attackers (and security researchers) insight into what code might be running on servers throughout the internet. Then they figure out what to send to get their code to run.

Attackers succeed by knowing things about our system that we don’t.

They know this weird __proto__ feature of JavaScript. They know the libraries and framework we’re using, and they know where its holes are.

Most software has way more open source library code than custom code. There’s lists on internet of ways to hack them. So they’re a source of risk… except, they’re also a source of fixes.

When a new vulnerability is found and published, it’s a race. The bad guys make programs to exploit it and start running them all across the internet just because they can. The open source maintainers publish a fix very quickly, and then it’s up to all of you to upgrade.

My favorite is the big equifax data breach, in 2017 like 150 million of us got our credit reports stolen in a breach that started in a customer complaint application that used Apache Struts 2. The maintainers published a fix in a few days, Equifax never updated their app, not for four months, not until after they noticed that people had been stealing data for months.

The number 1 by-far-the-biggest thing we can do to keep our software secure is update our libraries. All the time.

Listen to the knowledge coming to us through library updates. Defense against hole-boring insects is available to us, if only we respond.

Now this means we need to deploy our software frequently. Renew our cells, keep our plant healthy.

It’s funny, old-school computer security was afraid of change, change might introduce a vulnerability! Nooo, the world is introducing vulnerabilities. Change is on our side.

Security: change is on our side

Also, immutable infrastructure. Like at Equifax and a lot of infiltrations, the first thing an attacker does is install a web shell or some other means of easy access for them. Then they go sell the opening to someone who wants to commit Medicaid fraud. This stuff takes time, and if we redeploy the app to a new container or a new VM, and shut down the old one, we just took their access away.

So cloud-native deployments, even if you’re not in the cloud, help with security. That fresh infrastructure is another way change is on our side.

So we’re always changing, but we’re never taking away what our customers were counting on.

Software is never done. Growth slows but does not end until death.

Our software has value because it’s part of a larger system. It has value because of the business knowledge that our team, that we put into the software. It has value when it sends signals back to us about how it’s used, about the wider system.

So let’s not think of our jobs as moving a car along a roadmap. The software grows more like a vine around a rod. The business strategy gives us direction, and we are sensitive to local conditions, to all those surprises and edge cases we find along the way. All of those are increasing our knowledge and helping us better formulate the puzzle.

I am not a tree in a green field

And as a developer, I’m not a tree out in a green field making flowers for … maybe a bee? I’m part of a forest, a team, and we build relationships and share knowledge FIRST and put it into the code second.

Because it’s not about me. I have influence, not control. And it’s not about my app, or my service. We don’t design systems, we design subsystems. Which have influence, and not control.

And trees are green because efficiency isn’t everything. It’s not as important to go fast as it is to keep going.

When I need to get someplace new, and stay there, like sustainably, I don’t try to move as fast as I can.

Grow to where we are going.

It’s healthier in software.

It’s how we change ourselves as people.

I don’t will myself into losing weight, or sleeping better, or being okay with not traveling anymore. I help myself get there with new routines that I try and then try something else until I find what’s compatible. I reach out and seek new sources of connection, I sense and then I grow into a person more compatible with the current environment. I grow to where I need to be.

It’s how we change our culture.

Not by shoving, not by moving, not by discarding where we were or the path we take. Not by ignoring the people around us, but by bringing them along.

We aren’t only growing and evolving -in- our environment. We’re growing -with- it. We matter, not as competitors inside a niche, we matter as participants in bigger systems.

Nobody has control. We all have influence.

Pig: “Hi magic fairy. I need you to fix the whole world, virus, racism, planet, hunger.” Fairy: “Okay! just one problem: I don’t exist.” whump! “…but you do.” (pig donates to food bank)

In software, in ourselves, and in our culture — let’s grow to where we’re going.