Keeping Your Eyes on the Prize

I’ve heard people say things like, “we need to use the strategy pattern here” or “we need a repository layer between the services and domain objects.” Let’s take that at face value and assume that these are things that they “need” to do, in the sense that they’re solid solutions to some problem. The point of confusion then comes from a lack of understanding of the goal. I mean, I doubt that the goal is “to use the strategy pattern” or “add a repository layer,” so someone is explaining a means of achieving a goal.

If the context of the discussion is two people well aware of and in agreement upon the actual goal, then this is entirely unremarkable. It’s just a couple of people collaborating to solve a problem. Somewhat more interesting is the case of the two people not sharing a common goal. For instance, if the first person’s goal is “make it easy to add a new implementation to the code base” while the second person’s goal is, “practice using the strategy pattern,” agreement becomes a matter of coincidence rather than collaboration, and the possibility of tragi-comic feuding emerges. The most noteworthy case, however, is where one or more people are unaware of the goal or don’t actually have a broader goal. “We need to use the strategy pattern because my Software Engineering textbook says Gang of Four is good.” Or, in the Expert Beginner world, “we need to use Strategy Pattern because that’s just what we do.”

Lack of a Goal

I’m not going to spend a whole lot of time on this because it’s pretty straightforward. Assuming that the person in question isn’t a nihilist or troublemaker, this is the epitome of cargo cult. I think that perhaps the most iconic example of this is the pervasive mid-2000’s use of Systems Hungarian Notation. This gives rise to the following type of terminally stupid conversation:

Interloper: Why did you do this: “const char* lpcstr_str”
Cult Member: I wanted to declare a string.
Interloper: Okay, but why did you name it that?
Cult Member: Because it’s a string.
Interloper: That name seems inscrutable and redundant — what’s the upside?
Cult Member: I don’t understand the question. It’s a string. That’s what you name strings.

Cult member has no goal whatsoever because his routine has become a goal unto itself. And really, that’s sort of a sad state of affairs not worth elaboration.

Pawn

Lack of Consideration of a Goal

Not all participation in routine is the celebration of routine. Routine does, in fact, have a purpose. It’s sort of the human-natural way of prioritizing cognition. What I mean is, imagine a world where you approached everything as if it were a riddle requiring critical thinking. Every morning you’d stop to ask yourself if there wasn’t, in fact, a better way to brew your coffee than using your Keurig. And, the drive to work? Should you find a new route? Should you drive at all?

Nobody has time for this, so a great many activities are conducted on auto-pilot with rationale revisited only strategically. Every now and then you may wonder if you should make your coffee differently or drive to work via a different route, most likely as a result of ongoing frustration with something. And that’s fine. In fact, it’s probably efficient.

This applies in a limited way to programming. I say limited because programming is knowledge work and it’s also rarely repetitive if you’re doing it well. Programming isn’t like driving to work or making coffee; you’re generally blazing a new trail even if you’re doing something comparably formulaic like some kind of forms-over-data/CRUD app. The domain changes, the languages/frameworks/tools in use change, and the business context changes. There may be aspects of the craft that you don’t revisit as often, such as, say, which source control tool or programming language you use, but by and large programming demands fewer brain reps on auto-pilot than most other things in life. In this context, lack of consideration of a goal puts you in danger of settling in to a rut and not being at your sharpest.

Keeping your Eye on the Goal

As you go through your life as a programmer, I have a definite suggestion for how you can avoid a rut. Always be able to rattle off your goal when asked about what you’re doing. That’s it, really. The goal doesn’t necessarily have to be great, and your means of achieving it doesn’t need to be either (I mean, do your best, but I’m making a point here). Just knowing what it is you’re trying to accomplish well enough to articulate it will help you a lot.

So if you’re overhead saying, “we need to implement the strategy pattern here” and someone asks you why you think that, be ready with “the goal is to allow future implementations with a minimum of violence to the code base ala the Open/Closed Principle.” Now, it could be that the strategy pattern is a poor choice or that you’re gold plating or whatever else, but at least you’re not caught flat-footed when challenged on your motivation and, more importantly, thinking in terms of goals creates a concrete link between your solution and added value.

And if the next question you want to ask is, “what if someone asks you for the goal behind your goal,” this absolutely iterates. A logical follow up would be “why are you worried about future implementations,” and your logical answer may be, “we’ve been asked to add 3 already, so it seems like a 4th and perhaps beyond are likely.” Now, your connection of solution to broader goal is “business has created a lot of churn around X, so I think we can use the strategy pattern to minimize the risk associated with any more similar churn.” Want to go another round? How about the fact that each time this has churned it’s cost your company $15,000, and you think that, with the strategy pattern, you can cut that to $5,000.

So, where does the iteration end? Perhaps at “we’ll have more money if we do this.” Perhaps further (“we need more money so that…”). Perhaps not that far. But, really, the further back along the path of your reasoning, the better. The more you can tie your specifics to broader, strategic goals, the more persuasive you’re going to be and the more likely you are to have solutions that, even imperfectly executed, will be a help. So the next time you find yourself talking about patterns or repositories or frameworks or whatever, do an exercise and see how far back you can iterate if you were confronted with a child asking, “but, why?” ad nauseum. Worst case scenario? You waste a few minutes practicing justifications of your decisions.

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1688

  • Jordan Whiteley

    This kind of goal based thinking is what I’ve recently started using to combat my internal architecture astronaut. If I can blaze a trail straight to the goal I do it as quickly as possible. Once i’m green on the the entire feature I can start thinking about a ‘macro-refactor’ like introducing a strategy pattern.

    I used to think that if I didn’t have that strategy pattern my code was wrong and agonize over it. Then experience kicked in and I now follow (my own warped) rule of 3. If I don’t have 3 things that fit the pattern, it’s wrong for the design pattern to exist. Once the third thing is added, that’s the time to refactor the first two to fit the pattern. Same for factory patterns and whatnot. Anything less and I’m violating YAGNI.

  • http://www.daedtech.com/blog Erik Dietrich

    Sounds to me like a good approach. I followed a similar course in my thinking over the course of my career gravitating more toward a desire to minimize complexity up front, even when the solution wasn’t especially elegant. Patterns are great… when they’re solving problems that you actually have. :)

  • Pingback: Professional Development – 2014 – Week 36