Pierre Greborio.NET

Talking about .NET world

January 2005 - Posts

State machine implementation

Looking any bug track system you have to solve a basic problem: state machine. The state machine consider not only the state of the object but also how it should behave depending on its state. Consider the following states and behaviors:

State      Next state

New         Validated, Resolved
Validated  Resolved
Resolved   Closed
Closed      Reopened
Reopened  Validated, Resolved

The simplest way of changing the state is to have an enum containing the states and a ChangeState which check if the new state is valid or not:

public class Bug
{
  public enum BugState
  {
    New,
    Validated,
    Resolved,
    Closed,
    Reopened
  }

  private BugState _state = BugState.New;

  public string State
  {
    get
    {
      return _state.ToString();
    }
  }

  public void ChangeState(BugState newState)
  {
    switch (_state)
    {
      case BugState.New:
        if (newState == BugState.Validated || newState == BugState.Resolved)
          _state = newState;
        break;
      case BugState.Validated:
        if (newState == BugState.Resolved)
          _state = newState;
        break;
      case BugState.Resolved:
        if (newState == BugState.Closed)
          _state = newState;
        break;
      case BugState.Closed:
        if (newState == BugState.Reopened)
          _state = newState;
        break;
      case BugState.Reopened:
        if (newState == BugState.Validated || newState == BugState.Resolved)
          _state = newState;
        break;
      default: // no state to change
        break;
    }
  }
}

The above code is quite simple for two main reasons: there are few states and few behaviors. But the code can grow incredibly and become unmaintainable during the time. One of the possible solutions is to apply the State pattern.

The context class (Bug) contains the information of the current state through an instance of the state object (BugState)

public abstract class BugState
{
  protected Bug2 _bug;
  protected string _stateName;

  public BugState(Bug2 bug)
  {
    _bug = bug;
  }

  public string State
  {
    get
    {
      return _stateName;
    }
  }

  public abstract void ChangeState(BugState newState);
}

The constructor of the BugState requires the context (Bug class) which will be used by BugState subclasses in order to communicate state changes. An example of the five subclasses will be:

public class NewState : BugState
{
  public NewState(Bug2 bug) : base(bug)
  {
    _stateName = "New";
  }

  // Validate the behavior
  public override void ChangeState(BugState newState)
  {
    if(newState is ValidatedState || newState is ResolvedState)
      _bug.SetState(newState);
  }
}

Then the context class simple register the change from the state classes

public class Bug2
{
  public readonly BugState New;
  public readonly BugState Validated;
  public readonly BugState Resolved;
  //...

  private BugState _state;

  public Bug2()
  {
    New = new NewState(this);
    Validated = new ValidatedState(this);
    Resolved = new ResolvedState(this);
    //...

    _state = new NewState(this);
  }

  public string State
  {
    get
    {
      return _state.State;
    }
  }

  public void ChangeState(BugState newState)
  {
    _state.ChangeState(newState);
  }

  internal void SetState(BugState state)
  {
    _state = state;
  }
}

The pattern could be perfectioned in two points:

1. The states registered into the context could be pluggable
2. There should be a notification mechanism informing that the state has been changed.

HttpResponse Flush

Sometimes I need to flush the content of the buffer before the end of my PageLoad. The documentation says "Forces all currently buffered output to be sent to the client." That is not really true.

If the buffer doesn't contains at least 257 bytes (calculated empirically on my Windows XP SP2), the buffer will not be sent to the client. Is it a documentation error or code error ?

Posted: Jan 13 2005, 12:53 AM by PierreG | with 5 comment(s)
Filed under:
Model View Presenter in ASP.NET 2.0

Martin Fowler is introducing several new enterprise patterns for his new book. My attention was captured by the Model View Presenter pattern and I immediatly tryied to apply it in a simple ASP.NET 2.0 (version 8.0.40607.85) web form with a CheckBox, a TextBox a Button and a Label. the use case is really simple, I can edit into the textbox and save what it written into the label throught the button click event. If the checkbox is checked I can't edit anymore. [note: in this basic sample I don't have a domain object].

So, my partial class (of the view) will be:

public partial class MyView_aspx
{
  MyPresenter pmod = null;

  void Page_Load(object sender, EventArgs e)
  {
    pmod = new MyPresenter(this);
  }
  void cbEditMode_CheckedChanged(object sender, EventArgs e)
  {
    pmod.SetEditMode(cbEditMode.Checked);
  }
  void BtnLoad_Click(object sender, EventArgs e)
  {
    pmod.Save();
  }
}

and the presenter will be:

public class MyPresenter
{
  Page _form;

  public MyPresenter(Page form)
  {
    _form = form;
  }

  public void SetEditMode(bool isEditMode)
  {
    TextBox txtName = (TextBox)_form.FindControl("txtName");
    txtName.ReadOnly = isEditMode;
  }

  public void Save()
  {
    TextBox txtName = (TextBox)_form.FindControl("txtName");
    Label lblName = (Label)_form.FindControl("lblName");
    lblName.Text = txtName.Text;
  }
}

The code isn't perfect because I have to resolve the form controls at each call. The optimization could be to reference the view class (MyView_aspx) into the Presenter constructor, but this isn't possible (even if the Presenter lives in the same assembly of the web application) in this build (MS folks, is it by design or it will be possible in beta 2 ?).

Get the number of days between two DateTimes

Calculate the number of days between two dates seems really simple, but there are some exceptions. The simplest idea is to substract two DateTime and get the number of days in the resulting TimeSpan. The method doesn't work when the two dates are set with different year or the number of hour are less than 24 (consider 1/7/2005 10:00PM and 1/8/2005 8:00AM).

The solution (in this case applicable to Gregorian calendar) implies to define a date reference (ie. 3/1/1600) and calculates the astronomical day number:

int Days(DateTime time)
{
  int d = time.Day;
  int m = time.Month;
  int y = time.Year;

  if ((m -= 2) <= 0)
  {
    m += 12;
    y--;
  }

  y -= 1600;
  int cy = y / 100;
  return 365 * y + y / 4 - cy + cy / 4 + 367 * m / 12 + d - 31;
}

Finally, the number of days between two dates is given by the difference of their astronomical days number. The above formula has been attribued to Gauss.

Trace or healt monitoring ?

In ASP.NET 2.0 there is a new way to log (or trace) web applications/services: health monitoring. It's a new way to prop information (not only critical information) through several channels (by defaukt there many providers). In ASP.NET there is a similar feature (ok, hralth monitoring is more flexible): System.Trace.

So, is there any advantage of Trace over the new one ? I admit, I didn't studied healt monitoring too much, but it seems it is dependent only from ASP.NET. What happens for other kind (COM+, windows services, etc.) of services ? If I have a class library used by both services (IIS, COM+, ...) which kind of logging system do I have to use ? I think System.Diagnostics.Trace maintain an higher level of flexibility and independence.

More Posts