DaedTech

Stories about Software

By

Rapid Fire Craftsmanship Tips

The last month has been something of a transitional time for me. I had been working out of my house for a handful of clients pretty much all summer, but now I’ve signed on for a longer term engagement out of state where I’m doing “craftsmanship coaching.” Basically, this involves the lesser-attended side of an agile transformation. There is no shortage of outfits that say, “hey, sign up with us, get a certification and learn how to have meetings differently,” but there does seem to be a shortage of outfits that say, “we’ll actually teach you how to write code in a way that makes delivering every couple of weeks more than a pipe dream.” I believe this state of affairs leads to what has been described as “flaccid scrum.” So my gig now is going to be working with a bunch of developers on things like writing modular code, dependency inversion, test driven development, etc.

This background is relevant for 2 reasons. First of all, it’s my excuse for why my posting cadence has dipped. Sorry ‘bout that. Secondly, it explains and segues into this post. What is software craftsmanship, anyway? I’m apparently teaching it, but I’m not really sure I can answer this question other than to say that I share a lot of opinions about what it means to write code effectively with people who identify this way. I think that TDD, factored methods, iterative, high-communication approaches, failing early, and testable code constitute are efficient approaches to writing software, and I’m happy to help people who want to improve at these things as best I can.

In that vein of thought, I’d like to offer some suggestions for tangible and easy-to-remember/easy-to-do things that you can do that are likely to improve your code. Personally, more than anything else, I think my programming was improved via random suggestions like this that were small by themselves, but in aggregate added up to a huge improvement. So, here is a series of things to tuck into your toolbelt as a programmer.

Make your variable names conversational

ComboBox cb = new ComboBox();

Ugh. The only thing worse than naming the variable after its type is then abbreviating that bad name. Assuming you’re not concerned with shaving a few bytes off your hard disk storage, this name signifies to maintainers, “I don’t really know what to call this because I haven’t given it any thought.”

ComboBox dayPicker = new ComboBox();

Better. Now when this thing is referenced elsewhere, I’ll know that it probably contains days of some sort or another. They may be calendar days or days of the week, but at least I know that it’s talking about days, which is more than “cb” told me. But what about this?

ComboBox mondayThroughFridayPicker = new ComboBox();

Any doubt in your mind as to what’s in this combo box? Yeah, me neither. And that’s pretty handy when you’re reading code, especially if you’re in some code-behind or any kind of MVC model-binding scheme. And, of the objections you might have, modern IDE’s cover a lot of them. What if you later want to add Saturday and Sunday and the name becomes out of date? Easy to change now that just about all major IDEs have “rename all” support at your fingertips. Isn’t the name a little over-descriptive? Sure, but who cares — it’s not like you need to conserve valuable bytes of disk space. But with cb name, you know it’s a combo box! Your IDE should give you that information easily and quickly and, if it doesn’t, get a plugin that tells you (at least for a statically typed language).

Try to avoid booleans as method parameters

This might seem a little weird at first, but, on the whole your code will tend to be more readable and expressive if you don’t do this. The reason for this is that boolean parameters are rarely data. Rather, they’re generally control parameters. Consider this method signature:

void LogOutputToFile(string output, bool useConsole = false)

This is a reasonably readable method signature and what you can infer from it is that the method is going to log output to a file. Well, unless you pass it “true”, in which case it will log to the console. And this tends to run afoul of the Single Responsibility Principle. This method is really two different methods kind of bolted together and its up to a caller to figure that out. I mean, you can probably tell exactly what this method looks like:

void LogOutputToFile(bool useConsole = false)
{
     if(useConsole)
          Console.WriteLine(output);
     else
          _someFileHandle.WriteLine(output);
}

This method has two very distinct reasons to change: if you want to change the scheme for console logging and if you want to change the scheme for file logging. You’ve also established a design anti-pattern here, which is that you’re going to need to update this method (and possibly callers) every time a new logging strategy is needed.

Are there exceptions to this? Sure, obviously. But my goal here isn’t to convince you never to use a boolean parameter. I’m just trying to get you to think twice or three times about doing so. It’s a code smell.

If you type // stop and extract a method

How many times do you see something like this:

_customerOrder.IsValid = true;
_logfile.WriteLine("Finished processing customer order");

//Now, save the customer order
if(_repository != null)
{
     try
     {
          _repository.Add(_customerOrder);
     }
     catch
     {
          _logfile.WriteLine("Oops!");
          _showErrorStateToUser = true;
          _errorMessage = "Oops!";
     }
}

Would it kill you to do this:

_customerOrder.IsValid = true;
_logfile.WriteLine("Finished processing customer order");

SaveCustomerOrder();

and put the rest in its own method? Now you’ve got smaller, more factored, and descriptive methods, and you don’t need the comment. As a rule of thumb, if you find yourself creating “comment bookmarks” in your method like a table of contents with chapters, the method is too big and should be factored. And what better way to divide things up than to stop typing a comment and instead add a method with a descriptive name? So, when you find you’ve typed that “//”, hit backspace twice, type the comment without spaces, and then slap a parenthesis on it and, viola, new method signature you can add.

Make variable name length vary with scope size

This seems like an odd thing to think about, but it will lead to clearer code that’s easier to read. Consider the following:

Globals.NonThreadSafeSumOfMostRecentlyProcessedCustomerCharges = 0;
for(int i = 0; i < _processedCustomers.Count(); i++)
     Globals.NonThreadSafeSumOfMostRecentlyProcessedCustomerCharges += _processedCustomers[i].TotalCharge;

Notice that there are three scopes in question: method level scope (i), class level scope (_processedCustomers) and global scope (that gigantic public static property). The method level scope variable, i, has a really tiny name. And, why not? It's repeated 4 times in 2 lines, but it's only in scope for 2 lines. Giving it a long name would clog up those two lines with redundancy, and it wouldn't really add anything. I mean, it's not hard to keep track of, since it goes out of scope one line after being defined.

The class level scope variable has a more descriptive name because there's a pretty good chance that its declaration will be off of your screen when you are using it. The extra context helps. But there's no need to go nuts, especially if you're following the Single Responsibility Principle, because the class will probably be cohesive. For instance, if the class is called CustomerProcessor, it won't be too hard to figure out what a variable named "_processedCustomers" is for. If you have some kind of meandering, 2000 line legacy class that contains 40 fields, you might want to make your class level fields more descriptive.

The globally scoped variable is gigantic. The reason for this is twofold. First and most obviously, it's in scope from absolutely anywhere with a reference to its containing assembly, so it better be very descriptive for context. And secondly, global state is icky, so it's good to give it a name that discourages people from using it as much as possible.

In general, the broader the usage scope for a variable/property, the more context you'll want to bake into its name.

Try to conform to the Principle of Least Surprise

This last one is rather subjective, but it's good practice to consider. The Principle of Least Surprise says that you should aim to minimize the learning curve or inscrutability of code that you write, bearing in mind a target audience of your fellow developers (probably your team, unless you're writing a more public API). As a slight caveat to this, I'd say it's fair to assume a reasonable level of language proficiency -- it might not make sense to write horribly non-idiomatic code when your team is likely to become more proficient later. But the point remains -- it's best to avoid doing weird or "clever" things.

Imagine stumbling across this bad boy that compares two integers... sort of:

public bool Compare(int x, int y)
{
    Console.WriteLine("You shouldn't see this in production.");
    _customerCount = x; 
    return x.ToString() == y.ToString();
}

What pops into your head? Something along the lines of, "why is that line about production in there?" Or maybe, "what does a comparison function set some count equal to one of the parameters?" Or is it, "why compare two ints by converting them to strings?" All of those are perfectly valid questions because all of those things violate the Principle of Least Surprise. They're surprising, and if you ask the original author about them, they'll probably be some weird, "clever" solution to a problem that came up somewhere at some point. "Oh, that line about production is to remind me to go back and change that method. And, I set customer count equal to x because the only time this is used it's to compare customer count to something and I'm caching it for later and saving a database write."

One might say the best way to avoid this is to take a break and revisit your code as if you're someone else, but that's pretty hard to do and I would argue that it's an acquired skill. Instead, I'd suggest playing a game where you pretend you're about to show this code to someone and make mental note of what you start preparing yourself to explain. "Oh, yeah, I had to add 39 parameters to that method -- it's an interesting story, actually..." If you find yourself preparing to explain something, it probably violates the Principle of Least Surprise. So, rather than surprising someone, maybe you should reconsider the code.

...

Anyway, that's all for the tips. Feel free to chime in if you have any you'd like to share. I'd be interested to hear them, and this list was certainly not intended to be exhaustive -- just quick tips.

By

Chess TDD 15

Prompted by comments from a few people, I’ve decided to see if I like using Trello for keeping track of the TODOs instead of Excel. Also, learning from past feedback, I’ve defaulted Trello to being really big when recording so everything is legible, and I copied everything over from Excel. Hopefully I like it as I go, but please let me know if it’s more pleasing to view as compared with the Excel spreadsheet, if it matters to you one way or the other.

Also, a meta-note. I apologize for the time between posts in the series and for the lack of posting in general, but I’ve been traveling nonstop and am pretty much living out of hotels, meaning my life is one of 3G-ish wifi and sub-optimal setups. Luckily, I’m driving everywhere and lugging my boom mic, desktop and monitors with me so I can still record in the hotel. 🙂

Here’s what I accomplish in this clip:

  • Make the “blocked” algorithm for horizontal/vertical less dumb.
  • Start the implementation for “blocked” diagonal.
  • Inadvertently create a potential solution for the problem of knight’s oddball movement.

Here are lessons to take away:

  • Even little things matter when it comes to readability.  For instance, at 0:40 I noticed that my test class name ended in should but the methods started with “returns.”  So, I took the time to fix this.  My advice is to get in the habit of avoiding sloppiness and inattention to detail at any level of code.
  • Bear in mind that changing prod code is fine while green in TDD, provided you’re not looking to introduce new behaviors.  It’s a refactoring if your goal is continue satisfying existing test cases in a different way.
  • A little before 10:00, I refactored a bit of a test while red for the sake of readability.  I shouldn’t have.  My bad.  Lesson is, no matter how much TDD you do, sometimes you flub it.
  • Sometimes a great way to get things passing when the implementation is getting hairy is to tease out a conditional that only applies to your new case and do something obtuse.  Use with discretion because it can lead you into blind alleys and cause problems, but there are times when getting to green can provide an aha! moment.
  • You’ll notice I refactored to a different method signature, changed some stuff around, and then refactored back.  This kind of waffling is fine.  With TDD, you’ll get used to fearlessly refactoring and slinging stuff around until you settle on something you like (or at least thing is the least bad, for now).
  • Get it working ugly now, make it pretty later.  It’s sometimes amazing how an algorithm will suddenly make itself obvious after a bit of brute forcing and futzing around.

By

Be Idiomatic

I have two or three drafts now that start with the meta of me apologizing for being sparse in my posting of late. TL;DR is that I’ve started a new, out of town engagement and between ramp-up, travel and transitioning off of prior commitments, I’ve been pretty bad at being a regular blogger lately.

Also, special apologies to followers of the Chess TDD series, but my wifi connection in room has just been brutal for the desktop (using the hotel’s little plugin converter), so it’s kind of hard to get one of those posts going. The good news is that what I’m going to be doing next involves a good bit of mentoring and coaching, which lends itself particularly well to vaguely instructional posts, so hopefully the drought won’t last. (For anyone interested in details of what I’m doing, check Linked In or hit me up via email/twitter).

TheCouncil

What It Is to Be Idiomatic in Natural Language

Anywho, onto a brief post that I’ve had in drafts for a bit, waiting on completion. The subject is, as the title indicates, being “idiomatic.”

In general parlance, idiomatic refers to the characteristic of speaking a language the way a native would. To best illustrate the difference between language correctness and being idiomatic, consider the expression, “go fly a kite.” If you were to say this to someone who had learned to speak flawless English in a classroom, that person would probably ask, “what kite, and why do you want me to fly it?”

If you said this to an idiomatic USA English speaker (flawless or not), they’d understand that you were using a rather bland imprecation and essentially telling them to go away and leave you alone. And so we make a distinction between technically accurate language (syntax and semantics) and colloquially communicative language. The idiomatic speaker understands, well, the idioms of the local speech.

Being Idiomatic in Programming Language

Applied to programming languages, the metaphor holds pretty well. It’s possible to write syntactically and semantically valid code (in the sense that the code compiles and does what the programmer intends at runtime) that isn’t idiomatic at all. I could offer all manner of examples, but I’ll offer the ones probably most broadly approachable to my reader base. Non-idiomatic Java would look like this:

public void DoSomething()
{
     System.out.print("Hello!");
}

And non-idiomatic C# would look like this:

public void doSomething() {
     Console.WriteLine("Hello!");
}

In both cases, the code will compile, run, and print what you want to print, but in neither case are you speaking it the way the natives would likely speak it. Do this in either case, and you’ll be lucky if you’re just laughed at.

Read More

By

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.

By

Chess TDD 14: Figuring Out Blocking Pieces

In this installment, I’m looking to start defining the concept of “blocking” on a chess board. So far, I’ve been defining piece moves in a vacuum — put a rook down in (1, 1) and the rook can go anywhere in column 1 or row 1. But, what about when there’s a pawn at (1, 2)? That’s what’s on the docket in this episode.

Here’s what I accomplish in this clip:

  •  Started implementing the concept of pieces “blocking” one another.
  • Expanded the blocking logic to include horizontal and vertical blocking in both positive and negative directions.
  • Realized I’d been wrong about how Enumerable.Range() worked for a good long time because I had always used it for 0 indexed number generation, which masked my wrongness.

And here are some lessons to take away:

  • If you’re anything like me, sometimes you’ll thrash a bit between micro design decisions.  I introduced the concept of BoardCoordinate to avoid passing (int x, int y) to every method under the sun, but then I started to get annoyed by the ceremony of declaring new BoardCoordinate(x, y) everywhere.  Result was (for now) to implemented BoardCoordinate.For(x, y) which struck me as at least slightly more readable and elegant.  Point is, you probably won’t hit your most simple/elegant design on your first, second, or even third crack.  Keep at it, don’t be afraid to experiment, and solicit opinions and advice.  (Speaking of which, anyone with a good idea for this, please chime in!)
  • “Do the simplest thing you can to make the test pass” is not just a function of what you do in the production code but also of what test you’ve written.  In other words, make sure you don’t write an overly ambitious test like “test_that_all_end_user_requirements_are_satisfied” or the simplest thing you can do to make it pass will be really complicated.
  • TDD is the ultimate in “fail fast.”  I wasted about a minute of my time (twice) and a minute of yours (once) because I couldn’t figure out that I was calling Enumerable.Range(int, int) with the wrong second parameter.  But, seeing NCrunch’s dots turn red told me something was wrong very, very quickly while what I did was still fresh in my mind.  I didn’t know I was misremembering the method signature, but I did know that something about Enumerable.Range() in there was breaking things.  Without TDD, I’d have gone merrily on writing code for minutes or even hours until I fired up the whole application and wondered why the blocked rook could randomly move to one spot on the board in front of the opponent’s pawns or something.  I’d have wasted a lot more of both of our time trying to hunt down the problem then, when I had no clue which line of code was the offender.
  • There are times when the code smell of duplication or duplicate effort appears, but the solution isn’t immediately obvious (such as the case in this video where I was doing similar things for horizontal and vertical).  It’s my experience that you can find yourself in a blind alley when you try to abstract this to a common method where it becomes a snarl of conditionals or very dense, opaque mathematical logic.  Eliminating duplication is extremely important, but beware of times when you have “duplication elimination fools’ gold” and the gains in readability/maintainability actually go into the negative.  Be sure that your abstraction is actually making things simpler.
  • I didn’t like a number of things about this code when the clock started getting pas the 20 minutes mark and I felt the pressure not to make this a horribly long episode.  It might not be the same reason, but there are going to be times when you’re forced to get up and leave for the time being or for the day when you’re not thrilled with the code.  It’s okay — you’ll have another crack at it tomorrow with a fresh mind, and the TDD will help you pick right up where you left off.