DraftManualPageSeparationOfConcerns

Timothy Lethbridge edited this page Jun 14, 2016 · 3 revisions
Clone this wiki locally

Introduction

Umple has a variety of separation of concerns features, however there are some potential improvements. This page outlines some ideas.

Mixins

As we currently define them in Umple, a mixin is a set of directives that can be brought into a system by a use statement. In particular, several parts of a class can be brought together by declaring the class several times.

Example:

<>

class X { a; }

<>

class X { b; }

The result would be a class with both a and b.

Mixins are symmetric in Umple. File1.ump could have

use File2.ump;

or vice-versa.

Or a third file could include both of these.

Mixins allow features or aspects of a system to be kept in separate files.

Use cases for the current mixin feature in Umple:

  1. Dividing large files into smaller parts, e.g. placing the declaration of attributes and associations in one file and the methods in other files.
  2. Separating out a features or subsystems that can be put together in different ways to create a product line architecture.
  3. Separating multiple base languages in injected code

Issues with the current implementation of mixins

  • There is no way to create an element that will become part of more than one class
  • There is no way to mix in something, changing its name as this is done

Other languages that allow mixing generally allow this greater flexibility.

In other languages, there are two related capabilities.

  • Traits: Groups of methods that are either abstract or contain implementation code that only calls other methods in the trait
  • Mixins: Code that can be injected into various different classes

We will discuss both of these separately

Suggested syntax to simply extend umple mixin

At the start of the file, there would be a list of formal parameters. These are strings that could be substituted:

GeneralHierarchy.umpp

parameters <Node, SuperiorNode>;

class Node {
  // Methods that apply to all nodes
}

class SuperiorNode {
  0..1 -- * Node;
  isA Node;
  // Methods would go here
}

This example comes from Lethbridge and Laganiere 2004, p227

A program that wanted to use the general hierarchy pattern in the above example would include something like:

use GeneralHierarchy.umpp <Node ->> Employee, SuperiorNode ->> Manager>;

The key advantage is that all the relevant methods for this pattern would be imported, with appropriate names converted. Additional regular mixins could add other features to the Employee class.

Syntax issues to discuss:

  • Do we need the list of parameters?
  • Can a parameter be left off when using; if so no name change occurs?
  • Presumably types, attributes, classes, method names, etc. all could be renamed
  • Some name subsitutions might have unexpected effects (renaming too much). Perhaps things that can be renamed should be surrounded by some form of code like #Node#.

Use cases for parameterizes mixins in Umple

  1. Ability to define patterns involving multiple classes that are generally reusable. This would be useful because there are many patterns and nethods that people often have to re-code. We could then build a standard Umple library of such patterns.

Another example

<>

parameters <Vehicle, OnOfFPoint, location, number, Leg, ScheduledLeg, Route, ScheduledRun, ActualRun, Vehicle, ActualVehicle>

class Vehicle {
  id;
}

class OnOffPoint {
  location;
}

class Route {
  number;
  * -- 1..* Leg;
}

class Leg {
  * -- 1 OnOffPoint origin;
  * -- 1 OnOffPoint destination;
}

class ScheduledLeg {
  * -- 1 Leg;
  Time scheduledDepTime;
  Time scheduledArrTime;
  m1 () {
     // method code
  }
}


class ScheduledRun {
  * -- 1 Route;
  * -- 1..* ScheduledLeg;
}

class ActualRun {
  Date date;
  * -- 1 Vehicle actualVehicle
  * -- 1 ScheduledRun;
}

<>

use transport.umpp <Vehicle ->> Airplane, OnOffPoint ->> Airport, ScheduledRun ->> RegularFlight,   
  ActualRun ->>SpecificFlight>;

The idea is that parameters such as Leg that are not substituted would not be affected, so Leg would remain as is.

If two separate transportation.umpp instances were instantiated, then that would create multiple classes with the same name, that would be mixed correctly into each other causing errors. This could be prevented by simply using namespace statements prior to each use statement.

Traits

A trait is an ability to inject some code into several classes. Classically there are no attributes, just abstract methods or code that relies on those abstract methods. However in Umple, we could define traits in an extended way (as some other languages do)

Possible syntax

trait PersonallyNamedElement {
  firstName;
  lastname;
  fullName = {firstName + " " + lastName;}
  Boolean isLongName() {return lastName.length() > 1;}
}

A class that needed to have a name (Employee, Passenger, AccountOwner, etc.) could always inherit, but may prefer just to include such code instead to overcome the restriction on multiple inheritance.

Traits would operate like Interfaces in many respects, but they have extra capabilities.

class Employee {
  isA PersonallyNamedElement;
}

We reuse the isA keyword again, just as we reused it for interfaces.

A trait actually injects all its code when invoked by the isA clause.

In some cases, it might be nice to allow methods or other elements in a trait to be included with name substitution as in mixing as defined earlier.

class Customer {
  isA PersonallyNamedElement <LastName ->> Surname>;
}

It should be possible to build a class or trait with several other traits (e.g. T1, T2), interfaces and at most one supervlass

class X {
   isA T1, T2, I1, Super;
}

Aspects

In languages such as aspectJ, an aspect defines some code that will be injected into multiple places in the system based on a pattern. The code is injected at join points.

In Umple we have a rudimentary aspect system: It is possible in any class to declare something like

  before setName {codeToDo;}

Patterns are allowed such as set

However, Umple does not allow an aspect to work across the boundaries of classes. Research questions:

  1. To what extent would it be useful to add more powerful aspect cability to Umple (are there any key cases for this, or showstopper problems that we haven't been able to accomplish with what we have now)?
  2. What would the syntax look like? Currently we define before and after statements in a class. To cross class boundaries we would have to define injections as first-class entities.

In order to know about a new proposal for using aspect-orientation in Umple please see Aspect_Orientation

Generic classes

A generic class allows the type or some other feature to vary. C++ has supported Templates for many years, and Java for a few years. The concept is defined in UML.

Possble syntax:

class Wrapper <ContentClass> {
  * -- 1 ContentClass;
  // methods referring to the ContentClass
}
class ScrollingWraper {
 isA Wrapper <ContentClass ->> ScrollableElement>;
}

The syntactic mechanism should be harmonious with the method used for mixins and traits.

We may need our generic parameters to have certain properties (the required interface). For example in the above case it may be important that ContentClass implements a certain interface so that certain methods can be called on it. For example, ContentClass might need to have a display() method. Out of the context of a generic class, the normal way to say this in Umple would be to say

class ContentClass {
  isA Displayable;
}

Perhaps we could say:

class Wrapper <ContentClass isA displayable> {
  * -- 1 ContentClass;
  // methods referring to the ContentClass
}

Generic classes are important when creating lower level data structures; it remains a research question whether they are useful at the level of abstraction of Umple, and worth the extra complexity.

Variability modeling: Merging VML into main body of Umple

Anywhere in Umple you could put any code of the following form:

variation xxx {
   //Umple Code
   class X {}
   use gef.ump;
   requires aaa and bbb;  // These are also included (essentially children)
   requires not ccc; // ccc cannot be present at the same time
   requires ddd or eee; // One of these is required or both
   requires fff xor ggg; // Either of these is required but not both
   requires zzz <Vehicle=>Airplane>; // Rename elements from pattern using generics
}
use xxx; // instead of a file, use a defined variation, which would 

To make this work

  • the requires statement works like the 'use' statement in many ways.

  • the Umple code other than the requires clause could just be ignored during initial parsing and put in a string.

  • use clause with a variation actually brings in that variation as a string as if it was reading a file (tracking line number from the original file for debuggability)

  • use clause will automatically bring in the aaa and bbb above if they are not separately specified in use clauses.

  • in the above there would be a check that ddd or eee appear somewhere in a use clause and that only one of fff or ggg appear.

  • zzz Vehicle=>Airplane would be separate from zzz Vehicle=>Train

Note: Concerns: Groups of independently considered variations can be simply defined using mixins.

Example of using variability with mixins with generics

<>

use transport2.umpp;
use manyStops; // tells which of the variations in the above to include

<>

parameters <Route, ScheduledLeg>

require manyStops or singleStop; // one of the two variations must be present

variation manyStops {
  class ScheduledRun {
    * -- 1..* $$ScheduledLeg;
}  

variation oneStop {
  class ScheduledRun {
    * -- 1 ScheduledLeg;
}