Identify transition methods

Typically an entity must carefully control its transitions between states. As such, it is often better to create specialized methods for state transitions rather than expose a setState method. Typically the name of each specialized method will reflect the state being transitioned to.

Since a state-transition method will modify the entity's data on the database, each such method should take the entity's version number (assuming that the entity supports optimistic locking). Each specialized method is free to specify additional arguments which may be required, e.g.:

Suspend

Figure 1. Interface declaration of a "suspend" state transition method
/**
   * Suspends business pending investigation.
   *
   * Transitions the state to
   * {@linkplain MYLIFECYCLEENTITYSTATEEntry#SUSPENDED}, if it is
   * valid to suspend.
   *
   * @param reason
   *          the reason for suspension
   *
   * @param versionNo
   *          the version number as previously retrieved
   *
   * @throws InformationalException
   *           if the entity is not in a valid state to transition
   *           to
   *           {@linkplain MYLIFECYCLEENTITYSTATEEntry#SUSPENDED},
   *           or if any other validation errors are found
   */
       public void suspend(final String reason, final int versionNo)
       throws InformationalException;

Resume

Figure 2. Interface declaration of a "resume" state transition method
/**
   * Resumes business following a suspension investigation resulting
   * in acquittal.
   *
   * Transitions the state to
   * {@linkplain MYLIFECYCLEENTITYSTATEEntry#OPEN}, if it is valid
   * to resume business.
   *
   * @param versionNo
   *          the version number as previously retrieved
   *
   * @throws InformationalException
   *           if the entity is not in a valid state to transition
   *           to {@linkplain MYLIFECYCLEENTITYSTATEEntry#OPEN}, or
   *           if any other validation errors are found
   */
       public void resume(final int versionNo)
         throws InformationalException;

Close

Figure 3. Interface declaration of a "close" state transition method
/**
   * Ceases business with the agency.
   *
   * Transitions the state to
   * {@linkplain MYLIFECYCLEENTITYSTATEEntry#CLOSED}, if it is
   * valid to cease conducting business.
   *
   * @param endDate
   *          the date on which business with the agency was ceased
   *
   * @param versionNo
   *          the version number as previously retrieved
   *
   * @throws InformationalException
   *           if the entity is not in a valid state to transition
   *           to {@linkplain MYLIFECYCLEENTITYSTATEEntry#CLOSED},
   *           or if any other validation errors are found
   */
       public void close(final Date endDate, final int versionNo)
       throws InformationalException;

Implementations of these methods are free to perform method-specific validations and notifications, e.g. whenever suspend is called, to notify an investigations worker to launch an investigation.

Note that this approach of having specialized methods (e.g. controlling the setting of state and endDate through the close method) is far "cleaner" than an alternative approach of allowing a public setter methods for setEndDate and setState and having complex validation to ensure that whenever the state is modified (by calling code), that the endDate is set.