These are some code samples I put together for a job application.
MuleSource
This work is open source, so I will link directly to
the fisheye
subversion browser (sometimes fisheye is a bit slow; if you would
prefer I can place everything in a tarball - please just ask). It is
Java 1.4 (no annotations or generics) and follows company style
guidelines.
I want to show "real" code, even though it includes all the compromises
you'd expect from working on a 2.x release of a complex, existing
product under "startup pressure" - I think one of my strengths is being
able to adapt to existing code and short deadlines (the flip side of
that, though, is that I sometimes feel I don't fight hard enough for
time to refactor and polish).
Bean Definition Parser
This first example takes an XML configuration file and constructs an
"endpoint" (we build on
Spring's Extensible
XML authoring). These are complex Java objects responsible for
receiving and sending data. Many different endpoints exist (several for
each transport - HTML, POP3, JMS etc) so the challenge here is to make
something that is easy to configure (by whoever is writing a new Mule
transport) in the simple cases, but sufficiently flexible to accommodate
whatever extra configuration options might be necessary.
I have worked extensively on the Bean Definition Parser support in Mule.
My aim has been to construct a modular library of generic components.
In the code below, for example, the parser responsible for configuring
instances of a core Mule class is composed of three delegate parsers,
which all take information from the same XML element (different
attributes are enabled for each). In addition, standard pre and
post-processors allow us to "plug in" additional checks and processing.
AddressedEndpointDefinitionParser
- the main constructor here defines how the element is processed.
It's complex, but you should be able to see the modular and
declarative nature of the code. The "endpoint" presented to a user is
assembled from three Java objects -
endpoint, address
and properties,
each of which is constructed by a delegate parser. In addition
pluggable "pre-processors" (below) verify that the element attributes
meet certain conditions.
CheckRequiredAttributes
- an example pre-processor that verifies that the user has supplied
all the required attributes on the element (due to a directory
renaming the code is attributed to Daniel Feist, but in fact the
majority of all the code here is my own work (including an incorrect
comment which I have just seen and will fix at work tomorrow)).
Notification Manager
This example is more self-contained - a set of classes that allow users
(via the XML config, but not shown here) to register listeners for
particular events. The dispatch of events is based on the type of event
at runtime, using reflection. So a listener may be registered for any
class (and the relevant subclasses), and any object can be submitted to
the manager as an event - the manager must then send that event to all
suitable listeners.
The requirement here was to make a more efficient implementation, since
notifications can be generated within fairly tight loops in the system.
I achieved this by pre-calculating and caching as much information as
possible. In addition, client code can ask the manager whether a
particular event would be used (in a similar way to the standard logging
interface with "isDebugEnabled" etc). Studying the unit test below
should help clarify what is expected.
ServerNotificationManager
- this provides the public API. It delegates the work of storing the
configuration and handling notifications (classes below).
Configuration
- this stores the configuration. It is also responsible for caching
the resulting policy, which must be recalculated when the
configuration changes (this could be part of the manager - one reason
to separate it is that it isolates the synchronised methods and so
makes thread safety easier to check).
Policy
- the policy itself (this is a processed version of the configuration,
with as much information as possible pre-calculated and stored in hash
tables). The logic is pretty opaque, but at least it's isolated (I
wouldn't do this unless it was performance critical).
This is perhaps a bit "too cute", but since it's isolated in a test
case there's no harm done, and it's a good example of the kind of thing I
enjoy doing when I get a chance.
MapCombinerTestCase
- the test here is for merging Maps (ie hashed tables) recursively.
The functionality is needed in the XML configuration code we saw
earlier (we use Maps to store some configuration details in an
"untyped" manner, and need to combine them). Writing the tests in
plain Java would have been very verbose, because I needed to create
and populate Maps containing Maps (and Lists). Instead, I wrote a
parser for a tiny specification language, so that a string
like [a:[b:B,c:C]] describes a map with a single key a
whose value is a map with two keys (b and c).
Numerical
The above code is Java "enterprise" work. This final example is from 10
years ago and shows a simple numerical example in C. It is an
implementation of the 2D Kolmogorov Smirnov test (two samples)
that is O(n log(n)) - the standard algorithm (eg Press et al) is O(n^3).
muac.cmuac.h
- the implementation. I'm afraid I deleted the documentation for
the code when I re-designed this site, but the same algorithm was
discovered independently elsewhere - the idea is to add points
incrementally
to a tree, calculating the statistic from information in the tree
nodes. Since the implementation is in C a fair amount of work is
involved in managing the tree structure in memory (most of the gain
over existing implementations comes from the improved algorithm, but
reading the code I see I also tried to optimise memory allocation - if
I was writing this now, I would measure first to check that was
needed).