A Wiki is no place for a conversation

August 27th, 2008

In my experience, when it is suggested that a conversation be moved from a mailing list to a Wiki, nine times out of ten the conversation ends immediately without making it to the Wiki. When a conversation is transferred to a Wiki, nine times out of ten the conversation dies within a day.

Please don’t disrespect your co-workers and end a good discussion by asking that it be moved to a Wiki.

A Wiki is no place for a conversation. Just take a look at the conversations on the C2 wiki and see what an utter mess they are. Nobody can follow the conversations, yet we all know they contain valuable information. The most important technical criteria for encouraging participation in online conversations are distribution, presentation, chronology. In my opinion, conversations should be distributed in a push fashion, presented as discrete responses (ideally as a threaded conversation), and should appear chronologically so that people can see the history of the conversation. If these things don’t hold true, people don’t contribute to the conversation. These criteria are much more difficult to achieve in a Wiki than through a mailing list.

In addition to the criteria that promote participation, making your conversations searchable and archivable is usually a good idea. If you are asking for a conversation to be moved to a Wiki because you feel like its important and you want it to be captured, then you might consider using forum software (or an online newsgroup) instead of plain e-mail distribution.

Technical Tasks vs. Stories

August 13th, 2008

A lot of teams have trouble deciding whether a task should be declared as a technical task or a story. The simple answer here is that if a customer can ask for it, it should be a story.

For example, the following should be stories:
- Creating an installer - “As a customer, I want an easier way to install the application”
- Supporting an incremental DB tool (such as Liquibase) - “As a customer, I want an easier way to the application database when upgrading software releases”
- Supporting a new deployment environment - “As a customer, I want to be able to run on a 64-bit HP box”
- Improving the system performance - “As a customer, I want to run WizBang transactions faster (i.e. denormalize WizBangFoo and WizBangBar database tables)”

The following should be technical tasks:
- Refactor the new domain objects to eliminate duplication
- Make sure that PMD and Clover are running with the nightly build
- Run a continuous integration build
- Test integration between FooServer and BarWebService

Just because something sounds technical (like improving performance or supporting a new DB tool) doesn’t mean that it can’t be captured as a story. The problem with not capturing customer requirements as stories is that it becomes unclear when they should be prioritized. Who gets to decide? The team lead? The product manager? The architecture team? The project manager? The team? The receptionist?

The other problem is that you don’t get credit for the work and effectively devalue the stories that you are working on in the iteration in which you take on the (miscategorized) technical task.

Take a closer look at the tasks that you have sitting on a punch list or task board somewhere and see if it could be asked for by a customer. If so, write it up as a story and hand it over to your product manager.

In case you didn’t know, I’m running for president

August 4th, 2008

JavaRanch Promotion

July 3rd, 2008

Peter Johnson and I are doing a promotion for JBoss in Action on JavaRanch. We are officially answering questions related to JBoss and the book from July 1, 2008 - July 4, 2008, but I’ll probably hang out there for a while after in case more questions come in. Feel free to stop by the JavaRanch JBoss Forum if you have any questions.

Most common Persian words

November 10th, 2007

As a second-generation Iranian American, who has spent practically no time in Iran, I have found it difficult to learn the Persian language beyond mere kitchen talk. In an effort to improve my vocabulary, I sought out a list of the most common Persian words. I could not find such a list, so I searched for a Persian-language corpus that I could use to produce the list myself.

I came across the Hamshahri Persian Corpus and decided to use it. I ran a word count on the corpus to determine what the most common words are in the Persian language. I posted the results sorted by the most frequently used words here.

The list was rather long, so I’ve only included words that appeared in the corpus over 1000 times. I plan to start at the top of the list and make flashcards out of any words I don’t know or am unsure of. This should help me focus on words that are more commonly used. I hope you find it useful as well. I will post the Java code I used to parse the corpus if anybody is interested.

If I ever find the time, my next goal is to try to find phrases, word combinations, and word patterns. If anybody is interested in helping out, please let me know. I’d also be interested in finding out about similar (non-commercial) efforts for other languages, particularly other indo-european languages or other languages that use an Arabic script.

Taxonomy / Smells / Refactorings

October 8th, 2007

There are two documents that I frequently visit when I’m refactoring code, the first is A Taxonomy for Bad Code Smells, which categorizes various smells in Martin Fowler’s Refactoring book. The other is this Smells to Refactorings PDF file, which lists all the smells and refactorings from Fowler’s book as well as from Joshua Kerievsky’s Refactoring to Patterns book.

I’ve been looking for something that lists the various taxa, the smells, and the associated refactorings in both books, thus consolidating the tables on both of these documents. I couldn’t find one, so I’ve created one myself. I’ve published it via a Google Document, which is available here:

http://spreadsheets.google.com/pub?key=pRhKijBMGajDDo0hZjvv8GQ

There are a few of the refactorings that are in the Refactoring to Patterns book which were not part of the taxonomy in the first document. I’ve listed these at the bottom under unknown with my guess of where it should go listed next to it. Please provide me with feedback as to where you think these unknowns should go and I’ll update the document.

You know you’re not agile when…

September 28th, 2007

… you have a job description like this:


DESCRIPTION:
Career Growth! Terrific opportunity in a growing software company for a Java Developer. Must have experience with the design, documentation and implementation of Java 142. Must be strong with implementation of Java. Must also have experience with Spring or Struts. Any experience with Eclipse, Hibernate or Oracle is a great plus. Job duties will include taking a 220 page document of specs and implementing them accurately and efficiently. Will travel to various local client sites. Interviews are taking place right away.

Man am I glad that I’m not working for them! A friend sent me this today and we both had a good laugh.

Indicator Plants

August 9th, 2007

If you’ve ever been to a vineyard, you’ve probably seen that they plant rose bushes at the end of each row of grape vines. These rose bushes indicate if there is going to be a problem with the grape vines because the roses are generally weaker than the grape vines, yet have almost the same genetic make-up. The roses will die first if there is a pH-imbalance, insufficient water, too much water, too much sun, or other issues with the environment. The viticulturalists can then react before the problem grows out of proportion. The roses are “indicator plants” that help the vineyard achieve the highest value, by reducing the unnecessary cost of damaged vines.

One of the things that attracts me so much to Agile processes, is that they have so many things that act as indicators to help the company prevent lost time and effort, similar to how the roses help the vineyard prevent lost grape vines. Continuous customer feedback, tells us if we’re building the wrong thing. Burndown charts give us an indication that we’ve taken on too much work for an iteration, or that we need to rethink our release date or scope. Daily stand-up meetings let us know if something is blocking a developer and provide information to all team members so that problems can get rectified as early as possible. TDD leads our design, but the unit tests also remain as a regression to indicate a defect before it gets checked in to the repository. Retrospectives provide indicators of problems in our process and our teamwork. The list goes on and on..

Like viticulturalists, successful agile teams are continually looking for more indicators to help steer them to the direction of value by reducing the cost of mistakes. But this extends farther than just vineyards and software development; every organization needs to find ways to quickly detect problems and resolve them before they grow.

Designed vs. Open Inheritance

July 25th, 2007

I like Martin Fowler’s write up on Designed Inheritance, but I’m not so sure I agree with his implied suggestion that you cannot have designed inheritance and provide an enabling design.

If I have a component that is being called by other code, and that component is implemented as an abstract class that only allows subclasses to implement abstract methods (all concrete methods are final), then I cannot override the behavior of the parent class. This is designed inheritance because people can only subclass it in the way that I’ve designed. I wrote about this a few years ago when I talked about extending non-abstract classes.

To make this design “enabling” I can simply provide an interface for my component (above the abstract class), and make all the code that references the component point to the interface instead. Now, if I am developing a library and somebody decides that they want to extend it in a way that I didn’t anticipate, they can do so, they just have to implement the interface from scratch. They are free to do it, they just can’t misuse my implementation by using it in a way that it wasn’t designed to be used. I think its fair to have to go out of your way to provide an alternative implementation. Essentially, I’m saying that the framework provides open inheritance, but the implementation provides designed inheritance.

You only really have to worry about unanticipated uses if you’re writing a library anyways. If your writing code within an application, then I would stick to the designed inheritance and let people refactor and change the code if the requirements drive them to that. This is another perspective that I think Fowler didn’t address. I believe that Josh Bloch’s advice is probably geared more towards application developers, while Eliotte Rusty Harold’s comments are within the context of library development. These are different beasts. When you’re contributing to an application, you can change the code, when you’re using a library, you typically can’t.

Don’t mercilessly refactor unit tests!

July 25th, 2007

I teach TDD courses, and one of the questions that inevitably pops up is whether you should refactor your tests. When it comes to eliminating duplication in tests, my threshold is very high. By that, I mean that the most important thing to me is readability. I want to read a test like a mini story: I set this up, I execute this, I verify that.

One of the biggest annoyances I encounter with experienced TDDers is when they decompose tests to the point where you can’t see what the test is doing without bouncing around to 50 places in the code. I don’t care if I have duplicate setup for multiple tests if that setup is only 1-5 lines of code. If the entire test can be seen on the screen, then you can understand what it is doing much more easily. By eliminating duplication in test setup and verification, tests become less readable. For example, I might have to keep jumping to the top of the class (or worse yet to another class) just to see what the expected values are that I’m comparing to.

When I do eliminate duplication in tests, I try to use composed methods (with descriptive names) that are explicitly called from the test methods, rather than using methods that are automatically called by a testing framework (e.g. setup methods in JUnit); this maintains the readability of each test.

I’m not saying that you shouldn’t refactor your tests at all. I just recommend that you have a higher threshold and not be as “merciless” as you are on your real code.