views:

496

answers:

1

I'm trying to implement the state pattern for a multi-page registration form. The data on each page will be accumulated and stored in a session object.

Should validation (including service layer calls to the DB) occur on the page level or inside each state class? In other words, should the concrete implementation of IState be concerned with the validation or should it be given a fully populated and valid object? See "EmptyFormState" class below:

namespace Example
{
 public class Registrar
 {
  private readonly IState formEmptyState;
  private readonly IState baseInformationComplete;

  public RegistrarSessionData RegistrarSessionData { get; set;}

  public Registrar()
  {
   RegistrarSessionData = new RegistrarSessionData();
   formEmptyState = new EmptyFormState(this);
   baseInformationComplete = new BasicInfoCompleteState(this);
   State = formEmptyState;
  }

  public IState State { get; set; }

  public void SubmitData(RegistrarSessionData data)
  {
   State.SubmitData(data);            
  }

  public void ProceedToNextStep()
  {
   State.ProceedToNextStep();
  }
 }





 //actual data stored in the session
 //to be populated by page
 public class RegistrarSessionData
 {        

  public string FirstName { get; set; }
  public string LastName { get; set; }
  //will include values of all 4 forms
 }





 //State Interface
 public interface IState
 {
  void SubmitData(RegistrarSessionData data);
  void ProceedToNextStep();

 }

 //Concrete implementation of IState
 //Beginning state - no data
 public class EmptyFormState : IState
 {
  private readonly Registrar registrar;

  public EmptyFormState(Registrar registrar)
  {
   this.registrar = registrar;
  }

  public void SubmitData(RegistrarSessionData data)
  {    
   //Should Validation occur here? 
   //Should each state object contain a validation class? (IValidator ?)
   //Should this throw an exception?
  }

  public void ProceedToNextStep()
  {
   registrar.State = new BasicInfoCompleteState(registrar);
  }
 }

 //Next step, will have 4 in total
 public class BasicInfoCompleteState : IState
 {
  private readonly Registrar registrar;

  public BasicInfoCompleteState(Registrar registrar)
  {
   this.registrar = registrar;
  }

  public void SubmitData(RegistrarSessionData data)
  {            
   //etc
  }

  public void ProceedToNextStep()
  {        
   //etc
  }
 }
}
A: 

I prefer to validate at both the state (collection) level AND the final commit. In general, I prefer to validate as soon as possible as part of a good user experience. From a data validation/protection level I prefer to validate at the final save/commit level as well just in case something snuck through, protection against generall trickery, or (more likely) a different route to the save/commit point in the future.

James Conigliaro
The validation would definitely occur at every step/page. The issue is: should the server-side validation happen inside the concrete implementation of IState or on the page, before the data is fed to the state class (take a look at the EmptyFormState.SubmitData method)? How dumb should the state classes be? Should they do their own sanity checks?
philrabin