Progress in Learning

Back in the day, artists mixed their own paints. They bought minerals, ground them up, and mixed them with binder. Then in the 1800s, metal paint tubes became a thing, and people bought smooth, bright paint in tubes.

Do they still teach mixing your own pigments in art school? Maybe, in one class. I took one class in Assembler when studying Computer Science. That gave me some useful perspective and some vocabulary, but the baby computer designs we looked at were nothing like the computers we use.

I’m betting that art schools don’t return to pigment-grinding for months out of every year of school. There are new styles to learn, higher-level methods of expression that build on top of paint tubes.

Why do my kids spend months out of every year learning to do arithmetic by hand? They could be learning set theory, new ways of thinking that come from higher-level math.

Why are they learning cursive instead of coding? We can express ourselves at higher levels through computers.

Human culture advances through products. Paint in a tube is a product that lets artists focus on painting. It lets them work in new locations and at new speeds. Monet and the other Impressionists painted as they did because they could finally paint outside, thanks to tubes of paint!

I don’t want new computer programmers to learn the basics the way I had to learn them. They don’t need to program in C, except maybe one class for perspective, to learn the vocabulary of memory overflow. Learn queueing theory, that’s a useful way of thinking. Don’t implement a bunch of queues, except as extra credit.

Some artists still mix their own pigments.

Viewing a painting produced entirely with hand-ground mineral pigments is a completely different experience than looking at one made with modern chemical paints. The minerals scintillate and their vibrations seem to extend from the canvas.

Laura Santi

We need a few specialists to implement data structure libraries and programming languages. There are contests for mental arithmetic, if you enjoy that game. Calligraphy is a great hobby. When I sit down to learn, I want to learn new ways to think.

When younger people skip the underpinnings and learn higher-level concepts, that’s called progress.

Let’s reason about behavior

When we learn math, geometry, and logic in school, we’re always talking about things that are holding still. The element is in the set or it isn’t. The angle is acute or obtuse or right or we can’t know. Things are related or not. A thing has a property, or doesn’t.

Code can have properties. A function has side effects, or doesn’t. Data is mutated, or never. An API call can be idempotent. Whole programs can have properties and we like to reason about them.

Yesterday talking with Will Larson on >Code (episode 142), he pointed out that once we move beyond a single process, especially when we go to microservices and have oodles of processes running around, we don’t get to talk about properties anymore. Instead, we have behaviors. He said:

Properties, you can statically analyze.
Behaviors, you can verify they happen.

A call to one program, or even a series of calls, can be transactional. Once you’re in a distributed system, not a thing. You can talk about how the system behaves.

Rein pointed out that in distributed systems, properties are incredibly expensive. Guarantees like all-or-nothing transactions, exactly-once delivery, consistency are never perfect in the real world, and the closer you choose to be, the more you pay in money and latency. Coordination is expensive.

In addition, can we get better at verifying and reasoning about behaviors?

Will pointed out that fault injection is a way to verify behaviors. That makes sense: psychologists learn a lot about the way we think from a few people with localized brain injuries. Emitting and querying events is another way.

Then how do we reason about behaviors? Systems thinking helps. Will recommends Donella Meadows’s Primer as a start. (I loved that book too.) Also, the social sciences have been studying behaviors forever. Maybe their methods, like Grounded Theory, can help us.

We’re people, right? We have behaviors. If we can get better at naming and reasoning about them, maybe we can get better at being people. It could happen.

Other people’s messes

There’s a funny thing, that when I walk into the kitchen and there’s sunscreen on the counter that I left there before yesterday’s bike ride, there’s a plate that I put to soak on the counter and there’s a book about Klimt that I had hoped to read with my coffee, this is fine.

It doesn’t feel messy. I almost feel a comforting sense of continuity with my past self.

But when other people leave crab rangoons and cups and bowls and mail and washcloths lying around, ugh! mess!

It’s somehow different when I have the story behind it.

Code is like this too. If I remember writing it, then I know this nutty interface name was a placeholder. This ratty console.log helped me debug a tricky crash. I’m in the process of refactoring to use the new functions, but the old ones are still around some places.

When that’s anyone else’s code, it looks like trash.

This tells me: if the code is my own toy, and I’m likely to be back to it before I forget who I was when I wrote it, then all those intermediate states are fine. They might help me get back into this groove, even.

But if the code is shared, or if I won’t be back in it later this week, make small changes completely. One at a time, in series, so that each commit leaves the code clean. Put the sunscreen on and put it away. Wash the plate and put it in the dishwasher immediately. Take my coffee upstairs to drink with the book.

Sometimes I wish I lived alone, so I’d only have my own mess to deal with. I don’t want to code alone, though, except on toy projects. I do wish I lived with people who cleaned up after themselves. I resolve to make smaller messes in our shared code, one at a time.

Mostly we orient

Observe, Orient, Decide, Act. This is the OODA loop, first recognized in fighter pilots and then in the Toyota Production System. It represents every choice of action in humans and higher level systems: take in sensory data, form a model of the world, choose the next action, make a change in the world.

At least in fighter pilots, and in all our daily life, most of this is automatic. We can’t help observing while we are awake. We constantly decide and act, it is part of being alive. The leverage point here is Orient.

The model we form of the world guides our decisions, both conscious and unconscious. Once the pilot has a geometric plane of battle in mind, the decisions are obvious. Once you see the bottleneck in production, you can’t look away from it. When I have an idea what’s going on in my daughter’s mind, I can talk to her.

Our power to change our actions, our habits, and our impact on the world lies in Orient. When we direct our attention to finding new models of the world, whole new possibilities of action open to us.

Fighter pilots can see what is possible when they picture the battle in the best geometric plane. Production managers needs to look at the flow of work. In software, I look at the flow of data through services and functions — different from when I used to see in objects or think about spots in memory.

The power of breaking work into smaller chunks is the chance to re-Orient in between them. TDD gives us lots of little stable points to stop and think. Pairing lets one person think about where we are in the problem space while the other is busy acting. Mob programming gives us the chance to negotiate an orientation among the whole group.

That co-orientation is crucial to collaboration. With that, we can predict each other’s decisions and understand each other’s actions. If we have a shared model of the world and when we are going, plus trust in the competence of our team in their respective specialties, that’s when we can really fly.

(This post is based on a conversation with Zack Kanter.)

Brains and eyes: hierarchies in vision

We see with our brains. Then we check with our eyes.

Our retina takes in light, varying by brightness and color. It transmits information along the optical nerve to the primary visual cortex. There, specialized cells activate on outlines and contours in various orientations (horizontal, vertical, oblique). This part of the brain separates objects from backgrounds.

Along the pathway from there to the inferior temporal cortex, face-contours go one way, object-contours go another. Here and in higher-level processing, meaning and categories are assigned to images. Then we perceive.

All of this is affected by memories of things we’ve seen before. Visible edges are supplemented by inferred ones. Depth is judged by remembered sizes, among other clues; binocular vision is only useful close-up. What we think we’re looking at determines where our eyes move in their saccades, and this determines what we get a clear view of. Vision depends on context and history.

like, some light comes into the eyeball and hits the retina, which passes up data about colors and positions to the primary visual cortex, which comes up with contours and edges and depth and passes that on up to higher levels

This highly inexpert summary comes from listening to The Age of Insight, by Eric Kandel, neuroscientist. (Audible does not provide a PDF of diagrams, grr.)

Andy Clark goes farther in Surfing Uncertainty. At every level, from retinal nerve cell on up, signals from the outside are compared to expectations. Only surprises are transmitted up the hierarchy. Our vision starts with guesses, which are broken down into what we expect to see at smaller and smaller scales, and at each scale these guesses are tested against the incoming light signals.

expectations come from higher level brain function; they get broken up into what we expect to see in each area and then each cell. Each level compares these to what it’s getting from outside, and informs higher levels of differences.

This makes sense to me. When I hear stuff like “the retinal gangleon get the light signals and assemble them into colors and position, and then the primary visual cortex deduces edges and contours, and then the inferior temporal cortex recognizes objects and faces” I think: gah, that sounds like so much work.

Why would we do that work? I know very well that I see a sky and trees and billboards and road. Why would I ask my eyes to process the incoming data? If my retina cells don’t see blue (or gray or white) in the top part of the visual range, then I want to notice it. Otherwise, geez, take a breather. Read the billboards, they’re all different.

One day while carpooling to work, in the passenger seat, I played a game. I looked out the window and tried to see what was there. Not what my brain is trained to see, the buildings and billboards placed there by humans for humans to look at. I noticed some wild growth, some derelict corners and alleys, and many cell phone towers. Each time, I tried not to judge (categorize, evaluate) what I saw, but keep seeing.

It was exhausting! By the time I got to work, my brain was done. I didn’t get any useful code written that day. This is not what my eyes are doing most of the time.

In video transmission, we send deltas, not pixels. And we can use all kinds of protocols to describe common deltas, expected changes, to reduce bandwidth use. Our brains do that, too.

The hierarchy of vision communicates in both directions. Expectations down, surprises up. At every level, an interplay between meaning and incoming signals. Hypothesis, test. Result, new hypothesis, test. It’s a duck, OK yeah. It’s a rabbit, OK yeah.

Thinking about vision this way gives me new appreciation for how our past experience changes what we see. It also gives me new ways of thinking about hierarchies: the helpful ones pass information in both directions.

We see with our brains and our eyes and many nerve cells in between, working together in both directions. I wonder if we can work this well together in our organizations.

Rules are not easy

Sometimes in software design we get this idea, “We’ll make this a rule engine. Then the business can write the rules, and they’ll be able to change them without changing the code. That’ll make it more flexible.”

🤣

The rules are code; they change the behavior of the system. Rules interact in ways that are hard to anticipate. It’s harder to write rules than to write code.

It seems like we make business decisions in terms of rules, because we talk about them that way.

People make uncomplicated decisions by rule. We make complicated decisions by aesthetic (from expertise), and these are difficult or impossible to express in rules.

Real-life rules often contradict each other. A human with a feeling for the situation can prioritize among them.

For instance, “How do you position a picture in a column of text?” Back in the day, people laid out the newspaper pages, and they positioned them using some rules and also their eyes. How does a browser do it? Careful people have created nine precise rules for positioning float elements. Excerpt:

4. A floating box’s outer top may not be higher than the top of its containing block. When the float occurs between two collapsing margins, the float is positioned as if it had an otherwise empty anonymous block parent taking part in the flow. The position of such a parent is defined by the rules in the section on margin collapsing.

you don’t need to actually read this

If you think “Rules are declarative, they’re easier to reason about than imperative code” then go format a complicated web site with CSS. Make changes in the hundreds of lines of CSS, and see if you can predict the results. Now see if you can predict the results of changing someone else’s CSS.

Writing rules is hard. Designing a syntax and semantics that let people write rules to cover all the cases in the world, even harder. Do you really want to embark on that? Is it really more effective than changing some code when the business wants change?

As humans, we make aesthetic judgements for complicated decisions. This is one of our superpowers. Putting those judgements into rules is never easy; don’t pretend it is. And no, you don’t need to implement a rule engine.

Thanks to @nokusu for teaching me about floats and margins and other layout fun.

Human, or Person

Sometimes I think about, what if aliens kept humans as pets? Raised them from babies in isolation, without human language, without society. What would a human be like, outside of other humans?

Not a person.

As Abeba Birhane points out beautifully in her talk at NCrafts and article in Aeon, we aren’t people alone. We form ourselves in our interactions. “A person is a person through other persons.” A baby (while homo sapiens) is less of a person than an adult, because the adult has connections, the adult participates in many systems within society.

Every hear that saying “You are the sum of the five people you hang out with most”? Yeah. Good approximation.

We get meaning from interaction with others. We form our self through this. Most of our relationships are not transactional, we’re not in it for some end goal — the interactions have intrinsic value. They build and reflect who we are. That’s enough!

If you have a friend you wish you could do more for, know that being a friend is itself a thing. Listening, being present, sharing a reality with a person — this is already a thing. Often we help each other out in tangible ways, and that feels great. But a simple “I hear you, I see you” — we can’t live without that, we can’t be a person without that.

Without each other, might as well sit by the food bowl and yowl.

Why is CSS a thing?

All I want is a web page. I want this one thing on the left and this other thing on the right — why is this so hard?? Can I just make a table in HTML like I used to do in the nineties? Why do I have to worry about stylesheets? and, why are they so hard?

As a backend developer, I’m used to giving the computer instructions. Like “put this on the left and this on the right.” But that is not how web development works. For good reason!

As the author of a web page, I do not have enough information to decide how that page should be laid out. I don’t know who is using it, on what device, in what program, on what screen, in what window, with what font sizes.

You know who does know that stuff? The user agent. That’s a technical term for an application that presents documents to people. The browser is a user agent. The user agent could also create printed documents, or it could speak the document to a person whose eyes are unavailable.

The user agent runs on a particular device. Computer, phone, TV, whatever. It knows the limitations of the hardware. It can be configured by the user. The user agent can conform to various CSS specifications.

CSS is not a programming language. It is a syntax for rules, rules which give the browser (that user agent) clues about how to display the document. The browser combines that information with what it knows about the world to come up with a format to display (or speak) the document.

It turns out that rule-based programming is hard. It sounds like it should be easier than imperative code, but it is not.

So no, you don’t get to decide that this thing goes on the left and that thing goes on the right. The browser gets that choice.

But here’s something I learned yesterday: put each thing in a div, and give those divs display: inline-block. then the browser has the option of putting them next to each other, if that fits with those constraints that only it knows.

Implementing all the interfaces

Humans are magic because we are components of many systems at once. We don’t just build into systems one level higher, we participate in systems many levels higher and everywhere in between.

In code, a method while is part of a class which is part of a library which is part of a service which is part of a distributed system — there is a hierarchy, and each piece fits where it does.

An atom is part of one molecule, which combines into one protein which functions in one cell in one tissue in one organ, if it’s lucky to be part of something exciting like a person.

But as a person, I am an individual and a mother and a team member and an employee and a citizen (of town, state, country) and a human animal. I am myself, and I participate in systems from relationship to family to community to culture. We function at all these levels, and often they load us with conflicting goals.

Gregory Bateson (PDF) describes native Bali culture: each full citizen participates in the village council. Outside of village council meetings, they speak for themselves. In the council, the speak in the interests of I Desa (literally, Mr. Village).

Stewart Brand lists these levels of pace and size in a civilization:

  • Fashion/art (changes fastest, most experimental)
  • Commerce
  • Infrastructure
  • Governance
  • Culture
  • Nature (changes slowest, moderates everything else)

Each of these work at different timescales. Each of us participates in each of them.

We each look out for our own interests (what is the fashionable coding platform of the day) and our family and company’s economic interest (what can we deliver and charge for this quarter) and infrastructure (what will let us keep operating and delivering long-term) and so on.

Often these are in conflict. The interests of commerce can conflict with the interests of nature. My personal finances conflict with the city building infrastructure. My nation might be in opposition to the needs of the human race. Yet, my nation can’t continue to exist without the stability of our natural world. My job won’t exist without an economic system, which depends on stable governance.

If we were Java classes, we’d implement twenty different interfaces, none of them perfectly, all of them evolving at different rates, and we’re single-threaded with very long GC pauses.

Tough stuff, being human.

Rules in context: D&D edition

In Dungeons & Dragons (the tabletop game), there are universal laws. These are published in the Player’s Guide. They set parameters for the characters, like how powerful they should be relative to monsters. The Player’s Guide outlines weapons, combat procedures, and success rates. It describes spells, what they do and how long they last. What is a reasonable amount of gold to pay for a weapon, and how much learning (XP) comes from a fight.

The Players Guide does not tell you: everything else. What happens when a player attempts to save a drowning baby using a waffle?

The Player’s Guide represents the universal laws of D&D. The rules exist because they’ve been shown (over time, this is the 5th edition) to enable games that are fun.

Yet the prime directive of D&D is: what the DM says, goes. (The DM is the dungeon master, the person telling the story in collaboration with the players.) The DM can override the rules when necessary. More often, the DM makes up rules to suit the situation. The rulebooks do not cover everything the players might choose to do, that that’s both essential and by design.

In D&D, the DM sets the stage with a situation. Then the players respond, describing how the characters they control act in this situation. The DM determines what happens as a result of their actions.

In our game today, Tyler was DM. Tyler DMs by the “Rule of Cool”: “If it’s cool, let them do it. If it’s not cool, don’t make them do it.” One character, TDK Turtle, ran out of the inn with a waffle in hand. On his next turn, he tried to use the waffle to save a drowning baby.

Could that ever work? The DM decides. How unlikely is this? More unlikely than Turtle rolled. And yet Tyler came up with a consequence: Turtle threw the waffle in the river, our dog jumped in to eat the waffle, the baby grabbed onto the dog, and thus the dog saved the baby.

Every D&D campaign (series of games with the same DM and roughly the same players) has its own contextual rules. These build up over time. Our party has a dog because yesterday we rescued this pet from a Kuo-toa tribe that was trying to worship it as a Doge. (The Kuo-toa worship gods of random construction. Where by random I mean, DM’s choice. This DM chose Doge, because it advanced the plot.)

What works for a group of players, we stick with. What doesn’t, we leave behind. If it’s cool, do it. If not, don’t. Results drive future practices.

Our teams are like this. Humans work within universal laws of needing to eat and sleep and commute. Organizations impose constraints. Within these bounds, we come up with what works for us, what makes us laugh, and what helps us advance the plot of the system we are building.

Not every baby-saving-waffle-toss is the same. Not every party has this dog. Let teams build their own process, and don’t expect it to transfer. Do look for the wider rules that facilitate a productive game, and try those more broadly.