Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design pattern for surrounding code in start, complete and fail methods

Suppose I have various arbitrary sections of code to run, but before each section, I have to run a Start() method and then after each section I need to run a Complete() method. However, if an exception is thrown in the code section, I want to run a Fail(string message) method instead of Complete(). Is there a design pattern that elegantly encapsulates this to make it neat and easily repeatable?

For example, let's say I have a type called Thing that contains a Start() method that adds a row to a logging db table to reflect that a task is in progress, a Complete() method that changes that row to reflect that the task finished and a Fail(string message) method that changes the row to reflect that the task failed. These are just examples though, they could be doing any set-up and tidy up type tasks.

The naive implementation might be simply to call those methods manually:

public void DoStuff()
{
    var thing = new Thing();
    thing.Start();
    try
    {
        DoImportantStuff();
        thing.Complete();
    }
    catch (Exception e)
    {
        thing.Fail(e.Message);
    }
}

But if I'm going to have to repeat this in a lot of different places, it ends up creating quite a lot of duplication and it might be easy to forget to call Complete or mess this up in some subtle way.

In C#, there's the using pattern, which provides a good way of encapsulating most of this. For example, if my Thing type looked like this:

public class Thing : IDisposable
{
    public Thing(){
        Start();
    }

    private void Start() { /* start */ }
    private void Complete() { /* complete */ }

    public void Dispose()
    {
        Complete();
    }
}

My DoStuff() method could now be simplified to this:

public void DoStuff()
{
    using(new Thing())
    {
        DoImportantStuff();
    }
}

Which is much nicer. But it doesn't allow me to call Fail instead of Complete if an exception is thrown because (I think!) the Dispose method is essentially called in a Finally block.

I have thought of having a try/catch inside the using block and then setting a thing.HasFailed flag inside the catch block and then using that in the Dispose method to decide whether to Complete or Fail. But that seems a bit fiddly and I'd like the consumer of Thing to have to do as little as possible to make it work correctly.

So is there a design pattern that encapsulates what I want to do and avoids the need to manually write a try\catch each time?

like image 357
Tim Barclay Avatar asked Mar 04 '26 16:03

Tim Barclay


1 Answers

You could have a Thing like this:

public class Thing 
{
  private void Start() { /* start */ }
  private void Complete() { /* complete */ }
  private void Fail(string message) {}

  public void DoAction(Action action)
  {
      this.Start();
      try 
      {
        action();
        this.Complete();
      }
      catch (Exception e)
      {
        this.Fail(e.Message);
      }

  }
}

And Use it like this:

Thing thing = new Thing();
thing.DoAction(this.DoStuff);
like image 64
Ofir Winegarten Avatar answered Mar 06 '26 05:03

Ofir Winegarten



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!