Saturday, September 30, 2017

Functional adventures in .NET C# - Part 1, immutable objects


Lately I've been converted to the immutable data train, working with web technologies like React/Redux. I've started to wonder why I don't build all applications with immutable data, as it removes a big headache, if you get a reference to a data structure it will _always_ be the same data in it. Not like when you are working with ordinary data structures, where other threads or sub-functions can modify the in data when you aren't looking.

This is part 1 of this series. Here are links to all the other posts:
Functional adventures in .NET C# - Part 1, Immutable Objects
Functional adventures in .NET C# - Part 2, Application State

So, my native platform is .NET and C#, is there a way to work with immutable data out of the box or do we have to write something ourselves? It turns out that Microsoft has released an immutable library System.Collections.Immutable outside of the ordinary .NET versions as a NuGet package.
It has all the collections like
  • System.Collections.Immutable.ImmutableArray
  • System.Collections.Immutable.ImmutableArray<T>
  • System.Collections.Immutable.ImmutableDictionary
  • System.Collections.Immutable.ImmutableDictionary<TKey,TValue>
  • System.Collections.Immutable.ImmutableHashSet
  • System.Collections.Immutable.ImmutableHashSet<T>
  • System.Collections.Immutable.ImmutableList
  • System.Collections.Immutable.ImmutableList<T>
  • System.Collections.Immutable.ImmutableQueue
  • System.Collections.Immutable.ImmutableQueue<T>
  • System.Collections.Immutable.ImmutableSortedDictionary
  • System.Collections.Immutable.ImmutableSortedDictionary<TKey,TValue>
  • System.Collections.Immutable.ImmutableSortedSet
  • System.Collections.Immutable.ImmutableSortedSet<T>
  • System.Collections.Immutable.ImmutableStack
  • System.Collections.Immutable.ImmutableStack<T>
All well and good! But what of the all the POCO (plain old class object) and domain objects in your code? These need to be converted to immutables as well if you are to build something that can be relied upon.

So, how to do this in a simple way? After searching a bit on how other people are doing this I found this article by @davepermen and decided to take some of the ideas from there.

So here is the pattern that I'm currently using in a space game that I'm writing on my spare time.
public class Fleet
{
    public static Fleet Default { get; } = new Fleet();

    public uint Id { get; }
    public string Name { get; }
    public ImmutableDictionary<ShipType, ImmutableList<Ship>> Ships { get; }
        
    private Fleet()
    {
        Ships = ImmutableDictionary<ShipType, ImmutableList<Ship>>.Empty;
    }
    private Fleet(uint id, string name, ImmutableDictionary<ShipType, ImmutableList<Ship>> ships)
    {
        Id = id;
        Name = name;
        Ships = ships;
    }

    public Fleet Modify(uint? id = null,
        string name = null, 
        ImmutableDictionary<ShipType, ImmutableList<Ship>> ships = null)
    {
        return new Fleet
        (
            id ?? Id,
            name ?? Name,
            ships ?? Ships
        );
    }
}

Some key points.
Private constructor
The constructors are private, as the class is immutable, there is no real reason to have multiple 'new' fleet objects, just get the reference to the Default object.
So to create a new fleet we would do something like:
var fleet = Fleet.Default.Modify(_currentFleetId++, a.Name);
I.e. we get the reference to the default object and call Modify on it with the stuff that we want to have in our new fleet object.

All public fields are getters only
So that you can read the values from outside, but not set them other then from the constructor.

The Modify(T name = null) method
The only way to 'modify' state is to create use this method, and it does not really modify the state but it creates a new state based on the input. All attributes are nullable and with default values so that you only need to specify the values that change. The non-provided values will be copied from this object.
I.e. setting only the name would be like this:
fleet = fleet.Modify(name: "Battlestar!");

Explicit set to null methods
If you need to be able to set a value specifically to null, you would have to create a specific Modify method for that value, as if you send in null to the one provided it would copy the value from this instead of setting it to null.

public Ship RemoveTargetCoordinates()
{
    return new Ship
    (
        Id,
        Coordinates,
        ShipType,
        Health,
        MaxSpeed,
        Acceleration,
        Deceleration,
        null
    );
}
In this example we provide a copy from the current instance of all values but the one we want to set to null. Not the prettiest solution but works for now.

Update 20171003
There is no need to set to null, set the value to Default instead and instead of doing a null check check against the Default value. This solved all my 'set to null' issues in my code base so far. And this way there will not be a null reference exception in the middle of a chained function call.

Hope this helps someone out there getting started with functional programming in C#



Sunday, September 10, 2017

Typescript Array.Map


TypeScript made me go back to web development again, bringing in the compile time type checks really makes it easier to write correct code faster.
But sometimes it is a little tricky to figure out the syntax. For example last night when I tried to store the result from an array.map call in a variable. Most of the examples I found used the var keyword and pretty much ignoring the type check making me wonder why even bother with TypeScript if you don't use the types?

So, I wanted to try the array.map in the render method of a React JSX file to render a list of items. The end result was something like this:
public render() {
 const itemNames: string[] = ["Item One", "Item Two"];
 let itemNamesRender: JSX.Element[] = equipmentNames.map((name: string) => <li>{name}</li>);
 return <div>
  <h1>My Items</h1>

  <ul>{equipmentNamesRender}</ul>
 </div>;
}

Where the
let result: JSX.Element[] = array.map()
is the key. So pretty much just like all other variable declarations. The issue I had turned out to be that I didn't know that the type was JSX.Element, instead I was trying to force it to a string type.

Hope this helps someone out there. : )