The Time I Spoke at a Conference

I spoke at a conference for the first time last month. It was an exhilarating and educational experience, and because in my preparation I appreciated several posts and articles about giving presentations, I suspect sharing my observations may be valuable to somebody, somewhere.

Way Before

I’d set it as a goal for myself to give some sort of talk this year, but submitting abstracts to ThatConference seemed like a long shot. I figured maybe I could speak to a user group, or, if nothing else, I could wrangle some colleagues into a conference room for twenty minutes some time.

It was a long shot. And it didn’t pan out. Until it did. I submitted three abstracts and all three were rejected. Which was a bummer, but not a surprise. Little did I know that my company‘s sponsorship of the conference included a speaker slot, and it wasn’t spoken for. (And many, many thanks to them for trusting me enough to give me a crack at it.)

So I was in. I cheated, but I was in. I’ll take it. I even got to pick which of my three abstracts I would use.

(I could say something about writing abstracts, but there’s better material out there on that than I could write here. And mine were rejected, so you probably don’t really want my advice on such things anyway. I will say this, though: I chose topics and wrote abstracts that I thought would appeal to me, if I were attending a conference.)

Before

So I had a slot and I had an abstract but I didn’t have my content. At that point, the content seemed like the hard part, too, so I gave myself the majority of the three or so months before the talk to work out an outline of just what I wanted to say.

Fortunately, months earlier I had started collecting and stashing thoughts, references, quotes, etc. (The collecting wasn’t done with a particular topic or even a talk in mind. In fact, I actually came up with my topics based on the stuff I’d deemed important enough to jot down.) So I already had a list of things I thought were worth sharing. I worked it into an outline and sat on it for a while, thinking the meat of this project was done and feeling pretty good about it. (Oh, for that month back.)

Eventually, I turned my outline into slides. And when I went to do that I thought, oh crap, this is the hard part. What works as an outline doesn’t work with the sort of one-after-the-other, temporal flow that slides require. An outline has a structure you can see at a glance. When you deliver the same content via sequential slides, the flow of one point into another is much more important. Not only that, but my precious outline included several bullet points that needed to be split or combined to work in slide form. It was a lot more work than I expected, and I wonder now if that outline step hurt more than it helped.

My next mistake: No visuals. I think slides should be secondary to spoken content, and my early slides took that line of thinking a bit too far. Each slide had a simple heading or a short quote related to what I would talk about. Simple text on a simple background. What I’d actually say would be in the notes. I convinced myself that this would force me to make the spoken content great. Even when my wife saw the slides and gently encouraged me to include some pictures, I brushed her off.

Maybe constraints like that would work well for a great speaker. I’m not a great speaker.

And that’s what I found when I finally got around to doing a practice run, about a month out, to an empty room. It was terrible. Absolutely awful. I didn’t know my content, my flow was nonexistent, and — here’s the biggest takeaway — everything sounded good in my head and looked good on the page, but just didn’t sound right when spoken aloud. It felt like I was trying to write with my off hand, or parallel park on the left side of the street. Or some better metaphor.

I panicked. I had a trial run scheduled with some colleagues the next day. I canceled it. Maybe this is the hard part. Or, hell, they’re all hard parts. I needed to do some serious rewriting and practicing, simply to not look like an idiot up there. And I had a month.

So I hunkered down. I spent a lot of time on the thing. Even worked on it during a vacation, much to my family’s chagrin. I also watched some good talks to see how they handled all the things I did badly. My savior was Scott Hanselman’s productivity talk at Webstock 2012. Scott used pictures, and he used them extremely well, not leaning on his slides, but using them to punctuate and enhance what he was saying. He also moved quickly through slides and he made them funny. Very engaging. I was inspired. I did the same. It was a ton of work, as it meant finding appropriate (and preferably humorous) visuals for every point I wanted to make, but it worked out.

During all that work, I was painfully conscious of the fact that I wasn’t practicing. I knew that my previous practice run had been terrible, and that a lot of that was due to my delivery and the words not sounding right when spoken aloud. But it’s hard to stand up and speak aloud to an empty room. I knew it would sound terrible. In retrospect, I put it off way too long, and my eventual presentation would’ve been better if I’d taken much more time to practice.

About a week out, I finally did the heavily revised talk for a group of colleagues. I warned them that this was my first time through the slides since a painstaking rewrite. I had a whiskey beforehand. And it worked much better. It got some laughs. The flow still wasn’t great, and I realized that some of the content needed to be changed, moved or removed, but it was a start.

And so the next week was all about practice runs. I did one for my wife, and several for empty rooms. Each one made it better, shining a light on things that didn’t quite work. The night before the talk, I did two full run-throughs in my hotel room, and by that point I actually felt pretty good about it. (That was amazing to me at the time. It still is.) Ready enough. I slept well.

During

Day-of, I went straight to the room. My talk was after the keynote, and I could hear it in the distance. I paced. I made myself a drink. I ate M&M’s. I did the power pose. I made myself another drink.

People slowly filed in. It was exciting to see them showing up. It meant my abstract wasn’t terrible, at the very least. (There were three concurrent talks I’d have gone to over mine, based on the descriptions.) It was especially exciting to see the folks I knew who came out — looking out at smiling, forgiving faces, I’d quickly learn, can do a lot to calm your nerves when public speaking.

At 10:30 exactly, I had no choice but to accept my fear and start, so I dove in.

It went okay. According to my notebook from that day, I felt “75-80% happy with the content, and about 60% happy with the delivery.”” People laughed at some of the jokes. Even some of my screw-ups got chuckles, and I was able to recover from a few of them to turn them into laughs. (This seems like a big deal to me now. It means I was comfortable enough to think clearly up in front of people.) I’d been afraid to take questions and comments at the end, but did it anyway, and people were kind and shared cool things. I think I even made decent eye contact for the first time in my life.

There were some tough things, too. Looking out and seeing people on their phones while you’re talking can be discouraging. Seeing people get up and leave can be even more discouraging. I knew those things were coming, and I’d told myself not to take them personally, but they certainly weren’t positives. (The upside: I took them in stride and didn’t get flustered.)

After

I toasted the crowd at the end. Being done felt great. A few people came up to chat after, which I’d thought would be awkward, but really wasn’t, because they were really just eager to talk about stuff I care enough to speak about. A woman came up and showed me that she’d sketch-noted the talk, which was extremely cool. Some internet acquaintances had nice things to say about the way I used my slides to highlight the content instead of being the content. A colleague who’d seen my practice run a week before commented on how much better the actual talk was. A guy even stopped me in the hall later on and told me he enjoyed my presentation. Success!

I was (am) incredibly lucky to be surrounded by supportive people during all this. I’m not sure I could’ve gotten through it with my dignity intact without them (and I surely wouldn’t have been given the opportunity to begin with). A couple of coworkers talked to me later in the day about my content, relating it to their own lives. The boss’s boss even suggested I give the talk at the upcoming branch meeting. That makes you feel good. Humans are pretty great sometimes.

Speaking at ThatConference 2014

I’m pleased to report that I’ll be speaking at ThatConference this year. I’m giving a talk about professional development, entitled “The Evergreen Developer: Timeless Skills for a Long Career“.

Here’s the abstract:

Our favorite platforms, languages, and even design paradigms will inevitably become obsolete, some on shorter timelines, some longer. We knew when we signed up as developers that we’d have to constantly sharpen the saw technically, our entire careers. But there’s a whole world of skills you can invest in that will pay dividends for your entire career, regardless of the technology you’re working with. This session is a survey of those sorts of things.

We’ll talk about understanding our clients and coworkers and improving our communication with them, some ways to enhance our own productivity, and some ways we can improve our learning skills so that when we do need to learn new technologies, we’re well-equipped.

Hope you’ll check it out if you’re attending the conference.

Code Coupling

All implicit couplings seem convenient when first introduced, but later become reasons that the code cannot be easily diagnosed, repaired, or extended…

How often do we hear developers saying that they would love to make an improvement to the code structure, but that it would take too long, cost too much, and risk too much? Typically, the programmer sent to resolve the problem must write the code that the original author avoided. Unfairly, the original author may be initially credited with quick turnaround, when in reality he did an incomplete job that his colleagues must finish for him.

(src: http://pragprog.com/magazines/2011-01/code-coupling)

Names are Important

I can’t tell you how many times, even just recently, I’ve seen communication seriously hampered by confusion over the names people use for things.

For example, I might say “I like the design of this application”. That could mean, depending on your perspective (or even just your mood), a) the graphic design, b) the user interface design, c) the software design, and probably x other things I’m not thinking of. I suggested to a project manager once that we needed to spend more time on design, meaning our application’s software design. He walked away thinking I meant the UI design and, long story short, a bunch of people put a bunch of effort into a UI design review nobody was asking for.

Another example: I was on a project recently where something called a “view” was a part of the domain. Our application got things called views from another system and did some stuff with them. But our application already had something called a view, because it was built with a Model-View-Controller structure. So half the time when someone mentioned a view on that project, I had to do a little mental double take to make sure I was sure which kind of view was being discussed. (That domain also included “values”. Similar problem. Oy.)

On another application, the legacy code used one term to refer to a domain concept, but all the people involved when I worked on the team used a totally different term. Needless to say, the first time I went in to make a change to that code, I was very confused.

And, of course, there’s a ton of material out there on the importance of names within your code. The more clearly and consistently you name your classes, modules, functions, variables, and whatnot, the better the next nerd who comes along (or even future you!) will understand what they’re for. Code is a tool for communicating with humans as much as it is a tool for communicating with compilers and interpreters. That’s a big part of why we build abstractions.

Anyway, all these situations can be avoided with a little care. Pay attention to the names you use for things, in conversation and in code. Always think about whom you’re communicating with and whether you’re being clear.

HTML Helper Tidbit

ASP.NET MVC’s HTML helpers first look for a value in the request parameters, then look for the value in the viewmodel.

So, for example, if my request URL is /MyPage?foo=999 and my viewmodel has a property named “Foo” (or “foo”, it’s not case sensitive), the value output by HiddenFor(x => x.Foo) is going to be “999”, even if I set it my viewmodel property’s value to something else in my controller action.

(This was causing a colleague a lot of head scratching yesterday, so I thought I’d pass my explanation along here.)

Fun with Acceptance Tests

I’ve been spending some time writing some of my first SpecFlow tests lately, and it’s led me to sorting out some assumptions I’ve made about acceptance tests. I’m sure I’m not finished.

It seems to me that an acceptance test is meant to do two things: First, it defines a feature. Second, it can be used to verify that feature works as expected. Perhaps it seems weird to call these two separate concerns, but bear with me.

Your goal when defining a feature is to clearly and simply describe it. The test serves as an artifact of specification, an agreement among the team about how the software is meant to work. Thus you want it to be human-readable. Not just developer-readable. Everyone on the team should be able to read it and understand it.

A Given-When-Then scenario with this goal in mind might look like this:

Given I am an administrator
When I go to the settings page
Then I see the administrative settings tab

Your goal when verifying the feature is ensuring that if a series of steps is taken, an expected outcome occurs. Ideally, I want to be able to automate my acceptance tests, and so when I’m writing them, I’ll start thinking about the specific steps that need to be taken to verify that a behavior of the system is working as expected.

A GWT scenario with this goal in mind might look like this:

Given I go to /Login
And I enter the following data into the Login form
    | field    | value |
    | username | admin |
    | password | foo   |
And I click "Log In"
When I click the "Settings" link in the navigation
Then I am redirected to /Settings
And the administrative settings tab is displayed 

So now we’ve written two different tests for the same behavior. One with humans in mind, one with automation in mind.

When I sat down to start writing these tests, I thought the latter was clearly the way to go. It seemed like, yeah, the balance was tipped slightly toward automation, but the human-readability was still there if you put in just a little bit of effort. I was also pretty excited at the prospect of doing GUI automation with WatiN, and I wanted it to be super easy to reuse a lot of our step definitions to automate our tests.

I was not prepared, however, for the level of detail involved in going step by step through some more complex workflows. I was also not prepared for the amount of redundant “code” I ended up writing. And perhaps most importantly: As I’ve written more and more of these style tests, I’ve been getting more and more terrified by how brittle they seem.

So I took a break to read up on it. And write about it a little. And now I’m going to let the pendulum swing back the other way. We’ll see what happens. I suspect some pain will come when I start trying to automate, and maybe I’ll get closer to the “right” level of detail for definition and verification.

Agile Pitfalls

From a slide in a deck a friend of mine used in a presentation on agile/lean development: “Notable Pitfalls To Watch For As A Leader”:

  • Agile teams may be prone to rapid accumulation of technical debt
  • Agile methodologies may lead to team burnout due to an irrational culture of urgency
  • Agile requires more team and individual discipline, commitment and openness than a dysfunctional organization may be ready for
  • The high visibility on agile teams causes poor performers to stand out like a sore thumb
  • Agile teams have a tendency to focus on tactical accomplishments at the expense of strategic goals
  • People are led to believe agile development will solve all their problems with minimal effort and experience disillusionment when it doesn’t meet their expectations

These all rang so true to me that I had to share. Especially that last one (which is true about many, many more things than agile development).

All this “agile” and “lean” business sounds really good when you read about it, and, believe me, I do think it’s a great approach to building software for a lot of situations, but it can be a challenge to integrate these ideas into a business.

“Habit is habit, and not to be flung out of the window by any man, but coaxed down-stairs one step at a time.” – Mark Twain

It takes patience and discipline to move an organization down this path. Years of Waterfall and top-down project management experience don’t go away overnight. And that’s true for everyone involved: developers, project managers, product managers, testers, analysts, and on down the list. The larger and more complex the organization, the bigger the challenge, because the number of habits (“person-habits”?) you’re trying to change/create grows exponentially.

Agile Government?

This post from Ezra Klein, about how the TV show House of Cards is nothing like how Washington actually works, caught my eye:

[T]he main thing I’ve learned working as a reporter and political observer in Washington: No one can carry out complicated plans. All parties and groups are fractious and bumbling. But everyone always thinks everyone else is efficiently and ruthlessly carrying out complicated plans.

And:

There’s also a lot less long-term planning than you might think. In general, politicians are overworked and understaffed. They’re traveling constantly, buried under too many meetings and constituent requests, and working desperately to stay one step ahead of whatever they’re getting yelled at about that week.

Sounds like these guys could use some agile coaching.

A Team of Peers

I spent the first ten years of my career working for interactive marketing agencies, building websites with small development teams. I learned a lot in that environment about teamwork. In particular, I’m proud to have gotten fairly good at explaining technical issues to my non-technical colleagues and working with those colleagues to figure out how to use technology to solve business problems. A project team would generally involve a fair number of people in different roles: salespeople, creative folks and graphic designers, project managers, testers, etc, and I had to learn to collaborate closely with all of them.

But, perhaps surprisingly, I never had to spend much time working closely with my technical colleagues. At least not in situations where the relationship was one of peers. The dev team for a project would rarely exceed one or two, usually an “architect” and a “developer”. There was always a clear authority with respect to the software design. Early in my career, I was the developer, taking my marching orders from the architect. Later on, I was the architect, which meant that I would make decisions about the design and make sure the developer understood and executed them.

For the last year or so, though, I’ve been on a larger team. (Really, it’s a medium team, or even a medium-small team. We have six developers. There are much, much larger teams out there.) It’s also a “self-organizing” team. There’s no established leader. Or, rather, the actual leader lets the team really take the reins, acting more as a coach than a manager. This has all been a big change for me and has brought new challenges. Or, as I like to frame it to myself sometimes, new things to learn.

Lately, my metric for success is less about what I’ve accomplished over time period x, and more about what the team has accomplished. The code the team produces is the product. I might be happy with the code I write for a component, but that component is not my code. It’s the team’s code. That means another team member is going to add features to it or refactor it, and he may not do so exactly how I would like.

The end product, what matters, is that which the team produces, and so it’s my responsibility now not only to write code I think is good (in all the ways code can be good, hopefully specific to the needs of the project or component at hand), but to help ensure that the team writes code that’s good, according to the team. And that’s not just my responsibility. It’s the responsibility of everyone on the team.

You can have the most elegant/efficient/whatever solution in the world to problem x, but on a team of peers, everyone has to understand it and buy into it. I find myself, now, presenting bigger design ideas and tools to the team and rooting for us to try them out. I find myself thinking harder about my design decisions, because I have to explain them to somebody else who might know better. I ask myself better questions, because I’ve learned to expect good questions from my teammates.

I don’t know if this is a good thing. It often feels like things are harder. Having an explicit leader would eliminate a lot of conflict and (what I hesitate to call) overhead. I have a set of ideas about what makes for well-designed software. Everyone on my team does. And they don’t always fit together. They’re also constantly changing. So we have to work through how to work together while also trying to deliver features and value to the business. But our ideas are stronger for having been tested against each other’s. The ones that survive are, anyway. We’re getting better. And we’re getting better at getting better.

Separation of Concerns

I’ve been reading Domain-Driven Design and I just wanted to share this snippet, from chapter four:

In an object-oriented program, UI, database, and other support code often gets written directly into the business objects. Additional business logic is embedded in the behavior of UI widgets and database scripts. This happens because it is the easiest way to make things work, in the short run.

When the domain-related code is diffused through such a large amount of other code, it becomes extremely difficult to see and to reason about. Superficial changes to the UI can actually change business logic. To change a business rule may require meticulous tracing of UI code, database code, or other program elements. Implementing coherent, model-driven objects becomes impractical. Automated testing is awkward. With all the technologies and logic involved in each activity, a program must be kept very simple or it becomes impossible to understand.

I wish I could say this was obvious stuff.