Archive for January, 2007
I was reading through the Pragamatic Programmers’ List of Tips today, which is filled with fantastic, pithy advice. Undoubtably the most-quoted is the DRY principle: Don’t Repeat Yourself. More than just avoidance of code duplication, the principle states that:
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
It occurred to me that there is another, similar principle that could make the list. DRO: Don’t Repeat Others. These days we as developers are spoilt by the richness of open source libraries that we can choose from. Still, at times we fall prey to NIH (Not Invented Here) Syndrome, and are tempted to write our own frameworks and libraries. When there is an established and well-maintained open source alternative, it is almost certainly a mistake to write your own. The advantages of reusing open source are plentiful, with the most important being:
- Code for free. As obvious as you can get: code you reuse is code you don’t have to write. More importantly, it’s code you don’t have to debug.
- Developers for free. A well-maintained open source project brings more than just the code. The developers will keep improving the code over time, and you can take advantage of those improvements.
- Battle tested. A mature open source project will have been tested in the Real World. New code you write will take some time before it even reaches its first Real User for this acid test.
- Low Risk. For the manager wary of not having the code under their complete control: you always have access to the code if absolutely necessary.
So next time NIH hits you, fight the temptation. And next time you are struggling with the learning curve of taking on a new library, persevere. Leveraging open source pays: in the short term and more so over time.
Pulse has strong SCM integration, which includes showing changelist information for changes between builds. For some time, Pulse has had the ability to transform the commit comments that it displays to insert links to external systems. For example, you could link the text “bug 123″ to the summary for that bug in your issue tracking software. This is neat, as you can jump straight from Pulse to any external tool you choose to link to.
As part of Pulse 1.2, we have beefed up this system. One of our customers wanted to be able to strip redundant information from their commit comments as shown in Pulse. This led us to adding the ability to transform commit comments in more general ways than just linking. Now, you can specify an arbitrary regular expression to match and corresponding replacement text. The cool thing is that this mechanism gives you the power to do all sorts of useful transformations on your commit messages. It soon occurred to me that one very useful thing to do would be to support a Wiki-like syntax for your commit messages! For example, you can add a transformer to render text in bold when surrounded by asterixes:
The text between the asterixes is captured into group 1, and the replacement wraps this group with <b> tags. Now when viewing changes in Pulse, important bits stand out:
Of course, we can go much further. Linking is a good thing, so why not support turning anything that looks like a link into one? And anything that looks like an email address into a mailto: link? Here it goes:
Replacement: <a href=”$0″>$0</a>
Replacement: <a href=”mailto:$0″>$0</a>
Now whenever someone references a useful URL, it is but a click away from the Pulse web UI:
We have really just scratched the surface here. The mechanism is flexible enough to do all sorts of weird, wonderful and (hopefully) useful things! Give Pulse a try and go nuts!
So what is OSGi? If you head to the official website for the answer, you could be forgiven for thinking you had stumbled on a game of buzzword bingo. The terms “universal middleware”, “service oriented” and “component based” show up in the first couple of sentences! Putting marketing-speak aside, however, OSGi turns out to be a mature standard for dynamic modules (read: plugins) for Java. Despite the buzzwords, it is also pleasantly simple at its core (plugins are just Jar files with metadata in the manifest). If you’re looking to create a plugin-based application, or to add a plugin system to your existing application, then you should look into OSGi.
In our case, we are adding a plugin system to the next major version of Pulse. We have decided to go with OSGi for a variety of reasons:
- A robust standard for the basic requirements of a plugin system: such as plugin metadata, dependencies, classloading, service management, dynamic loading/unloading and so on. Why reinvent a less complete system?
- A simple core: OSGi plugins (known as bundles) are just plain old Jar files with some metadata. This simplicity will make our life much easier.
- Existing open source implementations: we have chosen the Eclipse foundation’s Equinox implementation, but there are others such as Felix, Knopflerfish and Oscar.
- Eclipse tooling support: as Eclipse uses OSGi under the covers, the Eclipse Plugin Development Environment has tool support for creating and managing OSGi bundles. One of our goals is to make the lives of plugin authors as simple as possible: tool support helps achieve this.
Of course, it is not all good all of the time. There are some challenges we face along the way:
- Lack of documentation: it is seriously difficult to find good documentation about OSGi and the implementations, apart from the standard itself (which happily is reasonably readable). The saving grace is having the Equinox code and a helpful development community.
- Embedding Equinox: the Equinox framework, as part of the Eclipse project, has a certain bias towards being used as part of the larger Eclipse platform (and Rich Client Platform). This is changing over time, but we are finding some interesting challenges embedding Equinox in Pulse.
- Impedence mismatches between Pulse and OSGi: at times the default OSGi behaviour is at odds with how we would like plugins to act in Pulse. For example, OSGi mandates that the state of plugins is persisted by the framework, whereas we want Pulse itself to have control over their state.
As we continue the implementation of a plugin system for Pulse, I’ll post more about the particular things we learn along the way. Hopefully this information will help fill the documentation black hole, particularly in a new area for Equinox: embedding in a standalone application.
Once a technology reaches buzzword-compliance, it starts to pop up in the least appropriate of circumstances. The current manifestation of this is the “improvement” of favourites management on javablogs.
Let’s review favourites as they were. You have the ability to add a chosen blog to your “favourites” list. You can also choose to ignore a blog, so that entries from that blog are hidden. To do this previously, you simply clicked on a “+” or “x” icon next to the header of any entry from the blog:
Simple, and effective. Now, swept up in the hype of AJAX, the mechanism for managing favourites has been updated. The same “+” and “x” icons still appear, but they no longer take direct effect. Instead, they pop up a dialog:
Wow, a nice piece of eye candy that serves no purpose whatsoever. The dialog gives exactly the same options as were available before. The text description of the actions could more appropriately be added as tooltips for the icons. To add insult to injury, you can’t even click on the text, but only the icons on the left. I can see the tagline now:
“Favourites management: Now with extra click!”
A great new feature we have introduced into Pulse 1.2 is tighter integration with change viewers. We have added simpler configuration for common viewers such as Fisheye, Trac and ViewVC (formerly ViewCVS), with custom configuration also possible for other systems. We have also deepened the integration by adding more direct links from Pulse back to your change viewer.
Now, when viewing changelist information in Pulse, you can directly access further information in your change viewer:
- The changelist itself can be viewed in the change viewer by clicking on the revision wherever it appears in the Pulse UI.
- Download and/or view the contents of any file as it was at the revision
- Jump directly to the diff view in your change viewer to see what changes were made to a file.
The shot below shows how these links are presented for each file:
This feature is simple but incredibly useful. Figuring out why a build is broken often boils down to seeing what has changed. With change viewer integration, this information is at your fingertips. There is no need to change context. Enjoy!
In my previous post, UnitTest++: The New Choice for C++ Unit Testing?, I gave a basic introduction to UnitTest++. Moving beyond the basics, you will often want to integrate UnitTest++ into your development process. A key to this is being able to generate test reports in a format amenable to integration. The default output of UnitTest++ is a simple, human-readable summary of the test results:
utpp.cpp(9): error: Failure in MyTest: false
FAILURE: 1 out of 1 tests failed (1 failures).
Test time: 0.00 seconds
This is fine for the developer, but not so easy to process in code for integration purposes. Luckily, the reporting mechanism is not fixed. The test runner accepts an instance of type TestReporter to use for reporting results. The default reporter, TestReporterStdout, produces the developer-friendly output shown above. A second reporter is also included in the UnitTest++ distribution: XmlTestReporter. As its name suggests, this reporter outputs results in XML format, which is much easier to digest in code.
Using the XmlTestReporter is easy. Just construct one with an output stream and pass it to the test runner when executing the tests:
int main(int, char const *)
The results in this case are saved to a file named “tests.xml”. An example XML report is shown below:
<unittest-results tests="3" failedtests="1"
<test suite="SuiteOne" name="TestOne" time="0"/>
<test suite="SuiteOne" name="TestTwo" time="0">
<failure message="utpp.cpp(14) : false"/>
<test suite="SuiteTwo" name="TestOne" time="0"/>
The report is easily interpreted, and can be easily parsed for integration in to other systems. A prime use case would be integration with a continuous integration server, such as Pulse, which is why I am looking into the reports myself .
Finally, if the XML format is not suitable for your purposes, you can also create your own test reporters. The interface is compact and easily implemented.
You are currently browsing the a little madness blog archives for January, 2007.