Thursday, April 30, 2009

Velocity

I just wanted to enshrine these words of Kent Beck before they're lost in the aether. Read carefully:


Another purpose of measuring capacity is to improve throughput. If you plan for less than your capacity, you get less done than you could have. If you plan for more than your capacity, you get less done than you could have.

Having a plan with "enough" work in it less some slack to improve the probability of meeting commitments increases the amount of work that gets done compared to planning for too much or too little.

Another C word (Convenience)

Corey Haines recently posted a note to the software craftsmanship mailing list about definable process.

What I love is the repetition of the phrase
choosing the 'most convenient' place to put the
code, rather than where it actually makes sense


I have fallen victim to this. Rather than trudge through the code to make something explicit, we looked for the most convenient point of code insertion. Even while my partner and I talked about how it felt too implicit and a little "clever", we tried anyway hoping it would save us the cost of tracking down the places where the code was needed.

It turned out to be too clever by half (at least) and got us into a mess of indirect recursion and ugliness. Eventually we figured out how to have the compiler & tests tell us where the code was used so we could make changes explicit in their context, and this took us all of an hour maybe. It was a small cost, and left us with a more explicit answer.

Of course, it also meant that some code was now being called in seven or eight places instead of one. As we made this change, it didn't seem quite DRY enough, but it was explicit and clear and worked. Lacking the imagination and time to figure out how to make it more DRY without sacrificing the clarity, we left it. We may get to revisit it at some time, we may not. But the code is working, it is explicit, it expresses itself well, and it has tests. We could do worse.

I think Corey Haines nailed this one. Read his post. There is undeniably a siren's song calling us to put code in the most convenient (however implicity) places in the code instead of putting it where it makes the most sense. And, as Wally remarked in his response to "The C Word", sometimes people scatter clever code around the project instead of going through the inconvenience of building it a place to live.

Convenience already has a pejorative sense, due to the Dana Carvey's SNL "church lady" character. I suppose all day I'll hear his/her voice in my head saying "Isn't that conveeeeeeenient?" and sometimes "Isn't that special?"

Monday, April 27, 2009

Rethinking The C Word (clever)

A friend rightfully takes me to task:
The anti-cleverness you describe is anti-badness. I think we all can agree that bad is bad. But you and most of the other anti-clever crusaders have no definition for it other than it made your life miserable or you at least don't like it.

And then you assume someone you never met thought they were being smart. That's where your ice gets really thin. You weren't there and you don't know what the constraints were at the time.

And what really makes it irksome is that you have a whole library of well defined "bad code smells" which are a lot more specific. Why don't you use those? Those have meaning and in many cases they have remedies.

It comes across as smug blaming of the guy who left, and dirties what I've observed is an otherwise a healthy data driven approach.

See, I like it when my friends help me keep it honest and real. If one wants to improve, one must remain introspective and consider feedback when it is given. Desiring to be both wise and pleasant some day, I thank my friend for this rebuke.

I should not assume that someone is proud of the way this code turned out, or that they did it to satisfy their own ego. That is as at least as likely as not to be unfair and wrong... and smug.

I'd not heard of the Anti-Cleverness Crusade before. I feel less lonely in my smug, opinionated jerkitude. I thought it was just me, Wally, and occasionally UncleBob. I wonder if there are membership dues. Or tee shirts. I could use a tee shirt.

When David Tennant as Dr. Who says "clever", I know he means "ingenious." Ingenuity can be wonderful or it can be awful, or perhaps wonderfully awful. In the series, the enemy is generally "clever" in the sense of being "ingenious" and "diabolical."

A bit of research (*cough*google*cough*) and I find something that reflects the sense I'm hoping to convey. Rube Goldberg's self-operating napkin is certainly clever, and ingenious. From the article:
A Rube Goldberg machine or device is any exceedingly complex apparatus that performs a very simple task in a very indirect and convoluted way.
When I say "clever" I am referring to misspent ingenuity. It is intelligence gone wrong.

I don't know a good word that says "unwanted, wasteful, vulgar ingenuity". My friend Wally simply said "clever" with that clearly pejorative inflection. It stuck with me. I have carried it for some years, and have spread the use of the term. I'm sure Wally picked it up somewhere as well. Having some handle for the idea has been helpful. I can't tell you how many times I've rethought some bit of work because it might be (in this sense) "clever."

It is not merely "bad". If it were bad, the code would not function correctly. The NOT (A XOR B) is a small thing, and I figured it out with a short pause, so it's not opaque or indecipherable. It has only two operators (where one is sufficient, so 200% overdesign). It does the right thing provided A and B are booleans and implemented in the expected fashion. It *works*. That makes "badness" a difficult call.

The term fragile doesn't properly apply though the code invites misunderstanding. It doesn't depend upon conditions not algorithmically guaranteed in the code around it. It doesn't have a set of values within the domain of the parameters that will provide undefined behavior. It's wrong, just silly.

My issue with the !(A^B) code is that it is indirect and convoluted. One has to run the truth table in his head. Knowing that T^T is false, and F^F is false, and that T^F and F^T are true, and that the result of that operation is inverted so that T becomes F and F becomes T. So it is F if A^B is T, which is the set of cases when A and B are non-identical. Therefore, it is the value of not-not-(A==B). Needlessly convoluted, but approachable. A bit high-handed. It's hard to not see it as arrogant, though we will endeavor here.

The rest of the framework I have trouble with indirectness. You have repetition (violates DRY) but it's only near-duplication. Some of the code being for rendering, and some of it for compiling data from the database, and some is for both. It takes time to determine which is which. You have to dig into the code, or conduct code experiments to see what values end up where, and which 'names' are actually keys that must match in multiple dictionary structures for the code to run. You have to know which constructor parameters are ignored (some are) and in which circumstances. It is implicit, and indirect, and convoluted. And largely test-free.

It is possible that the original author was so intelligent that he/she needed no cues or clues to know which part did which thing nor why. Perhaps they could hold it in their heads without struggling, even across days or weeks. Perhaps the indirectness seemed to them to be ingenious, or maybe they were ashamed that they couldn't think of something simpler. Maybe they were scrambling to get something out the door (a sin in itself). Maybe they were used to working with code that was far less clear and direct.

My friend points out that the original author(s)' motives are lost to me, and that it is poor form to speculate and/or lay blame in the absence of such information. I accept that criticism with thanks.

Whatever the reason, the code requires that the readers make a noticeable investment for little reward. A better framework (hopefully whatever we're getting next) will be much more direct, obvious, and clear.

I am willing to lay aside "clever" and accept a better term. Perhaps "clever" was a needlessly clever term to use. I wonder what Wally would say.


Best Rube Goldberg Ever - Watch more Funny Videos

Friday, April 24, 2009

Cool TDD Antipatterns Appearance on Stack Overflow

There is a cool outgrowth from James Carr's collaborative paper on TDD Antipatterns. There is a Stack Overflow article where you can vote to determine the most prevalent of the ugly smells.

I was a little pleased to see "Free Ride" as the number one last time I looked. Just pride of ownership, I'm not glad it's common.

Thursday, April 23, 2009

Code Patching in Legacy Messes

I really don't want to make this sound like a big deal. The whole thing happens in less than a week and really only affects a handful of files. Nonetheless we went through the gamut of emotions common to maintaining ugly code, and used a range of tools common to trying to do a craftsmanlike job in a legacy code base. Even with a small task, it can be a challenge to stay engaged and positive.

I'm working with a good partner on some bad code that wraps some SQL and does some dynamic web stuff for reports. If we were working in SQL, we could have written the query and been done with it. Even if it were SQL and a pile of if statements it would be comprehensible. The problem is that the code is clever and complicated. The people I work with have cleaned it up considerably from its original consultant-delivered form. We got to work with the good version.

It is a rather clever framework that hides the SQL behind a report by causing you to write chunks of SQL as literal strings in various disjointed locations, involving about three or four families of enums and collections of dozens of new objects, some near-duplicates of others. Some routines help write the code. Several routines accept parameters they don't use, and some sections of code are written in one place and discarded or replaced later in the routine. It's a little funky. No, it's a big funky.

The design principle most consistently followed is maximize the surface area of your code. It seems to ensure that adding a small feature to a report will require touching the program in many places. The second principle must be something about making the time sequence of events more obscure. Or about eager near-duplication.

Dead and live code were entertwined. We'd remove the dead code, but this is fragile and ugly old code and frankly we're afraid of it. We don't have the time budget to clean it all up. We work for a more forward-thinking company, so a few guys are already working on the replacement. Soon this code will die and be buried amidst celebration (locked in Ryan's Book Of The Dead Code), but for now a customer really wants this change and iteration is winding down. We want them happy, and want this done well.

Of course, it's heavily commented. Every method has a javadoc-style comment repeating the name of the method. Usually a three-to-five line comment once you count the flowerboxing. Sometimes they would repeat the names and types of parameters, too. Heavily, uselessly commented.

We had five useful tools that made this task less daunting and ultimately successful:
  1. The first weapon in our arsenal was teamwork. We would try to keep each other from getting depressed, and from refactoring the whole thing. We have a deadline, and we need to make a change. Can't clean it all up, have to make progress. We would each take breaks and were honest about when we were glazing and unable to keep thinking about it.
  2. The second was exploration. We spent the first pair-day just digging around in the code and trying to figure out what it was doing. We read the tests, seeing that they are a kind of gold standard test where a scenario was set up and clearly the resulting SQL was pasted into the test as the expected value. We can tell by the idiosyncratic formatting of the SQL. In the second day we're doing more experimentation. We wonder what happens if you comment something out. What if we change this string or that one? Can we instantiate this class and see what it actually contributes to the code? Developers who had worked in the code gave us a boost.
  3. The third tool was the tests. If we didn't have the gold standard tests when we picked up the code, we would surely have had to write them in order to make any reasonable progress at all. We added little to the body of tests, but it was enough.
  4. The fourth tool was a running application. It's always important to remember that the code is not the thing. It is the design for the product only. The product is information management. Without running the application, one cannot make informed decisions or informed guesses.
  5. The fifth tool was our analyst. Michael was helpful when we had requirements questions, and of course we had a few. The requirement was not all that complex, but we still needed an answer now and then.
It seemed like we had to spend a lot of non-productive time in questions and exploration and poking about, but we nailed the change, simplified a few small areas of the program, and improved the date handling today. No, it's not going up on my refrigerator door, but it works and is better than when we first found it.

PS: Mr. Smarty Pants Complex Coder, we're eroding your mess already, and soon it will be gone completely. Be happy or be sad, but it is happening.

PPS: I almost always use the word 'clever' in a pejorative sense, as I consistently did here. It is something I got from Walter Moore, and is a habit I'll keep for a lifetime perhaps.

Calculate the cost of a priority mistake

If you want an estimate of the cost of making a bad prioritization decision, try this cute little calculator.

"Clever"

Here's one for you. Given two boolean variables A and B, and a language where booleans are real types and not masqueraded integers, consider this:

if ( ! (A ^ B) ) { do_something(); }


Think about how you would have written this two-bool operation. Laugh with me.

Remote Pairing with YuuGuu

Our office firewall gets in the way of Yuuguu, probably by blocking UDP traffic I'm not sure what the real . Finally a coworker was WFH and we were able to try it. Hey, it worked. Lag wasn't bad, control wasn't hard to trade, and it didn't really get in the way.

It really shared the other guy's screen, not just certain windows. That was very convenient, but it also meant that I could see his IM and email notifications and the like. If you worry about such things, be warned. OTOH, it means that he could pop up editors, SQL tools, log tail programs, and the like without having to explicitely share them with me as he as to do in webex.

Yuuguu didn't include voice, but included a voice conference line. It does nice instant messaging and screen sharing, though. We skyped for voice, and yuuguu-ed for screen share. It can tie into your instant messaging accounts, which makes it easier to find people you know.

We had work to do, so we didn't spend so much time kicking the tires as we did trying to work through it. It was more important that it was transparent than feature-loaded. We didn't try five-way screen sharing (the max for the free version), nor the conference calling feature. I didn't see a way to do a shared whiteboard other than maybe firing up a graphics program on the host side of the talk. But that's enough most of the time. We don't use the webex annotation features that much either (too hard to get to them through the menu).

I give it a thumbs-up. If you can use it, give it a shot.

You Win Some, You Lose Some

My talk on remote pairing with Tim Gifford was accepted for Agile 2009. My talk on the In A Flash cards was not.

Ah, well, ya don't win them all. See you for some of the Wednesday fun at Agile 2009.

Tuesday, April 14, 2009

Shhhh.. busy!

I'm not typing a lot of blog this week. I'm typing more web searches and notes and stuff. I'm learning more about memcachd and tuplespaces and couchdb and DVCS, hanging with the offspring, and cleaning code. It's a busy time and I'm learning much. Hopefully I'll be contributing at least as much. We'll see.

Tuesday, April 7, 2009

Remote Pairing Month 3

Overall, this is not a bad process. When we're truly engaged and the bandwidth is good, and we don't have the same partner too long, it's a very workable arrangement. Overall, this is a good way to go about things. At least 80% of the time, it's great. There are a few issues that go into the 20% times when it is less than perfect.

Sometimes we can hold meetings well. Other times, the person on the phone is being left out. It is hard to hear the voices well, and forget about reading the whiteboard. If we're together, and can stay focused, and can keep chatter down to one voice at a time, and can keep background conversations quiet, then meetings work quite well. It's really a lot of effort on the part of the physical participants to stay attentive to the needs of the remote. I miss a lot of it. Face it, long distance may be the next best thing to being there, but it's a distant second. At least where meetings are involved, this is second-best.

It also seems difficult sometimes is when the other end has a lot of discussions going on so that we can no longer make out the voice of our partner, or any particular voice. Some people also have very round, mellow voices that blend into the background a bit too easily. Others have bright, crisp voices that cut through the mix even when they're ten feet away from the microphone.

Standup meetings are sometimes a total loss due to background sounds. I hear people typing better than I hear people talking, and sometimes I hear only the background chatter and various office noises (chairs, scooting, mouse clicks). It is very frustrating. I suppose this is what people have to deal with when they have new hearing aids: the electronics pick up sounds very differently and our brains have more difficulty filtering the sounds. Also the tiny webcams don't help with lipreading, which I find generally helps in noisy environments.

Perhaps the secret is that there should be a microphone somewhere in the center of the group, or the meeting should be in a more quiet place where the individual voices can be distinguished.

I've also noticed that you can't pair remotely all the time. You really need breaks to give your ears and eyes a rest. It is wearing to spend too much time with pixelated video, keyboard/screen lag, and severely clipped audio. Filtering out noise on the screen and in your earphone(s) divides your attention a bit.

Overall, this is a good way to work. I would certainly recommend that it is tried. Companies can bring in developers from a distance, continue pairing, and make some good gains. Developers can work and be useful from a distance. It is a good deal overall, but no work arrangement is 100% great 100% of the time. When you're remote, it's eye fatigue, ear fatigue, bandwidth, and the fact that you aren't there in person. You can work it out, but it's going to have rough moments.