should I use aspects?

October 21st, 2005

I know I blog about my current problems and observation, but that is what blogs are for, not?

My favourite project at work I consider already as a bunch of legacy code (not line is older that 18 months I think). A collegue labelled it yesterday as a “nice prototype” that grow a little bit too much. Well, I must admit he has a point. Design is simply non-existant (besides some small areas) or went in directions that haven now been proven to be dead-ends.

Two “aspects” are hot now: Logging and Security (I prefer to talk about Privileges). Logging was introduced by old-fashioned instrumenting (aka manually inserting logging-code). Pretty incomplete and all but flexible.

Privileges are “designed in”, but not in all necessary places. I am tempted to use Aspects to implement them for some important “point-cuts”, but I am hesitating.

First of all I am concerned that introducing AOP would open Pandora’s box. We have (yes we are doing code-reviews… but don’t ask) f**king lot of abuse of our framework and Aspects would open another way of creating incomprehensible non-refactorable code.

In some sense this applies even to my Privilege-aspect idea: If we had decided to use some IoC-container the main problem could be solved with a few lines of code. So the “need” for AOP in my case is simply due to inadequate design or is AOP a design-element?

I sure see good uses of AOP, but it seems not to be always clear when to apply it. A fool with a tool is still a fool, and if you only have / really love you hammer, you’ll do anything with your hammer.

static initializers considered harmful

October 16th, 2005

In C++ days we were very careful with static initializers because the initialization order is not defined by the language-specification.
Java is nice here, normally you can define terribly complicated sequences of static-inits and everything is fine. Well, not always.
I am working on a system where the designer used static initalizers as THE replacement for factories. This was initially driven by their preference of concrete classes to interfaces. So the static initializers trigger themselves in a manner incomprehensible to humans. The real trouble stroke when this fine-tuned order was changed by a innocious statement:

class Client {static final Disclosure defaultDisclosure = Disclosure.UNLIMITED;...}

Now loading Client.class triggered loading Disclosure.class which required a valid DataSource-connection in its static initializer…
The previous version of Client used the UNLIMITED only in a method

private void setDefaults() {this.disclosure = UNLIMITED;...}

so that the static inits could continue until the DataSource had been initialized before setDefaults() got called.
Lesson learned: static-initializers should not make any assumptions on the state of the system, since their order is not fixed for good.
static-initializers are simply amazing (in any sense of the word):

public class Enum1 {
public static final Enum1 ONE = new Enum1 (Enum2.NAME);
public static final Enum1 TWO = new Enum1 (Enum2.ID);
public class Enum2{
public static final Enum2 NAME = new Enum2(Enum1.ONE);
public static final Enum2 ID = new Enum2(Enum1.TWO);

Why does this work at all? Consider I load Enum1 first, then the new Enum1(Enum2.NAME) loads Enum2 completly. But stop: Constructing Enum2.ID requires Enum1.ID which is not yet initialized. But rest assured, it works.
But be careful: Within Enum2 you’ll will not be able to access a valid reference to Enum1! The parameter to the arg will be always null, otherwise it would be possible to construct a backwards referencing enum via

public class MyEnum {
public MyEnum(Hidden hidden) { other = hidden.other;}
private final MyEnum other;
public MyEnum getOther() { return other;}
public static final MyEnum ONE = new MyEnum(Hidden.TWO);
public static final MyEnum TWO = new MyEnum(Hidden.ONE);
class Hidden {
public Hidden(MyEnum other) { this.other = other;}
public MyEnum other;
public static final Hidden ONE = new Hidden(MyEnum.ONE);
public static final Hidden TWO = new Hidden(MyEnum.TWO);

This code compiles of course, but MyEnum.XX.getOther() always returns null.