Thursday, August 28, 2008

java.util.Calendar confusion - is it safe or not?

Currently I'm reading couple of technical and agile books (see the nice gadget on the right panel) and one of the books is "Effective Java - Second Edition" by Josh Bloch.

Josh's item number 5 - "avoid creating unnecessary objects" tells me that I should not create (unnecessary) instances of classes like java.util.Date and java.util.Calendar:

// DON'T DO THIS
public void someMethod() {
// unnecessary allocation of expensive object
Calendar cal = Calendar.getInstance();
...
}

He suggests using "heavy" objects only once, during the static initialization of the class:

public class Person {
...
static {
Calendar cal = Calendar.getInstance();
// do some initialization using Calendar instance
...
}
...
}

I can agree with this point but on the other hand consider a following snippet:

// DON'T DO THIS
public class Confusion {
private static final Calendar CALENDAR = Calendar.getInstance();

public void doSomething(Date date) {
CALENDAR.setTime(date);
...
}
}

This code does not perform initialization using Calendar but uses this class to perform some on-the-fly computations - this is the place where this example differs from the previous code snippets (I use "heavy" object after the class initialization and cannot do it in a different way). My code snippet is potentially dangerous: FindBugs tells me:

[STCAL] Call to static Calendar [STCAL_INVOKE_ON_STATIC_CALENDAR_INSTANCE]

Even though the JavaDoc does not contain a hint about it, Calendars are inherently unsafe for multihtreaded use. The detector has found a call to an instance of Calendar that has been obtained via a static field. This looks suspicous.

For more information on this see Sun Bug #6231579 and Sun Bug #6178997.

This way my code should be refactored to this shape:

public class Confusion {
public void doSomething(Date date) {
Calendar cal = Calendar.getInstance()
cal.setTime(date);
...
}
}

But hey! Josh Bloch tells me that creating java.util.Calendar is expensive and he's the Guru - he must be right. Maybe I missed the point of "creating unnecessary objects" and in my example if I want to operate on dates using java.util.Calendar object this is really necessary?

Anyway I'm a bit confused - how should I use java.lang.Calendar objects? Using them as a final static constants is dangerous but on the other hand creating them every time I need it can deteriorate the performance or memory footprint.

What do you think?

Tuesday, August 26, 2008

Maven supports JAR Hell

In one of my previous post I wrote that using development frameworks pays off and it is generally worth investing your time in learning how to use them. I was also clear that learning process is not easy and you could lose some hair from your head or simply go mad.

I would like to present an example how easily you can get lost using Spring Framework together with Struts 2 and Maven. The problem I'm going to present is often referred as a JAR Hell. I will present ideas how to cope with that.

The Problem


In the following paragraphs I'm going to present libraries dependency problems I encountered integrating Spring Framework with Struts2. I will also present how I discovered what the real problem is and how I solved it.

Let's go
In one of my projects I use Spring integration with Struts2. In order to use this integration I have to add following dependency to pom.xml:

<dependency>
  <groupId>org.apache.struts</groupId>
  <artifactId>struts2-spring-plugin</artifactId>
  <version>${strutsVersion}</version>
</dependency>

Spring dependency
I used not only Spring integration for Struts2 but Spring Framework itself thus I had to add dependency to it. If you want to use Spring you can add it to your project in two different ways. One way is to add only those Spring components you need - the full list is available here:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>${springVersion}</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>${springVersion}</version>
</dependency>
...

The other way
This was the way I used it at the beginning but later I decided not to trash my POM and to replace multiple dependency entries with one (full Spring package with all components - it's about 2.8 MB):

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring</artifactId>
  <version>${springVersion}</version>
</dependency>


Here is my full pom.xml I'm using in the example.

JUnit errors
I built the project and my tests were OK - I was happy. Unfortunately when I started developing next feature I created new Spring-based unit test i.e. (please refer to Spring documentation for details):

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:/spring/applicationContext*.xml",
"classpath:/spring/context-hibernate-test.xml"
})
public class ...Test {

and tried to run it from Eclipse. How surprised I was when I got this exception:

java.lang.NoSuchMethodError: org.springframework.core.annotation.AnnotationUtils.findAnnotationDeclaringClass(Ljava/lang/Class;Ljava/lang/Class;)


That's pretty strange one :) And the whole build process was OK when launched by Maven!

Investigation
I checked the Spring Forum and I found what causes this problem: So basically, just make sure you are using spring.jar and spring-test.jar from 2.5 RC1, and that should do the trick.
But Hey! I'm using Spring 2.5.5! WTF? After some brainstorming with myself I checked my project's build path and I found something strange - in my classpath there were Spring libraries spring-beans, spring-core, etc. with version 2.0.5 (yes - spring-2.5.5.jar was also there). It took me some time and brain-effort to identify my enemy. I checked struts2-spring-plugin POM. Everything became clear - this plugin imported Spring JARs in different versions than those I needed.

The Solution


There are two solutions to this problem.

First way
First one is to define Spring dependencies as separate modules i.e. this way. Maven will not import old JARs because you explicitly define which version you want.
Disadvantage of this solution is that you will have to know which components are used in runtime by your system - it's not always obvious at the beginning and you will have to understand many runtime exceptions before you get the correct dependency configuration. It's also possible that you will not set dependency for all Spring modules imported by Struts2 and in your classpath you will have almost all JARs with version let's say 2.5.5 but still some Spring modules will be imported with version 2.0.1.

The other one
The second solution is to define Spring dependency this way. With this solution you have to exclude problematic dependencies from struts2-spring-plugin:

<dependency>
  <groupId>org.apache.struts</groupId>
  <artifactId>struts2-spring-plugin</artifactId>
  <version>${strutsVersion}</version>
  <exclusions>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
    </exclusion>
  </exclusions>
</dependency>


This way you tell Maven that you only want struts2-spring-plugin and you don't need it's dependencies to be resolved automatically.
I think I don't have to describe disadvantages of this solution - anyway this is my preferred way of doing this.

Lesson learned?


I'm not going to throw away Spring and Struts2 integration because I have some problems with it. OK - I lost some significant amount of time on investigation the problem and finding the solution but I now know that I have to careful with Maven2 dependencies. Even if you depend on some concrete version of some framework Maven will automatically download and add missing dependencies. The problem is that it can make real mess in your classpath adding unnecessary JARs and it will be difficult to find the problem occurring in runtime.

The truth is that even with tools that manage software dependencies for you you may encounter some problems like the one I described. Managing dependencies is hard and I have no simple answer how to do it right at once. When you develop Java project you should use Maven-like tool but it still is not perfect (and probably will never be). The good idea in general is to version libraries you use (JARs, DLLs, whatever) and to put the used version in the file name (Maven does that automatically).

It's not very helpful tip but you should be careful :) and most of the time know what dependencies will be included with the next library you're going to use. You have to check for possible conflicts and resolve them by removing unnecessary dependencies.

I know it doesn't help much but that's the way it is - dependency management is hard. Full stop.

Originally published on AgileSoftwareDevelopment.com

Wednesday, August 20, 2008

Is everything OK for you?

People
picture courtesy of xurble@Flickr
I've talked with my friend recently and he complained about his team leader (actually he was explaining me why his team leader sucks). It's not about her personality or attitude but my friend's biggest complaint was questions his team leader asks him e.g.:

- Is everything OK for you?

Well... How can you answer this question. Is she asking about my private life, my development environment, my current assignments? What answer does she expect? If almost everything is OK for me but I have some ideas how to improve team's performance should I answer "Yes", "Yes, but..." or "No"? This is a wrong question IMHO - it shows lack of respect because team leader doesn't really care about the answer, it's like "How are you?".

If you are Team/Project Lead and you lead development team you should read this post and get to know engineer's point of view.


Why such questions suck?
Let's suppose I work in a team and I see that the code we are producing is not well tested. More so our team does not have any continuous integration (CI) tool installed. I want to share my ideas how to cope with such problems but my team lead is hard to catch and always busy.
Though she regularly asks me questions like "Are you OK with the team?", "Is everything OK for you?". Should I talk about CI and tests problems here? Is it a good time for her to talk about my ideas? These questions does not encourage me to touch any real problems our team might have.

What questions engineers expect?
Engineers are really concrete guys and they expect concrete questions. Yes - it hurts sometimes but what we are doing is often so complex that asking general questions refers to void - do you really want to know about void? (Isn't is an example of micromanagement?) In my friend's example the question his team lead asks are very general.

How much easier it would be if she regularly asked him questions like:
- Do you see any problems in the project we are currently developing?
- Do you think our development process is working well? Have you got any ideas how we can improve it?
- Do you need any help in what you're doing?
- Do you have any ideas how to ...?

Use your people's creativity
If you are managing software development team you should learn what questions to ask. You should ask questions that cannot be answer with simple "Yes" or "No". Ask questions that enable your engineers to express their feelings, ideas, fears. Your engineers are very creative (I'm sure of that) - let them talk to you and share their ideas, let them think and create!

Ask the right questions - you will get the right answers
If you're asking the wrong question like "Is everything OK for you?" don't expect the right answer (whatever it means). What do you expect from your engineer while asking such question? Are you expecting me to tell you about my weekend? Then ask me about the weekend. Are you expecting me to tell you about my children? Then ask me about my children.

Asking right questions is a key to good and open communication - and it's the most important factor in an efficient development team (see also XP Practices). Asking the right question will give you the right answer i.e. the answer for your concrete question - no misconceptions. If you want to ask me general question just to see if I'm not sleeping (keep-alive?) just say "Hello!" - if you want to ask a question and you don't expect any answer (ping?) - just don't do it! - you will not earn my respect by doing that.

If you are lucky to work in the Agile environment, this problem could be solved to some extent during Daily Scrum Meeting where you can share your ideas and problems or via the retrospectives when the team is encouraged to analyze their way of working.

Advice
If you're a team or project leader it means that you are smart enough to find some right questions that will let your engineer talk about real problems and real solutions. Ask your questions often and you will see how many opportunities you can find around you.

Be careful, when asking way too general questions - at times it might be worse, than asking no questions at all.

Originally published on AgileSoftwareDevelopment.com

Monday, August 18, 2008

Couple of book reviews (part 2)

It's been some time since my last book review but I've been reading - that's for sure. Here is the list of books I've read since May:



I was quite disappointed with this book especially when I read that agile development means lack of discipline (how about unit testing, pair programming, continuous integration, etc.) This book tries to give managers tool for deciding which methodology (waterfall/spiral/RUP or agile) is better to which kind of projects - the variables are criticality of the project (how many lives depend on this software), number of people developing this software and probably time (probably because I don't remember exactly). Anyway - I'm giving this book 3/5.



Excellent, brilliant, great book! This book is the best book written by Ken Schwaber about Scrum. It gives theoretical fundamentals for Scrum and answers the question "Why Scrum works better that waterfall for software projects?". If you use Scrum this book is absolute MUST for you. my score: 5/5.



This book gives project leaders seven agile tools that will make your team work better. Authors take as many ideas from Toyota lean methods as possible and they show why they work. After reading this book you can understand why old methodologies like waterfall doesn't work and why agile methods like Scrum works. Absolute MUST for agilists. Score: 5/5.



I will tell you one thing: the first book was much better. Although some thoughts in this book are really great, it is generally boring. And it's quite strange because I read the first book in couple of hours and I was fascinated. Maybe it's too similar, maybe author focuses too much on his American roots and American culture (too many "we are Americans and we do it like this and that"). Well, maybe this book is for Americans only. I'm giving this book 3.5/5 but only because I like the author and his previous book.

Sunday, August 10, 2008

Refactoring in action

Quite recently I attended my company's internal presentation regarding agile software development (ASD). During Q&A (questions and answers) part someone who was not convinced to use ASD complained that refactoring means rewriting the code from scratch. It's bullshit, of course, but as you can see people who don't know ASD can proliferate misconceptions about many ASD ideas.

In this post I would like to show you an example of refactoring in an unconventional way. I hope you will like it.


My very first apartment
Two years ago I bought my very fist apartment in the center of Gdynia. This picture of the kitchen was taken a day after housewarming party (before the rennovation):


Refactoring phase
We (me and my wife) didn't want to change too many things in this flat. We wanted to have a new kitchen and bathroom but the rest should be more or less untouched. In other words we wanted to do only slight refactoring of our apartment.

We were Product Owners and we changed our mind after some pieces of advice made by our parents and friends and we decided to change electrical, heating and water infrastructures as well. The refactoring was getting more serious.

When the heating and electrical teams finished they work (they completely destroyed our bathroom - this was part of the plan, unfortunately) we employed another team in charge of making our bathroom and walls flat ;) shiny, colorful and beautiful. At that stage we really wanted to keep the parquet on the floor but as our refactoring proceeded we discovered many unpleasant surprises ;) We had to remove the parquet and fill some holes in our floor with new layer of concrete! Oooops!

Our "product" looked like this (the middle of the "release"):


Refactoring often hurts
I as a Product Owner was in despair - I didn't want to watch this mess. Our apartment looked like big shit and it was getting worse and worse. Our refactoring phase was at the peek!

I was a good project manager of this project and coordinated work of 5 different teams - when one team finished the job the next one entered the flat few days later. Of course we had many many problems with the guys and it was often big hurt but my stubbornness and will made it to the happy end.

The refactoring was painful (especially that it was our beloved and very first apartment we wanted to inhabit very quickly) but the effect was stunning:


Retrospection
Our release took 2 months and the phases we went through were:

  1. completely destroyed bathroom

  2. destroyed walls in every single room

  3. destroyed floors


and maybe something more traumatic but I don't want to remember this.

We didn't destroy the structure of the walls and any other fixed elements of the building but within the flat we refactored almost everything. We made this flat amazingly beautiful, safe and modern (all "middleware" infrastructures are new). And it was worth it - even taking into account "renovation trauma" we still have :)

Software analogy
Please note that the analogy to the software refactoring is not very strong here as you will be probably tempted to perform rather shorter refactoring cycles. However, such big software refactoring happens (I used to do some) and can last even for half of the 30-day iteration but you have to perform them very carefully (hopefully you have good test coverage and you can sleep well after such operation). Going with this analogy further - it's much easier to make another short software refactoring task after few iterations and add some more features than destroying another room in the apartment while already living there - these worlds are not 100% compatible here :)

Refactor or not?
I think this example is quite extreme but hopefully shows how code refactoring could look like. In the middle of the refactoring phase, which can be project-wide and affect 80% of your classes and packages, you can have complete mess (or brothel if it translates to English). But at the end refactoring pays off and you can easily get new infrastructure and internal design. Your code will be more extensible and ready to implement new features. And it's not rewriting your code from scratch (look, we didn't destroy the whole floor of flats - we reordered the internals).

If you need to refactor your code significantly and you know the value will be greater than the cost you should definitely go for it. It could be painful, your manager and colleagues could hate you during this period of time but when they see the effect they will love you (of course if you succeed :). And you could go on holiday - someone else will add new feature basing on new refactored code.

Originally published on AgileSoftwareDevelopment.com

Thursday, August 07, 2008

How to start with Scrum

The best way to start SCRUM is to hire someone who worked in such environment - likely SCRUM Master. But if you want to learn about SCRUM from the Internet and books here is my checklist.

The best book I've ever read on SCRUM is Henrik Kniberg's ebook:
SCRUM and XP from Trenches

Quite short and comprehensive introduction to SCRUM by Pete Deemer and Gabrielle Benefield:
SCRUM Primer

The shortest encyclopedic description available on Wikipedia:
SCRUM (Development)

Good way to learn is to take good examples. One of them is Atlassian - you can learn how they do SCRUM with XP from their blog:
SCRUM and XP in Atlassian

If you want to have up-to-date news about SCRUM and agile world in general you should subscribe to some RSS feeds:
http://feeds.agilesoftwaredevelopment.com
http://www.scrumalliance.org/rss

I also have to mention Ken Schwaber's book (their are absolutely MUST):

If you are currently using Scrum you have to be also aware that even with this framework you can screw up. This presentation tells you what to do in order to succeed: 10 ways to screw up with Scrum and XP

Image taken from Henrik Kniberg's e-book

Wednesday, August 06, 2008

How issue tracking systems fit agile development?

Let's assume you work in an agile team and follow the Scrum framework. Let's also assume that you collect and track requirements "using" user stories. Mike Cohn in his brilliant book User Stories Applied somehow discourages from putting user stories into "digital tracker". In his opinion the best place for user story (most probably yellow or green sticker) is cork- or whiteboard.

As far user stories are concerned I totally agree - but what about programming tasks, bugs and other ah-hoc "low-level" developer's communication? How can small sticker with information like this As a user I want to ... [in order to ...] help itself developers deliver the user story to the customer?

Isn't some tool help needed here?

Agile development process
In my previous team we used Scrum i.e. we collected user stories from Product Owner, estimated them during planning poker session, planned the release and Scrum iteration, were meeting everyday during daily Scrum meetings, demoed product after iteration and finally we retrospected finished iteration. This is all about high level project tracking i.e. on the user story level. But we - developers - need to track also issues i.e. smaller tasks that can be implemented, fixed, commented, investigated, discovered, applied, etc.

The tool that was helping us track project from the developer's perspective was JIRA. This is not sponsored post and nobody pays me for advertising JIRA (maybe they should :) but I'm going to recommend this tool in the next paragraphs.

Let's break the story
OK - we have a user story As a user I want to create new account in the system. And this user story is cool from the user's perspective but it needs to be split into tasks during planning session. You need to:

  • Create database table for users

  • Create class representing the user

  • Create Data Access Object (DAO) for user objects

  • Create service class that integrate everything i.e. (basic flow) checks input parameters, creates user object from given input parameters, create transaction, stores user into database, handle exceptions, close transaction, return OK or error message back to the UI

  • Probably create UI to access this feature from webpage or thick client

  • Create automated tests including UI tests


As you see developers have a lot of work here with one simple user story. And these single tasks should be tracked.

Why to track it?
You should track your issues in order to store useful information about each task, decisions taken, problems occurred, etc. You should track your issues also because after couple of months you could ask someone a question why something was implemented this way not the other way. The answer will be in the issue tracker with links to the source code (you could see single lines that solved the problem). The communication history will be there for you.

Developers also need to communicate with stakeholders, users, bug reporters, etc. in an effective way. And it's not always possible to have them on-site. They have to be able to give the team feedback even if there is nobody in the office - you cannot call development team members when they are at home or during vacation.

As you can see there is many arguments for tracking your projects' issues.

How to track it?
Tracking issues is the job for issue tracker, of course :) Issue trackers enable bi-directional communication i.e. on the one hand customers can report problems and new features (?) and developers on the other hand can ask customers (or other developers) for clarifications (whether they correctly understand the issue, what is really necessary, etc.).

Of course, you can employ Excel sheet to track your issues but this "solution" does not scale and if your team is bigger then you alone you should resign from this concept - employ issue tracker instead.

Which issue tracker to choose?
You can find quite comprehensive comparison here. The decision is not easy because there is many systems that do the job but I would personally recommend JIRA.

JIRA is the best issue tracker I've ever seen and worked with. This tool is cool, sexy, easy to use, intuitive, easy searchable, etc. I can enumerate many many more advantages but I want to keep the size of this post reasonable.
This tool encourages everybody to add new issues/bugs, to comment, to fix them! It is the tool every decent software development team should use - and not only the agile one. JIRA is not only a great toy (yes, developers love toys) but extremely valuable stuff that helps us doing the software.

Of course JIRA is not the only choice and it's not very objective recommendation as I don't know many other trackers. However I worked also with Mantis and many internal issue trackers (yes, you know this kind of crap).

Should I resign from paper stickers?
NO! Keep your user stories on the board and meet everyday by it. It's much better to meet by the physical table and stickers that you can actually touch and move around the board. Don't abstract and digitize things that work good in the real world.

But when it comes to bugs, task and issues use issue tracker. It cannot be tracked other way effectively.

What about being agile?
If you are using issue tracker you still can "be agile", however your tracker has to be agile-compliant. Some issue trackers - most probably your internal corporation-wide crap - are not able to fit the agile world. With some trackers it's hard to create an issue, not to mention commenting it and passing some communicates at all. Some issue trackers can be successfully interchanged with an Excel sheet and the quality of the "tracking" will be the same.

Conclusion
Originally I wanted to conclude this post using such sentence "Issue trackers are definitely part of the Agile Development world!". However, later I realized that it's not true. JIRA issue tracker is one of the tools that definitely fits the agile world but it doesn't mean that all issue tracking systems fit this world too.

Not every issue tracker fits the Agile Development world - you should definitely track your projects' issues but if you want to stay agile use an agile issue tracker.

Originally published on AgileSoftwareDevelopment.com