To express the general form of the LoD, we formulate a relational structure PS that models program structures sufficiently well to express the LoD. PS models LoD as a join point predicate. We will then use PS to derive both the A program structure PS consists of a set of modules. Each module consists of a name and a set of members. There are three kinds of members: field, method and constructor. A field is a member that is associated with a module through a field name. A method is a tuple (name, argumentModules, returnModule, body). argumentModules consists of zero or more modules. returnModule is a module that is optional. The body consists of a set of join points, each consisting of a tuple (enclosing, this, target, member, returned), where enclosing is the enclosing method to which the body belongs; this is the enclosing module of the method to which the body belongs; target is a module and member is a member of target and returned is the module returned by the member. A constructor is a special kind of method where the returnModule is always the enclosing module to which the constructor belongs. The LoD is a predicate on join points that are presented as a stream of join points. A join point (enclosing, this, target, member, *) in a stream of join points satisfies LoD iff (1) target is an element of fields(this) or (2) target is an element of arguments(enclosing) or (3) target appeared in an earlier join point of the form (enclosing, this, this, *, target) or (4) target appeared in an earlier join point of the form (enclosing, this, *, C, target) where C is a constructor. fields(this) is the set of modules in fields of module this. arguments(enclosing) is the set of modules that are arguments of method enclosing. (1) is module-sensitive and (2)-(4) are method-sensitive. At any point during the testing of a stream of join points we maintain the set of potential preferred target modules which are the target modules determined by conditions (1)-(4). The potential preferred target modules that are actually used in the method body are called preferred target modules. GoF: A stream of join points satisfies the LoD if the targets of all join points are preferred. potential preferred join points inside method body of method M this = enclosing module of M LoD is a predicate on join points that is the union of the predicates Fields, Arguments, where (this, this, *, r) implies (this, r, *, *) where (this, *, C, r) implies (this, r, *, *) jps(this, fields(this), *) || jps(this, arguments(M), *) || jps(this, *, C) || jps(this, this, R) || jps(this, global(), *) fields(this) C is a constructor member R is a method member ========================= Hi Pengcheng: I have added more text at the end. (Text in /proj/adaptive/www/papers/law-of-demeter/checker/dry) -- Karl As worked out by Sergei, we need to follow the DRY principle in our paper: Don't Repeat Yourself. We have pairs of similarly looking definitions that we need to abstract out. Here is my sketch to be woven with the existing section 3 and Sergei's text. Pengcheng, please can you take the lead. We define a program model using labeled graphs: nodes: classes or objects, edges: part-of and use-of connections between classes or objects, join points (joining nodes) labels on nodes: members (methods and constructors) labels on edges: member call details (join point information) Law of Demeter (OOF = object-oriented form): %\begin{definition} %In all methods or constructors M only access %the potential preferred supplier nodes. %\end{definition} \begin{definition} In all methods or constructors M only potential preferred supplier join points are allowed. \end{definition} Interpretation 1: for a program P: SCF Nodes = classes Edges = member call sites, a kind of lexical join point Interpretation 2: for a program P and input I: DOF Nodes = objects Edges = dynamic member calls, a kind of dynamic join point For a program P and execution E(P,I) for some input I, we consider the set of lexical join points according to interpretation 1 and the set of dynamic join points according to interpretation 2 and we define a function, called Shadow, that maps a dynamic join point to its lexical shadow \cite{}. For a dynamic join point d, Shadow(d) returns the static part of d. We define an equivalence relation etc. (from 3.1). We view (1) and (3) as operators on join point predicates. apply (1) SCF = DCF apply (3) OF = SOf (Only five join point predicates! OOF, SCF, DOF, DCF, SOF) In Figure 1 we use also CF and OF. We want to check DOF using AspectJ. An OF checker could not be done easily without an AO language. We believe that AspectJ is the first programming language that makes it relatively easy to check DOF. For designing the checker, the AspectJ join point model needs to be linked to OF. A join point model consists of a set of join points, a means of specifying a set of join points and a means of specifying additional information at a set of join points. AspectJ uses two kinds of join point models: a dynamic one where the join points are points in the execution of a program and a static one where the join points are classes. AspectJ has excellent support for the dynamic object model, but only limited support for a join point model according to interpretation 1 above. For example, in the dynamic join point model we can easily talk about all method calls happening during the execution of a program by writing "call(* *(..))". However, we cannot easily express in AspectJ the set of all MethodCall-objects contained in a given Program-object. What is missing in AspectJ is that it does not expose the meta model of AspectJ in the form of a class graph and an abstract syntax tree and that it does not offer navigational capabilities in the meta model commensurate with the navigational capabilities in the dynamic model. Note to Pengcheng: "potential preferred supplier class" is the right order. ======== added Dec. 29, 9.30pm One justification why AspectJ should not expose the meta model is that we could just use Java to parse an AspectJ program and process the abstract syntax tree to check SCF. But a parser for AspectJ is already in the AspectJ compiler ready to be reused. Another justification why AspectJ should not expose the meta model is that the static join points don't need enhancement (advice) as opposed to the dynamic join points that need checking logic to be added. But the meta-level program can be viewed as a base-level program and we would like to have all the capabilities of AspectJ to process the meta-level objects (abstract syntax trees). See /proj/adaptive/www/papers/law-of-demeter/checker/vision-dynamic-static for the design of adding statically executable advice to AspectJ.