I would definitely recommend Mockito over EasyMock (and ofcourse, over JMock). I was initially hesitant of using Mockito on my project, but when I did, I found it a lot easier to use and with a lot less noise in test setup compared to EasyMock.
Using Dbdeploy with Ant, an example
Here is an example of using dbdeploy in an ant build file:
<taskdef name="dbdeploy" classname="net.sf.dbdeploy.AntTarget"
classpathref="lib.dir"/>
<target name="build" depends="create-build-directory"
description="Compile main source tree java files">
<echoproperties prefix="jdbc" />
<echoproperties prefix="smn" />
<javac destdir="${smn.build.dir}" source="1.5" target="1.5"
debug="true" deprecation="false" optimize="false" failonerror="true">
<src path="${smn.src.dir}"/>
<classpath refid="master-classpath"/>
</javac>
<dbdeploy
driver="${jdbc.driverClassName}"
url="${jdbc.url}"
userid="${jdbc.username}"
password="${jdbc.password}"
dir="${smn.base.dir}\db\deltas"
outputfile="${smn.base.dir}\db-deploy-output\all-deltas.sql"
dbms="mysql"
undoOutputfile="${smn.base.dir}\db-deploy-output\undo-all-deltas.sql"
/>
<sql driver="${jdbc.driverClassName}" password="${jdbc.password}"
url="${jdbc.url}" userid="${jdbc.username}"
src="${smn.base.dir}\db-deploy-output\all-deltas.sql"
print="true" classpathref="lib.dir" />
</target>
- Note: dbdeploy does not run your change scripts, you have to run the script it outputs with an sql task
- If you get errors like
> taskdef class net.sf.dbdeploy.AntTarget cannot be found
it means that the dbdeploy.jar is not in your classpath.
Removing duplication from ant build files
Once I started getting my ant build script to work for both my development and production environment, I started getting some (evil) duplication in it.
build.xml
<?xml version="1.0"?>
<project name="some-project" basedir=".">
<property name="dev-deploy.path"
value="./lib/apache-tomcat-6.0.18/webapps">
<property name="prod-deploy.path"
value="/usr/share/apache-tomcat-6.0.16/webapps">
<target name="copy-dev-war"
depends="build" description="copy WAR to webapps directory">
<copy todir="${dev-deploy.path}" preservelastmodified="true">
<fileset dir=".">
<include name="*.war"/>
</fileset>
</copy>
</target>
<target name="copy-prod-war"
depends="build" description=" copy WAR to webapps directory ">
<copy todir="${prod-deploy.path}" preservelastmodified="true">
<fileset dir=".">
<include name="*.war"/>
</fileset>
</copy>
</target>
</project>
As you can see the copy-dev-war and copy-prod-war targets are the same, except for the ${xxx-deploy-path} which is different for each. I couldn’t live with this. How do you get rid of the duplication and have just one target?
Create a build for each environment, which declares (or includes) specific environment properties, and then include a common file that holds the generic ant targets.
build-prod.xml
<?xml version="1.0"?> <project name="some-project-prod" basedir="."> <property name="deploy.path" value="/usr/share/apache-tomcat-6.0.16/webapps"/> <import file="build-general.xml"/> </project>
build-dev.xml
<?xml version="1.0"?> <project name="smn-stock-prices-dev" basedir="."> <property name="deploy.path" value="./lib/apache-tomcat-6.0.18/webapps"/> <import file="build-general.xml"/> </project>
build-general.xml
<?xml version="1.0"?>
<project name="some-project" basedir=".">
<target name="copy-war" depends="build" description="copy WAR to webapps directory">
<copy todir="${deploy.path}" preservelastmodified="true">
<fileset dir=".">
<include name="*.war"/>
</fileset>
</copy>
</target>
</project>
Now I can breathe ok. In this way I was able to remove several duplicate ant targets and significantly slim it down. Besides, adding a new deployment environment would just involve creating a build file which declares its environment specific properties, and then includes the generic build.xml
Frequently used Unix commands
These are written here primarily for my benefit - serves as a quick reminder for me cos I use them a lot
Find a file in the current working directory
find . -name “filename” -print
Scaling agile software development – a few suggestions.
If you are scaling an agile team from say 6 to 60, here are my suggestions. They are from my point of view as a developer:
1. Consider having one large team made up of smaller sub-teams.
Why: People work best in small teams. This sub-teams should be independent, poly-skilled teams. A large team of 60 can be made up of 6 sub-teams of 10 each consisting of developers, analysts, testers and so on. It may mean having 1 big stand-up for important announcements and then 6 different story-focused stand-ups around the 6 team story walls in the room. In one project I was on, a significant communication improvement in the teams when the teams business analyst (BA) and quality analyst (QA) sat together with the developers rather than on the BA desk or QA desk. However this meant that the BAs and QAs had to have their own stand-ups or meetings to help them communicate among themselves.
2. Keep everyone (customer, developers, BAs, QAs, Systems, designers etc) working in the same room if you can.
Why: People can quickly walk up to others, ask questions and get quick answers. Instead of a long explanation over email, or describing technical stuff over the phone, you can grab someone over to your desk and show them the problem directly on your screen. This powerful communication becomes even important as the team size grows. You may have to move to a bigger room.
3. Huddle frequently before and during the story.
Why: Ensure that everyone has a shared understanding of what is to be done. Written requirements on cards may be incomplete, ambiguous or unclear. The story cards are really discussion points, not requirement documentation. The huddle is a quick meeting to discuss what the card is about, and to ensure every one understands what the requirements are, and how the card will be tested / marked dev complete. When the devs pick up a card from the story wall, they should have a discussion with the BAs, QAs, and web developers. This discussion ensures everyone is clear on what is to be done, before the story is started.
Regularly through the development of the story, the devs should grab the BAs or QAs and show what they have working so far. This regularly discussion ensures problems are resolved while the story is in development, not after the story is completed, and dramatically increases quality.
4. Keep scaling balanced - Remember you would need to scale the customer as well:
Why: As the team grows, they need more of the customers time, or even more customer representation. Have a full time customer dedicated to an agile project requires a significant investment from the business. Plan for this. The customer available on the project should be a stakeholder who can take quick decisions on requirements – saying “Can I get back to you on this?” may slow down the development of a story. Too many BAs with too few customers causes a bottleneck, with the customer not having enough time to talk with the BAs, answer questions from developers, test and sign off stories.
5. Keep multi skilled teams sitting together
6. Make the build visible
Make your continuous integration build status visible on a large screen that every one in the room can see. That way every one can quickly see when the build is broken, or taken too long. I like the psychological effect of everyone seeing the build. Tools like cctray http://confluence.public.thoughtworks.org/display/CCNET/CCTray for cruisecontrol show the build status on each desktop tray. The downside is – not everyone remembers to launch cctray, or people just ignore it. A screen is more effective.
7. Keep the build time less than 10mins
See Martin Fowlers notes on keeping the build fast http://martinfowler.com/articles/continuousIntegration.html . A long build time is very expensive for a large team.
Agile developers make small changes and frequent checkins – not being able to checkin for hours means they . The cost of one large checkin is that it may involve merging and conflicts. If it breaks the build, then a big revert, may result, as well as loss in productivity – working code, mixed up with bad code. So if developers can’t checkin, very soon they can’t continue working. The difference is that this now affects 20 pairs of developers instead of 3.
8. Revert first, ask questions later
One major goal with continous integeration is to always keep the build green so people can check in. With a big team, many pairs are checking in all the time. You don’t have the luxury of diagnosing a build break on the continuous integeration server – that may take too much time, and if you don’t get it right the first time, the build goes through one more cycle before you realize its still broken – more time wasted, more developers drumming their fingers on the table. Just revert to the last green build , so others can checkin, then fix the problem on your workstation.
9. Use a searchable wiki
Project wikis tend to suffer from some disorganization as the project progresses. Since wikis are not always hierarchal in nature, a great search feature is essential. Which ever wiki solution you use, ensure that it has a great search feature – not just any search feature.
10. Rotate developers across teams
On a small project, a developer/ba/qa can understand how the whole system works. On a large system, this is not possible. Rotating people across teams helps knowledge sharing, helps people better understand the domain and increases communication in the team.
11. Have Brown bags
Create opportunities for the team to talk about things they are working, problems with project and how they could resolve them.
Unfinished article : work in progress.


