Stories about Software


Beware of Mindless Automation

Something I’ve seen a lot over the years is a tendency to locally maximize when it comes to automating processes. We’re software developers, and thus automation is what we do. But not all automation is created equally, and some of it can be fairly obtuse and misguided if we aren’t careful. And the worst part is that it’s pretty easy to fall into this trap.

For example, let’s say that you observe some people in your organization following a process. They have some Microsoft Word template that they’ve stored somewhere and they regularly open it up and fill it out with data that they pull from an internal system. They populate things like today’s date and various data points and then they do some light formatting based upon various criteria, such as putting items in red if they fall below a certain threshold. When finished, they print out the result, drop it in an envelope, and mail it to another office location of the company. At that location, they process the data and put it into the system — you don’t know too much about that system because it’s not your office location, but that’s the general gist of it.

So, what do you do if you have some spare time and empathy for manual process on your hands and are looking to make a name for yourself? Do you automate this process for them, to their many thanks and heaped praise? And, assuming you do, how do you do it? Do you write some code that pulls the necessary data from your internal system, fires up MS Word interop, and starts automatically generating the documents they’re using? Then, flush with success from that project, do you also automate the printing of the envelopes and metering of the postage?

If you do, how does that go as a function of time? I bet the users are very grateful at first, but then they come to rely on it. And, what’s more, they like the system less and less over the course of time. Every time the USPS changes the price of postage you have to go into this system and made changes, and, what’s worse is that the part that generates the documents seems to break every time there’s a new version or even an update to Word. And when the format of the documents that the other office is requesting changes, suddenly you’ve got a real project on your hands, since automating intricate, form Word documents is about as much fun as spending the afternoon trying to cram a decade of your life onto a one-page resume. Wasn’t this supposed to be helpful? Weren’t you the hero? Does no good deed go unpunished?

Let’s go back to the point where you decided to help. Was the automation as you conceived it worth doing or was it sort of marginal? I mean, you’re probably saving a few minutes for people and some fat-fingering opportunities, but what you still have is sort of an involved, manual process. What if you had stopped to think about the process and the larger goal: getting data from one system into another? Might you not have been talking about things like “web service” or at least “file transfer” instead of things like “Word interop” and “postage?”

Here’s the rub. When your users are solving your problems, they think like users and not like software developers. As such, they come up with non-programming, user solutions. Normal computer users understand MS Word and sending things via mail (or at least email), so they come up with processes that feature those tools. You’re a programmer. By all means, automate, but don’t mindlessly automate whatever they happen to be doing. That’s an optimization tweak. Real software engineering is about using software to create simple solutions to problems. I’ve seen many people fall into this trap and have fallen into it myself. When you’re writing software, asking “why” is invariably more important than asking “how.”


Static Analysis: Why You Should Care

I don’t want to go into a ton of detail on this just yet, but in broad terms, my next Pluralsight course covers the subject of static analysis. I get the sense that most people’s reaction to static analysis lies somewhere between “what’s that?” and “oh yeah, we use FX Cop sometimes.” To be sure, it’s not everyone’s reaction, but I’d say the majority falls into this category. And frankly, I think that’s a shame.

To bring things into perspective a bit, what would you do if you wanted to know how many public static methods were in a given namespace or project? I’m guessing that you’d probably hit “ctrl-shift-f” or whatever “find all in files” happens to be in your IDE, and then you’d start counting up the results, excluding spurious matches for public static classes and properties. Maybe you’d find some way to dump the results to Excel and filter or something a little more clever, but it’s still kludgy.

And what if you wanted to answer a question like “how many 20+ line methods are there in my code base?” My guess is that you basically wouldn’t do that at all. Perhaps you have an IDE plugin that offers some static analysis and LOC is a common one, but absent that, you’d probably just take a guess. And what if you wanted to know how many such methods in your code base also took a dependency on three or more framework classes? You’d probably just live with not knowing.

And living with not knowing leads to talking about code in vague generalities where loudness tends to make right. You might describe the whole reporting module as “tricky” or “crappy” or “buggy,” but what do those things really mean, aside from conveying that you more or less don’t trust that code? But what if you could run some qualitative and quantitative analysis on it and say things like “more than 80% of the methods in that module depend on that flaky third party library” or “there are several classes in there that are used by at least 40 other classes, making them extremely risky to change.” Now you have tangible, quantifiable problems for which you can find measurable solutions that can be validated. And that ability is solid gold in a profession often dominated by so-called religious arguments.


Static analysis of the variety that gives you detailed information about your code and warns you about potential problems combines two incredibly useful software development techniques: code review and fast feedback. Code reviews involve peer inspection of code, but it is conceptually possible to get a lot of the benefit of this activity by having the reviewers codify and store common rulesets that they would apply when doing actual reviews: no methods longer than X lines, no more code added to class Y, etc. Done this way, fast feedback becomes possible because the reviewee doesn’t actually need to find time with reviewers but can instead keep running the analysis on the code as he writes it until he gets it right.

There are plenty more benefits that I could list here. I even could talk about how static code analysis is just flat out fascinating (though that’s something of an editorial opinion). But, for my money, it makes the discussion of code quality scientific, and it dramatically speeds up the review/quality feedback loop. I think pretty much any software group could stand to have a bit of that magic dust sprinkled on it.


I Don’t Really Do That Anymore

The title of this post has become my answer to a surprising number of things lately and something of an unsatisfying conversation ender. For instance, I was having dinner with some friends the other night, and one of them mentioned a bizarre ‘pattern’ in the code he was working one where people would have a switch statement with a single case (and no default) instead of the more traditional if statement. There was some discussion of this approach as an anti-pattern, and when it was my turn to weigh in, I realized with some embarrassment that I couldn’t really remember off the top exactly how enums behaved in all situations. You see, I don’t really do that anymore. I don’t think I’ve typed “public enum Something {” in well over a year.

This comes up in other situations that I can think of. Someone was telling me about duplication in unit tests. Someone was asking me about cursors in stored procedures. Someone was showing me unit testing troubles they were having around a logger with a public static API. There seems to be an endless list of things to which my response is something along the lines of, “that was a point of ickiness for me too, so I wound up avoiding the whole mess altogether.” Or, more succinctly, “I don’t really do that anymore.”

It’s hard to know when saying something like that if you’re being off-putting and sounding like snot, and, more subtly, it’s hard to know whether or not you might be copping out. I tend to think I’m not, however. I don’t generally shy away from attempts at mastery and generally working toward understanding something. I find that usually I shy away from things that result in flailing without mastery — pain without gain. I never found that using enums resulted in cleaner, better, more defensible code, but I definitely found that using them was a surefire way to make me regret the decision later.

I’ll keep this post short and sweet (as an aside, I’m insanely busy, so I’m trying to gravitate a little more toward posting vignettes). Pay attention to what you find yourself avoiding and see if you can put some reason to it. If there’s some programming practice or construct that makes your fingers subconsciously clench every time you think about doing it, ask yourself why. It may be that a very good explanation or discovery awaits you at the end of some brainstorming and white-boarding. Likewise, if your friends, coworkers or peers in general seem to have developed an aversion toward something, ask them about it or do a little research for largely the same reasons.

We all learned hard lessons as children. After the first time you touched the hot stove, you surely never did it again (at least not on purpose). See if you can pull some wisdom from that stark, simple lesson, and put some solid rationale behind your aversions.


Wrapping Up and an E-Book: The Tragedy of the Expert Beginner

It’s been a pretty busy week for me, which is why I haven’t posted in over a week. I’m in the midst of my next Pluralsight course, and I spent the last week getting ready for closing, then actually closing, on a house. On top of that, the Expert Beginner e-book is now available!


Here is the start of the final post in the series and the conclusion of the book:

The real, deeper sadness of the Expert Beginner’s story lurks beneath the surface. The sinking of the Titanic is sharply sad because hubris and carelessness led to a loss of life, but the sinking is also sad in a deeper, more dull and aching way because human nature will cause that same sort of tragedy over and over again. The sharp sadness in the Expert Beginner saga is that careers stagnate, culminating in miserable life events like dead-end jobs or terminations. The dull ache is endlessly mounting deficit between potential and reality, aggregated over organizations, communities and even nations. We live in a world of “ehhh, that’s probably good enough,” or, perhaps more precisely, “if it ain’t broke, don’t fix it.”

There is no shortage of literature on the subject of “work-life balance,” nor of people seeking to split the difference between the stereotypical, ruthless executive with no time for family and the “aim low,” committed family type that pushes a mop instead of following his dream, making it so that his children can follow theirs. The juxtaposition of these archetypes is the stuff that awful romantic dramas starring Katherine Heigl or Jennifer Lopez are made of. But that isn’t what I’m talking about here. One can intellectually stagnate just as easily working eighty-hour weeks or intellectually flourish working twenty-five-hour ones.

I’m talking about the very fabric of Expert Beginnerism as I defined it earlier: a voluntary cessation of meaningful improvement. Call it coasting or plateauing if you like, but it’s the idea that the Expert Beginner opts out of improvement and into permanent resting on one’s (often questionable) laurels. And it’s ubiquitous in our society, in large part because it’s encouraged in subtle ways. To understand what I mean, consider institutions like fraternities and sororities, institutions granting tenure, multi-level marketing outfits, and often corporate politics with a bias toward rewarding loyalty. Besides some form of “newbie hazing,” what do these institutions have in common? Well, the idea that you put in some furious and serious effort up front (pay your dues) to reap the benefits later.

To read the entire conclusion, or if you like this series in general and want to support it, please consider buying the e-book. It is available right now on Amazon and will be available soon in other e-book stores as well. The price in all stores is $4.99. Here it is on the publisher’s site, where you will be able to find links to everywhere that it’s available. (As an aside, any of you with a blog should take a look at Blog Into Book, an 1871 startup that can help you generate an e-book from a book-worthy string of posts on your blog.)

In the interest of full disclosure, I will publish this last post in its entirety around the end of the year. This series of posts is, well, a series of posts, and I certainly don’t want to penalize regular readers of the blog by withholding content. But the e-book is more than just the posts strung together — it is complete with some additional content, better segues, and a more continuous flow. So I’d encourage you to get it if you want to see my conclusion sooner rather than later or if you’d like to read the series as a single work.

Also, I’d like to thank Amanda Muledy for editing and illustrating the book, as she does with my site.


Intro to Unit Testing 7: Overcoming Inertia and Objections

In this series so far, I’ve introduced the concept of unit testing, talked about how to avoid early failures and frustrations, and then dived more in depth into the subject. But now that you’re familiar with the topic and reasonably well versed in it (particularly if you’ve been practicing over the course of this series), I’d like to use that familiarity to discuss why unit testing makes sense in terms that you now better understand. And beyond that, I’d like to discuss how you can use this sense to overcome inertia and even objections that others may have.

The Case for Unit Tests

Alright, so this is the part where I offer you a laundry list, right? This is where I say that unit tests improve code quality, document your code, exercise your API, promote (or at least correlate with) good design, help you break problems into manageable chunks, expose problems earlier when finding them is cheaper, and probably some other things that I’m forgetting right now. And I believe that all of these things are true. But after a number of years of faithfully writing unit tests and practicing test-driven development (TDD), I think that I can offer those as appetizers or footnotes in the face of the real benefit: they allow you to refactor your code without fear or hesitation.

First to Contend With: Inertia

Inertia could probably be categorized as an objection, but I’m going to treat it separately since it manifests in a different way. Objections to doing something are essentially counterarguments to it. They may be lame counterarguments or excellent counterarguments, but either way, they take an active position. Inertia doesn’t. It’s either ambivalence or passive-aggressive resistance. To illustrate the difference, consider the following exchanges:

Alice: We should start trying to get our code under test.
Bob: Unit testing is stupid and a complete waste of time.


Alice: We should start trying to get our code under test.
Bob: Yeah, that’d be nice. We should do that at some point.

The former is a strident (and obtuse) counterargument while the latter is an example of inactivity by inertia. In the second exchange, Bob either thinks unit testing is a good idea — but just not now — or he’s blowing sunshine at Alice while subtly saying, “not now,” so that she’ll leave him alone and stop stumping for change (i.e. the passive-aggressive approach).

In either case, the best way to overcome inertia is to counteract it with activity of your own. Inertia is the byproduct of the developer (and human in general) tendency to get stuck in a rut of doing the comfortable and familiar, so overcoming it within your group is usually just a matter of creating a new rut for them. This isn’t necessarily an easy thing to do. You’ll have to write the tests, make sure they stay up to date, demonstrate the benefits to anyone who will listen, and probably spend some time teaching others how to do it. But if you persevere and your only obstacle is inertia, sooner or later test writing will become the new normal and you’ll get there.

Red Herrings and Stupid Objections


Around a year ago, I blogged about a guy who made a silly claim that he wrote a lot of unit tests but didn’t check them in. The reasoning behind this, as detailed in the post, was completely fatuous. But that’s to be expected since the purpose of this claim wasn’t to explain a calculated approach but rather to cover a lack of knowledge — the knowledge of how to write unit tests.

This sort of posturing is the province of threatened Expert Beginners. It’s the kind of thing that happens when the guy in charge understands that unit testing is widely considered to be table stakes for software development professionalism but has no idea how it works. As such, he believes that he has to come up with a rationale for why he’s never bothered to learn how to do it, but he’s handicapped in inventing an explanation that makes sense by virtue of the fact that he has no idea what he’s talking about. This results in statements like the following:

  • Unit tests prevent you from adapting to new requirements.
  • Testing takes too much time.
  • It wouldn’t work with our style of writing code.
  • You’re not going to catch every bug, so why bother?
  • Writing all of your tests before writing any code is dumb.
  • Management/customers wouldn’t like it and wouldn’t want to pay for it.

I obviously can’t cover all such possible statements, but use the smell test. If it sounds incredible or stupid, it probably is, and you’re likely dealing with someone who is interested in preserving his alpha status more than creating good work product. To be frank, if you’re in an environment like that, you’re probably best off practicing your craft on the sly. You can write tests and keep quiet about it or even keep them in your own personal source control (I have done both at times in my career when in this situation) to prevent people from impeding your own career development. But the best longer term strategy is to keep your eyes and ears open for other projects to work on where you have more latitude to set policies. Do an open source project in your spare time, grab an opportunity to develop a one-off tool for your group, or maybe even consider looking for a job at an organization a little more up to speed with current software development practices. You can stay and fight the good fight, but I don’t recommend it in the long run. It’ll wear you down, and you’re unlikely to win many arguments with people that don’t let a lack of knowledge stop them from claiming expertise on a subject.

I Don’t Know How to Unit Test

With inertia and silliness set aside, let’s move on to legitimate objections to the practice. At first blush, you may be inclined to scoff at the objection, “I don’t understand it,” particularly in an industry often dominated by people unwilling to concede that their knowledge is lacking in the slightest bit in any way whatsoever. But don’t scoff — this is a perfectly reasonable objection. It’s hard and often unwise simply to start doing something with professional stakes when you don’t know what you’re doing.

If the people around you admit to not knowing how to do it, this earnest assessment often indicates at least some willingness to learn. This is great news and something you can work with. Start teaching yourself how to do it so that you can help others. Watch Pluralsight videos and show them to your coworkers as well. If your group is amenable to it, you can even set aside some time to practice as a group or to bring in consultants to get you off to a good start. This is an objection that can easily be turned into an asset.

It Doesn’t Work With the Way I Code

I originally specked out this post in the series because of a comment in the very first post, and this section is the one that addresses that comment. Arguments of this form are ones I’ve heard quite frequently over the years, and the particulars of the coding style in question vary, but the common thread is the idea that unit testing creates friction with an established routine. This isn’t the same as “I don’t know how to unit test” because the people who say this generally do know how to write tests — they must or else they wouldn’t know anything about the subject and would make up Expert-Beginner-style stupid excuses. It also isn’t the same as the inertia objection because they’re saying, “I was willing to try, but I find that this impedes me,” rather than, “meh, I dunno, I like my routine.”

My short answer to someone who has this objection is, to put it bluntly, “change the way you code.” Whatever the specifics of your approach, when you’re done, you don’t wind up with a fast-executing safety net of tests that you trust — tests that document your intentions, keep your code flexible, help prevent regressions, and force your design to be easy to use and decoupled. People who code differently than you do, in that they unit test, do wind up with those things. So figure out a way to be one of those people.

On a deeper level, though, I understand this objection because it hits closer to home. I was never the type to bluster like an Expert Beginner, nor am I prone in the slightest to inertia. (I am pretty much the opposite, frequently biting off more than I can chew.) The other objections never really applied to me, but this one did both prior to starting to write tests and prior to adopting TDD as my exclusive approach to developing. You can read that latter perspective from my very early days of blogging. Years ago, I chafed at the prospect of unit testing because spending the extra time took me out of the ‘flow’ of my coding, and I balked at TDD because I thought “why would I start writing unit tests for this code when it might be refactored completely later?” In other words, neither one of these worked with my approach.

But in both cases, I relented eventually and changed the way I coded. I didn’t just one day say, “well, I guess I’ll just start writing code differently from now on.” What happened instead was that I realized that a lot of really bright people and prominent names in the industry had coding and design styles that were compatible with writing tests so it was at least worth trying things their way. It wasn’t a matter of doing something because the cool kids were doing it or resolving to change my ways. Rather, I thought to myself, “I’ll see what all the fuss is about. Then, I’ll either like it or go back to my way of doing things armed with much better arguments as to why my way is better.” So I poured myself into a different way of doing things, forced myself to keep at it even though it was slow and awkward, and, wouldn’t you know it, I eventually came to prefer it.

Convincing people in your group to follow that lead is not going to be easy, but it is doable. The best way to do it is to earn their respect and show them results. If your code is cleaner and freer of bugs and your past projects are easy to adapt and modify, people are going to notice and ask you what your secret is, and you’ll be in a position to show them. It may seem improbable to you now, but you can go from being a person quietly teaching yourself to unit test on the side to one of the key leaders in a software department relatively quickly. You just have to commit yourself to continuous improvement and moving toward proven, effective techniques. Unit testing is just one such technique, but it is a powerful and important one.