Integration of the Classbox Concept in the .NET Framework


[Background] [Classboxes] [Example] [Classboxes in C#] [Backend] [Summary] [Publications] [Contact]

Background

Nowadays, many software systems are built using the object-oriented software development approach. However, as many people know, the object-oriented approach can be troublesome when it comes to the extension of a program. More precisely, the mainstream object-oriented approach provides only limited support for horizontal or vertical addition to a class hierarchy.

While in general it is always possible to add (vertically) new classes to a system, existing classes can only be extended with new, orthogonal behavior (horizontally) in an often non-object-oriented style, that is, by breaking the object-oriented encapsulation property (e.g., the Visitor pattern). Such extensions are awkward at best, and error-prone at worst. Furthermore, the inheritance relationships in mainstream object-oriented languages are not powerful enough to capture many useful forms of incremental modifications.

There are several approaches to resolve this problem. One of them would be the classbox concept.

What are Classboxes?

Classboxes are a new module system for object-oriented languages that defines a packaging and scoping mechanism for controlling the visibility of class extensions to portions of object-oriented systems:
  • A classbox defines an explicitly named scope within which classes, methods, and variables are defined.
  • A classbox supports the local refinement of imported classes by adding and/or modifying their features without affecting the originating classbox.

How can we denote change?

Denote Change

Class extensions are used to add or refine features of existing classes in a namespace.

How can we manage change?

Manage Change

Class extensions are only visible in the namespace in which they are defined.

A Point Class Hierarchy Example

Point Classboxes
  • OriginalCB defines classes Point and BoundedPoint.
  • LinearCB imports BoundedPoint from OriginalCB and defines LinearBPoint.
  • ColorCB imports classes Point and LinearBPoint and refines Point locally with Color.
  • TraceCB imports classes Point and LinearBPoint and refines Point locally with Trace.
  • LinearCB, ColorCB, and TraceCB implicitly import the classes required to maintain inheritance relationship.

Explicit Class Extensions in C#

In our model, a classbox is represented as a namespace in C#. To implement the classbox concept, we add two new syntactic facilites:
  • extension-declaration
  • using-extension-directive

The syntax for extension-declaration:


	extension-declaration:
		extension identifier class-body ;opt
    
The syntax for using-extension-directive:
	using-extension-directive:
		using identifier = type-name extension-application
	extension-application:
		includes opt refinements opt
	includes:
		include type-list;
	refinements:
		append type-list;
     

ColorCB and TraceCB:

namespace ColorCB 
{
	using System.Drawing;
	using Point = Original.Point append Color;
	using LinearBoundedPoint = LinearCB.LinearBoundedPoint;

	extension Color 
	{
		private Color color;

		public Color Color { get{ return color; } set{ color = value; } }  
	}
}
    
namespace TraceCB 
{
	using Point = ColorCB.Point include TraceMoveBy;
	using LinearBoundedPoint = LinearCB.LinearBoundedPoint;

	extension TraceMoveBy 
	{
		public void MoveBy( int dx, int dy )
			{ Console.WriteLine( "MoveBy: {0}, {1}", new object[] { dx, dy } );
			  base.MoveBy( dx, dy ); }   
	}
}
    

The front-end translates the locally refined class Point in ColorCB and TraceCB into a new class Point as shown below:

public class Point : OriginalCB.Point 
{
	private Color color;

	public new virtual Color Color { get { return color; } set { color = value; } }

	// required constructor(s)
	public Point( int ix, int iy ) : base( ix, iy ) { }
}
    
public class Point : ColorCB.Point 
{
	public override void MoveBy( int dx, int dy )
	{	
		Console.WriteLine( "MoveBy: {0}, {1}", new object[] { dx, dy } );
		base.MoveBy( dx, dy ); 
	}

	// required constructor(s)
	public Point( int ix, int iy ) : base( ix, iy ) { }  
}
    

Remaining Issues

  • loss of identity for explicitly imported classes, since we create a new subclass for explicitly imported class
  • loss of inheritance relationship for imported classes due to new subclass (i.e., ColorCB.Point is not the supertype of OriginalCB.BoundedPoint)

Our solution: metadata transformations to rewire the inheritance chain of classes.

Backend Process Overview

The Backend process of the C# implementation of the classboxes concept utilizes the Common Language Infrastructure (CLI) of the .NET framework. A key aspect to our approach is that a growing number of modern programming systems compile program code into a platform-independent representation that is executed in a virtual execution system like CLI that use both Intermediate Language (IL) bytecode and metadata.

Our approach allows us to read assembly files that contain the corresponding metadata, transform it based on any local refinements that we define in the corresponding classbox, and write it back as transformed metadata into new assembly files of the corresponding classbox. Why do we have to transform this metadata? This is because metadata contains the structure of classes and their underlying class hierarchies that we want to extend in the classbox module. So, after the compilation process (which produces this metadata information), we carry out so-called code instrumentation to manipulate the metadata, and afterwards, we write the transformed metadata back into the assembly.

Overview of the Metadata Structure

The result of compiling classbox OriginalCB into the CLI is the assembly OriginalCB.dll that has the following layout:

Metadata OriginalCB

Given above is an example of how classbox OriginalCB is represented in the metadata that is contained in the assembly OriginalCB.dll.

Imported Token Types:

  • MODULE: contains the information of the module name;
  • TYPEDEF: encodes a defined type;
  • TYPEREF, MEMBERREF, ASSEMBLYREF: reference to a type defined elsewhere;
  • ASSEMBLY: the name of an assembly file and its version;
  • FIELD: index to FIELD table that contains continuous definition of the field defined within a given type.

Rewiring of the Inheritance Graph

By rewiring the metadata we create the structure of a classbox and integrate all locally refined classes into their corresponding class hierarchy.

Rewiring

Required Metadata Transformations

  1. Create a new version of OriginalCB.dll and name this assembly OriginalCB(1).dll;
  2. Add an ASSEMBLYREF token for ColorCB to the metadata of OriginalCB(1).dll;
  3. Add a TYPEREF token for ColorCB.Point to the metadata of OriginalCB(1).dll;
  4. Set the Extends column of TYPEDEF token for class OriginalCB.BoundedPoint to point to the newly added TYPEREF token OriginalCB(1).dll.
  5. Create a new version of LinearCB.dll and name this assembly LinearCB(1).dll;
  6. Change the ASSEMBLYREF token for OriginalCB.dll in LinearCB(1).dll to OriginalCB(1).dll.

The Assembly Structure of ColorCB

Structure of ColorCB

Summary

Classboxes provide a feasible solution to the problem of controlling the visibility of change in object-oriented systems without breaking existing applications, as they strictly limit both its scope and impact to clients of the extending classbox. Consequently, classboxes can significantly reduce the risk for introducing design and implementation anomalies due to the need to adapt a software system to changing requirements.

We have developed an approach to augment C#, an industrial-strength programming language, with the classbox concept. In our model, classboxes are represented by C# namespaces and the corresponding operations are defined using a small extension to the C# language. The integration of this extension is achieved by means of code instrumentation to rewire metadata type declarations in assemblies. This approach allows us to imprint the structure of a classbox in metadata, resulting in a seamless integration of classbox concept into the .NET framework.

Next Steps

  • Explore class restructuring
  • Apply technique to other VESs
  • Extend classbox concept

Publications

Contact

  • Markus Lumpe (ISU)
  • Jean-Guy Schneider (Swinburne)
  • Andre Lokasari (ISU)
  • Hua Ming (ISU)

Last modified: 2006-03-29 — Markus Lumpe