• No results found

4.8 Implementation Methodology

4.8.4 Usage

A minimal runnable OGJ+ program should have the lines shown in Fig.

4.18. The Compiler is available for the Windows platform from the follow- ing link:

http://homepages.ecs.vuw.ac.nz/˜ahmkhal/

To run OGJ+, Java should be run from the command prompt as follows:

X:\>java -jar "OGJ JDK6 v20130630.jar" "Class.java" See subsection 4.1.1 for discussion on OGJ+’s main() method (and

thus the begin()).

1 import static OGJ.ArraylessMain.*; 2 import OGJ.Owners.*;

3 import OGJ.*; 4

5 public class AnyClassName<OwnerVariable extends World> 6 extends OwnedObject<OwnerVariable> {

7

8 static { begin(); }

9 public static void main(OwnedArray<World, OwnedString<World>> args) { 10

11 } 12 }

Figure 4.18: Mandatory declarations required for a minimal runnable OGJ+program

Chapter 5

Generic Ownership Compliant

Collections

To evaluate the applicability of OGJ+’s encapsulation system to a real life

code base, we decided to refactor the JDK 1.6 Collections Framework. We found that Java Collections Framework is large, complex and important enough to be representative of the encapsulation issues we are targeting (e.g., the iterator pattern). Not to mention the fact that ownership was first introduced to target aggregation and container objects; and in the end, the refactored framework is in fact integrated to the new language. That is, OGJ+has its own collection library.

The Java Collections Framework [1, 5, 49] was introduced in JDK 1.1, and then redesigned more thoroughly in JDK 1.2. With generics intro- duced in JDK 1.5, a collection object became restricted to hold a particular data type, since the only thing a collection knows it holds was a handle to an Object. Finding out type mismatches at compile time is known as compile-time type safety, which relieves programmers of the burden of casting when reading elements from collections. So, what we are about is supporting owner detection, as companion to type detection, through generic declarations.

In terms of encapsulation, a collection object can have its state compro- 79

80 CHAPTER 5. GENERIC OWNERSHIP COMPLIANT COLLECTIONS mised via an incoming reference to its internal representation. How? One of the very short, but most substantial, answers is: Iterators. The idea is that for a collection object to be able to share its element objects, an itera- tor needs to access the elements stored in that collection. As explained in subsection 2.3.1, an iterator can bypass the collection’s interface and refer directly to any arbitrary element by maintaining an incoming reference to the collection’s private representation that can in turn be mishandled via public getter/setter methods.

With ownership types, it is possible to have the internal representation explicitly declared as owned by its respective collection class. That is, a collection’s representation is hidden: constrained to interact only with its owner collection object, with no incoming aliases.

This chapter explains how we refactored the JDK 1.6 collections’ code base, in order to use OGJ+’s ownership support. The classes

under study are the ones which are circled in Fig. 5.1 and Fig. 5.2. These classes include all of the general-purpose implementations, namely

ArrayList, LinkedList, ArrayDeque, PriorityQueue, HashMap,

LinkedHashMap, TreeMap, HashSet, LinkedHashSet, and TreeSet. Also, the legacy implementations Vector and Hashtable will be investi- gated, as well as the special purpose implementation IdentityHashMap. The non-circled components in Fig. 5.1 and Fig. 5.2 are (1) the abstract data types, or interfaces, of which the collection classes provide implementa- tions, and they appear in red colour; and (2) the extended abstract classes that provide the skeleton implementations of the relevant abstract data types. All of these classes and interfaces are subject to refactoring.

Typically, the refactoring of a class (or interface) starts off by declaring a distinguished owner for the class itself, then the appropriate owner pa- rameters and bounds are supplied to the type parameters, as explained earlier in the thesis, and as will be explained later in this chapter. If the class is not extending another class in the hierarchy depicted in Fig. 5.1 (or Fig. 5.2), then the class should extend OwnedObject and the owner

81

Figure 5.1: Iterable Collections

82 CHAPTER 5. GENERIC OWNERSHIP COMPLIANT COLLECTIONS of the class should be preserved as explained earlier in chapter 3. In a similar manner, an interface should extend IOwnedObject, if it is not ex- tending another interface in its respective hierarchy. Refactoring the body of a class starts off by identifying its representation part and making it owned by This (i.e., to be private and hidden). Owner This will not al- low any access to that representation part unless through variable this. The other non-representation objects will be initially siblings owned by the same owner as the defining collection class, which means that these objects can only be shared with objects owned by the same owner as the current instance of the defining collection class. Exceptions occur when, for example, a representation object is originally being assigned to any of the other objects. In this case, such objects will need to be made owned by This, and thus they will need to be only accessed via variable this, which at times is not the originally intended receiver. Here we come to what we call cross incompatibility between owners. The remainder of this chapter explains the modifications found necessary, and why a particular object had to become private, sibling, public or subject to context covari- ance.

Identifying the representation part for this particular refactoring was straightforward, as we considered every private field, in the original im- plementations, a representation object. Otherwise, the determination of the representation part of an object relies on human judgement, if not de- sign principles.

Since most collection classes have compile-time dependencies on other classes in the framework, the priority was always to make sure that the whole set of classes under refactoring can altogether be successfully com- piled with OGJ+, after every modification cycle. For rapid error reporting

for that whole set of classes, we utilised the JUnit testing framework which provides an automated infrastructure for running repeatable tests. That is, the collection classes were dealt with as passing test cases that should al- together produce no errors. Modifications to one class can cause another

5.1. INTERFACES 83

Related documents