Compared to the Minimal App discussed in Chapter 3 we have to deal with a number of new issues:
In the model code we have to add for every property of a class
a check function that can be invoked for validating the constraints defined for the property, and
a setter method that invokes the check function and is to be used for setting the value of the property.
In the user interface ("view") code we have to take care of
responsive validation on user input for providing immediate feedback to the user,
validation on form submission for preventing the submission of flawed data to the model layer.
For improving the break-down of the view code, we introduce a
utility method (in lib/util.js
) that fills a
select
form control with option
elements the
contents of which is retrieved from an entity table such as
Book.instances
. This method is used in the
setupUserInterface
method of both the
updateBook
and the deleteBook
use
cases.
Checking the constraints in the user interface (UI) on user input is important for providing immediate feedback to the user. But it is not safe enough to perform constraint validation only in the UI, because this could be circumvented in a distributed web application where the UI runs in the web browser of a front-end device while the application's data is managed by a back-end component on a remote web server. Consequently, we need multiple constraint validation, first in the UI on input (or on change) and on form submission, and subsequently in the model layer before saving/sending data to the persistent data store. And in an application based on a DBMS we may also use a third round of validation before persistent storage by using the validation mechanisms of the DBMS. This is a must, when the application's database is shared with other apps.
Our proposed solution to this multiple validation problem is to keep the constraint validation code in special check functions in the model classes and invoke these functions both in the UI on user input and on form submission, as well as in the create and update data management methods of the model class via invoking the setters. Notice that referential integrity constraints (and other relationship constraints) may also be violated through a delete operation, but in our single-class example we don't have to consider this.