Thursday, August 20, 2009

Staying Current: A Software Developer's Responsibility

I have a personal hatred for weekend conferences*. To me, a weekend conference ensures that I'll be "working" for 12 straight days.

I understand that opinion isn't universal.

Some people have problems getting time "off" to attend conferences. These situations feel like a fundamental misunderstanding of a software developer's responsibilities. Part of your (software developing) job is staying up on current technologies. That means doing some research during your day.

(almost directly stolen from Ward on technical debt)
If you spend your entire day coding and never looking at new things, you accrue productivity debt. In the short term (say the last week of a release), it makes sense to take on a little debt. However, in the long term, assuming little or no payment, the interest (where interest equals the gap between your skills and the current solutions) will render you a NZPP (Net-Zero Producing Programmer). In a typical organization you can coast as a NZPP for around 6 months and slowly transition to a NNPP.

It is your responsibility not to become a NZPP (or NNPP). Most talented software developers refuse to work with NZPPs. At the point that you become NZPP, you usually have to declare bankruptcy (with regard to software development). You generally have two choices: take a much lower paying job where you can learn new things or move into another role. If you want to be a software developer, neither of these outcomes is desirable.

Luckily, you have the power to avoid becoming a NZPP. Most employers will happily buy you technical books and send you to technical conferences. In my opinion, whether or not you took advantage of these benefits should be noted on your performance review. Not staying current as a software developer, especially when the opportunity is offered to you, is software malpractice.

I once created a list of things I look for in potential team-mates.
  • Have you tried Test Driven Development? Can you name something you liked and something you disliked?
  • What language(s) that are gaining popularity, but not yet mainstream, have you written Hello World in?
  • Do you read books or blogs looking for new ideas at least (on average) once every two weeks?
  • Do you at least attempt to learn a new language every year?
  • Have you ever run a code coverage or cyclomatic complexity tool against your codebase?
A commenter said something along the lines of
Not everyone has the personal free time to dedicate to doing all of these things
And, that is the fundamental flaw. Employees (and even some employers) seem to think that these are activities that should be done in your off time. I can't disagree more. These are things that a responsible developer needs to do as part of their job, thus it can be done during work hours.

20% time isn't something Google invented, it's just something they named, formalized and made popular. The activity itself is something good software developers have been doing for years. I applaud Google for making it a standard, thus ensuring that it's employees always have the opportunity to stay current. However, your company doesn't need to standardize on 20% time for you to stay current.

It's your responsibility to make time in your day to read a book or a blog.

You should also take advantage of a company sponsored trip to a conference. If you've attended conferences before and derived little value, I highly suggest the QCon conferences and JAOO.

Once you start doing research as part of your job you'll find that conferences are just like work, except the focus is 100% on research. And, it's not something you want (or should have to) spend your personal time on, it's just another productive day of doing what you have a responsibility to do.


* Which is why Josh and I run SpeakerConf Tuesday-Thursday. You can travel to, attend and travel home without missing a weekend day.

Monday, August 17, 2009

Macros Facilitate Expressive Code

Someone once asked me if I thought Clojure was more expressive than even Ruby. I didn't have enough information to form an opinion then, and I still don't now. However, I recently noticed something that led me to believe the answer could actually be yes.

I was looking through the code of clojure.test on Friday and I noticed something interesting. In clojure.test, the form(s) passed to the "is" macro are wrapped by a try/catch. It caught my eye because I often want to do the same thing in other languages, and usually I have to settle for much less elegant solutions.

Here's a bit of example code to help create some context
(deftest a-test
(is (= 1 (some-function-that-throws-an-exception)))
(println "this code still executes"))
For this example to work you'll have to ignore the fact that you probably don't want this behavior. In practice I prefer my tests to abort on the first failing assertion; however, in this blog entry I'm focusing on what's happening, not what I theoretically prefer.

In the example I call a function the same way I would anywhere else, and the framework has full control over what happens if my function throws an exception. This is accomplished when the "is" macro takes the forms and manipulates them into something similar to the original code, but with additional capabilities.

This particular example struck me as one where macros allow you to write only what you want, and the macro adds the additional behavior that you desire. However, the key is, you don't have to do anything special to get this additional behavior.

Consider trying to do the same thing in Ruby. In Test::Unit you would need an assert method that took a block.

def safe_assert_equal
result = yield
assert_equal result.first, result.last
rescue Exception=>e
puts e
end

class Testable < Test::Unit::TestCase
def test_something
safe_assert_equal { [1, 2] }
end
end

The additional syntax isn't drastically invasive; however, you are forcing additional syntax and requiring the understanding of why it's necessary.

Of course, in Java things would be even less expressive. The most likely solution would be to put the assertEquals in a Runnable, but I'd be interested in hearing other ideas. Regardless of the solution, it would obviously be invasive and take away from the readability of the test.

Being able to only say what is necessary is powerful. Stuart Halloway likes to talk about Essence and Ceremony, where Essence is the ability to say only what you want, and Ceremony is all the additional things you are required to say.

Macros seem to be a powerful tool for those looking to write Ceremony-free code.

Tuesday, July 07, 2009

More Trust, Less Cardwall

Last weekend, at the Hacker B&B, I mentioned to Jason Rudolph that my current team has no cardwall. He was a bit surprised and asked what we do have.

We track what needs to be done in 3 stacks: Eventually, This Release, and Tech.

Our stakeholder gives us requirements all the time. We also think of things that need to be done on a fairly regular basis. All requirements are captured on an index card with about 5 to 6 words. These cards are not the entire story (pardon the pun), instead they are a placeholder for a conversation. That's fairly standard for the projects that I'm a part of.

New cards are put in Eventually, unless they need to be done for This Release. When a card is done, it's put in a Done stack. Our stakeholder goes through the Done cards every few days and discards them after a quick once-over.

That's it for requirements. It's a very slim process. We estimate at the release level, not the card level.

Some cards are purely technical. We put those in the Tech stack and the team prioritizes as they wish. In general we work on Tech cards when no-one is available to pair. However, sometimes a Tech card is the highest priority and it can get picked up instead of a This Release card.

I mentioned to Jason that I believe we can be successful with this process because of the trust that our stakeholder has in us. As a consultant, I always felt like a vendor instead of a partner. Now that I'm full-time, we're all on the same team. When you're on the same team you don't seem to need as much ceremony and information radiation. This definitely isn't universal, but it's been my experience since I joined DRW.

I definitely prefer the slimmed down process, but I only see it working in an environment with a very high level of trust.

Update: Credit due to Chris Zuehlke for leading the fight for the slimmed down approach. We are more productive thanks to his efforts.

Thursday, June 25, 2009

Programmer Confidence and Arrogance

At SpeakerConf 2009, one of the speaker's wives asked me: Why is it that most speakers are confident, and some are simply arrogant. The question was also in the context of "software is nerdy, how can you speakers be so cocky". I pondered for a minute and replied: When no one knows what's "correct", people with confidence generally win the discussion.

Imagine the early days of medicine. Three different doctors give you three different surgery options. There's not enough experience in the industry to show which is the correct choice. Who do you trust? Probably the doctor who managed to be the most confident without being overly aggressive or cocky.

As I've said before, we're still figuring this stuff out. I constantly try to improve my processes for delivering software. I share those processes via speaking and blogging. However, I'm definitely aware that I could be doing it entirely wrong.

In general, I'm weary of developers who speak in absolutes. Most solutions I've seen are contextual, and even in context they tend to be fragile. We simply don't have the heuristics to determine what true best practices (for our field) are.

When pondering the original question I remembered when I wrote about Despised Software Luminaries. At the time I blamed passion; however, I'm guessing confidence and arrogance probably also weigh heavily on the source of animosity.

There's a direct correlation between being a luminary and your compensation package. Therefore, luminaries are enticed to gain as much market share as possible. Your luminary status is determined by the speed at which your ideas are adopted. And, without absolute proof of correctness, the speed at which your ideas are adopted can largely based on your confidence. I'm sure some luminaries see this situation and walk the line between confidence and arrogance.

Of course, not all luminaries are in it for compensation. I truly doubt Martin Fowler does what he does for money. But, the people who are looking to take market share from Martin may be motivated by a compensation package. Therefore, it's pretty hard to escape the the effects of confidence and arrogance.

The confidence and arrogance discussion is also interesting if you've ever met a luminary who you found to be completely incompetent. Perhaps they truly don't know what they were talking about, and they've just been confident enough to fool the majority of people they've met so far.

Wednesday, June 24, 2009

Java: Method Chain with Snippet

I've noticed a pattern pop up a few times in my Java code in the past 6 months. Maybe it's a decent pattern, or maybe I only have a hammer.

The problem I'm trying to solve is setting some global state, running a test, and ensuring that the global state is set back to it's original (or correct) value. My usual solution to this problem is to remove global state, but not all global states are created equally. The two global states I've been unsuccessful at removing are the current time and system properties.

In my previous post I described how I freeze time using the Joda library. The example code for freezing time was the first time I used a Method Chain with a Snippet. At the time I thought it was an ugly solution, but the best I could come up with.

A few months later I was testing some code that set and read from the system properties. My first tests set the properties and didn't clean up after themselves. This quickly caused trouble, and I found myself turning to Method Chain with Snippet again.

Here's some example code where I verify that setupDir doesn't overwrite a default property:

@Test
public void shouldNotOverrideDir() {
new Temporarily().setProperty("a.dir", "was.preset").when(new Snippet() {{
new Main().setupDir();
assertEquals("was.preset", System.getProperty("a.dir"));
}});
}

And, here's the code for the Temporarily class

public class Temporarily {
private Map properties = new HashMap();

public void when(Snippet snippet) {
for (Map.Entry entry : properties.entrySet()) {
System.setProperty(entry.getKey(), entry.getValue());
}
}

public Temporarily setProperty(String propertyName, String propertyValue) {
if (System.getProperty(propertyName) != null) {
properties.put(propertyName, System.getProperty(propertyName));
}
System.setProperty(propertyName, propertyValue);
return this;
}
}

The code works by setting the desired state for the test, chaining the state cleanup method, and passing the test code as a Snippet to the state cleanup method. The code exploits the fact that Java will execute the first method, then the argument to the chained method, then the chained method.

For the previous example, the 'setProperty' method is executed, then the Snippet is constructed and the initializer is immediately executed, then the 'when' method is executed. The Snippet argument isn't used within the when method; therefore, no state needs to be captured in the Snippet's initializer.

This pattern seems to work well whenever you need to set some state before and after a test runs. However, as I previously mentioned, it's much better if you can simply remove the state dependency from your test.