Things I Can't Have

Whenever I start on a new team, there's one thing I want and never get. I'm not a betting man, but I've even bet that this thing I want won't happen. I've never lost that bet.

When I started writing the new Test::Harness, I had a .perltidyrc file which, while not perfect, allowed me to easily format my code with the following vim mappings:

nnoremap ,pt  :%!perltidy -q<cr> " only work in 'normal' mode
vnoremap ,pt  :!perltidy -q<cr>  " only work in 'visual' mode

These were glorious. I could tidy an entire file, or just a section (very useful when working with DBIx::Class::Schema::Loader). It made life on Test::Harness pleasant. In fact, sometimes there would be discussions about whether or not my .perltidyrc was good. One contributor to the project was very vocal about the need to change the tidy config. I was adamant that I wouldn't for one simple reason: if I'm working on your project, I will follow your formatting guidelines. If you're working on my project, you'll follow mine.

That's why I always want the formatting to be automated. Aside from making this happen in Test::Harness (and Andy Armstrong, the current maintainer, happily follows this), I've never convinced a team at work to implement it. Why? You won't believe how stupid the answer is, but ... well, yes you will believe how stupid the answer is.

No team I've ever worked with has accepted automated formatting because it's not perfect. That is to say, it's not perfect for their style of perfect. If they can't have it exactly their way, they'll take nothing, thank you. There's a saying that you shouldn't let perfect be the enemy of the good, but for some reason, people just won't accept this for code format standards. It gets so ridiculous that one overzealous developer tried writing a PPI-driven post-processor to fix curly braces exactly how he wanted them. Naturally, it failed horribly on common cases and, again, automated code formatting was abandoned because it couldn't be perfect (and I won a £5 pound bet with our team lead over that one).

So why am I ranting about this? Here's the code I'm looking at right now:

$self->add_link( VersionTypeVersion => [
         { version_id    => "Version2",
     version_type_id => "signed",
         },
     ] );
$self->add_link( VersionTypeVersion => [
         { version_id    => "Version2",
     version_type_id => "Original",
         },
     ] );

$self->add_data( Guidance => [
         { id => 'L2',
      short_description => 'contains strong language',
         },
         { id => 'L3',
     short_description => 'really dull',
         },
     ] );

(Update: ironically, that little monstrosity above apparently is an interesting side effect of the "tabs versus spaces" wars and some people having editors which automatically "fix" this problem.)

The point of automating your code formatting isn't to satisfy your personal whims on how code should look. It's to standardize the code formatting so that developers can look at code and more quickly grok its meaning and not having a hodgepodge of different styles. I might hate your 3 character indentation, but if it's your project, I'm going to follow it. More than once I've had inconsistent formatting lead me astray because I didn't read the code as carefully as I could. For example, how quickly can you spot this bug?

$self->add_ondemand({
  brand => 'Hardtalk',
  sort_title => 'brown',
  title => 'What does Gordon Brown think of free votes?',
  schedule_date => $schedule_date,
  start => '2008-03-26T18:00:00',
  end  => '2008-03-2618:30:00',
  scheduled_start => DateTime->now->subtract( days => 1 ),
  scheduled_end => DateTime->now->add( days => 6 ),
  category_id => '9200005',
});

Compare:

$self->add_ondemand({ 
  brand           => 'Hardtalk',
  sort_title      => 'brown',
  title           => 'What does Gordon Brown think of free votes?',
  schedule_date   => $schedule_date,
  start           => '2008-03-26T18:00:00',
  end             => '2008-03-2618:30:00',
  scheduled_start => DateTime->now->subtract( days => 1 ),
  scheduled_end   => DateTime->now->add( days => 6 ),
  category_id     => '9200005',
});

I can see the bug much faster in the second version. In fact, there's a darn good chance I'll see it before I even run the code.

11 Comments

Just as a note: if the bug is supposed to be the missing 'T' in the second example, then it's no surprise it's hard to find it in the first one, since it isn't there :)

IS there a bug in the first code block? I see something wrong with the 'end' value in the second block, but it's not wrong in the first block...

We're trying to make this work in Padre.

Padre supports project-specific Perl::Tidy configurations, and should at some point should be able to automagically spot that you are editing something in a project with different tidy settings to your personal settings, and then (potentially forcefully) apply those to the current file instead of your personal preferences.

This isn't exclusive to code formatting. People only seem to trust automatic tools (in general) if they make no mistakes. That's why we're not going to see driverless cars for a while.

I do think, though, that forcing a code policy using perltidy is trying to solve a culture problem only with technology and that usually doesn't work.

From my own experience, talking to people yields much better results than shoving perltidy (or Perl::Critic) rules down their throat.

At one place I've worked, we actually had perltidy run automagically on commit. I didn't agree with all the tidying rules we applied, but they were sane enough that I couldn't be bothered to "untidy" to my person style when I checked code out.

As well as makign the code easier to read, it also makes diffs smaller and so easier to read and review.

Have you actually discussed this with people here? Cos it would get my whole-hearted support.

@Nilson

People only seem to trust automatic tools (in general) if they make no mistakes.

I really don't find that to be true. What I see is people will use an automated tool if it saves time. Perltidy is not perfect but the time I spend fixing perltidy over the time it saves me is enormous.

That's why we're not going to see driverless cars for a while.

That metaphor is a bit hyperbolic. Formatting code doesn't require the accuracy of driving where life and death come into play.

I do think, though, that forcing a code policy using perltidy is trying to solve a culture problem only with technology and that usually doesn't work.

It's more about project efficiency than a cultural problem. Inter-developer communication becomes more efficient when people are using the same code standards. Using an automated tool saves time and frustration by reducing the learning curve.

As we are learning from agile methodologies automating the processes that can be automated saves time and pain.

From my own experience, talking to people yields much better results than shoving perltidy (or Perl::Critic) rules down their throat.

Talking to someone about the value of code standards and automating that process are two different things. The former being a management/cultural issue and the latter is an automated tool.

A big part of the problem with PerlTidy, I think, is that it’s an all-or-nothing proposition.

It would be nice if it were possible to get it to tidy up some very clear non-controversial cases (eg. badly formatted hash table literals as in Ovid’s example) without necessarily having it standardise all other aspects of formatting.

That way you could argue for some big-impact normalisations without forcing everyone to buy into all group preferences 100%, and thus avoid the political quagmire for those bits that really help.

Perltidy is a very nice and useful tool, but I would never want the formatting to be automated, because

a) any formatting can be read equally easily as long as it is "reasonable". Of course there are some golden rules, like aligning the arrows, as demonstrated in your example; but for other things like indentation wars, I really don't care. In our team some people indent at 2, some people at 4, and it's not a problem.

b) there are always some places where a human decision is better than an automated tool. For example there are various ways to align the ternary operator ..?..:.., and the proper alignment often depends on the context (how many ?: in a row, how long the operands are, etc.). For another example, I often have some tabular datastructures embedded in code (dispatch tables, decision tables, lists of arrayrefs of qw/../, etc.) and by carefully designing the source layout, the datastructure becomes more immediate to read -- see for instance http://cpansearch.perl.org/src/DAMI/Games-Pentominos-1.0/lib/Games/Pentominos.pm

c) code readeability is much more impacted by factors not detected by any automatic tool (like choosing proper names for variables and methods, giving names to intermediate results instead of chaining dozens of lines of complex expressions, etc.)

d) if you give many rules, people in the team may consider them as an end goal, instead of a begin goal : as soon as the rules are satisfied, they feel they have done the job, and forget to think further if something more can be done to improve readability.

@dami

You picked a fairly simple example of 2v4 indent, but simple indentation is not where the problem usually ends. I have been maintaining legacy code for most of my career and that is not what happens in real life. Often you'll get 3, 4 or more different indenting styles, no alignment, and single line overload. Perltidy handles these (and others) almost instantaneously. Before perltidy I would often spend more time formatting code so I could read it before I could fix the bug (and I am not being prissy here, I doubt anyone could read that unformatted code without issues).

No one is saying that variable naming (self-documenting code) isn't a bigger part of writing maintainable code than code formatting, but the structure of code aides skimming and identifying flow control. Keeping it consistent across a project is helpful in getting new members of the team familiar with the code as soon as possible and current members get familiarity. Self-documentenation and other aspects of maintainable code can't be automated, but this (for the most part) can - enjoy the time savings and grab a frosty beverage afterwards.

As for d): I think you have a dim view of developer intelligence, if you think any decent developer would confuse code formatting/standards with the end goal. If the project's team feels it's draconian then the problem is buy-in (management) not the tool.

No one is saying perltidy is perfect. And I do occasionally fix what perltidy does for better readability, but you're getting into a baby/bathwater condition.

Leave a comment

About Ovid

user-pic Freelance Perl/Testing/Agile consultant and trainer. See http://www.allaroundtheworld.fr/ for our services. If you have a problem with Perl, we will solve it for you. And don't forget to buy my book! http://www.amazon.com/Beginning-Perl-Curtis-Poe/dp/1118013840/