Recent Posts (page 27 / 65)

by Leon Rosenshein

Hyrum's Law

With a sufficient number of users of an API, it does not matter what you promise in the contract:
All observable behaviors of your system will be depended on by somebody.

    -- Hyrum’s Law

Or, what’s old is new again. The earliest reference to Hyrum’s Law I could find was in late 2016, but that’s hardly the first time I ran across the idea. That’s just the name with the weight of Google behind it.

I ran across a variant of it when I was working on Falcon 4.0. Our testers decided some debug code was a great feature, so we ended up shipping it. After that I went to work for this little software company called Microsoft. Microsoft was the dominant force in the industry for many reasons at the time. At the time, and still, to a large degree, Microsoft focused on the enterprise customer. Customers who would have 10s or 100s of thousands of licenses and build lots of internal tools and processes use Microsoft products. And not just Windows/Office. Flight Simulator sold 100s of thousands of copies of each version. From the operating system to the office suite, to games, companies lived on MS software. And when you have a single customer with that many licenses you listen to what matters to them.

And one of the things that was important to customers was that things keep working. We dealt with that a lot on Flight Simulator. We spent a large percentage of our time in each development cycle making sure things were bug-for-bug compatible. In Windows it turned into an entire feature of its own, Compatibility Mode.

But unless you’re building the actual end user experience(and even there, your bug is their feature), you need to have some kind of interface to what you’re building. If there’s no way to provide input/read output it’s not doing anything but turning electricity into heat, so there will be some kind of API. Given that constraint, there are a few things to keep in mind.

  1. Version your API: Get people into the habit of specifying the version, so when it changes it’s not a mental shift.
  2. Eliminate, or at least minimize side effects: The fewer side effects, the less likely sers are to start depending on them.
  3. Keep the API as focused as possible: The bigger the surface area of your API, the more unique combinations of things users will come up with/ 
  4. Expect the unexpected: Users will come up with new and interesting ways to use the API that you didn’t intend. Be prepared to support them
  5. Instrument your API: That way you can understand how it’s being used and be less likely to be surprised when something stops working.
by Leon Rosenshein

Managing Expectations

A suggestion by a general to a private is an order. An order from a 2nd Lieutenant to a Master Sergeant is a suggestion.

    — Unknown

I cannae change the laws of physics! I've got to have thirty minutes!

     — Scotty (eight minutes before the Enterprise might be destroyed)

Although they come at it from different directions, both of those are about expectation management. Whether you’re asking/demanding something, or being asked/told to do something, the expectations, on both sides, are defined not just by the words, but by the situation.

When a general walks into a briefing room and asks someone to get a cup of coffee, he or she probably expects to get one, but doesn’t expect someone to stop doing what they’re doing and get the coffee. But chances are that the soldier fresh out of boot camp will do just that. Because their expectations are different. The opposite happens when the butter-bar fresh out of West Point tells the Sergeant Major what to do. The Sergeant Major doesn’t drop everything and do it, but instead explains the situation to the 2LT. Meanwhile, in the mid-2200s, Montgomery Scott was viewed as a miracle worker by telling people he couldn’t change the laws of physics.

But what has any of that got to do with work? It’s about managing expectations. It’s about how you handle the unexpected but foreseeable future. And it’s about understanding the impact your position relative to another person changes how what you say is heard.

One good example is what happens when your understanding of the situation changes. Your estimate of the time to complete should change as well. It might go up or down. What you do with that information is the important part. If you think you’re going to be finished sooner say something. But also say something if you think it’s going to take longer. You don’t want to surprise anyone. What you’re doing is almost certainly a dependency of someone else’s. They’ve planned for it to arrive at a certain time. They have an expectation. And now it’s wrong.

Think about how you’ve felt when someone missed a deadline. No one likes it. But the sooner you find out about it, the sooner you can adjust your plan. Or, if the timing is the critical factor you can discuss ways to have something done in time. It might be less than ideal, but it can still add value. There are lots of ways to start that conversation, but that’s a topic for a different time.

And that’s effective expectation management.

by Leon Rosenshein

Katas

How do we get great designers? Great designers design, of course.

                          -- Fred Brooks

So how are we supposed to get great architects, if they only get the chance  to architect fewer than a half-dozen times in their career?

                         -- Ted Neward

If you don’t know what an architectural kata is, think of it this way. It’s a low risk opportunity to design a green-field solution based on a simple (½ page) RFP. In the before times we did these in-person. Usually as a group of strangers at a conference or other kind of gathering, but sometimes as intact teams or cross team, site based sessions. Lately, like everything else, they’ve gone virtual. Last year a group of us did the inaugural O’Reilly kata event. Our team, the SelfDrivenTeam, placed in the top 10 and made it to the semi-finals. Looks like O’Reilly is doing another round next month.

Normally it’s a 2-3 hour, time-boxed event, but because it’s a virtual event, they gave us a few weeks to put together the initial proposal and then more time to build the final preparation. And because they’re not interactive you need to be a little clearer up front about the why’s and their implications. You also get to show off your sales and marketing techniques as part of the final presentation. If you’re interested in putting together a team and have any questions just let me know. Happy to discuss and/or provide feedback and pointers.

Either way, katas are a great way to take a break from your day to day work and try something new. The time commitment is low, but the rewards can be high. You get to think about a different domain. You get to approach something without years of legacy code you need to support. You can try out different architectural styles and see how they fit together in a new space. You get to collaborate with people you might not normally get to work with. And, depending on the venue, you can get direct feedback from your peers (in-person) or leading experts in the field (O’Reilly).

And if anyone wants to have a kata event for their team/org once we’re back in the office let me know. I’m sure we can work something out.

by Leon Rosenshein

Context

Context can mean a lot of different things in different contexts. Golang even has a built in interface for it. Today I’m using context in the context of communication. Specifically, context as the collection of thoughts, ideas, and biases two or more people bring to a conversation. Even more specifically, the context I’m talking about is the difference between the contexts the people in that aforementioned conversation have.

There are the things you know (your context), the things the other people know (their context), the things everyone knows (global context) and the overlap between those three (shared context). This is important because good communication starts from that shared context and builds out from there. Without that common framework you might connect, but probably not. Certainly not as well as both sides think they’ve connected. And guess what, The overlap between those three is much smaller than you think it is.

Non-overlapping circles

So what can you do about it? The best thing is to provide that shared context. And that means knowing who you’re talking to. Knowing the lens they see the situation through. Knowing what’s important to them, and the language they use to describe it lets you show that what you’re saying is important to them.

And don’t be subtle. Don’t show the facts and let them guess what your point is. Tell the whole story. What the situation was. What changed. What the situation is. Why the change is significant. And most importantly, what, if anything, you want them to do with the new information. Should they start doing something, stop doing something, do more/less of something, or are you just providing more context for future decisions?

Because context is the most important part. 

by Leon Rosenshein

Marie Kondo It

You know what kind of code has zero bugs? The kind you didn’t write. You might have less features, but I assure you there are no unhandled exceptions or edge cases in code that doesn’t exist. Less code equals fewer interfaces, fewer special cases, fewer leaky abstractions, and fewer hidden bugs.

But you can’t just remove things that don’t spark joy. Some things are simply necessary, not joyful. But you do want to remove things that diminish joy. Tha 3000 line file full of utility functions. All the places where you have custom code for the same purpose that almost match each other. Things that are almost done.

The KonMarie approach has 6 rules, and while written for tidying physical spaces, you can apply the same ideas to software as well.

Commit yourself to tidying up. Whether you call it tech debt, cruft, or code smell, start by recognizing that things could be better and allocate time to making it happen. It could be an ongoing percentage of your sprint budget, a dedicated sprint (or more), or maybe a specific story in your backlog

Imagine your ideal lifestyle. As with any journey, you need to know where you’re going or you’ll never get there. It could be a grand vision for an entire platform, or just removing the dread of going into a small area of the codebase

Finish discarding first. Start by removing the things that aren’t used. All the commented out code. The left-over helper functions. Unused levels of abstraction. The extra headers/imports. Then land the change. You’re not finished discarding until the change is part of the codebase.

Tidy by category, not by location. Once you’ve gotten down to what you need, gather like things together. Call it Single Responsibility, containerizing, lumping, or domain driven design, it’s about abstractions, mental models, and reduced cognitive load.

Follow the right order. Start with the easy things. Dedup pure duplication. Extract those couple of methods in a library that should be in their own library into one. Make the next step easier. Land each fix along the way. Provide incremental value and cleanliness along the way. Reward yourself and the team with the improvements.

Ask yourself if it sparks joy. As you go a-tidying, go in the direction that seems cleaner, not just to yourself, but to your customers and users. Because we all want to share the joy.

by Leon Rosenshein

Lessons From Buckaroo Banzai

But first, today is a day like any other day, but it's also different. Especially here in Colorado, but not just here. Shocking events are just that, shocking. And it takes time to process them. So take the time. Take care of yourself. Recognize that different people process shock differently. Don't expect today to be just like any other day.



I first heard the phrase Don’t tug on that in The adventures of Buckaroo Banzai Across the Eighth Dimension. Seemed reasonable at the time. Apparently it’s common advice in the fashion world, book restoration, and mushroom hunting as well. And it makes sense. Trim something to a clean end, make a small repair and move on. If you pull on that thread then you could easily distort something else in a different location and have an even bigger problem.

The same logic can apply to software as well. When you run into a problem where the situation you’re in almost matches the situation some library was built for, so you make a small change at the top of the library to handle your case. Then you realize that you need to go a little deeper, making another small change. And it happens again, and again. Until eventually you get things working for your case. But you find that all those small, inconsequential changes mean that the library doesn’t work in the standard case anymore.

Or maybe you find that you need to start using the latest version of the library. But that changes not only the interface, but a “bug fix” breaks a feature you’ve been relying on. So now you need to change all those use cases as well.

If the software world that has come to be called Yak Shaving. All those extra things that might be needed, but sure feel like procrastination, or maybe muda. And they certainly don’t feel like they’re related to the problem at hand.

And that’s where it gets interesting. Figuring out if it’s easier/better to fix/update that library (pull the thread) or change the code that has the problem to work with the existing library (cut the thread). And it’s made even harder because you don’t really know what the thread is attached to until you tug on it. So it’s hard to estimate which will be better in the long run.

When I approach something like that I often have a good estimate of the “cut” case, because it’s localized and I’ve been thinking about that area. If I can’t think of any other uses of the change (YAGNI) then why bother. If there are some possible uses then I might make an attempt at the library change. If I get to ~75% of the estimate and don’t feel any closer to resolution I’ll re-evaluate. At that point I know more about what it will take and the expected benefits. And being aware of the Sunk Cost Fallacy I can try to make an unbiased decision.

And on the other extreme, if changing the library is going to be a really good thing for lots of people and use cases, then I make the change. But not as a single PR. As a task unto itself that adds value. Then I make the original change.

by Leon Rosenshein

Tell Me About A Time When ...

I’ve been doing interviews for a while now. And one of the questions I like to ask candidates, of all levels, is to tell me about a time when they made a mistake that had significant impact. I find that there’s a lot of signal in the answer. There’s information on how self-aware the candidate is, what they find important, and how they respond to mistakes, both in the moment, and afterwards.

Because one of the follow on questions, if it doesn’t come up in the discussion, is “What did you, or anyone else, do to try and make sure it didn’t happen again?” And the response to that question has even more signal. It says a lot about how the candidate can generalize from specifics and how they think about the future. Answers can range from “I learned to do/not do X before I Y” to defining team/org processes as a way of reducing the likelihood of the issue to tooling with automated validation that prevents bad things from happening.

It’s those tools and automated validations that have the most impact on the future, and that’s what I really want to see in a candidate. Even with the most junior candidates or college interns I can end up having an interesting discussion of how a whole class of problems can be prevented. We can talk about Post-Incident reviews and root cause analysis and what you do when you find the root cause.

Because when it comes down to it, especially if you want to be able to get a good night’s sleep, how you prevent issues is more important than how you deal with them.

by Leon Rosenshein

String Style

Text is hard. Ascii is fairly straightforward, but Unicode is hard, and UTF-8 is NOT Ascii. Styling your text is hard too. Markdown is supposed to be simple and hopefully transportable, but …

And that doesn’t even get into how you type out an identifier, even if you’re using ASCII. Most (all?) languages use a space as a separator, so if you want a variable for the number of words in a paragraph you can’t use “number of words”. That makes sense. So eliminating spaces is a common pattern.

But there’s no one way to eliminate spaces. You could just drop them, or you could replace them. Or keep them? But what do you replace them with? An underscore is a common replacement, and sometimes, but not always, you can use a dash. And what about letter case?

For your pleasure, a list of possible string cases

Name/Example

Description

flatcase

Remove the spaces and don’t capitalize anything

UPPERFLATCASE

Remove the spaces. Capitalize everything

camelCase

Remove the spaces. Capitalize the first letter of all but the first word

PascalCase

Remove the spaces. Capitalize the first letter of all the words

snake_case

Replace the spaces with underscores. Don’t capitalize anything

camel_Snake_Case

Replace the spaces with underscores. Capitalize the first letter of all but the first word

Pascal_Snake_Case

Replace the spaces with underscores. Capitalize the first letter of all the words

SCREAMING_SNAKE_CASE.

Replace the spaces with underscores. Capitalize everything

kebab-case

Replace the spaces with dashes. Don’t capitalize anything

camel-Kebab-Case

Replace the spaces with dashes. Capitalize the first letter of all but the word

Pascal-Kebab-Case

Replace the spaces with dashes. Capitalize the first letter of all the words

SCREAMING-KEBAB-CASE.

Replace the spaces with dashes. Capitalize everything

Given all of those options, which do you choose? First and foremost, use whatever is in the file you’re editing. After that, use one of our style guides (C++, Go, Python). Then listen to your language and it’s style. And whatever you do, don’t use StUdLYcaPSfOrAnythinG

by Leon Rosenshein

Creep

Creep is not just a really bad acronym for political fundraising group. It’s also moving slowly forward, or in development terms, Scope/Feature Creep is when the requirements expand beyond the initial definition. The question is not if it’s going to happen, but what you’re going to do about it and if it’s a good thing or not.

Invariably, when you’re trying to do something you, and possibly no-one, has ever done before you’ll find that the work needed does not exactly match the work you expected. Some things you expected to need won’t be needed, and some things you never thought of (those unknown unknowns) will show up. You’ll often hear that called scope or feature creep.

But more likely, that’s not what’s happening. What’s really happening is that as you work on the project, you discover things that you didn’t know when you started. Or, as @jeffpatton said,

“Scope doesn’t creep, understanding grows“

And that’s a whole different kettle of fish.

First of all, if your understanding grows, that’s a good thing. The better you understand a problem the better you can make the correct tradeoffs needed to add customer value soonest. Sure, when you started you thought you needed to deliver feature A to the customer to add value. But that was before you really understood the problem. Along the way you learned that before you can do A, you need to do B, but guess what, B is valuable in its own right. So go ahead and deliver B as soon as you can.

Looking at it as understanding growing also has the benefit of making it more likely someone will say something. If you’re not punished for recognizing the additional work, or even better, rewarded for learning a new truth, think how much more likely people will be to tell you. If there’s more work to be done the schedule is going to change, whether you find out sooner or later. It’s better to find out sooner, so you can do something about it. If nothing else, you can be transparent. Best case, as I noted above, you find a way to deliver value earlier and everyone is happy.

So next time your understanding grows, don’t look at it as scope creep, look at it as an opportunity to add value sooner.

by Leon Rosenshein

Artificial Stupidity

Back when I was working on Combat Flight Simulator we had a problem. The game had varying levels of difficulty, but what did that mean? What’s the difference between Easy, Medium, and Hard? There were lots of things we did before we gave anyone a chance to try it out. Some were simple, like unlimited ammo and fuel, or invulnerability. Others were a little more involved, like changing how accurate your aim needed to be and the damage radius of things. Once we had that working we let others try it.

And it still wasn’t “fun”. This led to long discussions about what “fun” is, but one of the things we settled on was not just the ability to return to base successfully, but to complete the mission, and for air superiority missions, that meant stopping enemy aircraft. Unlimited ammo/fuel helped because you didn’t need to worry about having the perfect shot. Invulnerability or increased “hit points” meant you survived. But neither of those added up to stopping the other side.

What we found was that our AI was too good. Or at least never bad. We gave them a set of rules and models and they followed them. Exactly. Every time. Which meant that even if you knew the rules as well, if you made the smallest mistake they’d end up on your “six”. And that just wasn’t fun.

So what we ended up doing was implementing artificial stupidity. Depending on the difficulty setting, some number of the enemy AI and your wingmen will make suboptimal decisions. They might roll too far out of plane, or not turn at the right radius. And sometimes they’ll just do something random (simulating panic).

And of course, what’s old is new again. Seems like some folks working on chess AI took that approach and went a step farther. Not only does this new version make mistakes, it can make mistakes like a specific person. Of course, being able to predict a person’s moves, their tell, isn’t new. Apparently what’s old is new again. 

In retrospect, having your opponent be perfect isn’t much fun. We should have known that.