Skip to content

Functional approach

Can improve:

  • Predictability
  • Maintainability
  • Testability

Taming side effects

Side effects make the code more difficult to test and reason about

We can reduce side effects by enforcing immutability

public class NoSideEffects {

    // no setter => value cannot change
    public int Result { get; }

    constructor(int value) 
    {
        Result = value;
    }

    public NoSideEffects Add(int value)
    {
        // return a new object to prevent side effects
        return new NoSideEffects(Result + value);
    }
}

Emphasizing expressions

Can simplify code by always returning a value

Allows piping by method chaining

Statements

Have side effects

string result;

if(number >= 0)
{
    result = "positiv"
}
else 
{
    result = "negative"
}

Expressions

Always return a value and have not side effects

Expressions can be called once or any number of times and they will produce the same result, for a given input.

Expressions are easier to test

var result = number >= 0 ? "positiv" : "negative"

Expression Methods

public static partial class FuncExtensions
{
    public static TResult Map<T, TResult>(this T value, Func<T, TResult> function) =>
        function(value);
}

public static partial class ActionExtensions
{
    public static void Do<T>(this T value, Action<T> function) =>
        function(value);
}

internal static void Calculate()
{
    "-2".Map(int.Parse) // string -> int
        .Map(Math.Abs) // int -> int
        .Map(Convert.ToDouble) // int -> double
        .Map(Math.Sqrt) // double -> double
        .Do(Console.WriteLine); // double -> void

    // Equivalent to:
    Console.WriteLine(Math.Sqrt(Convert.ToDouble(Math.Abs(int.Parse("-2")))));

    // or
    string input = "-2.0";
    int output1 = int.Parse(input); // string -> int
    int output2 = Math.Abs(output1); // int -> int
    double output3 = Convert.ToDouble(output2); // int -> double
    double output4 = Math.Sqrt(output3); // double -> double
    Console.WriteLine(output4); // double -> void
}