Saturday, January 24, 2009

Making fields and methods as private as possible - a postmodern Thatcher.

Fields and methods should be declared as private as possible. As I mentioned in an article on the subject "I thought of writing a tool to do this that I was going to call "Thatcher" - it would privatize as much as possible".

I only realized a few days ago that I've already written it (I really am quite dense), and in fact had written it several years before writing that article.

How do you tell if fields and methods can be made private?

I think the most popular ways for people to tell are:
  • look for all references to the field or method and see if any are outside the class it is declared in
  • change "public" to "private" and see if it fails to compile (e.g. red Xs in eclipse)
Unfortunately, both of these approaches have limitations for most enterprise java applications (particularly web applications). These approaches don't work if the field or method in question is used reflectively, e.g. by a template (e.g. FreeMarker, JSP etc). That's the limitation of a static analysis implementation of "Thatcher".

If you are paranoid, how do you tell if fields and methods can be made private?

The only safe way to tell, for a field or method that you want to see if it can be private, is to make it private and then see if the application still works.

How to automate that?

If you have good test coverage, then "the application still works" is automated as "the build (including tests) passes" (e.g. the build that you use on your CI server).

Then you are left with the problem "how do I tell if "public" can be changed to "private" and the build (including tests) still passes?".

Now that sounds familiar to me - it's rather close to what Jester does.

Jester - a mutation testing tool

I wrote Jester as a mutation testing tool. As it says on the web site: "Jester makes some change to your code, runs your tests, and if the tests pass Jester displays a message saying what it changed." The idea is that if you can change your code and the tests still pass then the tests aren't covering the code (other possibilities are that it's a behaviour preserving change, or the code is redundant).

Jester as a postmodern Thatcher

Jester can be used to implement Thatcher by configuring it to mutate "public" to "private" and "protected" to "private" (package visibility is harder!). I think this could be described as a postmodern programming approach - (re)using some code to do something it wasn't designed for.

I hadn't thought of doing this until it occurred to me a few days ago (and now it seems so obvious) because I had imagined that Thatcher would use static analysis and hence be very different (that's my modernist thinking, it would have to use static analysis to be a fast and "proper" implementation and the fact that it wouldn't always be correct would be a fault of the imperfect world).

It might be that someone has proposed this before (in which case, sorry, I don't remember).

Limitations of Thatcher implemented using Jester

It should be noted that using Jester for implementing Thatcher only works if your build (including tests) has sufficient coverage that you are happy that if it passes then that means the application works.

Also note that using Jester for this could take a really long time. If your build takes an hour then it would take many machine days to privatize even a very small amount of code.

An example run of Thatcher implemented using Jester

Here's an example of using the latest version of Jester ("simple jester" also described here) as Thatcher. For this example, I'm using Checkstyle as the code base for which I want to make fields and methods as private as possible. I chose Checkstyle for this example because the build is very fast!

(To try this out for yourself, you will need Java installed with java, javac and ant on the path. These instructions are for Windows. Replace <wherever> as appropriate).
  • download checkstyle
  • unzip
  • cd to <wherever>checkstyle-src-5.0-beta01
  • in order to check that everything is OK so far, execute "ant run.tests"
should get:

BUILD SUCCESSFUL
Total time: 33 seconds

(or whatever time)
  • download Jester (the simple-jester variety)
  • unzip
  • cd to <wherever>simple-jester-1.1
  • for the step below to work, execute "setcp.bat"
  • in order to check that everything is OK so far, execute "test.bat"
should get:

17 mutations survived out of 19 changes. Score = 11
took 0 minutes

(or whatever time)

In order to check that the checkstyle build can be run from the jester directory (i.e. still in <wherever>simple-jester-1.1) (which makes it simpler for running Jester in this example)
  • ant -f <wherever>checkstyle-src-5.0-beta01\build.xml run.tests
should get:

BUILD SUCCESSFUL
Total time: 21 seconds

(or whatever time)

Now edit "mutations.cfg" (in <wherever>simple-jester-1.1) and replace contents with:

%public%private
%protected%private

That configures Jester to try mutating "public" to "private" and "protected" to "private". Unfortunately, Jester cannot currently be configured to not mutate literal numbers - so in order to avoid Jester making mutations to literal numbers you have to be a bit cunning.

Create a text file in folder "<wherever>simple-jester-1.1\\jester" called SimpleIntCodeMangler.java with contents:

package jester;

public class SimpleIntCodeMangler implements CodeMangler {
public SimpleIntCodeMangler(ClassSourceCodeChanger sourceCodeSystem) {
}

public boolean makeChangeToClass() throws SourceChangeException {
return false;
}
}

Then (in <wherever>simple-jester-1.1) execute "javac jester\SimpleIntCodeMangler.java".

If "." is on the classpath before simple-jester.jar then the new version of SimpleIntCodeMangler will replace the version in simple-jester.jar, so Jester won't do the literal number mutations.

Now to run Jester/Thatcher (just on the one class "Checker"), execute:

java jester.TestTester "ant.bat -f <wherever>checkstyle-src-5.0-beta01\build.xml run.tests" <wherever>checkstyle-src-5.0-beta01\src\checkstyle\com\puppycrawl\tools\checkstyle\Checker.java

(note that on windows it has to be "ant.bat" and not just "ant")

Now Jester will run for a while, and eventually you get:

4 mutations survived out of 24 changes. Score = 84
took 5 minutes

If you want a simple way to visualize the results, then run "python makeWebView.py" and have a look at "jester.html".

To get the code changed to make methods and fields private which can be made private, then run "python makeAllChangesFiles.py jesterReport.xml" and you get a version of Checker.java called Checker.jester (in the same folder, i.e. "<wherever>checkstyle-src-5.0-beta01\src\checkstyle\com\puppycrawl\tools\checkstyle\") which has all the privatizations where the tests still pass.

The results for Checker.java show that addFileSetCheck, setModuleFactory, setSeverity and setClassloader can be made private and the "ant run.tests" build still passes. Having had a look at the code - it might be that these methods need to be public for something not covered by the tests but are needed for the application to work (because the only tests are unit tests and not end-to-end tests; this is a limitation mentioned earlier).

And finally

If you like that (or even if you don't) then please donate to my 5 countries (300 miles) in 3 days bike ride to raise money for the National Autistic Society.

Copyright © 2009 Ivan Moore

Saturday, January 17, 2009

My favourite conference (SPA) is open for registrations. Book before 31 January to catch the early-bird discount rate.

I'm programme co-chair (with Mike Hill) and very happy with the programme we've been able to assemble.

Book now.

Copyright © 2009 Ivan Moore

Sunday, January 4, 2009

Charity Day

I am doing a charity bike ride in June to raise money for the National Autistic Society (NAS). One of my sons is autistic and the NAS have been very helpful. I did a London to Paris bike ride for NAS in 2007.

Please donate!

Time is money

For the 2007 bike ride I paid the costs myself so all money donated went to the NAS. For the 2009 bike ride I'd like to do something equivalent but slightly different. I'm offering a day of my time for a donation that more than covers the costs. (The alternative is that I pay using roughly a day of my usual billing - but I'd like a generous charity minded company to donate more than that).

That day could be:
  • Refactoring and TDD Training
  • continuous integration - e.g. installing an automated CI system (e.g. TeamCity, build-o-matic or whatever)
  • Agile consulting (I've been doing "Agile" a long time - papers at XP2000, XP2001, XP2002, OOPSLA, TOOLS. Presentations at XPDay, SPA, ACCU etc)
  • other stuff (dunno - email me and we can discuss)
and there is more:
  • publicity - I'll write a short blog article - anything from just the name of the company and the donation up to an article about what I did for you (you can review/edit before publication)
  • "small print" - I'm based in London, England. Anything outside of London might require you to pay expenses too.
  • "more small print" - If I get multiple offers then I'll choose whichever I prefer.
To discuss this, or for more details, please email ivan at teamoptimization.com

If you aren't in the market for a day of my time then please make a donation of any amount you'd like!

Copyright © 2009 Ivan Moore

Sunday, December 14, 2008

Running builds for previous revisions

Can you run the build for a previous revision of your code? Can you do that fully automatically or do you need manual steps? Should you care?

It's good to have an automated build

As Martin Fowler says "... you should be able to walk up to the project with a virgin machine, do a checkout, and be able to fully build the system."

There are lots of benefits of having a fully automated build. It means all developers are building in the same way, reducing "it works on my machine" problems. It helps with productivity - you don't make mistakes doing the build and then have to do it again to get it right. There are other benefits too - but there are lots of other articles about this topic so I don't want to repeat them here.

Turning the dials up

What Martin Fowler doesn't say is "... do a checkout for any revision ..." (rather than just the most recent), but I think it is what you should aim to do.

Why "any revision"?

One reason you might need to run the build for any revision is in order to work out which commit broke the build in the case where you have multiple commits between builds and the build is broken. There are other reasons too - e.g. finding out what change introduced some bug that has been hiding undetected for a while (i.e. didn't cause the build to break but now you've found it and want to find out how to fix it or when/how it got introduced).

(As an aside - some CI servers can help reduce the occurrence of multiple commits between builds, but even if you are running a CI server which builds multiple revisions in parallel on multiple build agents, if the build farm isn't large enough for the number of commits and the speed of the build, then you will end up with multiple commits between builds. Or if you take the approach of having the CI server run the build before committing then you end up with a bottleneck delaying commits if you don't have enough agents.)

Can you run the build for a previous revision of your code?

If your system includes a database - how do you manage the database schema? In some teams, this is one of the dirty secrets - it's done by running some scripts manually as necessary - hence you can't run the build for a previous revision (or in some cases even the most recent revision) just by checking out the code (for that revision) and running the build.

Many teams use something like dbdeploy so changes to the database are made as delta scripts which make the necessary changes to the database in synch with code changes. Although this allows database migration forwards in time - how many teams implement the rollback scripts to allow the database to be reverted so that it is in synch with previous revisions of the code? Often you have to just rebuild the database from scratch in that case - and the build script might not do that automatically.

What if you use maven and have snapshot dependencies? How do you build the code the same as it was built an hour ago?

Why fully automate?

Any manual steps in something that you don't do frequently makes it likely that you'll find it difficult to do when you need to. Furthermore, manual steps to build previous revisions prevent you from taking advantage of all of the features of some CI servers (TeamCity, Pulse and build-o-matic all allow manually triggered building of a previous revision of the code. build-o-matic will automatically build previous revisions of your code in some circumstances, so if your build doesn't support running the build automatically for a previous revision then it won't always work as expected).

One of the logical conclusions - your development environment should be checked in

Being able to run the build for any revision of your code might require you to have more things in your source control system than you are used to. This can be controversial (even though it's mentioned in Martin Fowler's well read CI article). I like to have absolutely everything that the build depends on in the source control system - even when it isn't source.

For example, on a Java project, I like to have Java itself, Ant etc all checked in. If you change which version of Java you use (which you are more likely to do than you might think) then you want to ensure that everyone is using the same version and that you can build the project as it was in the past (if Java isn't checked in then how are you going to be sure what version it is or was)? This can be controversial (Martin Fowler mentions "Java development environment" as something that you might not check in but I disagree with him on this specific case) - but if you take the ability to check out and build the code at any point in time it to it's logical conclusion then you have to include everything you need to build it - machine set up and all. One of the advantages of taking things to this level is that it is trivial to set up a new development machine - you just check out everything and you are ready. This isn't always possible - particularly on Windows - but is a worthy aim and more achievable than you might think.

Copyright © 2008 Ivan Moore

Saturday, December 13, 2008

Software Craftsmanship conference 2009

The Software Craftsmanship conference 2009 is open for session proposals. Please submit a session proposal. I think the conference is now fully booked for attendees but you can still get in to the conference if you get your proposal accepted.

It's a great idea for a conference. I think a lot of progress has been made in our industry to improve processes. As teams become better in their processes, programming practices and code quality become relatively more important.

The timing of the conference is great - with the release of more books now that concentrate on code quality (like clean code).

Copyright © 2008 Ivan Moore

Thursday, December 11, 2008

Refactoring and TDD Training Course

I'm offering a completely new style of training course on refactoring, TDD and just programming better. It is pair programming with me (or others depending on demand).

It'll be similar cost per person per day to other courses, but instead of a classroom, it's one-to-one instruction at your site. It's also working on your code base, improving it during the course (possibly adding features too). Attendees will retain more learning that is directly applicable compared to more regular classroom courses. They will learn things from this course in addition to refactoring and TDD, like better use of the IDE, frequent commits, retro-fitting unit tests to their actual code base rather than just in the abstract.

See my "programming in the small" and "programming in the large" articles to get an idea of the sort of programming things that the course will include. (My PhD was in refactoring (completed 1996), I started using JUnit in 1998 and mock objects in 1999). Email me to book a course (and discuss course length - anything from one day upwards) - ivan at teamoptimization.com

Copyright © 2008 Ivan Moore

Wednesday, December 10, 2008

People over Process

The Agile Manifesto values "Individuals and interactions over processes and tools".

I have heard a lot of people talk about "People over Process" somewhat differently than my interpretation.

In this article, I'll refer to a fictional developer called Chuck - nothing is implied by the name.

Chuck doesn't want to write tests

A frequent interpretation seems to be, if Chuck doesn't want to write tests (for example) then that's OK because people are more important than processes or tools. A lot of the time, people talk as if the question of whether Chuck is worth keeping in the team or not isn't a consideration - you just have to do the best you can with the team you've got; after all, people are more important than processes so that's OK (a non sequitur, but I've heard it said).

This can be a difficult one to argue against. Whether someone is any good at software development or not, they are "more important" than process, tools, software - but that is a different "important".

The worst sort of "Agile"

The worst examples of "Agile" software development are where people take the approach that as long as you do the currently accepted "Agile things" (or at least some easy subset like iterations/sprints, stand up meetings etc etc) and keep your current team (because "people are more important than processes or tools") then you are "Agile". This is the opposite of my interpretation of the agile manifesto - but quite common!

My interpretation of "People over Process"


The single most important thing is to get the right people in the team. Just making your existing team follow a set of processes (like iterations/sprints, stand up meetings etc etc) is much less important than having the right people in the team. I think that is what the Agile Manifesto is trying to say.

As Simon Baker says "Put the right people in the right environment and trust them to get things done."

The consequence of this is that you should hire the best developers you can (this article describes the best way to interview them). The less palitable consequence is that you should remove developers from a team if they are not good for the team. That doesn't necessarily mean removing them from the company - it may be that there is another role or team in which they would contribute more. You should also consider whether a developer can improve - my experience has been that pair programming really helps to develop developers.

So should Chuck be made to write tests (or whatever)?

I'm not sure this is the right question. Really the question should be "is Chuck any good for the team?". If Chuck doesn't want to write tests then I think it's unlikely (but not impossible) that Chuck is (what I consider to be) a good developer. It would probably be counter productive to "make" Chuck write tests, but I'd be happy to pair program with Chuck to show him how it works. If Chuck still doesn't want to write tests then I might prefer not to be on the same team as Chuck (one way or another).

Copyright © 2008 Ivan Moore