DaedTech

Stories about Software

By

Surviving Software Heroes

There’s an entertainer named Garrison Keillor who talks about the fictional town of Lake Wobegon.  At the end of live monologues on this subject, he ‘signs off’ with the following summation.

Well, that’s the news from Lake Wobegon, where all the women are strong, all the men are good looking, and all the children are above average.

Heroes of Software

Most of our life is spent in search of a place where all of the children are above average — a place where we can all grow up to be heroes.  Society idolizes its ready-made heroes: royalty, athletes, celebrities, and even, to some lesser extent, great thinkers, executives, and artists.  There are also situational, role-based heroes, such as first responders or even people who perform some bit of heroism in a pinch, such as pulling a potential drowning victim from an icy lake.  The key here is specialness.  Heroes are special.

For the rest of us ordinary mortals that don’t knock in World Series clinching home runs or play home run hitters in movies, we’re left to manufacture our own specialness narratives.  Smartest lady in the room?  The guy with the legendary collection of beer steins from each year’s Oktoberfest?  Sometimes you have to dig pretty deep to find a venue in which you’re significantly above average.  It is to this need that I attribute hardcore conspiracy theorists and people who fret endlessly about organic food, holistic medicine and ‘ancient’ treatments — being in possession of some kind of uncommon knowledge that the ‘sheeple’ lack is a path to specialness, if not heroism, per se.

We have heroes in the software world.  They’re the ones with encyclopedic knowledge of the domain and the existing code base.  They’re the ones who are known for being reliable when the chips are down — getting in early, staying late, and coming through in the clutch with a put-upon, but satisfied expression.  They make project managers swoon and gush during their academy award speeches.  They come in late sometimes and leave early other times, when there isn’t delivery pressure, because they’re trusted with the special privileges that fall to A players on teams.  But they do it knowing that, at any moment, they might need to swoop in and take over entirely while the rest of the team twiddles their thumbs and gets out of the way.

SuperDev

And you know what?  They love it.  Because in the narrow scope defined by their cube farm, they are heroes.  They are Michael friggin’ Jordan.  They’ve found their specialness in life. Read More

By

Subtle Naming and Declaration Violations of DRY

It’s pretty likely that, as a software developer that reads blogs about software, you’ve heard of the DRY Principle. In case you haven’t, DRY stands for “Don’t Repeat Yourself,” and the gist of it is that there should only be one source of a given piece of information in a system. You’re most likely to hear about this principle in the context of copy-and-paste programming or other, similar rookie programming mistakes, but it also crops up in more subtle ways. I’d like to address a few of those today, and, more specifically, I’m going to talk about violations of DRY in naming things while coding.

DRY

Type Name in the Instance Name

Since the toppling of the evil Hungarian regime from the world of code notation, people rarely do things like naming arrays of integers “intptr_myArray,” but more subdued forms of this practice still exist. You often see them appear in server-templated markup. For instance, how many codebases contain text box tags with names/ids like “CustomerTextBox?” In my experience, tons.

What’s wrong with this? Well, the same thing that’s wrong with declaring an integer by saying “int customerCountInteger = 6.” In static typing schemes, the compiler can do a fine job of keeping track of data types, and the IDE can do a fine job, at any point, of showing you what type something is. Neither of these things nor anyone maintaining your code needs any help in identifying what the type of the thing in question is. So, you’ve included redundant information to no benefit.

If it comes time to change the data type, things get even worse. The best case scenario is that maintainers do twice the work, diligently changing the type and name of the variable. The worst case scenario is that they change the type only and the name of the variable now actively lies about what it points to. Save your maintenance programmers headaches and try to avoid this sort of thing. If you’re having trouble telling at a glance what the datatype of something is, download a plugin or a productivity tool for your IDE or even write one yourself. There are plenty of options out there without baking redundant and eventually misleading information into your code.

Inheritance Structure Baked Into Type Names

In situations where object inheritance is used, it can be temping to name types according to where they appear in the hierarchy. For instance, you might define a base class named BaseFoo and then a child of that named SpecificFoo, and a child of that named EvenMoreSpecificFoo. So EvenMoreSpecificFoo : SpecificFoo : BaseFoo. But what happens if during a refactor cycle you decide to break the inheritance hierarchy or rework things a bit? Well, there’s a good chance you’re in the same awkward position as the variable renaming in the last section.

Generally you’ll want inheritance schemes to express “is a” relationships. For instance, you might have Sedan : Car : Vehicle as your grandchild : child : parent relationship. Notice that what you don’t have is SedanCarVehicle : CarVehicle : Vehicle. Why would you? Everyone understands these objects and how they relate to one another. If you find yourself needing to remind yourself and maintainers of that relationship, there’s a good chance that you’d be better off using interfaces and composition rather than inheritance.

Obviously there are some exceptions to this concept. A SixCylinderEngine class might reasonably inherit from Engine and you might have a LoggingFooRetrievalService that does nothing but wrap the FooRetrievalService methods with calls to a logger. But it’s definitely worth maintaining an awareness as to whether you’re giving these things the names that you are because those are the best names and/or the extra coupling is appropriate or whether you’re codifying the relationship into the names to demystify your design.

Explicit Typing in C#

This one may spark a bit of outrage, but there’s no denying that the availability of the var keyword creates a situation where having the code “Foo foo = new Foo()” isn’t DRY. If you practice TDD and find yourself doing a lot of directed or exploratory refactoring, explicit typing becomes a real drag. If I want to generalize some type reference to an interface reference, I have to do it and then track down the compiler errors for its declarations. With implicit typing, I can just generalize and keep going.

I do recognize that this is a matter of opinion when it comes to readability and that some developers are haunted by the variant in VB6 or are reminded of dynamic typing in Javascript, but there’s really no arguing that this is technically a needless redundancy. For the readability concern, my advice would be to focus on writing code where you don’t need the crutch of specific type reminders inline. For the bad memories of other languages concern, I’d suggest trying to be more idiomatic with languages that you use.

Including Namespace in Declarations

A thing I’ve seen done from time to time is fully qualifying types as return values, parameters, or locals. This usually seems to occur when some automating framework or IDE goody does it for speculative disambiguation in scoping. (In other words, it doesn’t know what namespaces you’ll have so it fully qualifies the type during code generation to minimize the chance of potential namespace collisions.) What’s wrong with that? You’re preemptively avoiding naming problems and making your dependencies very obvious (one might say beating readers over the head with them).

Well, one (such as me) might argue that you could avoid namespace collisions just as easily with good naming conventions and organization and without a DRY violation in your code. If you’re fully scoping all of your types every time you use them, you’re repeating that information everywhere in a file that you use the type when just once with an include/using/import statement at the top would suffice. What happens if you have some very oft-used type in your database and you decide to move it up a level of namespace? A lot more pain if you’ve needlessly repeated that information all over the place. Perhaps enough extra pain to make you live with a bad organization rather than trying to fix it.

Does It Matter?

These all probably seem fairly nit-picky, and I wouldn’t really dispute it for any given instance of one or even for the practices themselves across a codebase. But practices like these are death by a thousand cuts to the maintainability of a code base. The more you work on fast feedback loops, tight development cycles, and getting yourself in the flow of programming, the more that you notice little things like these serving as the record skip in the music of your programming.

When NCrunch has just gone green, I’m entering the refactor portion of red-green-refactor, and I decide to change the type of a variable or the relationship between two types, you know what I don’t want to do? Stop my thought process related to reasoning about code, start wondering if the names of things are in sync with their types, and then do awkward find-alls in the solution to check and make sure I’m keeping duplicate information consistent. I don’t want to do that because it’s an unwelcome and needless context shift. It wastes my time and makes me less efficient.

You don’t go fast by typing fast. You don’t go fast, as Uncle Bob often points out, by making a mess (i.e. deciding not to write tests and clean code). You really don’t go fast by duplicating things. You go fast by eliminating all of the noise in all forms that stands between you and managing the domain concepts, business logic, and dependencies in your application. Redundant variable name changes, type swapping, and namespace declaring are all voices that contribute to that noise that you want to eliminate.

By

Discoverability Instead of Training and Manuals

Documentation and Training as Failures

Some time back, I was listening to someone explain the finer points of various code that he had written when he lamented the lack of documentation and training available for prospective users of this code. I thought to myself rather blithely and flippantly, “why – just write the code so that documenting it and training people to use it aren’t necessary.” I attributed this to being in a peevish mood or something, but reflecting on this later, I thought earnestly, “snarky Erik is actually right about this.”

Think about the way software development generally goes, especially if you’re developing code to server as a framework or utility for teammates and other developers. You start off with clean code and good intentions and you hammer away at making some functional software. Often things go well, but here and there you hit snags and you do a bit of duct-taping and work-around-ing (working around?), vowing to return later to straighten things out. Sometimes you do just that, but other times you realize that time and budget are finite resources for the effort and you reconcile with shipping something that’s not quite perfect.

But you don’t just ship something imperfect, because you’re diligent and responsible. What do you do instead? You go into those nasty areas of the code and you write inline comments, possibly containing apologies. You make sure that the XML/Java doc comments above the methods/classes are quite thorough as well and, for good measure, you probably even writeup some kind of manual or Word document, perhaps with a Visio diagram. Where the code is clear, you let it speak for itself and where it’s less than clear, you document.

We could put this another, perhaps more blunt way: “we generally try to write clean code and we document when we fail to do so.” We might reasonably think of documentation as something that we do when our work and intentions fail to speak for themselves. This seems a bit iconoclast in the face of conventional methods of communicating and processing information. I grew up as a programmer reading through the “man pages” to understand all manner of *Nix command line utilities, system calls, etc. I learned the nitty-gritty of how concepts like semaphores, and IPC and threading worked in this fashion so it seems a bit blasphemous, even to me, to accuse the authors of these APIs at failing to be clear or, really, failing in any way.

And yet, here we are. To be clear, I don’t think that writing code for which clients need to read manuals is a failure of design or of correctness or of a project or utility on the whole. But I do think it’s a failure to write self documenting code. And I think that for decades, we’ve had a culture in which this wasn’t viewed as a failure of any kind. What are we chided to do when we get a new appliance or gadget? Well, read the manual. There’s even an iconic acronym of exasperation for people who don’t do so prior to asking questions: RTFM. In the interest of keeping the blog’s PG rating, I won’t say here what it stands for. In this culture, the engineering particulars and internal mechanisms of things have been viewed as unknowable mysteries and the means by which communication is offered and understanding reached is large and often formidable manuals with dozens of pages of appendices, notes, and works cited. But is that really the best way to do things in all cases? Aren’t there times where it might be a lot better to make something that screamed how it should be used instead of wasting precious time?

Lifejacket_Instructions

Image courtesy of “AlMare” via Wikimedia Commons

A Changing Culture

An interesting thing has happened in recent years, spurred on largely by Apple, initially, and now I’d say by the mobile computing movement in general, since Google and Microsoft have followed suit in their designs. Apple made it cool to toss the manual and assume that it is the responsibility of the maker of the thing, rather than the user, to ensure that understanding is reached. In the development world, champions of clean, self-documenting code have existed prior to whatever Apple might have been doing in the popular market, but the concept certainly got a large, public boost from Apple and its marketing cachet and those who subsequently got on board with the movement.

Look at the current state of applications being written. This fall, I had the privilege of attending That Conference, Dotnet Rocks Edition and seeing Lwin Maung speak about mobile concepts and the then soon-to-be-released Windows 8 and its app ecosystem. One of the themes of the talk was how apps informed you of how to use them in intuitive ways. You didn’t read a manual to know that the news app had additional content — it told you by leaving the next story link halfway off the side of the screen, practically begging you to paw at it and scroll to the side. The idea of Windows with lots of headers at the top from which you can drill hierarchically into the application is gone and being replaced instead by visual cues that are borderline impossible to screw up.

As this becomes popular in terms of user experience, I submit that it should also become popular with software development. If you find yourself writing some method with the signature DoStuff(bool, bool, int, bool, string, bool) you’ll probably (hopefully) think “man, I better document this because no one will ever figure it out.” But I ask you to take it a step further. If you have the time to document it, then why not spend that time fixing it instead of explaining yourself through documentation? Rename DoStuff to describe exactly what stuff it does, make the parameters significantly fewer, get rid of the Booleans, and make it something that’s pretty much impossible to misunderstand, like string.RemoveCharactersFromTheEnd(6). I bet you don’t need multiple appendices or even a manual to figure out what that does.

Please note that I’m not suggesting that we toss out all previous ways of doing things or stop documenting altogether. Documentation certainly has a time and a place and not all products or APIs are ones that lend themselves to being completely discoverable. What I am suggesting is that we change our culture as developers from “RTFM!!!!” to “could I have made that clearer?” We’ve come a long way as the discipline of programming matures and we have more and more stakeholders who are less and less technical depending on us for more and more things. Communication is increasingly important and communication on clear, broadly understandable terms at that. You’re no longer writing methods being consumed by a handful of fellow geeks that are using your code to put together a BBS about how to program in COBOL. You’re no longer writing code where each byte of memory and disk space is precious so it’s far better to be verbose in voluminous manuals than method or variable names. You’re (for the most part) no longer writing code where optimizing a few cycles trumps readability. You’re writing code in a time when terms like “agile” and “maintainable” reign supreme, there’s no real cost to self-describing code, and the broader popular in general expect their technology to be discoverable. It’s a great time to be a developer — embrace it.