a little madness

A man needs a little madness, or else he never dares cut the rope and be free -Nikos Kazantzakis

Zutubi

Archive for August, 2009

Pulse Continuous Integration Server 2.1 Beta!

Exciting news: today we’ve pushed the latest version of Pulse, namely 2.1, to beta! This is the culmination of months of hard work on a ton of new features and improvements, including:

  • Project dependency support.
  • Easier multi-command projects.
  • Personal build improvements.
  • Fine-grained cleanup rules.
  • Built-in reference documentation.
  • Pluggable commands (build tool support).
  • A simpler, faster configuration UI.

The new features are described in more detail on the 2.1 beta page. The largest are the first two: dependencies and multi-command projects.

Project Dependencies

The ability to deliver artifacts from one build to another is a long-standing feature request. Pulse 2.1 supports this as part of a larger dependencies feature. Essentially you can declare one project to be dependent on another, allowing the downstream project to use artifacts built by the upstream one. Artifacts are delivered through an internal artifact repository.

The dependencies feature goes beyond artifact delivery. It also includes smarter triggering for dependent projects, the ability to rebuild a full dependency tree and a new “dependencies” tab which allows you to visualise the dependency graph.

Dependency support is built on top of Apache Ivy. Our aim is for interoperability with existing tools like Ivy and Maven, but without being Java-specific.

Multi-Command Projects

We’ve always had support for multi-command projects in the Pulse build core. However, to access this full flexibility you previously had to write an XML “pulse file” by hand. As of 2.1, the configuration GUI exposes the full flexibility of the underlying build core. This allows you to define multiple recipes per-project, each of which can have multiple commands. All of the advanced command options once restricted to XML files are now also accessible in the GUI.

A key feature related to this is the ability to plug in new commands (e.g. to support a new build tool), and have the plugin seamlessly integrated into the add project wizard. If you plug in support for a command, you get simplified wizard creation of single-command projects using your plugin for free.

Give It A Go!

You can download Pulse today to try it out. Free licenses are available for evaluation, open source projects and small teams.

Functional vs “Java” Style

Stephan Schmidt started it with his third point:

Do not use loops for list operations. Learning from functional languages, looping isn’t the best way to work on collections. Suppose we want to filter a list of persons to those who can drink beer. The loop versions looks like:

List beerDrinkers = new ArrayList();
for (Person p: persons) {
if (p.getAge() > 16) {
beerDrinkers.add(p);
}
}

This can – even in Java – be rewritten to a more a functional programming style. For example using Google collections filter:

Predicate canDrinkBeer = new Predicate() {
public boolean apply(HasAge hasAge) {
return hasAge.getAge() > 16;
}
};
List beerDrinkers = filter(persons, canDrinkBeer);

Then Cedric Beust countered with:

No loops

Java is not very well suited to a functional style, so I think the first example is more readable than the second one that uses Predicates. I’m guessing most Java programmers would agree, even those that are comfortable with comprehensions and closures and especially those that aren’t.

I guess this means I’m not “most Java programmers”. Although I find the verbosity of the anonymous Predicate in Stephan’s code lamentable, aside from that I think the functional style is far superior. And I don’t believe it should be seen as in any way at odds with “normal” Java style. There’s no magic here: it’s just a straightforward anonymous class and filtering is a very simple concept to understand. Conceptually it is no harder than the explicit loop: in fact it is easier as you know the higher purpose as soon as you see “filter”.

The higher level of abstraction is the key to its superiority. Every non-trivial Java project will include many instances of searching, filtering, folding and so on of collections. Repeating this most basic of logic time after time fills the code with mechanical details that hide its true purpose. Why not get those details right once (in a library) and then never have to see them again?

In fact, once you embrace this style, things get even better. Not only can you reuse basic operations like filtering, you can also:

  1. Compose these operations to form even higher-level manipulations.
  2. Build up a reusable set of functors (Predicates, Transforms, etc) instead of using anonymous classes.

The latter point is important, as it allows you to remove an even more damaging sort of repetition — that of your project’s domain-specific logic. Reduce Stephan’s example to:

List beerDrinkers = filter(persons, new CanDrinkBeerPredicate());

and it is clearly superior.

Really, I think it is a shame to see Java programmers hesitant to use this style. The ideas may come from the functional world, but there is nothing but basic Java code at work here. The abstractions are both simple and powerful, which to me is the very definition of elegance.

Apple and the Futurist

I know what you’re thinking: yet another blog about the current App Store controversy. Perhaps you’re wondering which I’ll take out of the disenchanted iPhone developer / one-eyed fanboy angles? Well, for a change, neither. I’d actually like to start with a story…

Some years ago, when my wife and I were buying our first apartment, I found myself making small talk with the present owner. Following the usual script, I inquired how the chap made his living — and discovered that he was a futurist. I took this to mean he was some sort of Dr Who-like figure, navigating his way through time while fighting a variety of evil (yet comic) adversaries. Perhaps sensing my confusion, he went on to explain that this involved working for government think-tanks, speculating on the future and advising on policy.

This started me on a rant about politicians, in particular the shallowness of policy and the tendency to optimise for media sound bites and short election cycles. His response is where it gets interesting. He made the point that although what I said was true, it was wrong to attribute all the blame to the politicians. After all, the reason politicians act this way is because that is what gets them votes: both directly and indirectly via media exposure. So both the voters and media are driving a lot of this nonsense by rewarding shallow policies with votes and air time. His conclusion was that the cycle would never be broken by the politicians themselves — change would have to start from the bottom up.

You can probably see where this is going. Just as I had railed against the politicians, developers are now complaining about Apple’s locked-down App Store. The system is opaque, unfair and at times downright stupid. Blatantly anti-competitive policies are thinly veiled as protection of the user experience. But as wrong as this may feel, should we really expect Apple to change anything? Frankly, they own the platform and are entitled to set the policies they have. And so far, consumers and developers have been voting with their dollars and applications in droves. Even if consumers aren’t fully informed, developers can’t claim to be unaware of these policies, yet still they flock to the platform. With this kind of real, positive feedback, why would Apple feel compelled to rethink their policy?

If you believe the App Store policies are wrong, then cast your vote. Don’t buy an iPhone, and (more importantly) don’t develop iPhone applications. Realistically, in the near term consumers will keep buying the iPhone — it’s still a great product. But if enough developers vote with their applications, over time other platforms will surpass it. Apple’s marketing campaign doesn’t quite have the same ring to it when there isn’t an “app for that”. And if Apple see this shift they will hopefully rethink their policies, and the iPhone will thrive once again.

Pulse Continuous Integration Server 2.1 M5

Things have been a little quiet on the Pulse 2.1 front as we have been busy squeezing tons of extra continuous integration goodness into the existing 2.0 series. Don’t think that 2.1 has been standing still, though, it’s been steadily moving along in the background. Today all that background effort has culminated in a fifth milestone build, Pulse 2.1.4, available on the Early Access Program page.

A combination of the merges across from 2.0 and continued work on new features means that this milestone includes over 100 new features, improvements and fixes! I told you it wasn’t standing still!. This milestone should also be the last before 2.1 reaches beta and is promoted to the main website.

Major changes since the previous milestone fall into two categories:

Dependencies

  • Dependency UI updates: Daniel rightly pointed out that our UI for dependencies leaked too much “Ivyness”1. Now the artifacts published from a build are more closely integrated with Pulse’s existing artifact capturing.
  • Control of build version and status: you can now configure the version and status of your builds for dependency purposes. Downstream projects can be configured to pick up only artifacts of a given or more “stable” status (e.g. milestone, release).
  • Cleanup rules for published artifacts: define if/when artifacts published to Pulse’s internal repository are cleaned up to save disk space.
  • Repository access controls: configure who has what access to the internal artifact repository.
  • Reporting of retrieved artifacts: the build status tab now shows which artifacts were pulled in from upstream projects.

Personal Builds

  • Choose build revision: You may now specify the revision to run a personal build against, rather than having it forced as the latest revision at the time of the build request. The personal build client walks you through available options (including current, floating and last-known-good revisions), or you can specify a custom revision.
  • No forced update: requesting a personal build no longer forces an update of your working copy. Instead you can choose when this is desirable.
  • Pluggable patch formats: Pulse now supports multiple formats for the patches submitted as part of a personal build. Apart from the existing format, plugins have been added to read standard patch files (unified diffs) and git patches (including git binary diffs).
  • Submit existing patches: You can now submit patches from existing files, rather than based on the changes in a working copy. Along with pluggable patch formats, this opens up many new possibilities for submitting personal builds.
  • Smarter patch creation and application: the support for pluggable formats also led to improvements to our existing format and the application of patches. The existing format now uses unified diffs where possible. On application, unclean patching is detected and reported.

Watch this space for more information about Pulse 2.1 and these new features as it hits beta. Oh, and head on over to that Early Access Program page if you’d like to try 2.1 out!


1 We use Apache Ivy internally for dependency management, but aim to make it support all types of projects.