Tags:
create new tag
view all tags

Lazy Initialization

Context

An internal, application specific set of design rules in the implementation of TyRuBa. These rule ensure that the instance variables of SomeSpecificClass are properly initialized before being used.

While this rule is specific to a particular class in the TyRuBa code base and governs the internal structure of that class, it is likely that similar structural idioms are used elsewhere (to lazyly create PreparedInsert instances used by a class.

Description

In the class tyRuBa.engine.MetaBase the following design rules are adopted to govent orderly initialization of fields that hold an instantce of PreparedInsert.

  1. The fields that hold an instance of PreparedInsert should match the naming pattern *Fact.
  2. The *Fact fields should be set to null initially.
  3. Any method that uses a *Fact field must call the method lazyInitialize first.
  4. All *Fact fields are initialized in lazyInitialized.

Rationale

Following this group of rules dictates exactly how and where the *Fact* should get initialized and makes it easy to verify that indeed they are initialized before they are used.

Example

public class MetaBase {
   
   private PreparedInsert typeConstructorFact = null;
   private PreparedInsert nameFact = null;
   private PreparedInsert subtypeFact = null;


   private void lazyInitialize() {
      if (typeConstructorFact==null) 
         try {
            typeConstructorFact = engine.prepareForInsertion("meta.type(!t)");
            nameFact = engine.prepareForInsertion("meta.name(!t,!n)");
            subtypeFact = engine.prepareForInsertion("meta.subtype(!super,!sub)");
         } catch (ParseException e) {
            e.printStackTrace();
            throw new Error(e);
         } catch (TypeModeError e) {
            e.printStackTrace();
            throw new Error(e);
         }
   }
   
   public void assertTypeConstructor(TypeConstructor type) {
      lazyInitialize();
      try {
         typeConstructorFact.put("!t",type);
         typeConstructorFact.executeInsert();
         
         nameFact.put("!t",type);
         nameFact.put("!n",type.getName());
         nameFact.executeInsert();
         
         type.setMetaBase(this);
      } catch (TyrubaException e) {
         throw new Error(e);
      }
   }
        ...

Definition

JQuery

These rules can be partly verified by JQuery.

The following queries can be run on the MetaBase class (i.e. with ?this bound to the MetaBase class) to verify some parts of the desing rule.

The following query detects methods that access a *Fact* field but do not call lazyInitialize:

    reads(?M,?f,?), re_name(?f,/Fact$/), 
    NOT( EXIST ?lazyInit : 
           name(?lazyInit,lazyInitialize), calls(?M,?lazyInit) )

This rule is weaker than our actual design rule: it does not guarantee that the lazyInitialize is called before accessing the field. However, this is a good enough rule in that it ensures that at least the developer did not forget the call. It is unlikely in this case the call is not in the right place (at the beginning of the method).

The following query ensures that all *Fact fields are initialized in the lazyInitialize method (so they are not accidentally forgotten).

   field(?this,?f),re_name(?f,/Fact$/), 
   name(?writer,lazyInitialize),       
   NOT( writes(?writer,?f,?) )         

The following query finds violations of the naming convention for Fact fields:

    field(?this,?f),type(?f,?PrepIns),name(?PrepIns,PreparedInsert), NOT( re_name(?f,/Fact$/) )

The following query ensures finds if their are any field writes in the wrong places (i.e. outside of field initializers where they are supposed to be set to null, or outside of lazyInitialize method.

   field(?this,?f),re_name(?f,/Fact$/),
   writes(?writer,?f,?loc),
   NOT( Initializer(?writer) ; 
        name(?writer,lazyInitialize) )

This rule is also weaker than the actual design rule: it does not verify that a null value is assigned in the initializer or a non-null value is assigned in the lazyInitialize method.

MetaL

I don't know if this can be verified by MetaL. But it is possible MetaL may be able to verify a more general constraint that nothing should be used before it is initialized.

AspectJ

AspectJ can express some of the same things that JQuery can but not all of them.

  • can verify that field writes appear in the right contexts only (I think).
  • cannot verify that all fields are properly initialized inside of lazyInitialize (AspectJ can say what is not allowed but can not say what is mandatory).
  • AspectJ can enforce the Fact field naming convention (I think).

HypotheticaL

naming convention

    forall field(PreparedInsert MetaBase.*) => nameMatch(*Fact)

Calls lazyInitialize:

    forall get(MetaBase.*Fact) 
    always precededby( call(MetaBase.lazyInitialize()) )

No initialization in wrong place:

    forall ?f=field(MetaBase.*Fact) && set(?f) 
    always withincode(MetaBase.lazyInitialize()) || withincode( initializer ?f )

Ruminations

-- Main.kdvolder - 05 May 2005

Edit | Attach | Watch | Print version | History: r2 < r1 | Backlinks | Raw View |  Raw edit | More topic actions
Topic revision: r2 - 2005-05-05 - KrisDeVolder
 
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback