Table of Contents
The three example apps that we have discussed in previous parts of this tutorial, the minimal app, the validation app, and the enumeration app, have been limited to managing the data of one object type only. A real app, however, has to manage the data of several object types, which are typically related to each other in various ways. In particular, there may be associations and subtype (inheritance) relationships between object types. Handling associations and subtype relationships are advanced issues in software application engineering. They are often not sufficiently discussed in text books and not well supported by application development frameworks.
A unidirectional functional association is either one-to-one or many-to-one. In both cases such an association is represented, or implemented, with the help of a single-valued reference property.
In this chapter, we show
how to derive a plain JS class model from an OO class model with single-valued reference properties representing unidirectional functional associations,
how to code the JS class model in the form of plain JavaScript model classes,
how to write the view and controller code based on the model code.
When coding a class, the ES2015 feature of function parameter destructuring allows using a single constructor parameter that is a record with a simplified syntax for defining its fields. We make use of this new feature for obtaining a simplified class definition syntax illustrated by the following example:
class Book {
constructor ({isbn, title, year, ...}) {
this.isbn = isbn;
this.title = title;
this.year = year;
...
}
...
}
A single-valued reference property, such as the property
publisher
of the object type Book
, allows
storing internal references to objects of another type, such as
Publisher
. When creating a new object, the constructor
function needs to have a parameter for allowing to assign a suitable value
to the reference property. In a typed programming language, such as Java,
we would have to take a decision if this value is expected to be an
(internal) object reference or an (external) ID reference. In JavaScript,
however, we can take a more flexible approach and allow using either of
them, as shown in the following example:
class Book {
constructor ({isbn, title, year,
publisher, publisher_id}) {
...
// assign object reference or ID reference
if (publisher || publisher_id) {
this.publisher = publisher || publisher_id;
}
...
}
...
}
Notice that the record parameter's publisher
field
represents a JS object reference while its publisher_id
field
represents an ID reference. In JavaScript, we can use a disjunctive
expression like expr1 || expr2
for getting the value of the
first expression, if it is defined (and not 0), or else the value of the
second expression. We handle the resulting ambiguity in the property
setter by checking the type of the argument as shown in the following code
fragment:
set publisher(p) {
var publisher_id = "";
// p can be an ID reference or an object reference
publisher_id = (typeof p !== "object") ? p : p.name;
...
this._publisher = Publisher.instances[ publisher_id];
...
}
Notice that the name
of a publisher is used as an ID
reference, since it is the standard ID of the Publisher
class.