Ideas:chad3f:RPFramework

From Arianne
Jump to navigation Jump to search

RPClass Initlialization

Issue

The current RPClass definition initialization model as-used is prone to problems and higher maintanance than should be needed. The current form would be coded similar to:

class SomeClass {
  public static void generateRPClass() {
    RPClass rpclass = new RPClass("some");
    rpclass.add("foo", RPClass.STRING);
  }
}

class OtherClass {
  public static void generateRPClass() {
    RPClass rpclass = new RPClass("other");
    rpclass.isA("some");
    rpclass.add("bar", RPClass.STRING);
  }
}

class AnotherClass {
  public static void generateRPClass() {
    RPClass rpclass = new RPClass("another");
    rpclass.isA("some");
    rpclass.add("bar", RPClass.STRING);
  }
}

class MainClass {
   void initFunction() {
     SomeClass.generateRPClass();
     OtherClass.generateRPClass();
     AnotherClass.generateRPClass();
   }
}


This has the following problems/short-comings:

  • It requires the generate methods to be explicitly called from some initialization code. The was an actual stendhal problem were several generateRPClass() methods were defined, but never called.
  • The generate methods have to be called in the proper order. This requires the initialization code to know the implementation details (at least the class tree) of the RPClass's that it's configuring. As a result, unnecessary code-coupling is formed. If it is done wrong, or the heirarcy changes after the fact and nobody thinks to check those fragile dependancies, it could break.
  • The parent RPClass is assigned after creation [via isA()], so there's the chance it could be missed. Or worse yet, called twice with different parents (that could have some nasty unexpected effects).
  • The assigned parent is typically assigned by name, rather than object, which can make it prone to spelling errors. If you're lucky, it will throw an exception, if not a hard to track problem may arise. Also passing the name means a common base class has to be resolved several times.

Proposed Replacement

Using static RPClass constants, and relying on the JVM to enforce initialization order, many of these potential problems can be made nearly impossible.

The replacement code would look like:

class SomeClass extends RPObject {
  public static final RPClass RPCLASS = createRPClass();

  private static RPClass createRPClass() {
    RPClass rpclass = new RPClass("some");
    rpclass.add("foo", RPClass.STRING);
    return rpclass;
  }
}

class OtherClass extends SomeClass {
  public static final RPClass RPCLASS = createRPClass();

  private static RPClass createRPClass() {
    RPClass rpclass = new RPClass(SomeClass.RPCLASS, "other");
    rpclass.add("bar", RPClass.STRING);
    return rpclass;
  }
}

class AnotherClass extends SomeClass {
  public static final RPClass RPCLASS = createRPClass();

  private static RPClass createRPClass() {
    RPClass rpclass = new RPClass(SomeClass.RPCLASS, "another");
    rpclass.add("bar", RPClass.STRING);
    return rpclass;
  }
}

class MainClass {
   void initFunction() {
   }
}

In this code, when one of these java classes is loaded, the static initializer will automatically call it's createRPClass() method. If the class has a super-RPClass [such as OtherClass.createRPClass() uses], before the reference to SomeClass.RPCLASS is used, the JVM will have loaded SomeClass and called it's createRPClass().

If the parent RPClass is only assignable during the constructor of sub-classes [i.e. normal use of isA() goes away], then it will be more obvious that the parent has been omitted. Of course, someone could always call the RPClass constructor with no parent argument, and still forget the super, unless the only constructor(s) available required the parent, in which case the new RPClass(null, "name") would be very obvious as having no parent.


Benefits:

  • Guarantee order of creation.
  • Compile-time parent checking (look ma' no strings).
  • Never having to resolve RPClass's by name (in init code anyway), since the JVM will assign the runtime constant once, and everything else uses this value.
  • No explicit need to force class definition from a common setup class/method, as long as the class containing the RPCLASS constant is referenced before any RPObject instances using that class are bound to their RPClass. And this can be guaranteed if the constant is used when setting the RPObject's class (with the same benefits as RPClass gets).



Message Protocol

TBW



Back to Ideas