I often find myself writing code like


var status = ExecuteProcessingStep1();
if( status == CANCELED_BY_USER )
{
   return;
}
status = ExecuteProcessingStep2();
if( status == CANCELED_BY_USER )
{
   return;
}

/// and so on

I’ve find out an interesting idea to refactor this code here:
External Link
I’m not sure, though, that I’ll use it, unless the code gets too complicated.
The reason is it may mislead some developers.

What I’ll target:

var steps = new[]
          { 
              () => GetSourceFileFromUser(),
              () => ExecuteImportWizard(),
              () => HandleNewDomCreated()
          };

steps.WithBreakOnUserCancellation().Execute();

The scenario supported by this code:
– an application renders charts
– each chart has a DOM behind it, to contain the data and the data presentation settings
– the chart data can be imported from an external source, such as an Excel file (it cannot be linked yet)
– when the user initiates an import, the following actions must be executed:
– the system asks the user for the Excel source file by showing a ‘browse for file’ dialog; if the user cancels this dialog, the operations stops
– an import wizard (like the one in Word) is displayed; if the user cancels this dialog, the operation stops
– the data from the Excel file is used to create a chart; the application has a large number of actions that are triggered by the creation of a chart.

Now, this code looks like a Linq extension.

using System;
using System.Collections.Generic;

namespace ConsoleApplication5
{
    class Program
    {
        static void Main(string[] args)
        {
            var steps = new Func<bool>[]
                        {
                            () =>
                            {
                                Console.WriteLine( "Executing step 1" );
                                return true;
                            },
                            () =>
                            {
                                Console.WriteLine( "Executing step 2" );
                                return true;
                            },
                            () =>
                            {
                                Console.WriteLine( "Executing step 3" );
                                return false;
                            },
                            () =>
                            {
                                Console.WriteLine( "Executing step 4" );
                                return true;
                            },
                        };

            steps.ExecuteWithBreakOnUserCancellation();
        }
    }

    static class LinqExtensions
    {
        public static void ExecuteWithBreakOnUserCancellation( this IEnumerable<Func<bool>> steps )
        {
            foreach( var step in steps )
            {
                if( ! step() )
                {
                    Console.WriteLine( "Step execution returned false, stopping processing ..." );
                    return;
                }
            }
        }
    }
}

As you can see, the With… configuration doesn’t seem to be achievable; but an easy solution exist, simply implement an ExecuteWith… LINQ extension.

To actually achieve the syntax steps.WithBreakOnUserCancellation.Execute() the code should implement a class, maybe named TransactionScriptProcessing, that accepts the With… configuration API.

Advertisements