DCL: Dependency Constraint Language

 

MANUAL


1.1.0




Table of contents


1. Project Goals


2. The DCL Language


3. The dclcheck Tool


4. Installing DCL


5. Contact


6. References




1. Project Goals


Current mainstream programming languages support information hiding by the means of interfaces and visibility modifiers (such as public, private, and protected). However, they do not provide means to restrict inter-module dependencies. In practice, any public service provided by a module (or class) M can be used by any other system module. In order to tackle this problem, we have designed and implemented DCL, a dependency constraint language that allows software architects to restrict the spectrum of dependencies that can be presented in a given software system.


DCL provide architects with means to define acceptable and unacceptable dependencies according to the planned system architecture. Once defined, such restrictions can be automatically enforced by a tool integrated to the Eclipse IDE. Thus, our ultimate goal is to provide architectural conformance by construction, using a static, declarative dependency constraint language.




2. The DCL Language


The main purpose of the proposed language is to support the definition of constraints between modules. In our notation, a module is just a set of classes. Suppose, for example, the following module definitions:


module View: org.foo.view.*

module DataStructure: org.foo.util.*, org.foo.view.Table

module Model: org.foo.model.**

module Remote: java.rmi.UnicastRemoteObject+

module Frame: "org.foo.[a-zA-Z0-9/.]*Frame"



Module View includes all classes from the package org.foo.view. Module DataStructure includes all classes from the package org.foo.util and classes Table and Tree from the package org.foo.view. Thus, the * operator designates all classes from a package. Futhermore, module Model includes all classes from packages whose name starts with org.foo.model, such as org.foo.model.DAO, org.foo.model.BO, org.foo.model.DTO etc. The reason is that the ** operator matches all classes from packages having the specified prefix. The + operator matches sub-types of a given type. For example, module Remote denotes all subclasses of java.rmi.UnicastRemoteObject. To finish, the module Frame includes all classes whose qualified name starts with org.foo. and finishs with Frame.


The language supports the definition of the following constraints:


Only classes from module A can depend on types defined in module B, where the possible dependencies are as follows:


  1. only A can-access B: only classes declared in module A can access non-private members of classes declared in module B. Access in this case means calling methods, reading or writing to fields.


  1. only A can-declare B: only classes declared in module A can declare variables of types declared in
    module B.


  1. only A can-handle B: only classes declared in module A can access and declare variables of types
    declared in module B. In other words, this is an abbreviation for only A can-access, can-declare B.


  1. only A can-create B: only classes declared in module A can create objects of classes declared in
    module B.


  1. only A can-extend B: only classes declared in module A can extend classes declared in module B.


  1. only A can-implement B: only classes declared in module A can implement interfaces declared in
    module B.


  1. only A can-derive B: only classes declared in module A can extend a class or implement an interface declared in module B.


  1. only A can-throw B: only methods from classes declared in module A can throw exceptions declared
    in module B.


  1. only A can-useannotation B: only classes declared in module A can receive annotations declared in
    module B.


  1. only A can-depend B: only classes declared in module A can depend from types declared in module B. In other words, this is an abbreviation for only A can-access, can-declare, can-create, can-extend, can-implement, can-derive, can-throw, can-useannotation B.



Classes from module A can only depend on types defined in module B, where the possible dependencies are as follows:


  1. A can-only-access B: classes declared in module A can only access non-private members of classes declared in module B.


  1. A can-only-declare B: classes declared in module A can only declare variables of types declared in
    module B.


  1. A can-only-handle B: classes declared in module A can only access and declare variables of types
    declared in module B.


  1. A can-only-create B: classes declared in module A can only create objects of classes declared in
    module B.


  1. A can-only-extend B: classes declared in module A can only extend classes declared in module B.


  1. A can-only-implement B: classes declared in module A can only implement interfaces declared in
    module B.


  1. A can-only-derive B: classes declared in module A can only extend a class or implement an interface declared in module B.


  1. A can-only-throw B: methods from classes declared in module A can only throw exceptions declared
    in module B.


  1. A can-only-useannotation B: classes declared in module A can only receive annotations declared in
    module B.


  1. A can-only-depend B: classes declared in module A can only depend from types declared in
    module B.



Classes declared in module A cannot depend on types defined in module B, where the dependencies that can be forbidden are as follows:


  1. A cannot-access B: no classes declared in module A can access non-private methods or fields of
    classes declared in module B.


  1. A cannot-declare B: no classes declared in module A can declare variables of types declared in
    module B.


  1. A cannot-handle B: no classes declared in module A can access or declare variables of types
    declared in module B.


  1. A cannot-create B: no classes declared in module A can create objects of classes declared in
    module B.


  1. A cannot-extend B: no classes declared in module A can extend classes declared in module B.


  1. A cannot-implement B: no classes declared in module A can implement interfaces declared in
    module B.


  1. A cannot-derive B: no classes declared in module A can extend a class or implement an interface
    declared in module B.


  1. A cannot-throw B: no methods from classes declared in module A can throw exceptions declared in
    module B.


  1. A cannot-useannotation B: no classes declared in module A can receive annotations declared in
    module B.


  1. A cannot-depend B: no classes declared in module A can depend from types declared in
    module B.



Classes declared in module A must depend on types defined in module B, where the dependencies that can be required are as follows:


  1. A must-extend B: all classes declared in module A must extend a class declared in module B.


  1. A must-implement B: all classes declared in module A must implement at least an interface declared in module B.


  1. A must-derive B: all classes declared in module A must extend a class or implement an interface declared in module B.


  1. A must-throw B: all methods from classes declared in module A must declare that they can return with exceptions declared in module B raised.


  1. A must-useannotation B: all classes declared in module A must receive at least an annotation declared in module B.



The figure below summarizes the DCL language's syntax:


















3. The dclcheck tool


dclcheck is a tool that verifies whether the source code (i.e. the concrete architecture of a target system honors a set of dependency constraints defined in DCL. This tool has been implemented as an Eclipse plug-in.




4. Installing DCL


In order to install DCL and a demo system follow the procedure below:

  1. Download

       - dclcheck

       - myAppointments source files

  1. Unzip dclcheck in the Eclipse root directory;

  2. Unzip myAppointments and import its source files to Eclipse;

  3. Open Eclipse. As you can observe, a right click button in a project will enable an option dclcheck.


In development:

  1. We are adjusting the dclcheck's implementation to work fine in Eclipse Ganymede version. Nowadays, the plugin is just compatible with Eclipse Classic;


  1. We are developing an Eclipse Update Site to make the installation task easier.




5. Contact


If you want to discuss DCL, please send an email to Ricardo Terra or Marco Túlio Valente.




6. References


  1. Ricardo Terra and Marco Túlio Valente. A Dependency Constraint Language to Manage Object-Oriented Software Architectures. Software, Practice & Experience, 2009.


  1. Ricardo Terra. Conformação Arquitetural utilizando Restrições de Dependência entre Módulos. 2009. Dissertation (Master Degree in Informatics) - PUC Minas, CAPES. Advisor: Marco Túlio Valente. (in portuguese)


  1. Ricardo Terra and Marco Túlio Valente. Verificação Estática de Arquiteturas de Software utilizando Restrições de Dependência. In: II Simpósio Brasileiro de Componentes, Arquiteturas e Reutilização de Software, 2008, Porto Alegre. II Simpósio Brasileiro de Componentes, Arquiteturas e Reutilização de Software, 2008. p. 24-37. (in portuguese)


  1. Ricardo Terra and Marco Túlio Valente. Towards a Dependency Constraint Language to Manage Software Architectures. In: 2nd European Conference on Software Architecture, 2008, Paphos. Lecture Notes in Computer Science, 2008. v. 5292. p. 256-263.