To begin with, the Action should be as insulated as possible from the actual implementation of the model. This can be done by using abstraction. For example, if the model uses JNDI to look up a username and password in an LDAP server, you shouldn’t put JNDI-specific code in the Action.
Instead, the Action should communicate through an interface (or at least a well-defined API) to the model, and the model should do all the work of setting up and making the JNDI call. That means if you want to change the model later to have it use JDBC to talk to Oracle, for example, only the model code would change; the Action could remain untouched.
To illustrate this, take a look at Stock.java (see Listing 9.1), which implements the model ...