Archive for March, 2005

What to do about TODOs

Many projects I work on are littered with TODOs, FIXMEs, or XXXs. Some programmers use these tags to remind themselves of stuff to do later on in the project. Sometimes, these programmers also comment out whole sections of code using block comments like /*, or even an #if false. To these people I say: a source code file is not a notepad.

The problem with TODOs has to do with the maintainability of the code. If another programmer looks at a class file that contains lots of task tags, he might become confused: to what degree is this class finished? It gets even worse when someone fixes the issue that is mentioned in the TODO, but forgets to remove the tag. There is nothing left to do, but the TODO remains.

Commenting out blocks of code has the same issue: a coworker has to determine why the code was commented out. Was it because it no longer works? Or because it might be useful in the future? But hasn’t XP taught us that planning upfront is the wrong thing to do?

I suppose that using TODOs has something to do with the fact that it is hard to stamp your code with the label finished. As long as there are some TODOs in there, you always have an excuse for a bug, and you never have to take responsibility.

I try never to check in anything that contains a task tag or a large code block comment. I try to keep the code 100% finished, at all times. This doesn’t mean that it does everything yet, but it means that it does everything it is supposed to do correctly. If it doesn’t, you’ve found a bug. Clear and simple.

Comments (7)

XFire Annotations

Recently, I have been working on annotation support for XFire, the light-weight, next-gen, Axis-less Java SOAP framework. Basically, what we are aiming for is that you can use JSR-181-like annotations to export your web service:

package org.codehaus.xfire.annotations.sample;
…
 
@WebService
public class EchoService 
{
    @WebMethod
    public String echo(@WebParam(name=“name”,header=true) String input)
    {
        return input;
    }
}

You can see that you no longer need a service interface class to define what methods are exported @WebService annotates the class EchoService and the XFire runtime that it is a web service. @WebMethod annotates the method echo, and tells the runtime that the method can be invoked over the web. Finally, @WebParam tells the runtime that the echo method accepts a parameter, which should be expressed as SOAP header. Note that you no longer need a separate service interface to define the contract of your web service; you do so with annotations.

These are just examples, there are lots more annotations coming. Take a look at JSR-181 if you’re interested.

If everyone was running Java 5, then the above would be nice and dandy. However, some people are three versions behind and stuck on Java 2. Other people already use some sort of annotation framework, and do not want to use two in one project. Thus I decided to offer the annotation for two the most popular old-style annotation frameworks: Commons Attributes, and backport175. (As a matter of fact, these are the only kind of annotations supported at the moment because I’m developing on a Mac, and [Mac OS|Java] Tiger is still a month away).

The Commons Attributes version of the sample above would be very similar:

package org.codehaus.xfire.annotations.sample;
…
 
/**
 * @@WebService()
 */
public class CommonsEchoService
{
    /**
     * @@WebMethod()
     * @@.input @WebParam(name=“name”,header=true)
     */
    public String echo(String input)
    {
        return input;
    }
}

And everything would work exactly the same as previously!

For you as a XFire user, this means that you can migrate from for instance Commons Attributes to Java 5 with minimal effort. All it should take is changing some imports and moving the annotations out of the Javadoc.

Comments (2)

Towards an Oject-Oriented build

For the umptieth time, I am creating a build environment. And for the umptieth time, I am frustrated with the possibilities that Ant, or–in this case–NAnt–provide. To quote Alef: we’ve got ourselves a pretty decent multi-project build system, continuously integrating and all.

Right now, I’m trying to “port” this system to NAnt for our upcoming .NET-based projects. The system consists mostly of generic build files, which are imported into the project build.xml. Thus, all targets are defined in one place: a common build-common.xml file, and we don’t have to copy and paste anything. Using imports or includes is about the best you can do when you want to create a multi-project build system.

However, sometimes you want to override a target in a specific project. For instance, in some projects, I want to do a code-generation step before compiliation. In other projects I want to do some post-processing after compilation. You can’t do this generically in Ant, unless you use something like the following:

<project name=“sample” >

    <import file=“build-common.xml” />

    <target name=“compile” depends=“pre-compile, common.compile, 
        post-compile” />

    <target name=“pre-compile”>
      <!– Do code-generation step –>
    </target>

    <target name=“post-compile”>
      <!– Do post-processing step here –>
    </target>

  </project>

Note that you cannot have two compile targets, since all targets and all properties live in a global namespace, though Ant 1.6 gave imported targets a separate namespace. Also note that if you use the code generation steps in any other project, I will want to move its definition to a global import/include file too.

Now let’s say that I also want to delete the generated code when I call the clean target. So, in addition to the above, we also have to add the following:

<target name=“clean” depends=“generated-clean, common.clean”>

<target name=“generated-clean”>
      <!– Clean generated code here –>
</target>

Now imagine that I want to use three different code-generation tasks in my project (which isn’t that weird: I have had projects where I did wsdl, commons attribute, and xdoclet generation). Before you know it, you will end up with targets that are called pre-compile-custom, and post-clean-common, and whatnot. Eeek.

Imagine…

Now imagine this: an object-oriented build, where you can use the object-oriented principles you know to solve these issues. Imagine that there are common classes and interfaces that perform build tasks. For instance, there is an interface that is implemented by all tasks that can be cleaned:

public interface Cleanable {
    void clean;
}

For a project, you will probably want implement a basic Project interface and perhaps extend a DefaultProject. But in the project, you can decide where and how to override the default behavior, and use common build components to build you project. For instance, project will definitely also implements Cleanable, and its implementation will look something like:

public void clean() {
    for (int i=0; i < buildComponents.length; i++) {
        if (buildComponents[i] instanceof Cleanable) {
            Cleanable cleanable = (Cleanable)buildComponents[i];
            cleanable.clean();
        }
    }
}

Of course, too make it easier to change your project build, you will probably write in a language like Groovy or IronPython. That way, you can write the real meat of the build in Java or C#, and the rest in a scripting language. Also, there will probably be some kind of (N)Ant-wrapper, so that we can its handy tasks.

Now I know that greater gods have toyed with this idea. I read of people that deserted and returned to Ant. I even looked at Maven, Ruby and Rake. However, none of these solutions give me the satisfaction of the solution I propose above.

To be continued, I am sure…

Comments off

Architecture vs. Infrastructure

This is my first post on Neo (.NET Entity Objects), a framework for .NET developers who want to write enterprise applications with an object-based domain model. I have been using Neo for little over a year now, and it has suited me perfectly for my .NET ORM needs. To further quote the website:

Neo includes tools that create an extensible object-based domain model as well as the database schema from a an abstract description of the model. At runtime, rich schema information is used to dynamically generate all SQL required for object persistence management. Being based on ADO.NET data sets, a Neo domain model is independent of the actual backing store and works equally well with databases and objects in an XML representation.

One of the nicest features features of Neo is that it encourages you to place the business logic in the domain objects. As developers, we have been thought good object-oriented practices such as data abstraction, information hiding, encapsulation, inheritance, polymorphism. It almost seems that we forgot about these principles when we started to make Enterprise software: in both J2EE land and .NET, I often see the following architecture:

  1. Data layer, which contains value objects with just properties,
  2. Business or service layer, with Manager or Service classes that manipulate the data objects
  3. Presentation layer, which calls the business layer

This not a object-oriented architecture (which combines data and process together), this is a functional architecture. Why should we give up on our OO-practices? Because we want to store something in a database? Shouldn’t that be just a matter of serialization…

As counter-argument, I am often told that enterprise-like features such as security, transactions, or auditing cannot be implemented when using a behavioral domain model. Thus, what you see is that the infrastructure of the project is often more important than the architecture; it seeps through the design. Martin Fowler calls this the Anemic Domain Model anti-pattern.

I think that this is wrong: the infrastructure should be a thin layer on top of the architecture, and never influence it. And to end this post on topic: Neo nudges you in the right direction: for every entity, it generates two classes: a value-containing base class, and a behavioral subclass that you are supposed to edit.

Comments (4)

Another JTeammate joins the club

Rob, one of my coworkers, has just started blogging. His first post is about integrating with JIRA, Atlassian’s excellent issue tracker.

Keep em coming, Rob!

Comments off