Adapted/Adaptable

Here’s a trade-off:

“The better adapted a system is to a particular environment, the less adaptable it is to new environments.” – Jerry Weinberg

Or, if you’re more self-centered:

“The better adapted you are, the less adaptable you tend to be.” – Weinberg, again

I see this everywhere now.

Think about when you’re struggling with a problem and you bring someone else in to take a look, to get “fresh eyes” on it. In any situation like that — and they’re many and varied, from pair programming to hiring a consultant — you are adapted to the problem context, and the other person is not. The other person is more adaptable, and thus less likely to be making as many assumptions as you. That can help.

I think about adaptedness versus adaptability when I hang out with my toddler. He’s as newbie as you can get, worlds more adaptable than me. He has the ultimate Beginner’s Mind. And he’s way more perceptive than I am. He notices every dog that barks in the distance. He notices every plane that flies overhead. Meanwhile, to me, all that is background noise at best. I’ve learned to consider it unimportant. I’ve adapted, for better or worse. Autopilot engaged.

I think about adaptedness versus adaptability when I pick up a wine menu in a restaurant. Someone who drinks a lot of wine is probably adapted within that domain. They know what they like. Maybe they like an extra dry red from a certain region, a certain kind of grape, with notes of cedar or orange peel or chocolate or whatever. I can’t really even write intelligently about that, because I’m not adapted. To me, it’s red or white, dry or sweet. What I am is adaptable: I’m happy enough with just about any red wine.

I thought about adaptedness versus adaptability when I saw these photos of athletes with vastly different body types. They’re all differently adapted. Being well-adapted for gymnastics calls for very different training (and a very different body to begin with) than being well-adapted for weightlifting. Competitions involving multiple activities, like maybe a decathlon, require athletes to be less adapted to individual activities, meaning they’re more adaptable.

I think about adaptability versus adaptedness when I play RPGs (which is admittedly rare nowadays). I used to play World of Warcraft a lot. I was a rogue. My specialty was dealing damage. I was adapted to do some stabbing. Other classes could have different specialties. A priest might be adapted to healing. A warrior might be adapted to tanking (drawing bad guys’ attention and taking a lot of damage without dying, often with the help of a healer). Still other classes could be more adaptable. A priest could choose to be decent at doing damage, at the cost of some healing potential. A warrior could sacrifice some tanking ability to do more damage. A druid could try to be competent at damage-dealing, healing, or tanking. Adaptable.

I thought about adaptedness and adaptability when I wrote about plans versus planning. In a sense, the act of planning makes you more adaptable, because you’re considering possibilities. But picking a plan can make you less adaptable, unless you’re willing to let go of that plan when the situation changes.

I think about this adapted/adaptable frame with respect to my software development work, too. The longer I spend with a language, on a platform, in a code base, or at a company, the more adapted I get. This is good when it comes to solving problems in whatever context I’ve become adapted to. I learn more of the details and have to think and learn less to solve a small, particular problem. It’s less good when I need to move on to a new context. I can’t add a feature for a new client until I’m familiar with the client, project, code base, tool chain, etc.

Should you try to be adapted or adaptable? It depends. It’s complicated. It depends on the situation and on a lot of factors around it. And even taking that into account, it feels unlikely to me that you’ll ever be able to look back and say you got it “right”. These are directions, not goals, not ends. They’re interesting to think about. They can be a tool in your toolbox for thinking about different kinds of problems.

I will say this: For me, as a technology professional, my plan is still what I said in Finding Fox Work: “Be a specialist and a generalist.” That is, be adapted to something (or a few things), but commit cycles to staying adaptable, too. Be a hedgehog and a fox.

Four Point Oh

Doesn’t a 4.0 GPA mean you’ve succeeded at everything you’ve tried?

If you’ve succeeded at everything you’ve tried, have you been trying very hard?

How are you going to handle failure?

Black Box

Draw a box around the system. Look at the inputs and outputs of that box. Not at what’s going on inside it. Decide how successful it is, what you want to change.

Then take that hat off and put on a different one when you go inside the box.

To Kill An Idea

If you want to kill an idea, steer it through a bureaucracy.

If you want to kill an idea, send it to a committee.

If you want to kill an idea, insist on following the rules to the letter.

If you want to kill an idea, give it a name.

If you want to kill an idea, make it the law of the land.

If you want to kill an idea, tell me it’s better than my idea.

Misdirected

Many times, this has happened:

  1. I have a cool idea to make a thing.
  2. I do not act on my idea.
  3. Later on, someone else has the same idea.
  4. They act on it. They make it happen.
  5. The thing is successful. The person who acted on it gets notoriety and/or money for it.

This is not a weird scenario. I’m sure it’s not unusual.

What’s weird is that when it happens to me, I get angry at the other person and not at myself.

I Don’t Know

“I don’t know.”

The ability to say this is a thing that elevates really good developers. And knowledge workers in general. Hell, even just people in general.

But technical people have a particularly hard time saying we don’t know how to do something. We feel like we’re supposed to know. (“Feel“, not “think”. It bothers us when we don’t know. And when we look like we don’t know.)

This tendency makes us susceptible to promising things even when we have no idea whether we can deliver them. Throw in a little flattery and it’s even harder.

Try this on for size: “I don’t know how to do that. Here’s what I could do to learn.”

JavaScript Classes: Orientation

What’s a class?

A class is a sort of template for creating objects.

What are objects?

Let’s say objects are little bundles of data and behavior. We’re talking about JavaScript objects here. Without classes, a JS object might look something like this:

let user = {
  firstName: 'Jane',
  lastName: 'Smith',
  getFullName: function getFullName() {
    return this.firstName + ' ' + this.lastName;
  }
};

We call this “object literal notation”. The object literal is the thing with the curly brackets. It creates an object with a bunch of properties, defined by name-value pairs.

In this case, the names firstName, lastName, and getFullName represent public properties of the object. The values associated with those names are the values stored in those properties.

I can call user.getFullName() and it returns "Jane Smith".

Okay. I get objects. And classes are templates for creating objects. Why do we want templates for creating objects? Why not just use object literals?

The same sorts of reasons you’d want a template for creating anything: creating an abstraction for a complex task means you don’t have to think about the details involved, and you isolate those details so they only exist in one place in your code.

More concretely: What if you wanted three user objects to represent three different people? With object literal notation, that might look like this:

let user1 = {
    firstName: 'Jaime',
    lastName: 'Lannister'
    getFullName: function getFullName() {
      return this.firstName + ' ' + this.lastName;
    }
  },
  user2 = {
    firstName: 'Cersei',
    lastName: 'Lannister'
    getFullName: function getFullName() {
      return this.firstName + ' ' + this.lastName;
    }
  },
  user3 = {
    firstName: 'Tyrion',
    lastName: 'Lannister'
    getFullName: function getFullName() {
      return this.firstName + ' ' + this.lastName;
    }
  };

Yuck. There’s a lot of duplication here. If I want to change what getFullName does for a user object, I have to change it in three places. If I want to add a property to user objects, I have to add it in three places. Yuck.

To remove this duplication, you might consider using a function as a template for creating your user objects:

function createUser(firstName, lastName) {
  return {
    firstName: firstName,
    lastName: lastName,
    getFullName: function getFullName() {
      return this.firstName + ' ' + this.lastName;
    }
  };
}

let user1 = createUser('Jaime', 'Lannister'),
  user2 = createUser('Cersei', 'Lannister'),
  user3 = createUser('Tyrion', 'Lannister');

This puts the information about how a user object is created into one place. You simply call that function when you want to make a user, rather than outlining the entire user object.

Makes sense. But if I can use functions as templates for creating objects, why should I care about classes?

That’s a good question. The answer, unfortunately, is: “It’s complicated.”

Classes are very familiar for a lot of developers. For the communities around many popular programming languages, classes are the most common way to organize code. By far.

As JavaScript started taking over the world, those other developers started using it. Some a little, some a lot. And some of them missed classes. They missed classes so much that they came up with ways to create class-like things anyway. Adding an actual class keyword to the language is nice for those people.

Classes can be a mechanism for code reuse, too, via inheritance.

What’s inheritance?

Remember when we said a class was a template for creating objects? Inheritance is a way to make a new template by using an existing template as your starting point.

It’s another way of reducing duplication and creating more elegant abstractions.

Sounds pretty awesome.

It can definitely be handy. But it can also create some pretty awful messes. Like any tool or technique, before you go too deep with it, you should invest some time in really understanding it. Make sure you have a handle on the potential consequences of your design decisions.

In my opinion, inheritance tends to be overrated. It’s fine for some things, but it’s not a tool I reach for often. Composition is often preferable.

What the hell are you talking about?

Let’s talk more about inheritance later. It’s safe to pretend it doesn’t exist for now.

Fine. Let’s get to the point here. What does a JavaScript class look like?

Oh yeah. Like this:

class User {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFirstName() {
    return this.firstName + ' ' + this.lastName;
  }
}

let user1 = new User('Jaime', 'Lannister'),
  user2 = new User('Cersei', 'Lannister'),
  user3 = new User('Tyrion', 'Lannister');

This is similar to what we did above with the object literal notation and the function.

What’s different?

It’s mostly syntax, as you can see at a glance. We don’t define all the public properties as name-value pairs anymore. We define properties for data in the constructor. We define properties for behavior in function definitions. (BTW, in OO world, these are called “methods”, not “functions”.)

The constructor is a special function that gets called when you create an object using your class, via new User(...). Remember before when we said classes can be good for organizing code? Constructors are one aspect of that. They’re the appropriate place for code that helps construct the object.

And then getFirstName moves to a nice, declarative function (method) definition. It also only gets created once, regardless of how many users I create.

Wait. What?

Hmm. We’ll talk about this more when we get to inheritance in a future post. Let’s keep it at a high level for now.

Think of it this way: The function lives on the template, not on the instances. On the class, not the objects. When objects want to run it, they go back to the class and say something like “run this function, use me as this, and return the result.”

Um. Why?

Again, more on this in a future post. But for now: Imagine I create a hundred users. I’ll use way less memory if they all point to a single instance of getFirstName than if they each have their own copy of it.

What To Do

If I could tell you exactly what to do, I could just as easily tell someone else.

When someone can tell you exactly how to do a job, that job is on a path to commoditization. Maybe even automation.

High-value work doesn’t come with a map.

Measure Twice

“Measure twice, cut once.”

I love this. Such a simple expression of an idea. The idea is (ir)reversibility.

In a lot of situations, you can make a call and if it turns out to be a bad one, you can change it without a lot of negative consequences.

When you make a decision that’s irreversible, you need to be super careful. You should weigh your options carefully before you take action.

Reversibility exists on a sort of spectrum, though. Some things are flat-out impossible to reverse. Some things are pretty hard to reverse. Some things are just kinda hard. And some things are trivially easy.

How does this thinking apply to software development? You can make a reversibility forecast along with every software design decision you make. “If I design the code this way and then change my mind, will it be hard to update the design later?”

How does this thinking apply to business? Similar: You can make reversibility forecasts along with decisions about hiring, resource allocation, business development, product development, etc.

Reversibility is a factor to consider in decisions you make in just about any domain, really. It’s something to pay attention to. Where you only get to cut once, be sure to measure twice.

Small Pieces

Small pieces are easier to understand. Small pieces can be understood. You can fit the whole thing in your head when it’s a small piece.

If you build something complex from small pieces and then you need to make a change, there’s a good chance you’ll really only need to change one small piece. And if you need to change more than one, you might have identified a new concern, something that might be better as its own small piece.

When small pieces break, they tend to break in a self-contained way. When they don’t work how we expect, it’s usually pretty easy to see what the problem is.