As an xUML action language, Scrall handles data types a bit differently than a programming language. It relies on two orthogonal mechanisms for defining data structure, the class model and a system of defining data types.
The class model describes things of interest (classes) and their constraints in some subject matter domain. We model information with classes and relationships so that we can observe and reach logical conclusions about those things.
Data types establish the values that may be assigned to attributes and variables. We can manipulate those values and compute with them, but we don’t use data types to make logical statements.
So if a clump of data has interesting behavior, interactions and constraints that we must manage and is relevant to a domain’s subject matter, we will probably model it out with classes, attributes and relationships. If, on the other hand, that clump of data has no interesting internal properties and can be managed by standard algebraic operations, we may relegate it to type definition.
For example, if our subject matter is a map editing system, latitude and longitude might be modeled out with “Latitude” and “Longitude” classes so that we can define rules about how they interact. On the other hand, if our subject matter is a vehicle tracking system, we may simply define a data type called “GPS Coordinate” along with some operations to compute distance between two GPS Coordinate values.
Ultimately, it is the modeler’s decision to determine what data must be broken down into modeled components and what things are just values based on the relevant subject matter of the domain to be modeled.
Modeled data vs. data types
Modeled data is captured in an xUML class model. All the components of the data are visible as model elements such as classes and attributes. Scrall provides actions that let you select instances and attribute values. These actions don’t vary from class to class. They are always the same.
Data types are defined with a data typing system orthogonal to the class model. We don’t have a language for specifying data types yet, but expect to make use of the overall theory described in Type Inheritance and Relational Theory, C.J. Date, O’Reilly, 2016 since it reconciles nicely with the relational theory upon which are class model is based.
The basic idea, as presented in the book above, is that a data type defines a set of values and a set of compatible operations. For example, the data type Integer defines a finite set of integers (not in math, of course, but always on hardware) bounded by some system maximum and minimum values. Compatible operations include +, -, * and %.
We rarely use such unconstrained data types when we model. Instead, we use constrained, domain specific types such as Pressure, Altitude, Tail Number and so forth. Here units, precision limited ranges, enumerations or filtering patterns are applied to constrain assignable values.
Unlike a modeled class which makes all of its attributes visible, a data type has no user visible components. In other words, Scrall actions can nimbly operate on any attributes and relationships among classes, but Scrall doesn’t know anything about the structure of your custom defined data type.
That said, Scrall can invoke any operations that you have defined for your data type. These operations can select specific values (literals) from the data type defined set, select components of some underlying structure or perform computations.
Consider a simplified GPS Coordinate type that you might define. Let’s say that it has components Latitude and Longitude, each of which are based on the system supplied Real type. Let’s say you have a Current position attribute of a Vehicle class typed as GPS Coordinate. To set the value to some starting position passed into a state activity:
tracked vehicle.Position = in.Position
The system will automatically supply setter and getter operations accessible by the familiar dot notation.
You may have defined an operation on the GPS Coordinate data type to determine the distance from some other instance of Vehicle.
dist from ref = tracked vehicle.Position.distance( reference vehicle.Position )
In Scrall, we also use the dot notation to invoke a type specific operation.
You may also define an operation to convert the location to polar coordinates and return only the angle coordinate.
loc polar = tracked vehicle.Position.theta
Note that the actual internal representation (polar or cartesian) is hidden.
Operations can be symbolic or named.
Symbolic prefix and infix operators
For a numeric type such as Integer, the usual operations are available using standard math operators such as
^. Unary prefix operators such as
— are also supported. The data type system should provide a way to define other operator symbols. It is up to the model developer to avoid collisions with Scrall language symbols.
Consider the Counter data type. It is based on Integer, but constrained to values
0..maxint]. The only supported operations are increment, decrement and reset.
-- operators might be defined to perform in the increment and decrement operations. If so, you could do this in Scrall:
c::Counter // explicit variable declaration, starts at 0 ++c // now it is 1 c.reset // now it is 0 again
Scrall does not allow uninitialized variables. So, when a variable is declared, the data type should define some default initial value or initialization operation.
Alternately, operation names can be used instead:
c::Counter c.inc c.dec; c.dec; // c is still zero
Note that the decrement operation can prevent a Counter variable from going negative.