DaedTech

Stories about Software

By

How to Perform Effective Team Code Reviews

Editorial Note: I originally wrote this post for the NDepend blog.  You can check out the original here, at their site.  While you’re there, check out all of the new tech debt-related features in the newest version of NDepend.

I’ve heard people say (paraphrased) that teams succeed uniformly, but fail each in its own unique way.  While I might argue the veracity of this statement, it evokes an interesting image.  Many roads, lined with many decisions, lead to many different sorts of failures.

Code review presents no exception.  Teams can fail at code review in myriad, unique ways.  And, on top of that, many paths to broader failure can involve poor code reviews (doubtless among other things).

How can I assign such importance to the code review?  After all, many would consider this an ancillary team activity and one with only upside.  Done poorly, code review catches no defects.  Done well, it catches some defects.  Right?

How Code Review Can Go Wrong

Simply put, code review can have worse than zero effect.  Ineffectual code review suffers mainly the opportunity cost of the participants’ time.  But toxic code review creates morale problems, counterproductive team dynamics, and damaging distractions.

So the first order of business is to avoid a net negative effect.  To do this, one simply has to remove the potential of toxic culture from the process of code review.  Of course, that’s a bit easier said than done, but a lot of it just means following basic rules of human decency.  Start by treating one another with respect.  Then ensure that all participants feel comfortable getting and receiving feedback.  Enlist the help of even-tempered, charismatic folks to lead by example.

Once you’ve insulated yourself against the most damaging effects, it’s time to guard against ineffectual code reviews.  It is toward that end that I’ll be focusing for the remainder of this post.  Ineffectual code reviews can ways time, as I mentioned earlier.  But they can also create a false sense of security and lead to poor choices.

So what makes code review effective?  How can your team get the most out of this activity?  I’ll offer some thoughts based on firsthand experience across a wide number of organizations.

Read More

By

Don’t Just Flag It — Fix It!

Editorial Note: I originally wrote this post for the SubMain blog.  You can check out the original here, at their site.  While you’re there, download a trial of CodeIt.Right.

More years ago than I’d care to admit, I took a software engineering course as part of my graduate CS program.  At the time, I worked a full time job during the day and did remote classes in the evening.  As a result, I disproportionately valued classes with applicability to my job.  And this class offered plenty of that.

We scratched the surface on such diverse topics as agile methodologies, automated testing, cost of code ownership, and more.  But I found myself perhaps most interested by the dive we did into refactoring.  The idea of reworking internal structure of code while preserving inputs and outputs is a surprisingly complex one.

Historical Complexity of Refactoring

At the risk of dating myself, I took this course in the fall of 2006.  While automated refactorings in your IDE now seem commonplace, back then, they were hard.  In fact, the professor of the course considered them to be sufficiently difficult as to steer a group of mine away from a project implementing some.  In the world of 2006, I suspect he had the right of it.  We steered clear.

In 2016, implementing automated refactorings still presents a challenge.  But modern tool and IDE vendors can stand on the shoulders of giants, so to speak.  Back then?  Not so much.

Refactorings present a unique challenge to tool vendors because of the inherent risk.  They can really screw up users’ code.  If a mistake happens, best case scenario is that the resultant code fails to compile because then, at least, it fails fast.  Worse still is semantically and syntactically correct code that somehow behaves improperly.  In this situation, a refactoring — a safe change to code — becomes a modification to the behavior of production code instead.  Ouch.

On top of the risk, the implementation of refactoring anywhere beyond the trivial involves heady concepts such as abstract syntax trees.  In other words, it’s not for lightweights.  So to recap, refactoring is risky and difficult.  And this is the landscape faced by tool authors.

I Don’t Fix — I Just Flag

If you live in the US, you may have seen a commercial that features a funny quip.  If I’m not mistaken, it advertises for some sort of fraud prevention services.  (Pardon any slight inaccuracies, as I recount this as best I can, from memory.)

In the ad, bank robbers hold a bank hostage in a rather cliche, dramatic scene.  Off to the side, a woman stands near a security guard, asking him why he didn’t do anything to stop it.  “I’m not a robbery prevention service — I’m a robbery monitoring service.  Oh, by the way, there’s a robbery.”

It brings a chuckle, but it also brings an underlying point.  In many situations, monitoring alone can prove woefully ineffective, prompting frustration.  As a former manager and current consultant, I generally advise people that they should only point out problems when they have also prepared solution proposals.  It can mean the difference between complaining and solving.

So you can imagine and probably share my frustration at tools that just flag problems and leave it to you to investigate further and fix them.  We feel like the woman standing next to the “robbery monitor,” wondering how useful the service is to us.

Levels of Solution

Going back to the subject of software development, we see this dynamic in a number of places.  The compiler, the IDE, productivity ad-ins, static analysis tools, and linting utilities all offer us warnings to heed.

Often, that’s all we get.  The utility says, “hey, something is wrong here, but you’re going to have to figure out what.”  I tend to think of that as the basic level of service, or level 0, if you will.

The next level, level 1, involves at least offering some form of next action.  It might be as simple as offering a help file, inline reading, or a link to more information.  Anything above “this is a problem.”

Level 2 ups the ante by offering a recommendation for what to do next.  “You have a dependency cycle.  You should fix this by looking at these three components and removing one mutual dependency.”  It goes beyond giving you a next thing to do and gives you the next thing to do.

Level 3 rounds out the field by actually performing the action for you (following a prompt, of course).  “You’ve accidentally hidden a method on the parent class.  Click here to rename or click here to make parent virtual.”  That’s just an example off the top, of course, but it illustrates the interaction paradigm.  “We’ve noticed a problem and you can click here to fix it.”

Fixes in Your Tooling

When evaluating your own tools, look to climb as high up this hierarchy as you can.  Favor tools that identify problems, but offer fixes whenever possible.

There are a number of such tools out there, including CodeIt.Right.  Using tools like this is a pleasure, because it removes the burden of research and implementation from you.  Well, you can always do the research if you want, but at your own leisure.  But it’s much better to do research at your leisure than when you’re trying to accomplish something else.

The other, important concern here is that you find trusted tooling to help you with this sort of thing.  After all, you don’t want something messing with your source code if it might mess up your source code.  But, assuming you can trust it, this provides an invaluable boost to your effectiveness by automatically resolving your problems and by helping you learn.

In the year 2016, we have far more tooling available, with a far better track record, than we did in 2006.  Leverage it whenever possible so that you can focus on solving the pressing problems of your day to day work.

By

Turning Tech Hobbies into Side Hustle

I just dug up a tweet I made about 4 years ago.  I did this because I remembered saying it, and because it perfectly illustrates a distinction I’m going to make today.  Specifically, I’ll talk about the distinction between technical hobbies and side hustle.  And, I’ll then advocate for side hustle.  But first, the tweet.

Quick and to the point.  The year was 2013, and, during the course of yet another oppressive Chicago winter, I wanted to learn F#.  At the time, I ran an IT department as the CIO for a company, and I had come to miss writing code.  So, I took to Twitter and threatened to teach myself yet another programming language.

I’m embarrassed about this tweet, in a sense.  You might think the fact that I never wound up learning F# embarrasses me.  But no, I’ll get over that.  Rather, the undirected, goalless nature of the sentiment embarrasses me.  It does in the context of career, anyway.

Programming Hobbies

Before I go any further, I want to talk about the idea of hobbies and career.  At times, I’ve enjoyed hobbies, such as guitar playing, cooking, and home improvement, among others.  Given that I’ve historically earned my living in software development, nobody would confuse these hobbies with career plays.

The line blurs a bit with certain other considerations, however.  For instance, I could have regarded writing as a hobby for a good bit of my career.  These days, however, people explicitly pay me to write in various capacities.  This kind of knocks writing out of the realm of pure hobby for me.  And then there’s time you spend outside of work doing what you do for a living.  Let’s say, going home to learn F#.  It doesn’t pay your bills, but you can file it under the heading of “sharpening the saw.”  Sure, my job may not call for F#, but it makes me a better programmer (and, a better CIO, I guess).  So it counts as career-something.  Right?

Actually, I would now argue that no, it does not.  Had I gone home to learn F#, for the sake of learning F#, I would have engaged in a hobby rather than a career play.  You can’t just blindly count something tangentially related to stuff you do for a wage as career improvement.  And yet, we do that.  A lot.

Read More

By

Two Flavors of Technical Opportunists: Missionaries and Mercenaries

“Missionaries and mercenaries” has a pretty intriguing ring to it, huh?  I wish I could claim credit for it, but I heard about it on this podcast with Ribbonfarm creator Venkat Rao.  Apparently, entrepreneurs use this pithy phrase to make a distinction among themselves.  I’ll explain in more detail shortly.

First, however, I’d like to do a bit of explanatory housekeeping.  In the coming months, I’m going to make some changes to my life.  Specifically, I plan to wind down the management consulting in favor of creating content (products) and offering productized-services.  This may sound a little crazy to you.  It would have sounded crazy (or naive) to me up until a few years ago.  Why trade a high profile consulting career for… an unknown?  So I want to explain myself before I lose sight of the fact that I might need to explain that to people.

On “Trading Hours for Dollars”

I’ll tell a quick story to clarify.  A few years back, I’d decided to leave a CIO position in favor of consulting as a free agent (which may also sound crazy, but it worked out).  As I looked to build my book of business, I was chatting with fellow Pluralsight author John Sonmez about the jump he had made away from full time employment.  He said something during that conversation that I’ll never forget, when I asked him about how he finds consulting work.

“To be honest, I’m trying to get away from trading hours for dollars.”

When you listen to the podcasts I listen to, read the books I read, and talk to the people I talk to, you’ll hear this a lot.  At the time, however, I had never heard anyone say that.  I probably replied with something noncommittal like, “oh, that’s awesome, man.”  Meanwhile, I recall thinking to myself, “I don’t even… wat?”

These days, I completely get it.  Back then, I didn’t.  And so I want to start bridging the gap before the curse of knowledge consumes me and I just assume that everyone shares my perspective on hourly work and the corporate condition.

Developer Hegemony launches on May 2nd, and people have been asking me what comes next.  Well, among other things, I plan to pursue a line of business wherein I help support people executing their plan to achieve developer hegemony.  But before I can do that, I have some mental groundwork to lay.  And that brings me back to missionaries and mercenaries.

Opportunist Escapees

If you’ve only recently come to read my blog, understand that I mean something deeper than the dictionary definition when I talk about “opportunists.”  I explain in depth in this post, but this graphic should suffice.

Most simply, opportunists are those who maneuver their way to the top of the pyramid-shaped corporations.  The C-suite consists exclusively of these folks, but you’ll also find them at all levels of the organization.  I think of those working their way up as “ascendant opportunists.”

But wherever you find them in the corporate hierarchy at the moment, you’ll find that all of them have ceded good faith with the organization.  In other words, opportunists ascend rapidly by coming to understand the essential bankruptcy of the corporate advancement narrative.  They arrive at their positions and status through the lonely recognition that the normal corporate rules are for the idealists and pragmatists around them.  They chuckle internally, behind a careful poker face, at the notion that companies can have such things as “missions” and “values.”

If you really want to dive deep into the psyche of the opportunist, my book talks about this archetype and the other players in detail.  For our purposes here, I want to talk about what happens to these players when they exit the game.  (And make no mistake, they’re the only ones who ever do this side of retirement.)  What fates await opportunists that exit pyramid-shaped corporate life?

Read More

By

So, You’ve Inherited a Legacy Codebase

Editorial Note: I originally wrote this post for the SubMain blog.  You can check out the original here, at their site.  While you’re there, have a look around at some of the other posts and sign up for the feed.

During my younger days, I worked for a company that made a habit of strategic acquisition.  They didn’t participate in Time Warner style mergers, but periodically they would purchase a smaller competitor or a related product.  And on more than one occasion, I inherited the lead role for the assimilating software from one of these organizations.  Lucky me, right?

If I think in terms of how to describe this to someone, a plumbing analogy comes to mind.  Over the years, I have learned enough about plumbing to handle most tasks myself.  And this has exposed me to the irony of discovering a small leak in a fitting plugged by grit or debris.  I find this ironic because two wrongs make a right.  A dirty, leaky fitting reaches sub-optimal equilibrium and you spring a leak when you clean it.

Legacy codebases have this issue as well.  You inherit some acquired codebase, fix a tiny bug, and suddenly the defect flood gates open.  And then you realize the perilousness of your situation.

While you might not have come by it in the same way that I did, I imagine you can relate.  At some point or another, just about every developer has been thrust into supporting some creaky codebase.  How should you handle this?

Read More