Refactoring to functional programming in C# by examples: (of what worked for me at least)

Consider the initial code block. This code uses a repository and specifications to build the underlying data. The initial code solves the problem by using the repository, adding some data, then saving the information to the database.

public IWebApiStatusInfo updateAsset(vmAsset asset)
{
    var result = new WebApiStatusInfo();

    var repoAsset = uow.Repo<Asset>();

    var dbasset = repoAsset.GetById(asset.assetID);

    dbasset.AssetPartNum = asset.barcode;
    
    repoAsset.Update(dbasset);
    try
    {
        uow.Commit();
    }
    catch (SqlException e)
    {
        result.addError("DBUpdate", e.Message);
        return result;
    }
    catch (InvalidOperationException e)
    {
        result.addError("DBUpdate", e.Message);
        return result;
    }
    catch (Exception e)
    {
        result.addError("DBUpdate", "Update Person Failed, please check the data entered.");
        return result;
    }
    result.payload = true;

    return result;
}

This code is strait forward. The WebAPiStaatusInfo return object is passed back to the Web API Controller. The first part creates a Repo based on our type of “Asset” widget. The second part of the code performs a try/catch statement to commit the changes to the database. There is a specific type naming called “DBUpdate” which is a magic string that gets passed back to the calling system to know where an exception occured. The payload is then set to the boolean value of true / false and the result reutrned.

In C# functional refactoring we must first consider all statements as candidates for replacement. Consider the following refactoring:

First lets create a static class as an extension onto the Repo:


public static class SRepoExtensions
{
 public static Asset ToNewDBAsset(this vmAsset asset, List<AssetPropType> propTypes)
 {
     //Asset initialization logic removed for brevity
     return new Asset();
 }
 public static IRepository<T> Build<T>(this IUow uow, Func<IRepository<T>, IRepository<T>> act) where T : class
 {
     return act(uow.Repo<T>());
 }
 public static IRepository<T> SafelyExecute<T>(this IRepository<T> repo, Action act, Action<string, string> writeTo, string operation) where T : class
 {
     try
     {
         act();
     }
     catch (SqlException e)
     {
         writeTo(operation, e.Message);
     }
     catch (InvalidOperationException e)
     {
         writeTo(operation, e.Message);

     }
     catch (Exception e)
     {
         writeTo(operation, "Uncaught Exception: " + e.Message);
     }
     return repo;
 }
 public static WebApiStatusInfo Set(this WebApiStatusInfo webApiStatusInfo, Func<WebApiStatusInfo, object> payload)
 {
     webApiStatusInfo.payload = payload(webApiStatusInfo);
     return webApiStatusInfo;
 }
}
 

This class clearly removes the try / catch block and places it into a static method enabling it to be resused by anything that needs this sort of logic to catch the specific types of exceptions.

The Build method is key for creating a factory which will instantiate the IRepository from the unit of work using the uow.Repo() method call.

Next, we use the static methods to refactor the original code to be more functional in nature.

DTO Base gives us the uow as a factory for the repository. For more information on unit of work for the Entity Framework, see…

implementing the repository and unit of work patterns in an asp net mvc application

public class dtoTest : DTOBase
{   private readonly Func<List<AssetPropType>> _assetPropTypes;
  public dtoTest(Func<List<AssetPropType>> assetPropTypesFunc){
    _assetPropTypes = assetPropTypesFunc;
  }
  public IWebApiStatusInfo WebAddRequest(vmAsset asset)
  {
      return new WebApiStatusInfo().Set((result) => AssetMutate("DBAdd", result.addError, 
          (repo) => {
              repo.Add(asset.ToNewDBAsset(_assetPropTypes()));
              uow.Commit();
          }));

  }
  public bool AssetMutate(string def, Action<string, string> action, Action<IRepository<Asset>> repoFunc)
  {
      uow.Build<Asset>((repo) => repo.SafelyExecute(() => {
          repoFunc(repo);
      }, action, def));
      return true;
  }
}

The refactored code now is more functional in nature by removing the statements in favor for expressions. The AssetMutate method is specifically defined to use the try catch static statement and execute the “repoFunc”.

Also, teh WebApiStatusInfo.Set(func) method is designed to assist with the return value without specifically setting the WebApiStatusInfo object to a variable before calling the necessary expressions which will build the response.

This should be clear to see that the logical flow of the code is that the intent to WebAddRequest is to create a WebApiStatusInfo response, then apply the necessary operations on the asset parameter and return the

Also, the new values required for the _assetPropTypesFunc are passed in with a lambda expression to ensure the dtoTest is immutable.

The outcome is that the code is much more readable and the logic contained in the static extensions are reusable and modular in nature.