Practically Agile
Using Agile in less-than-perfect situations since Y2K
Using Agile in less-than-perfect situations since Y2K
Many people conflate formality and rigidity, treating them as inseparable. It is easy to see why. Formality leads to rigidity as mechanisms are put into place to ensure formalized practices and processes are followed. You have likely seen this go wrong as I know I have. Architecture groups and PMOs shift their focus. No longer an aid to progress, they become an obstruction. They keep their formality, but lose their purpose as they become rigid.
Agile is, in part, a reaction to the rigid process models of the past. It is no surprise that many throw formality out as well. However, without a degree of formality, we lose repeatability. This has happened in countless efforts to implement Agile methods. The team, seeing a chance to break from the rigidity, pushes off any attempts at formality as well. As the project progresses, cracks begin to form. There is no formal test plan, so high-level bugs creep in. That is, while the expressed stories may work as requested, certain aspects are simply not covered. Because there was no formal effort to design the user interface flow, usability of the product starts to plummet as the complexity of the combined requirements weighs upon each successive screen.
These, and other aspects, are things we as software development professionals have learned to do reasonably well in the last 30-plus years. Ignoring them hurts our chances of success. Are these things non-Agile or anti-Agile?
No they are not. To completely ignore formality would be to throw even Agile practices out the window. Software development requires people to coordinate actions. The amount of formality to do so varies based upon the team and its goal. However, some degree of formality can be an aid when more than one person is involved.
It is all in how we apply formality. Things such as test plans, information architecture and user interface flow, and domain modeling applied in an “all up front” fashion would be difficult to reconcile. However, none of these things has to be rigid. They can adapt just as easily as we can refactor our code. If the plans are designed with this in mind, small adaptations are easy while larger ones remain possible.
It is worth repeating that not every effort requires the same degree or type of formality. If a project is just starting or has only minimal and very simple user interactions, perhaps a comprehensive outline of user interface flow really isn’t necessary. However, we must train ourselves to recognize when it becomes necessary. As soon as anyone in a retrospective or user demo says, “I can’t find a screen where I can do X,” it might be time to examine the flow. In fact, it may be worth formalizing a list of “smells” that point to the need for adding some of these practices. Somewhat similar to those in Agile Adoption Patterns. What do you think?
Tags: agile, retrospectives
Great post from Bill Mill. Go on, read it. When you’re done, here’s the key quote:
The Warriors could optimize like crazy for the press, but they’d be training and working and trading and drafting to be, at best, a pretty good team.
This is why those that preach from the gospel of Lean try to impress upon us that local optimization is an insidious evil. It often looks good from a certain viewpoint, but it can hide other improvements that would provide a more holistic benefit. It can even prevent you from reaching your true goal.
At the risk of this becoming a bile blog, I have another Java rant. It has been a long-standing tradition (12 years?) among Java developers to cry out that the date implementation in Java is pretty terrible. So, it’s not just me
As a bit of history, the folks at Sun (soon to be Oracle) tried to fix this by all but requiring that Date objects be wrapped with Calendar objects in JDK 1.1. They couldn’t just fix the date implementation directly because of another long-standing tradition: new Java versions must be backward-compatible with previous versions. Regardless, this fix has long been considered a kludge at best, but most of us learned to live with it. Preamble out of the way…
I was working with someone today who had a Calendar object. They wanted to compare it with another object to see which was earlier. So, they called Calendar.after(Object). Makes sense right? Only this method returned false even when the other object was definitively a representation of a time after that represented by the Calendar object. This seemed odd to the developer in question.
The observant among you may have noticed that I did not say they were comparing with another Calendar object. They were, in fact, comparing against a Date object. Knowing that, I immediately suspected the problem. A quick trip to the API docs showed me this gem:
Returns whether this
Calendarrepresents a time after the time represented by the specifiedObject… if and only ifwhenis aCalendarinstance. Otherwise, the method returnsfalse.
So, rather than throwing an IllegalArgumentException or having the method specifically only take a Calendar object, this method and the corresponding before(Object) method both just return false when you send in… anything else. So Calendar.after("dates in Java suck") returns false.
There are no good reasons for this that I can think of, so I went to the Bug Parade. There, I found a few tickets that were marked as fixed or otherwise closed. However, this is still obviously a problem, right? Refining my search, I found what I think is the most recent one. It is marked as “Closed, Will Not Fix”. Why? Here is the relevant part of the comment:
It’s hard to change the implementation at this point. Please use compareTo(Calendar) added in 1.5.0.
I’m sorry, can’t we at least deprecate things that are this broken? Do we not do that after the heckling caused by deprecating 60% of the methods in Date?
A follow up question… Where is the replacement library? We had java.nio, why not create a new java.date? For that matter, why hasn’t a third party library really taken off here? My suspicion is that JPA integration is the main challenge. Especially since, in addition to the problem of them having the same class name, java.sql.Date extends java.util.Date.
Maybe I’ll try out Joda Time or another 3rd party replacement. Does anyone know how their Hibernate sub-project works in the field? (Update: The goal of JSR-310 is actually to get Joda Time into core Java. It had been tentatively scheduled for Java 1.7. A quick look around shows that there was some struggling to get it completed and tested for inclusion. I was not able to determine an outcome. Anyone know?)
I’ll try to make my next post about something more positive.
Tags: bug, calendar, date, java, rant
I am a fan of The Pragmatic Progammers series of books. They have mostly good material and I like their publishing methods. One of their books I have been meaning to read for a while is Agile Retrospectives: Making Good Teams Great by Esther Derby and Diana Larsen. I am happy to say that while it may not be the best of the Pragmatic series, it keeps up the good name. I would give it a seven out of ten.
Those of you who run in Agile circles should recognize those Author’s names. Esther wrote another Pragmatic book, Behind Closed Doors, with Johanna Rothman. I’ve read a number of her blog postings and articles over the years and generally like her style. She is also active at the Agile Conference, running the “Open Jam” stage/sessions. Diana was a director of the Agile Aliance from 2004-2006 and speaks at number of conferences.
The book follows a common pattern: a topic introduction, a set of “recipes”, and some wrap-up. In this case, the introduction covers the first three chapters. The first describes what a retrospective is, providing a framework for retrospectives by breaking them into five parts:
The second chapter describes the importance of fitting the retrospective to the organization, schedule, and other factors. The advice here is generally good. Using the same activities in every situation is at best not going to be as successful as using activities properly tailored to the context.
Chapter 3 gives some advice on how to effectively lead a retrospective. I found this reasonably informative, but some of the specifically recommended dialog felt a little like “pop psychology.” For example, “I’m hearing labels and ‘you’ language.” However, that is not to say that it isn’t good advice, or that I haven’t used something very like it before. And, of course, having lead a few retrospectives, some of this may have been more obvious to me than it would to someone without that experience.
The majority of the book’s content is in Chapters 4 through 8. These work much like a prix fixe menu for your retrospective. That is, they provide a set of activities from which to choose in building a retrospective with the parts described in the first chapter. Each chapter focuses on activities for one of those parts. If you have ever been in a retrospective, you will likely have seen at least a few of these. You may also have seen some that are not mentioned. What makes this valuable is not that it is unique or complete. It serves as a reference when trying to build a retrospective. I can easily see a team turning to this each iteration, especially when their last retrospective may have seemed stale or less productive.
Chapter 9 outlines some of the differences between retrospectives at iteration end compared to project or release retrospectives. These can be different in multiple ways (length of history being discussed, number of people involved) and the book provides some good insight here.
Chapter 10 is short, but provides some good advice and tips for how to get a team (and to a lesser extent an organization) to follow through on the decisions made as a result of the retrospective. After all, retrospection without adaptation is worse than wasteful.
Overall, I like the book. That said, if you are about to lead a retrospective for the first time, this book will not take the place of having been in a retrospective or having a good coach. This book can serve as good preparatory material to help build your confidence and give you options for when things take unexpected turns.
I would recommend this book more strongly to those involved in or leading retrospectives and finding them to be getting stale or losing effectiveness. The lists of activities provided in the middle chapters might just help.
Tags: book review, retrospectives
The last few months have been pretty mixed for me as a programmer. I have been a Java developer since the 1.0 days circa 1996-1997. (Netscape IFC anyone?) For me, it was a great change from C and C++. That’s twelve-ish years with most of my professional work in one language. For the last couple of years, I have been doing a bit more project and people management and less programming. When I have done programming, it has been largely Ruby, HTML/CSS, Javascript and even some C#.
Therefore, it was with a great deal of happiness that I was able to take on a much more developer-oriented role in my latest Java project. I was back in the groove. There were some annotations I had to learn or re-learn, but they mostly made sense. I was concretely producing value again rather than just enabling others to do so.
Over time, I found myself stumbling over difficulties that were entirely Java-centric. I kept running into problems with Generics. Java reflection was a morass of generics and class-casts. I found myself every single day having to say, “I hate Java Generics.”
// a sample usage of generics
// based on a real usage in my current project
Map<Class<ReasonableClassName>, ReasonableClassName> objectByType =
new HashMap<Class<ReasonableClassName>, ReasonableClassName>();
// pre 5.0
Map objectByType = new HashMap();
I was never a fan of the Generics proposal for Java 5. It is just overly verbose as the example above shows. The Java 5 version provides type safety, but at what cost? Fortunately, back then, I was able mostly to ignore this. I only really used generics when using collections, and I tend to wrap those in more domain-friendly objects. That practice also meant I didn’t really need generics in the first place, but c’est la vie. I was happy enough.
In the current project things are somewhat different. I am building upon legacy code, using a lot of collections in a single class, and using a lot of reflection. I found APIs that were inconsistent in their use of Generics. For example:
// from java.lang.Class
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) {
// ...
}
public Constructor<?>[] getDeclaredConstructors() {
// ...
}
Note that when getting a single declared constructor, it returns a properly specified constructor that will create something of the type of the class. However, if I want the full list of constructors, the array returned now doesn’t know what type the created objects would be. There is a reason for this: having a “genericized” array is “bad”. Don’t ask me why. Folks much more familiar with the generics implementation struggle to understand the reason for this.
Regardless, it means I need to cast the result. Is that not what generics were supposed to save me from? This also could lead (depending on the context) to entirely unnecessary type checks or even a compiler warning for “unchecked type cast”. In short, what I have found is that for every benefit generics provide, there are multiple hoops to jump through or other problems that detract from it. Yes, some of this is caused by the implementation and not the concept, but that makes me think worse of Java, not better.
There is also a push to add more “safety” to the language through annotations and other means. Java cannot take more overhead pushed into doing simple things. I am far from the only one to think this. As an example, see this post from almost a year ago.
I am pretty fluent in Java (sans generics) at this point. It is by far the language I know best. However, I now realize that while Java may continue to be what I am paid to do, my personal first choice will have to be something else. Using the language is too much work; it is too cumbersome. I like Ruby already, but maybe I’ll delve deeper into Scala. At least both of them run on the JVM.