SIGAVDI #46: Corned beef & cabbage edition

Hello friends,

It's been two weeks since the last SIGAVDI. I visited my kids in Pennsylvania last weekend, then came home and went into a bit of an emotional tailspin. As of today (Sunday) I'm feeling a bit better. I attribute the improvement mostly to getting some much-needed human touch and socialization over the past two days. It's amazing how much these things help.

Heads up: I'm officially looking for a part-time consulting client. There's some more info here; feel free to pass it along!

Some premises about my relationship with unit testing:

  1. I like test-driven development.
  2. I like driving out individual object design small, isolated (e.g. no database) unit tests.
  3. I think of these unit tests as a design aid, full stop. Any help they provide with preventing regressions is gravy.
  4. I treat unit tests as disposable. Once they have served their purpose as design aids, I will only keep them around so long as they aren't getting in the way.

These four premises are strongly interconnected. Take away #1 (test first), and tests are no longer a design aid and none of the other points are valid. Take away #2 (isolation) and we get into integration test territory where there's a much higher possibility of tests having regression-prevention value. Take away #3 (design focus) and the other points lose their justification. Take away #4 (disposability) and I spend all my time updating tests broken code changes.

This makes  it easy for me to find myself at cross purposes with others in discussions about unit testing, because often they come into the conversation not sharing my premises. For instance, if your focus in unit testing is on preventing regressions, you might well decide isolated unit tests are more trouble than they are worth. I can't really argue with that.

A recent conversation on this topic inspired the thought from the driving-design perspective, maybe unit tests are really just a crutch for languages that don't have a sufficiently strong REPL experience. While I don't think this is strictly true, I think the perspective shines a useful light on what we're really trying to accomplish with unit tests. I almost think that what I really want out of unit tests is the ability to fiddle with live objects in a REPL until they do what I want, and then save that REPL session directly to a test for convenience in flagging API changes.

That conversation also spawned the idea of immutable unit tests: unit tests that can only be deleted, never updated. A bit like TCR. I wonder if this would place some helpful incentives on the test-writing process.

So I tweeted about some of these thoughts and someone was like “don't say that in public, you might lead junior developers astray”. And it got me thinking about how I've said similar things in the past. There's a trope in the developer practices conversation that goes: “there are some things experts do which we shouldn't talk about in public, because someone impressionable might get the wrong idea.”

The more I think about this, the more I wonder if it's healthy or constructive. What do you think?

Sometimes you make me feel like I'm living at the end of the world.

— The Cure, Plainsong

I've been thinking and talking to friends about apocalyptic relationships. That's my phrase for relationships that are premised on a model of “you and me against the world”. Imagine the post-apocalyptic film or novel of your choice, with the two romantic leads braving a treacherous wasteland full of bandits and mutants, and you have the right idea.

Apocalyptic relationships are inward-facing. They survive on the energy of “anti”. They have only one speed: intense. They draw their intensity from scarcity. You and me: we're the only ones who can help each other through this hellscape.

For many years I was in a relationship that only really worked when it was in the apocalyptic mode. Now I feel like I'm keenly sensitized to the “smell” of potential apocalypse. I've been talking to friends about their experiences with apocalyptic pairings. Once likened it to a “Bonnie and Clyde” feel. A relational suicide pact. They all agree though: these relationships are engrossing, intoxicating, profoundly difficult to move on from, and they feel like nothing else could ever come close in terms of intensity of feeling.

I'd be curious to hear your experiences and thoughts, if any.

OK, let's see how I did:

This week my friend Janelle is visiting (you should check out her book!). We're mostly going to be working on our own respective projects, but I'm hoping to make some kind of collaboration emerge as well. Goals for the week:

  • Stream/record some kind of collab with Janelle (IdeaFlow demo??).
  • Finalize my new working arrangement with Cohere.
  • Get to a tentative agreement on a consulting gig (probably over-optimistic but I can hope).
  • Nail down April travel plans.
  • Clean up the weight room and do some lifting.
  • Sundry RubyTapas and Rubber Duck meetings and related work.
  • Attend a new meetup (I have one picked out already!)
  • Attend some part of Big Ears Festival.

OK, that's it for this week. Thanks for reading!

How to meet people at tech events when you’re awkward and shy

Are you a meetup wallflower? Believe it or not, so am I.

Jessica Kerr isn't, though. She's one of the most vibrantly social developers I know. The other day I asked her: what are some ways to get over awkwardness and make valuable connections at tech events? We recorded the conversation, and you can watch it right here. Or, you can get an enhanced version with edited video, audio downloads, and a PDF below.

Want to get the key takeaways AND support more content like this? I'm trying an experiment. I've distilled the conversation down to a concise, tightly-edited 15-minute version. You can have .mp4 and .mp3 versions of both the long and short versions, AND a PDF we authored together containing 32 takeaways (including a few we didn't talk about in the video), for just $5.

Sarah Mei says“Highly recommend… even the PDF summary had several new ideas I’m going to try out at my next meetup.”

SIGAVDI #45: Pimento Cheese Edition

Hello Friends,

First off, sorry if you got another duplicate SIGAVDI from last week. Drip's RSS-to-email service apparently doesn't keep track of the IDs of posts it has already syndicated.

Let's start with a picture of a flower before I get cranky.

Last week I tried to get started with AWS Lambda. It did not go well. I did a lot of cursing on Twitter and on stream.

The AWS developer experience is straight-up awful, and it's a wonder to me that anyone tolerates it. It's reminiscent of J2EE a couple decades ago, in that there is a lot of totally unnecessary ceremony, but it's “the standard” so everyone assumes that this is just the way it has to be.

Now there is a devoted technical priesthood, who have invested both their livelihood and their sense of mastery in the persistence of the status quo. Not to mention the strata of parasitic services which exist solely to put a simplified face on AWS services, and whose existence thus depends on raw AWS continuing to be a shitshow.

These are not good incentives to have in your developer ecosystem.

Example 1: In the 500 page official guide to AWS Lambda, there is a section that instructs the developer to “write the following JSON”. There follows three pages of JSON intended to be entered into a text field. Someone actually wrote that out and said “yep, this is acceptable, ship it”.

Example 2: In order to use the AWS CLI for the first time, I am instructed to:

  1. Log into the web portal
  2. create a new user
  3. create a new administrative group
  4. and search through several hundred permission bundles in order to find the correct one to…
  5. …assign admin rights to the new group, so that I can finally
  6. Copy an ID and a key to the CLI setup.

Compare this to the Heroku CLI experience.

AWS is also reminiscent of the Microsoft developer ecosystem a couple decades ago, in that the breakneck pace of API updates gives invested developers no time to step back and evaluate alternatives.

(For the record, no, this complexity is not essential—from what I've seen so far the Microsoft Azure experience is a shining example of how it can be done better. My how the mighty have… gotten their shit together.)

Someone quoted Hanlon to me in reply to one of my tweets: “Never attribute to malice that which is adequately explained by stupidity”. I don't think systems like this stem from malice. Sociotechnical systems are more like water seeking the least opposed path through which to flow. All it takes for malicious attributes to spontaneously emerge is for no one to reflect on the outcomes.

One other insight that came out of that rotten experience: good APIs and good documentation are inseparable. You can't have the one without the other. You get them both at once, when the people tasked with communicating to developers are empowered to say “the experience I am documenting is unacceptable, let's change this”. I watch Jessica doing this for Atomist on her streams all the time, and it's great. I've also heard the same kinds of stories from Azure's DevRel team, and it shows in the quality of both their docs and their DevX.

I wrote some advice to a friend the other day. It's about the worlds we hold inside, and the longing we sometimes have for someone to come join us in our inner worlds. It went something like this:

No one can join us in our inner worlds.
There is a place inside where we all stand alone.
It's not about finding someone to join you.
It's about joining with others and building worlds in the connections.
This requires a letting-go.
Letting go of control.
Letting go of dreams.
Not forever, just for a time.
Every time I let go it's painful.
Every time, I don't want to.
Someone says “come build this thing with me”.
And it's not my trip. It's not my brand. It's not my dream. It's not my thing.
But I work with them.
And a thousand insights take flight
Worlds take shape between us.
It's… washing up on other people's shores.
Allowing their dreams to take precedence for an hour or a day or a week.
This is how we entangle ourselves with the world
And in return we get leverage.
And our insights are deepened.
And we are enriched.

Let's see how I did.

  • ✔ The usual RubyTapas stuff. Eh, sort of.
  • ✔ Nail down March travel plans.
  • ❌ Write and publish a post about the consulting gig I want to pick up. Didn't happen.
  • ✔ Evaluate open loops of projects-that-could-be-generating-revenue-if-I-finished-them, pick one and make a concrete plan to finish it by a specific date. Yep! I picked the “Flawless Ruby” course I've been quietly developing, and added 17 new lessons to make it content-complete.
  • ✔ Submit to a conference. Two, in fact: DevOpsDays/Serverlessdays Atlanta and THAT Conference.
  • ❌ Clean up the weightlifting room so I can start working out there again.

Next up:

  • Create and launch a marketing campaign for Flawless Ruby.
  • Publish “Beyond Business Cards”, a recorded discussion I had with Jessica Kerr about how to meet people at tech events.
  • Get next week's RubyTapas episode out the door.
  • Visit my kids.

SIGAVDI #44: Goat Cheese Edition

Hello Friends,

I'm having trouble writing this today. I'm already two days late, and I feel completely uninspired.

Spring has been sputtering hesitantly to life around here. Here is a flower of some sort from my front garden.

While I was working with Betsy Haibel on her Asynchronous JavaScript course I got curious about what some of the patterns would look like in Ruby. Specifically, I wanted both to understand Promises better, and figure out whether they were also necessary in a language like Ruby that has built-in Fibers (short answer: nope).

I spent a lot of the past week writing and re-writing Ruby demo code to explain various async patterns like demultiplexing, Reactor, Promises, and JavaScript's async/await keywords. This is all going to make its way into some RubyTapas episodes. But now that I've spent as much time on it as I have, and written this much code about it, I think I'd like to expand it into a course of some kind. “Understanding Async with Ruby and Marshmallows”, how does that sound? Would you be interested in such a course?

In the process I wrote up a list of all the many ways I misunderstood Promises along the way.

I am very anxious today. For the usual reason, money. My income consists of a) subscription income plus b) some kind of special sale or two, often of a new product, over the course of a year. I haven't done (b) in quite a while, and I'm getting to the point of wondering if I'll make each upcoming month's expenses.

This anxiety always comes with a heaping helping of frustration at the sense that I'm constantly mired in upkeep. I want to make new things and yet week after week I feel like I just tread water. It's a vicious cycle: the longer I do it, the less inspired I feel.

And then when I do  have time to work on something big, I feel like I don't know what project to choose and so I dither.

I wonder if this is what it's like for other people in my line of work? I'm pretty successful as pro-developer-trainers go. I wonder if other people who do what I do, feel this way?

My laptop is failing and this is bumming me out too. I really want to buy a shiny new video editing laptop to take the failing laptop's place while it's in the shop, and then to become my “home” machine once my little lightweight Spectre comes back to me.

Do I need to buy a shiny new laptop? No. I could resurrect one of my old machines for the interim. I want to buy a new one because I'm anxious and stressed and feeling useless, and my brain wants to avoid these feelings with dopamine. Shiny new computers come with lots of dopamine. Unfortunately, it always runs out.

It's time to take a consulting gig for extra revenue. Well, not just extra revenue. I haven't worked with a team since… 2011? I burned out hard on working other people's problems, and that burnout played a big role in the creation of my education business.

I want to be in the thick of it again. I've had a lot of new ideas since my last coding job, and I want to have a real sociotechnical system to bang those ideas against. See what sticks and what falls apart.

And I want to feel the pain again. I want to remember firsthand why I care about making systems better. Maybe feel some of the frustrations that burned me out last time around, but this time collaborate on ways to overcome them.

In short I crave inspiration. If you have a lead on a position you think might be right for me, please do reply!

Prefer part-time and flexible, since I still have a business to run. Must at least partially involve pairing/coaching/collaborating with other people. Bonus points if the company doesn't mind me livestreaming some of the work.

OK here's the thing: I take a look at my situation. I come to the conclusion: I will take a consulting gig. This will help.

Then I waffle, and dither. If I take a consulting gig, I won't be able to work on new products! I won't be able to do any of the stuff on my list! What if it's a terrible mistake?!

But (and here is where I give myself advice): interaction spurs progression. The point is not to make the right call. The point is I need to put certain stresses on my mental system in order to cause it to respond in desirable ways.

Stresses like time pressure. Stresses like other people's perspectives and questions. Stresses like client expectations. I can't simulate these stresses.

This is what I don't remind myself of often enough. Analysis paralysis is never-ending. A nice hike or a vacation in the tropics can help with clarity, but true shifts only occur under stress. And true inspiration only occurs in friction with other ideas. I don't need to make the right call, I need pressure to force me to make more calls.

OK, let's see how I did. I'm going to cut myself some slack and include stuff I did in the “overtime” since Sunday.

  • Burn Catch up on snail-mail. For real. I only got about 2/3 of the way through but I'm counting this as a win.
  • ✔ The usual RubyTapas stuff, including several guest chef meetings. Done.
  • ✔ Actually show up for a >Code episode. Done! We talked to “Pragmatic” Andy Hunt and it was great 😁
  • ✔ Write and record VO for two RubyTapas episodes.
  • ✔ Go running. I got three miles in and I am gloriously sore.
  • ❌ Investigate my options for some part-time consulting work. I did not scope this well enough.
  • ❌ Livestream on my own at a “regular” time. Didn't happen.
  • ✔ Livestream with Jessica. Did happen! We paired on her Atomist microgrammar GUI.

What's next:

  • The usual RubyTapas stuff.
  • Nail down March travel plans.
  • Write and publish a post about the consulting gig I want to pick up.
  • Evaluate open loops of projects-that-could-be-generating-revenue-if-I-finished-them, pick one and make a concrete plan to finish it by a specific date.
  • Submit to a conference.
  • Clean up the weightlifting room so I can start working out there again.

Things I’ve Misunderstood About Promises

Since I've been mucking about with JavaScript more, I've discovered that for some reason the Promise pattern is a profoundly unintuitive one to me. In my quest to accurately model their semantics in my mind, I've read through the A+ spec and written a couple of partial Promise implementations of my own. I still don't feel like I've completely nailed it down.

Here is an incomplete list of my misunderstandings (so far) about Promises.

  1. Promises are not boxes that values appear in.
  2. Promises are not really about values at all.
  3. Promises are also not about the work.
  4. Or about managing work.
  5. They are a signaling mechanism off to the side of the work.
  6. Promises aren't about giving you something to wait on.
  7. You don't know when a Promise will be fulfilled; you only get to say what should happen if and when it's fulfilled.
  8. A Promise is not a pure data structure. A complete implementation requires a deferral mechanism (e.g. a way to kick TODOs into a global reactor next-tick queue).
  9. Promises are not about pulling. They are about pushing.
  10. Promises will not make your async code visualizable as a nice clean dataflow diagram (look to actors and channels for that).
  11. Promises are terribly named. They give no assurance about anything. (Cynical readers might argue that this makes them exactly like real-world promises).
  12. Promises do not manage or perform work. A chain of promises:
    1. Signals when new work can be started.
    2. Channels results from one operation to the next.
  13. Of the two, only the signaling part is essential. The channeling part can be and is often unused.
  14. .then() is not an operation on a Promise. .then() is a specialized constructor of new Promises.
  15. Promises are causality insertions.

SIGAVDI #43: X-Wing Edition

Hello friends,

Jessica was in town this week. We made a spaceship (pictured below). We also did some livestreaming. We Paired with Bunny on some basic client-side JavaScript, and Jessica showed me what she's working on for Atomist.

I've been thinking about a tension in how we think about relationships.

When I was growing up I was heavily influenced by the point of view that compatibility is basically irrelevant, and relationships are all about the work you put into them. This came primarily from a parent who felt that arranged marriages were the ideal kind of marriage, as well as this jackass who taught that dating was a bad idea (he has since repented).

(Aside: never trust a relationship book by someone under 40).

While this perspective can obviously be taken to extremes, there's a kernel of usefulness in it. It's the idea that you're going to have to work at a relationship. That's a pretty good expectation to set.

On the opposite extreme is the societal trope about how when you meet “The One”, everything will just flow. It'll feel right, and easy! The kernel of truth here is that compatibility matters. The failure mode is an endless search for the perfect partner, based on some list of requirements.

I was thinking about this tension recently, and how I've seen it play out in various people's relationships. And what struck me was that while we usually prepare young adults for the idea that relationships will require some amount of work, we don't usually give them any calibration.

How much work is a reasonable amount of work? The easy answer is it depends, but I think that's a cop-out. There is such a thing as an unreasonable amount of work, a not-OK ratio of pain-to-pleasure in a relationship. But without a wide variety of experiences, you have no idea where your current experience falls on that continuum!

And you can try reaching out to friends and mentors for help, but chances are you'll get wildly mixed messages! Because everyone's labor-sensitivity is calibrated differently. One person's “dealbreaker” is another person's typical Tuesday.

It's also not useful to fall back on the idea that “different people have different tolerances”. Because tolerance isn't fixed. One thing I've learned about being human is that we have an almost infinite capacity for building up tolerances. Saying “it depends on your tolerance level” is tantamount to saying “there is no such thing as Too Much Work”.

This problem of calibration extends far beyond relationships. One of the sensibilities I've honed as a developer over the years is a sense of how hard is too hard. What is the pain point that indicates I am almost certainly fighting the system, and that there is a better way to do it?

These days I feel like I have pretty good idea of when to stop, step back, and ask around for alternative approaches. But when you're a novice, it can be scary to do that! You have a sense that this stuff is supposed to be hard, and so the pain you're feeling right now… well, it's probably perfectly normal, right? And you should just apply yourself more dilligently.

From relationships, to documentation, to system monitoring… it's not enough to say “there will be some friction”. Expectation of friction is useless without calibration. Some of the most useful guidance we can receive are concrete heuristics for what amount of difficulty/pain/failure is reasonable… and what amount is not.

Hanging out with Jessica always spawns a lot of philosophical, systems-thinky conversations. Today I tried to sum up some of the ideas we've been knocking around in a tweet, and I thought I'd make a first crack here at expanding on them.

Value over simplicity.

Valuable systems are complex ones. Let's put paid to the idea we can have one without the other.

Communication over correctness.

I'd rather work with a system that gives me a good idea of what it's trying to do and fails at it, than one that is “correct” but inscrutable.

Learning over longevity.

One of the most pernicious, difficult-to-root out biases I've found in my own psyche is the idea that something has to be long-lived
(at least theoretically) in order to be “good”, “right”, or “important”.

E.g.: A divorced marriage is a “failed” marriage. A political system is “broken” unless it can last forever. Tests are only valuable if they can be retained indefinitely for regression-checking. Successful code is modified rather than replaced.

I'm trying to replace this bias with the idea that a thing is right, good, useful, and important so long as you (or more importantly, the entire sociotechnical system around it) learns from it.

Importantly, this is not the idea of “learning from failure”. It's the philosophy that the learning is the aim. Sometimes other interesting benefits fall out along the way. Sometimes artifacts you create along the way remain stable for a while. Others don't. Sometimes your direction changes with the learning, and the change renders artifacts obsolete. This is fine.

Context over consistency.

This one feels pretty self-explanatory to me… there's no such thing as a universal best-practice. There is little to be gained and much to be lost from aggressive standardization. Things that work well only work well in a given context. There is no universal or objective correctness.

Movement over stability.

Nowadays I seek forward motion, rather than trying to converge on some ideal stable state. It's deeply uncomfortable for me, still. But I'm working at it.

Remediation over rigor.

I'm not 100% on the terminology for this one yet. But the basic idea is that I'm not interested in making systems rigorously robust. I don't want to trace out every possible failure mode and plan for it. I also don't believe it's possible to make systems that can erase all consequences of failure.

Instead I want to build systems that are optimized for making things right when something goes wrong. That can mean anything from well-maintained backups, to having a well-trained and empowered support team.

Connection over completeness.

This is something I talk about in my #NOCODE talk. It's less important to build a system that covers every last jot of needed functionality, and more important to build one that has well-established ways of reaching out for help when something goes beyond its capacity to handle.

This has obvious implications for life in general, e.g. knowing people with skills you lack. But it's also applicable to software systems which can ask a human for help with resolving an unhandled situation.

Right, let's see how I did.

  • ✔ Tie up loose ends from the Cohere meetings. Inasmuch as I did some due diligence, made some concrete decisions, and communicated them, yes.
  • ❌ Catch up on my snail mail. Ugh, nope. There's something tax-related in that pile and that always puts me off the whole enterprise.
  • ✔ Catch up on RubyTapas TODOs. Done.
  • ✔ Catch up on email. Done. And I finally rigged up a new shared inbox for certain non-business stuff, so e.g. I don't have to forward emails from the propane company to my assistant anymore. Win.
  • ✔ Finish unpacking and go over notes from AIT. Done.
  • ✔ BONUS TASK: Populate and organize my conference RADAR board. I now have a much better sense of which confs are coming up when, and a way to track which confs I'm hoping to get into.  

This week:

  • Burn Catch up on snail-mail. For real.
  • The usual RubyTapas stuff, including several guest chef meetings.
  • Actually show up for a >Code episode.
  • Write and record VO for two RubyTapas episodes.
  • Go running.
  • Investigate my options for some part-time consulting work. I'm looking to close a cash gap, make myself useful on a team, and satisfy my urge to have a real sociotechnical system to bang my ideas against again. (Feel free to get in touch if you have a lead…)

As always, thanks for reading. Cheers!

SIGAVDI #42: Ultimate Answer Edition

Hello friends,

I spent last week on the tropical island of Anguilla with a bunch of software luminaries. My life is sometimes surreal.

At the moment though, I'm looking out on a chilly, thick fog up here at Fair Pavilion. I can't see the sun. This matches my internal climate pretty well. The world has sharp edges, and my journey seems to be one of exposing ever greater surface area to it.

This is fine.

“This is fine”. My friend Jessica says this a lot. It has been seeping into my personal vernacular lately. To me it represents a whole philosophy of life, strongly at odds with how I once lived.

“This is fine” is the choice to accept a situation exactly as it is, without panicking. Without judgment. Without amplifying the negatives. Without feeling compelled into instant corrective action. Without appealing to outside powers for intervention.

The kids colored on the wall. This is fine. They are kids. We will paint these walls before we sell the house.

The venue I was going to get all my friends together at is unexpectedly closed. This is fine. We will buy some beer, rearrange some furniture, and hold it at my house. Mess be damned.

I spent my afternoon crying in grocery stores and parking lots. This is fine. Longing means I am living.

I mentioned previously that I have been talking with my friends at Cohere about helping me out with aspects of my business that I suck at and/or just don't enjoy very much. These discussions brought me face to face with the fact that I did pretty terribly, business-wise, last year. I dropped my revenue by $60k and increased operating expenses by the same amount.

Or to put it another way, I coped with the aftermath of an unexpected divorce and almost a year of solo parenthood by delegating as much as I could, and doing the bare minimum to keep the business afloat.

This is fine.

Let's see how I did. There wasn't a SIGAVDI last week, but that's because I was traveling. Here are my goals from two weeks ago.

  • ✔ Make preparations for a week of travel. Yep.
  • ✔ Get this week's RubyTapas out. Also yep. Check out this awesome episode on building a REPL with Ruby's Binding class from guest Adam Fernung.
  • ✔ Make sure next week's RubyTapas is on track.
  • ❌ Tie up loose ends from the Cohere meetings. Not quite there yet.
  • ✔ Finish at least one new RubyTapas script and record VO.
  • ✔ Catch up on my email.
  • ❌ Catch up on my snail mail. God I hate the mailbox.
  • ✔ Somehow leave the house to see other human beings during this crazy week. Amazingly, I managed to make this happen.

This week, like every post-travel week, is all catch-up. Sigh.

  • Tie up loose ends from the Cohere meetings.
  • Catch up on my snail mail.
  • Catch up on RubyTapas TODOs.
  • Catch up on email. Again. Sigh.
  • Finish unpacking and go over notes from AIT.

See you next week!

Why I suck at writing talks with good transitions (and how I’m improving)

Smooth transitions help hold the audience's attention

Saron Yitbarek has a great post about how improving your transitions can really spruce up a tech talk. Specifically, about how the transition to a new slide should begin before you actually switch to that slide.

The goal is to make slides support your points, rather than having them introduce your points. It's an important skill to learn for giving talks. Go read her article.

But it's difficult to remember what the next slide will be

I try to practice this technique in my talks, but I've never found it easy. I often have trouble remembering exactly which slide comes next, and it's hard to transition when you can't remember what you're transitioning to.

This problem was exacerbated by some technology choices I made early on. Like many other programmers, in composing my early talks I looked down my nose at dedicated presentation apps such as PowerPoint or Keynote.

Instead I tried to “keep it simple”. I used presentation tools such as Beamer, S5, or RevealJS, that would enable me to use a text editor I was already comfortable in to write my talks, and generate either PDF or HTML slides.

The problem here is that in most cases, these tools didn't give me the ability to see what slide was “up next” on my laptop screen.

A full-featured presentation app can help

By contrast, dedicated apps like PowerPoint and Keynote have a Presenter View which shows the current slide, the next slide, and any speaker notes you've added. You can set your laptop screen to show Presenter View, and the main projector screen to showing just your current slide.

Now, there's an argument that used to keep me from using these kinds of tools. It goes like this:

“Someday, you might have a problem with your laptop and have to present your slides on someone else's machine using just the PDF backup. And anyway, shouldn't you know your talk well enough to dispense with crutches such as Presenter View? Maybe you're just not practicing enough.”

This argument used to have a lot of weight for me. But my views have evolved over time.

In particular, the idea that you should memorize your talk perfectly is an implicit argument for doing few, painstakingly prepared, carefully rehearsed talks.

But that's not the kind of speaker I want to be. In fact, that perfectionist paradigm of speaking has held me back. I'd rather be the kind of tech speaker who can quickly throw a new talk together and not get hung up on imperfection. If I've fully memorized a talk, that means I'm “resting on my laurels” instead of learning and iterating and flowing with ideas.

And if that means leaning on tools to help me get through relatively less-rehearsed material, I'm OK with it.

Abrupt transitions are a byproduct of bullet-driven writing

The other reason I've had trouble with transitions comes from how I typically compose my talks. Usually I collect a bunch of bullet points around the topic I'm tackling. Then I gradually massage the points into an outline, and then create slides for the outline points.

The problem here is that when you do bullet-driven talks, they naturally turn into a set of semi-connected points, each one introduced by a new slide.

Recently I had a particularly bad experience with a talk. I was on a three-city conference tour, giving a presentation I'd delivered several times in the past. I was pretty confident in it, since it was a “polished” talk.

But once I was on stage in the first city, I found myself with low energy, and constantly losing my place in the talk. I walked off that stage feeling deeply disappointed in my own performance, and questioning whether I could in good conscience give that presentation again.

So build your talk around a narrative

After agonizing over it for a few days and talking it over with some friends, I finally discovered an underlying thread that I'd never identified before. I quickly rewrote the talk to periodically re-emphasize that thread. And I re-ordered sections of it to have a natural flow, guided by the thread.

As soon as I started giving the new version of the talk, I knew I was “back”. The energy was there again, and the post-talk audience reviews showed a clear and marked improvement in how it was received.

The key to the change was in identifying a clear narrative through the material. Since then, I've been focusing more than ever on putting the narrative first, and getting away from the “bullet-driven” approach.

Outline your story, not your points

One thing that has particularly helped with this is a technique I learned while studying copywriting. Somewhere, I ran across the advice to write your content subheadings so that even if someone just skims the headings, they will still come away with a summary of the whole piece. Instead of subheads full of pithy wordplay, have them clearly and plainly summarize the paragraphs that follow.

Recently I needed to restructure another of my talks into a ten-minute version. Instead of pulling out slides which represented the “important points” from the main talk, I first opened up a blank, full-screen Markdown editor. In the editor, I wrote out ten sentences (one for each minute!) that together told the story of the point I wanted to get across.

It looked like this:

- Refactoring and redesigning software is hard.
- I’ve started seeing an underlying pattern to the hard.
- OOP was supposed to be about messaging, 
- But messaging semantics are impossible in the C++/Java/Ruby/etc.
- As a result our systems are full of processes modeled as transactions.
- This exhibits as BOTH splitting processes across multiple objects, and as objects containing parallel “stories”
- Implicit to message oriented is process oriented
- What if we structured our systems, not by actions, not by data globs, but by process?
- What if we used this as the heuristic for refactoring?
- …what if we applied this to our lives as well?

Once I had my rough storyline, I transferred these points as named slide sections into PowerPoint. Then I copied/added slides that would support each step in the story under the sections. In the process, I also edited and simplified the story headings.

The final presentation, with slides collapsed to just show the section names, looked like this:

(By the way, you might have noticed I'm using the same technique for the subheadings in this article 😉)

Lean on tools, tell a story, and let slides be illustrations

In conclusion: great transitions can make a big difference in how your tech talk comes across. But for some of us, they don't come easy. The two main strategies that have helped me improve my transitions are:

  • Don't be too proud to lean on “business-y” presentation tools like Presentation View and speaker notes.
  • Write your outline as the steps in a story, not as a list of points you want to get across.

I hope this helps someone out there.

SIGAVDI #41: Officially bored with winter edition

Hello friends,

“So will you stay here? How long? Where else might you go?”

I've heard these questions from a lot of friends in the past year. I don't know the answers.

Back when I was raising a family here, and thought I was going to be continuing in that for the foreseeable future, I also thought that being adjacent to the Smoky Mountains for the next 5-10+ years would be pretty ideal. Now I don't know.

I love these hills. I love hiking them. Something about the way the land works here settles my soul like nowhere else I've been (yet).

But one of the things I've realized is that my idea of what were “my activities” was constrained by what I could allow myself to like. Or dream of. Hiking was a “safe” pastime in the context of my former living situation. More social activities weren't, and so I told myself I wasn't that sort of person anyway.

This has been an ongoing theme of the past year+ of expansion and reorientation. Coming to terms with how much of what I thought of as “me” was circumstantial rather than innate.

Example: my whole life when I would take those Myers-Briggs tests I'd come out somewhere between INTJ and INFJ. I took one recently and came out ENFP.

My whole life I've identified strongly as an introvert. Lately I've come to question even this. I wonder if perhaps being raised alone in the woods simply gave me so much social anxiety and so few tools to overcome it, that I adapted to being alone. And told myself I liked it.

I used to think the crash that would follow social “highs” was a sign of my introversion. Now I wonder if it was just repressed extroversion going into a sulk after getting a taste of what it needed.

These days I feel like I'm growing in reverse. From settled old man to rolling stone.

One thing is for sure: there is no longer any talk of where I will “end up”. My life is a generator function. There is no known endpoint. There is only .next().

I spent the past week pairing, plotting and planning with my friends from Cohere. Most of the time was spent recording hours of pair-programming video with Betsy Haibel for their forthcoming Untangling Asynchronous JavaScript course. I know way more about JavaScript, Node, and Express than I knew a week ago.

But we also took time to make some concrete plans for working more closely together on my existing business. As I alluded to in a previous SIGAVDI, I am coming to terms with the fact that I enjoy and am good at only certain parts of my work. Namely the parts that involve learning, communicating, and working with people. I am not so good at the daily operations and upkeep aspect: the metrics-monitoring, optimizing, prompt-email-replying, bug-fixing, regularly-promoting parts. The Coheres and I have been hammering out a novel and mutually-beneficial arrangement which I hope will get those parts of my business on track while freeing me up to do more of the stuff I'm best at.

OK, let's see how I did.

  • ✔ Record lots of course video with Betsy. Done! In fact we finished primary filming ⭐
  • ✔ Publish a RubyTapas episode, even if it isn't the planned one. Done! I recorded a short-notice episode on exploring unfamiliar APIs in a REPL.

What's next:

This week I'm preparing to travel to a nifty invite-only conference for most of next week. I would like to be excited about this except that I HAVE SO MUCH TO DO BEFORE THEN that I don't have time to be excited 😱.

  • Make preparations for a week of travel.
  • Get this week's RubyTapas out.
  • Make sure next week's RubyTapas is on track.
  • Tie up loose ends from the Cohere meetings.
  • Finish at least one new RubyTapas script and record VO.
  • Catch up on my email.
  • Catch up on my snail mail.
  • Somehow leave the house to see other human beings during this crazy week.

Wish me luck.

SIGAVDI #40: Absinthe edition

Hello friends,

I found this in my notes and I can't remember if I've written about it yet:

You can choose the rarest, most delicious variety of olive. And pick out the creamiest, most luscious flavor of ice cream. But if you put the two together you're probably not going to get a very good sundae.

It's tempting to pick and choose from “best practices”, or from amongst the most popular features, and try to put them all together in a perfect sundae. We do this sometimes when deciding how our teams will operate. Or what features our programming language should have. Or when comparing feature lists on comparable services.

The problem is that practices and features are never “best” objectively. They are only “best” in a context… of other practices or features.

eXtreme Programming works (when it does) because it's a set of mutually-reinforcing practices. If you pick out just “no code review” and “test-driven development” but leave behind pair-programming, small releases, constant refactoring, and an on-site customer, you are likely to wind up with a big ball of mud that isn't fit to purpose.

See also: programming languages that never met a PL buzzword they didn't try to assimilate. Object-oriented! Functional! Dynamic! Static! Actor-model! Floor polish! Dessert topping!

I said I was going to make this newsletter more personal going forward and it occurs to me I haven't actually written much that's personal in the last few. I guess that's because I've been, for the most part, ridiculously happy, and happiness is dull to write about.

Happiness also brings with it the dangerous temptation to write about “how to be happy like me”. And that's where shitty self-help books come from.

Happiness is always spiky and ephemeral too. If you sampled me regularly over the last month you'd get an overall trend of joy, but you'd also get individual datapoints way down in “anxiety”, “loneliness” and “depression”.

Brene Brown says that everyone practices dulling their emotions to some degree. And that when you dull one emotion, you dull them all. Conversely when you allow yourself to feel more strongly, you don't get to pick and choose which feelings. I'm in a period of opening up to levels of pleasure and happiness I'd never felt before. And that means also feeling sadness, loss, sympathetic pain, loneliness, and fear that much more keenly.

OK. Let's see how I did.

  • ✔Submit a talk proposal to NordicJS (and use this as a pull to get my ducks in a row for talk submissions – update bio, abstracts, talk history page). Done! In the process I put together some convenient pages with abstracts, video, and nice things people have said about the talks I've been doing lately.
  • ✔Make sure I'm on top of at least the next two RubyTapas episodes. Well, sort of. I've caught up on a lot of my RubyTapas TODOs, but I think this week's guest ep is still going to be delayed. I may have to come up with something short-notice while the originally planned episode is completed.
  • ✔Make plans for the upcoming Cohere/ShipRise Smoky Mountain Retreat. We'll be working on the AsyncJS course and other plots & plans. What do I need to do to prep? I checked this off by saying “hey, I'm super anxious because I never host people so please work with me on this, OK? 😅”. Sometimes “done” means “feelings communicated and expectations managed”. 
  • ❌Reimplement Promises in Ruby, again, based on the A+ spec. Nope, but I wound up writing some new code to illustrate polling solutions to async problems, which needs to come before Promises in the sequence that I'm building.

Extra credit:

This week:

This week is unusual because Betsy Haibel is in town so we can work on Cohere's AsyncJS course together. We've been working on the course a little at a time for a while, but we kept losing momentum. So we decided it might work better if we just huddled up and focused for a week. Wish us luck!

As far as an actual TODO list goes…

  • Record lots of course video with Betsy.
  • Publish a RubyTapas episode, even if it isn't the planned on.

As always, thanks for reading, and don't be a stranger to my inbox!