Happy Friday, everybody. I’m still figuring this digest thing out, so please bear with me. But no matter how I iterate, what you’ll get is an aggregated link to posts that I’ve written for my Hit Subscribe business.
I’m thinking I’ll do picks each week as well as the digests. You know how podcast panelists do “picks” at the end of a lot of podcasts? I’ll give you some picks each week. At least, unless this turns out to be a bad idea, in which case, I’ll stop.
Jogging without headphones. For years, I’ve always doubled up on productivity by listening to podcasts or audio books while jogging, if not watching Pluralsight courses. But recently a terrible pair of bluetooth headphones (seriously, don’t buy them — shop around for a competitor) broke, and I just went jogging with my thoughts. It’s been a huge boost to the amount of creative thinking I do in a week.
I cannot rave enough about payroll service, Gusto. If you need to run payrolls for your business, these guys make it seriously easy, even paying taxes for your automatically. Before I switched, I’d been using Intuit’s online payroll, which was the user experience equivalent of a grizzly bear carrying a raccoon in a backpack and both of them are mauling you. Gusto restored my faith in humanity.
Every now and then, I get nostalgic for computer games from my childhood. When I do, abandonia usually has me covered.
The Post Digest
And now, the post digest.
I write a lot of posts about static analysis, since it’s something of a specialty of mine. Here’s another primer I did about it for TechTown training. In it, I evangelized a bit, encouraging readers to look past the really dull name and see that underneath it lies a cool concept.
In another NDepend post, I talk about a novel way to settle the inevitable squabbles among a development team. Make your arguments, and then prove them visually, using automated tooling to paint pictures of your codebase. My personal favorite for proving a point has always been the dependency death star.
And, finally, I wrote a post for Monitis trying to get a little more specific around the generalized and often hype-y term, “big data.” This post took a longer view, tracing a history of the concept back to the early days of Java and .NET.
Time for another installment of reader question Monday. Today, I’m going to answer a short and sweet question about how to deal with an “irksome” code reviewer. It’s both simple, and fairly open ended, making it a good candidate for a blog post.
How do you deal with peer code review and irksome coworkers? Any trick?
Okay, first things first. This could cover a lot of situations.
Theoretically, someone could be writing extremely problematic code and finding coworkers “irksome” simply for pointing that out. And, at the complete other end of the spectrum, the code may be fine but a toxic culture creates endless nitpicking.
So you must introspect and also think in terms of your goals. What is it that’s irking you, exactly, and what is the desired outcome?
I’ll frame the post roughly in terms of goals, and my advice for achieving them. Really, that’s the only way to do it, since code review processes vary so widely from team to team.
A Bit of Perspective on Code Reviews and Code Reviewers
Before going into any advice, let’s consider the subject of code review itself. There are two conceptual levels at play.
Obvious Level: A Practice with Demonstrable Benefit
A well-conducted code review process helps with code quality and it helps developers learn. In his book Code Complete, Steve McConnell cited a study that found “formal code inspection” to be the most effective defect prevention method.
This put it ahead of even automated unit tests in the study.
But, beyond that, code review has important human ramifications as well. People learn and share knowledge through this process.
And they use it to prevent the kind of defects that result in frustration for the team: rework, embarrassment and even a need to come in on weekends. People with a stake in the codebase get emotionally invested.
Subtle Level: Small Kings in Small Kingdoms
There’s also another, more subtle element at play, however.
I talk extensively about these terms in my book, Developer Hegemony, but you can read a brief primer here. Software developers (to my endless irritation) are pragmatists (line-level laborers) with almost no actual influence in the corporate world.
When you participate in the so-called “technical track,” you typically never have people reporting to you, earning only developmental titles that include things like “senior,” “tech lead,” and “architect.”
So often, the only simulacrum developers get of actual organizational power comes during interviews and code reviews. Decent human beings handle this well, looking to mentor and teach.
But there are a lot of less-than-decent human beings out there, who relish these opportunities to wield what little power they have. The phrase, “a little man with a little power” comes to mind.
Few things seem as institutional to the programming world as what I call the experience tuple. A company needs to hire someone to automate something, so, naturally, it asks the software development group to make alphabet soup for dice.com. “We need someone with (C#, XML, HTML, JS, ASP, MVC, REST, Angular, AJAX) with (React, MSTest, Moq, CSS) as plus.” Presumably then, polyglot applicants stand a better chance. But I’d argue that they also face something I’ll call the polyglot’s dilemma.
Hold on to your hats, programmers, because this will get counter-intuitive before it makes sense. With that in mind… where to start?
Problem Solvers and Problem Transformers
Well, perhaps categorizing hired software developers as problems makes for a good start. I don’t mean problems in a negative sense, but rather in the same vein as puzzles. A business hires software developers for some broader purpose. Maybe they work on internal automation that reduces operating expenses. Or perhaps they produce software sold as a good or service and add to top line revenue.
In either case, the business implicitly says “I need help increasing our profitability.” And you show up saying the following.
I have (8, 10, 10, 4, 6, 3, 1, 1, 0) years of (C#, XML, HTML, JS, ASP, MVC, REST, Angular, AJAX). Now while the rest of you figure out how to make use of me, I’ll be over here sharpening the saw with some code katas.
Whenever I’ve had management responsibility, I’ve subconsciously put people into two buckets. Problem solvers take a problem I have and make it go away. Problem transformers take a problem I have and solve it by bringing me the next problem. (I’m omitting non-performers who don’t solve problems at all as beyond the scope of this post.)
For instance, take the problem of a malfunctioning production server. A problem solver would go off and come back with a functioning production server, somehow. A problem transformer would come back, report that the problem was caused by a faulty power supply and ask what I wanted to do about that new problem.
As programmers, we behave as problem transformers. We present ourselves and our skill sets as problems in need of management solutions.
While out on a jog recently, I found myself listening to an episode of .NET Rocks, in which the discussion covered the surprising percentage of developers still using Winforms and the general topic of using licensed controls written by third parties. This started a train of thought in my head that might end in mild controversy, but I think it’s worth exploring a bit.
Two profiles (well, more like caricatures) of developer came to mind, standing in stark contrast to one another. First is this Winforms developer that is more or less cobbling together spare parts to build applications. He uses a WYSIWYG editor, employs some kind of “database form wizard” to bind a GUI widget directly to a table, plops a slew of obscure third party controls into the code, and ships some kind of Franken-app not actually involving much code. The second profile rounds out the dichotomy and consists of the foundational crafter. This person builds her own tools and controls using low level language constructs and the command line, and assembles these works of art into ever-higher layers of abstraction until shipping a hand-crafted app.
If I’m running a business, give me the first person.
Undoubtedly, the crafter harbors a better, more fundamental grasp of the principles of computer science, and she undoubtedly offers the most versatility. If she can build a compiler, use that to build a text editor, use that to build a source control system, use that to build a web server, and use that to build the sexiest, popping-ist, UX-friendliest website you’ve ever seen, she is the most employable, most full stackable programmer ever. The business will never encounter a situation beyond her grasp. But who cares, if the business just needs a checkbox added to a battleship gray, outdated Windows application?
I practice test driven development. I rail against the evils of copy and paste programming. I counsel clients on the dangers of technical debt and feature slow down. I advocate wholesale for clean code. And because of all these things, I understand that every single line of code you write is an incremental business liability. So why would I take the cobbler over the crafter? Don’t get me wrong — if I had to pick one of the two of them to write a given module, I would take the crafter. But for approach, I would take the cobbler because the cobbler makes most of the code someone else’s problem while the crafter makes it all my problem.
What I really want is someone with the chops of a crafter and the reluctance to write more code than necessary of a cobbler.
Three weeks, three reader questions. I daresay that I’m on a roll. This week’s question asks about what I’ll refer to as “how to de-brilliant your code.” It was a response to this post, in which I offered the idea of a distinction between maintainable code and common code. The lead-in premise was that of supposedly “brilliant” code, which was code that was written by an ostensible genius and that no one but said genius could understand. (My argument was/is that this is usually just bad code written by a self-important expert beginner).
The question is, as follows, verbatim.
In your opinion, what is the best approach to identify que “brilliant” ones with hard code, to later work on turn brilliant to common?
Would be code review the best? Pair programming (seniors could felt challenged…)?
Now, please forgive me if I get this wrong, but because of the use of “que” where an English speaker might say “which”, I’m going to infer that the question submitter speaks Spanish as a first language. I believe the question is asking after the best way to identify and remediate pockets of ‘brilliant’ code. But, because of the ambiguity of “ones” it could also be asking about identifying humans that tend to write ‘brilliant’. Because of this, I’ll just go ahead and address both.
Find the Brilliant Code
First up is identifying brilliant code, which shouldn’t be terribly hard. You could gather a quorum of your team together and see if there are pockets of code that no one really understands, or else you could remove the anchoring bias of being in a group by having everyone assess the code independently. In either case, a bunch of “uh, I don’t get it” probably indicates ‘brilliant’ code. The group aspect of this also serves (probably) to prevent against an individual not understanding simply by virtue of being too much of a language novice (“what’s that ++ after the i variable,” for instance, indicates the problem is with the beholder rather than the original developer).
But, even better, ask people to take turns explaining what methods do. If people flounder or if they disagree, then they obviously don’t get it, self-reporting notwithstanding. And having team members not understanding pockets of code is an ipso facto problem.
An interesting side note at this point is whether this illegible code is “brilliant” or “utter spaghetti” is going to depend a lot more on knowledge of who wrote it than anything else. “Oh, Alice wrote that — it’s probably just too sophisticated for our dull brains. Oh, wait, you were reading the wrong commit, and it’s actually Bob’s code? Bob’s an idiot — that’s just bad code.”
De-Brilliant The Codebase
Having identified the target code for de-brillianting, flag it somewhere for refactoring: Jira, TFS, that spreadsheet your team uses, whatever. Just make a note and queue it as work — don’t just dive in and start mucking around in production code, unless that’s a team norm and you have heavy test coverage. Absent these things, you’re creating risk without buy in.
Leave these things in the backlog for prioritization on the “eventually” pile, but with one caveat. If you need to be touching that code for some other reason, employ the boy-scout rule and de-brilliant it, as long as you’re already in there. First, though, put some characterization tests around it, so that you have a chance to know if you’re breaking anything. Then, do what you need to and make the code easy to read; when you’re done, the same, “tell me what this does” should be easy to answer for your teammates.
De-brillianting the codebase is something that you’ll have to chip away at over the course of time.
De-Brilliant The Humans
I would include a blurb on how to find the humans, but that should be pretty straightforward — find the brilliant code and look at the commit history. You might even be able to tell simply from behavior. People that talk about using 4 design patterns on a feature or cramming 12 statements into a loop condition are prime candidates.
The trick isn’t in finding these folks, but in convincing them to stop it. And that is both simple to understand and hard to do.
During my undergrad CS major many years ago, I took an intro course in C++. At one point, we had to do a series of pretty mundane, review exercises that would be graded automatically by a program (easy things like “write a for loop”). Not exactly the stuff dreams are made of, so some people got creative. One kid removed literally every piece of white space from his program, and another made some kind of art with indentations. When people are bored, they seek clever things to do, and the result is ‘brilliant’ code.
The key to de-brillianting thus lies in presenting them with the right challenge, often via constraints or restrictions of some kind. They do it to themselves otherwise — “I’ll write this feature without using the if keyword anywhere!”
The Right Motivation
Like I said, a simple solution does not necessarily imply an easy solution. How does one challenge others into writing the kind of straightforward code that is readable and maintainable?
Code review/pairing presents a possible solution. Given the earlier, “can others articulate what this does” metric, the team can challenge programmer-Einstein to channel that towering intellect toward this purpose. That may work for some, but other brilliant programmers might not consider that to be a worthwhile or interesting challenge.
In that case, automated feedback through static analysis might do the trick. FXCop, NDepend, SonarQube, and others can be installed and configured to steer things in the general direction of readability. Writing code that complies with all warning thresholds of such tools actually presents quite a challenge, since so much of programming is about trade-offs. Now, a sufficiently determined clever coder could still invent ways to write hard-to-read code, but that would be a much more difficult task when he’d get slapped by the tool for chaining 20 Linq statements onto a single line or whatever.
Of course, probably the best solution is to work with the sort of people who recognize that demonstrating their cleverness takes a backseat to being a professional. They can do that in their spare time.
If you have a question you’d like to hear my opinion on, please feel free to submit.