Friday, November 11, 2005

Index Cards

Extreme Programming has this strong tradition of using index cards to track user stories, or to aid in design through the use of CRC cards.

Now, I have always had a strong preference for Excel spreadsheets.  You can print them, e-mail them, share them, and save them.

But there is something wonderful in the very nature of index cards.  Their very constraints create interesting feedback loops.  Think of all the objections that you might have against them:

Index cards are too easy to lose.

Yes – but why are you writing anything important on an index card in the first place?   At the end of the day, the only important work product is the code.  Requirements and any other models exist to facilitate conversations about the code.  If you have been writing tests along the way, when the coding is done, the requirements don’t need to exist anymore.  The requirements aren’t sacred.  The only thing that is sacred, the desires of your users, cannot be captured in any format, but must be discovered through a constant dialog.

Index cards are too bulky.

If you have more index cares than you can manage, then your user stories are either too fine grained or your scope is too ambitious.  Either way, the cards are telling you that you need to change.

This is a pet peeve of mine.  Quite often, when you are doing the wrong thing, it will be difficult.  The correct solution is not to make it easier to do the wrong thing, but to change what you were doing in the first place.  

Only one person can “own” an index card at a time.

So what?  Distributed ownership is the worst thing that can happen in project management.  If everyone owns a task, then no one is really responsible for carrying it out.  

Having said all that, I am still mulling over the use of index cards in my process, and have started collecting links about index cards in del.icio.us.

Tuesday, November 08, 2005

Holistic thinking is disruptive

In the November issue of the Atlantic Monthly, there was a brief article about the heuristics used by the US intelligence community to detect spies.
They may also take a "holistic view of world affairs" that could lead them to believe espionage is "morally justifiable."
You can read this any number of ways, and I won't debate the ethics of making decisions to support particular policies of this adminstration in spite of common sense (or holistic thinking) telling you otherwise.

But I would like to touch briefly on his this might affect your organization. When it exceeds a certain size, every organization begets a hierarchy of departments. While the organization, as a whole, might wish to move in one direction, each department has its own incentives, which sometimes contradict the organization's larger goals.

In such a world, to think holistically is to think about disruption, as any move to re-align the departments with the organization's goals will result in disruption to that department's practices.

Monday, November 07, 2005

Behavior Driven Development

I recently read an interesting paper by Dave Astels, entitled A New Look at Test-Driven Development, which suggested that Test Driven Design is overly focused on testing, which gets in the way of reaping the true benefits of TDD.

I agree that using the word “test” when describing TDD definitely gets in the way, when explaining it to other people.  Management asks, “Why are we hiring testers if developers will be writing tests?”  Developers ask, “Why should I write unit tests for code that will get tested by the (manual or automatic) acceptance tests?”  And so on.  You get the usual objections to TDD.

So I am down with giving TDD another name, but what threw me was the suggestion that we ought not to use the word “test” when actually writing the tests.

In Behavior Driven Development, tests are called “specifications.”  Fixtures are called “contexts.”  And instead of assert, one would say “should.”  (Dave’s essay has examples of their usage.)

Initially, I was fairly dismissive of what seemed like a cosmetic change, but I decided to give it a go for the past week.  Here is what I found.

I wrote more, smaller test fixtures.  Whereas I used to write test fixtures with names, like CustomerFixture, I found myself creating many little contexts, with names like CustomerWithOverdueBill or CustomerWithoutAddress.  

I wrote more asserts per test.  Each test started with a particular context, invoked a particular operation in that context, and then verified the expected resulting context.  That verification often took multiple asserts.

The tests naturally had better names.  In the past, when writing tests for a Customer class, I might have tests with names like testSetAddress.  Now, I find myself thinking in terms of scenarios, so that the CustomerWithoutAddress context might have a specification like settingAddressForFirstTimeSendsNotifcation.

In summary, this change in perspective has proven extremely useful, so I am sticking with it.

Sunday, October 30, 2005

Monday, October 10, 2005

Planarity.net

A way cool game that tests your facility with spacial relationships:

Planarity.net

Monday, September 12, 2005

Are iterations hazardous to your project?

Are iterations hazardous to your project?: "That surprise experience helped open my eyes to why 'iterations' may be hazardous to your project: Danger grows when the results of the iteration are not directly linked to delivering the product to the end user. Without that linkage, iteration results hang in the air just as badly as the old, pre-agile forms of wandering in the wilderness."

This could be filed under the general heading of "Don't let the process become the goal," which is a disease that strikes nearly every organization.

Here is how it happens:

Management wants feedback that the team is making progress towards a particular goal, so they add instrumentation to the process to gather metrics. The team responds by trying to improve those metrics. If management chooses the wrong metrics, the end effect is that they drive the team away from its goals, rather than towards them.

I think that all of Alistair's observations and recommendations are dead-on.

Thursday, August 11, 2005

Laziness Driven Design

I have become fanatical about writing unit tests for every method on every class, regardless of how trivial that method first appears. ( "But it's just a getter!" )

This leads to an interesting laziness driven feedback loop. Here's what happens:

I am implementing a feature, and think that the shortest distance between two points, is to add another dependency onto one of my classes, but then I realize that this new dependency would further complicate all of my tests, requiring large changes. Ugh! I don't have time for sweeping changes to my test suite.

So, in my laziness, I skip over the initial, obvious solution, think a little bit harder, and come up with a truly simpler solution.

Monday, August 08, 2005

The PO-STAR Movement

In the past year, I have seen an increasing number of "Plain Old *" abbreviations:
  • POJO - Plain Old Java Objects
  • POCO - Plain Old CLR (.NET runtime) Objects
  • POX - Plain Old XML
At this point, I think it qualifies as a crypto-movement, and the clue to the genesis of this movement is in Andy Smith's "Why Frameworks Suck."
Frameworks hurt sharing. I’d really like to give you this fork Jimmy, but you’re gonna need a knife and plate to use it.
The alternative to PO* is to buy into some framework, which inevitably prevents code reuse as your classes become riddled with framework junk.

You know a library is really a framework when:
  • It requires you to derive your classes from some library class.
  • It requires you to use their main() function.
  • It requires you to use their Application class.
  • It requires your classes to depend on some third party library.
  • The setup() and teardown() methods of your test suites become really complex.
Nearly every time that I have written framework-like functionality into an application, I have found that I was able to factor it out in favor of simple library classes that are themselves PO* objects.

Sunday, August 07, 2005

I Heart Python

I have been playing around with Python at home, developing a simple web application, and I just wanted to say that I think that Python is awesome.

Fear of the Domain Model

Did you ever notice that many programmer's tend to shy away from developing a domain model?

This is a pretty reasonable reaction. We want to exploit our strengths, and leave the domain to the domain experts. We want to continue to improve our knowledge of computer technology, because this translates into a personal asset.

I think that the ability to elicit domain knowledge from a domain expert and convert this into a viable domain model is a more important skill than the knowing the latest technology that your tools vendor is trying to push at your CIO.

A rich domain model is truly fertile ground for developing applications, and building working, valuable applications is way more important than extending one's knowledge of the solution domain.

Friday, August 05, 2005

The Garden



Originally uploaded by Jennifer Dunne.
This is picture of a flower in my wife's garden.

Tuesday, April 12, 2005

Thoughtless Interfaces

Here is a great write-up on how to not create an interface: IFoo as Foo's interface is evil and should be punished.

It's all about responsibilities, people!

Monday, April 11, 2005

Toothpaste



Originally uploaded by Jennifer Dunne.
My wife took these wonderful pictures of toothpaste, which had quietly extruded itself from the tube in the middle of the night.

Thursday, April 07, 2005

Trust is an essential deliverable

From Exploration Through Example:

Sometimes teams are jumping into Agile to avoid the horror of the previous release. The code was too buggy, or too late, or cost too much per feature, or all three. In such a case, the programmer team is probably not trusted by the business people. If so, trust is an essential deliverable. It's not enough to be better; you have to be visibly better soon. Delivering tested, working features at frequent intervals is a key way to get trust back. Another way is close cooperation with a product owner that demonstrates that the team's orientation is toward helping her meet her goals. But more generally, the team should pay active attention to how well they're doing at building trust, not just at building code.

Tuesday, March 22, 2005

A Perfect Recipe for a SOA Failure

From SOA is a Business-Driven Architectural Style:

"It means that for SOA to be successful, it must be a 'top-down' approach. And top-down, means problem to architecture to solution. It does not mean, working from what we have and just wrapping it with new technologies just because we can. This bottom-up approach is quite natural and easy and is the perfect recipe for a SOA failure. "

I will go a bit further and say that any architecture that isn't bent on solving a particular problem is a recipe for failure.

Monday, March 21, 2005

Searching Google for Books

I had heard about Google Print a while back.

I hadn't realized that the Google Library project would mean that public domain books, like Huckleberry Finn, would now be searchable via Google.

You just enter "book" followed by the book title in Google.

Yahoo has acquired Flickr

Thoughts on Flickr and Yahoo (by Jeremy Zawodny)

I hope they don't mess it up. :-)

Wednesday, March 02, 2005

Being Careful Is Not The Solution

Sometimes, when you touch a piece of code, or a build script, or a configuration file, you might feel the urge to be very careful, because your change might break the overnight build, or result in a subtle bug.

Being careful is not the solution. You cannot be careful all the time. Sooner or later, you will let you guard down and make a mistake. It is inevitable. If you are lucky, this mistake will occur when you have loads of time to diagnose it. If you are unlucky, you'll get a bad build at the 11th hour.

When you find that you need to be careful, you should ask yourself, how can I change this situation so that mistakes are either impossible to make or discovered immediately after making them?

If you think about it, you probably already know a few strategies for achieving this right now:
  • Unit tests insure that your classes behave as you expect them to.
  • Asserts (Design by Contract) achieve the same thing from a different direction.
  • Code generation eliminates duplication, so that you only have to make a change in one place.
  • Static type checking catches mistakes at compile time.

Tuesday, March 01, 2005

Jellyfish


Jellyfish
Originally uploaded by JohnDunne.
This is a jellyfish that we saw while poking around the aquarium at the Mandalay Bay hotel in Las Vegas.

Thursday, February 17, 2005

Need Driven Development

In "Mock Roles, Not Objects" [1], Freeman, Pryce, Mackinnon, and Walnes say:

A core principle of Lean Development is that value should be pulled into existence from demand, rather than pushed from implementation: The effect of ‘pull’ is that production is not based on forecast; commitment is delayed until demand is present to indicate what the customer really wants.

This is the flow of programming with Mock Objects. By testing an object in isolation, the programmer is forced to consider an object’s interactions with its collaborators in the abstract, possibly before those collaborators exist. TDD with Mock Objects guides interface design by the services that an object requires, not just those it provides. This process results in a system of narrow interfaces each of which defines a role in an interaction between objects, rather than wide interfaces that describe all the features provided by a class. We call this approach Need-Driven Development.

I recently experienced the opposite of this approach. I had done some initial design, and come up with a list of classes and their responsibilities. I picked the most important class and started implementing it.

So how did I mess up?

You need to start at the edge of the system, from the external interfaces and work your way in. My "important class" was not nearly as important as I thought it was, and certainly was not more or less important than any of my other business objects.

When I finally got around to implementing my external interface, which was a messaging layer, I found that some of my earlier assumptions did not hold true. I had over-implemented some of the business objects. It is easy to fall into this trap with TDD, because you can implement your objects before anyone actually needs them.

If I were to do it over again, I would not forgo that initial design, because it certainly helped the process along, but I would always start my implementation with the classes that are closest to the business requirements.

[1] http://joe.truemesh.com/MockRoles.pdf

Tuesday, February 15, 2005

We’ll ship when the product is ready.

From the Internet Explorer team:

I’ve gotten questions about the ship date. Yes, we have a date in mind. I’ll talk about the date after we get feedback from customers and partners. We’re going to release a beta and listen, then refresh the beta and listen some more. We’ll ship when the product is ready.

This is a refreshing point of view, that you don't hear too often. I imagine that the IE team is under a certain amount of pressure, due to Firefox's increasing marketshare.

Monday, February 14, 2005

This is my brain in....

del.icio.us

You can map your del.icio.us tags with this handy tool.

Pilers vs. Fliers

This is a great posting about the importance of not letting your inbox pile up.

If Your Inbox Has More Than a Screenful of Messages In It, You’re Rude

I totally agree with Jason Clarke. My own system is to move every e-mail that I have read to a folder called "Read Mail". If I don't have the time to immediately respond, I hit the "Reply" button and save the reply in my "Drafts" folder. If I need to do some research before replying to the e-mail, I copy it to my "Tasks" folder which automatically creates a new Task.

Sunday, February 13, 2005

The Gates in Central Park


The Gates in Central Park
Originally uploaded by JohnDunne.
We took a walk on Central Park yesterday to view "The Gates."

Here is a satellite image of The Gates.

2/15/04 - Added satellite image.

Friday, February 11, 2005

Get Your Code Head On

Ever since I adopted test driven development, I have noticed a subtle shift in my development patterns.

Before TDD, I used to make a lot of effort to get into a "code head", a place where the code would just flow. To get there, I would eliminate all distractions and think about nothing but the code. Any lengthy interruption would set me back by an hour or two, because I needed to remember everything.

Now, I don't bother to remember anything. I maintain a to-do list of tests that I need to write, and I cycle continuously through "write test --> write code --> check-in". If I forget something, the tests tell me immediately.

This has meant a lot to my productivity as I get interrupted a lot. ;-)

2/12/05 - Updated wording.

Tuesday, February 08, 2005

Creating Abstractions

To properly write testable code, you need to be able to test your objects in isolation. In practice, this means that your objects must only depend on abstractions that can be easily stubbed out.

Wagging the Dog

How do you know what to pull out into an abstract interface? Let's look at an example.
class Dog
{
void bark();
void setOwner( PetOwner* o );
PetOwner* getOwner();
}
You might want to just abstract the whole thing, like this:
struct IDog
{
virtual void bark() = 0;
virtual void setOwner( PetOwner* o ) = 0;
virtual PetOwner* getOwner() = 0;
}
This is often referred to as the pimpl idiom , but it has some problems.

- It presupposes that all clients want to deal with a Dog, forcing clients to write different implementations for cats and parakeets.
- It is harder to mock, requiring you to mock the whole beast rather than the one part that you care about.

We have achieve physical isolation of the Dog code, but have not logically decoupled anything.

Consider Your Clients When Creating Abstractions

When you create an abstraction, remember that you are defining an interface between two units of code. You need to take into account both classes, rather than just one. Sometimes, this can be tricky, but fortunately, TDD helps us to learn what the needs of both classes are.

And we have some rules of thumb to guide us. When we create abstractions, we may want to consider abstracting capabilities and roles.

Capabilities

A capability is an interface that, you guessed it, denotes the ability to do something. By convention, capability class names end in "-able", like ISerializable or Serializable.

By pulling a capability into its own interface, you make it easy for clients to get only what want.
struct IBarkable
{
virtual void bark() = 0;
}
It makes it possible for me to write a re-useable client, that works with anything that barks, and not just dogs.

void makeThemAllBark( std::vector& barkers );

Roles

A role is an interface that has a meaning to a particular audience. The same object may fulfill many different roles.

In our Dog example, having an owner is not a quality which is intrinsic to dogs. You can pull that out and say that this is a quality of a pet.
struct IPet
{
virtual void setOwner( IPetOwner* o ) = 0;
virtual IPetOwner* getOwner() = 0;
}
You can add this interface to any class that needs to support "pet ownership" semantics. You might see an opportunity to create one standard pet implementation which you can mix-in to different animal classes.
class PetImpl
: public IPet
{
virtual void setOwner( IPetOwner* o );
virtual IPetOwner* getOwner();
}
The Abstract Dog

Our final class looks like this:
class Dog
: public IBarkable,
public IPet,
public PetImpl
{
// IBarkable
virtual void bark();

// IPet is implemented by PetImpl
}

Wednesday, February 02, 2005

Things to Say When You're Losing a Technical Argument

A useful list of ready made arguments, when you find yourself in one of "those" situations.

Things to Say When You're Losing a Technical Argument

How to Organize Your Blogs

When I first got into reading blogs, and the number of blogs to which I subscribed started to become unmanageable, I organized them by topic. This seems to be a pretty common method, as I see it whenever someone publishes their OPML file.

The problem with topic-based organization is that no one ever stays on topic, as proved by this very same posting to a blog entitled "Reflections on Programming."

Even if every blog did stay on topic, you are faced with a ever growing list of blogs where only some of them are truly important. By nature, you will be more interested in some topics than others. You wind up with 50 subscriptions under "Programming" and just one subscription under "Snow Boarding". You never miss a posting about "Snow Boarding", but you frequently skip Raymond Chen's latest posting, because it gets lost in the noise.

The solution is to organize your blogs, based on their relevance to you. I have three categories: "Must Read", "Should Read", and "Whenever". I meticulously read the stuff in the first category, while I only skim the stuff in the last category. As the blogs evolve, I move them up and down in the list. Sometimes, they fall off the bottom when I am no longer interested them.

Here are my subscriptions on bloglines: http://www.bloglines.com/public/JohnDunne

Note to bloggers: These are organized based on their relevance to me, and should not be construed as a judgment about the overall quality of your blog.

Note to RSS Reader authors: My ideal feed reader would allow me to view my blogs by both category and relevance.

Tuesday, February 01, 2005

TDD Meets GTD

In David Allen's "Getting Things Done" [1], tasks are organized in terms of Next Actions. A next action is the absolute next thing you need to do to advance towards a particular goal.

For example, a goal might be to organize your finances. The next action might be to balance your checkbook.

As you complete each next action, you figure out what comes next, and add it to your list. You organize your next actions in terms of the context in which they will be done. This might seem counter-intuitive, but it make sense when you think about it. If you have a big requirements meeting coming up, wouldn't you rather have a list of issues to discuss in the meeting in one place? Other forms of organization, like chronological or topical, fall apart, because there is no guarantee that the timing will work out the way you expect or that you will be able to remember the topics that you created from one day to the next.

In Test Driven Development [2], you constantly cycle between writing tests and implementing the functionality that they test. I find that I sometimes lose my place, and over implement a class, writing code that will never really be needed.

So I started maintaining a "test to-do list". Whenever I encounter a situation where I think I am going to need another test, I just add it to the list. This keeps me focussed on getting tests to pass. When I eventually get back to the to-do list, I sometimes find that I did not need that functionality at all.

Like GTD's Next Actions, I store my to-do list with the test suite itself, so whenever I turn my attention back to that suite, I have a list of outstanding issues.

[1] http://www.davidco.com/
[2] http://c2.com/cgi/wiki?TestDrivenDevelopment

Saturday, January 22, 2005

Switching to Feedburner

After seeing the statistics that Feedburner provides, I decide to follow my colleague, and make the switch as well.

You can now subscribe to this blog at http://feeds.feedburner.com/ReflectionsOnProgramming.

I will let you know how this experiment pans out.

Friday, January 14, 2005

Flickr

This is a test post from flickr, a fancy photo sharing thing.

Thursday, January 13, 2005

Keeping you reading list in del.icio.us

A while backed, I blogged about how you can use del.icio.us to manage your workflow.

I recently discovered Firefox's Live Bookmarks feature, which allows you to create a set of bookmarks from an RSS feed.

del.icio.us allows you to get an RSS feed for any combination of tags.

Are you thinking what I am thinking?

I created a Live Bookmark called "Reading List" and pointed it at http://del.icio.us/rss/johndunne/toread

I wish my defect tracking system had an RSS interface. I would love to be able to get a set of bookmarks to all issues assigned to me.