We are organizing the first ever ReactiveUI virtual conference, register and join us on September 19th!

Blog

In Praise of Elevated Values

Published
Thursday, July 16, 2020
Category
Article
Author
Rich Bryant

In Praise of Elevated Values

Always Wear Protection

You know what you don't get when you work with Enumerables and Observables?

This.

I hate NullReferenceExceptions. There's a very simple reason why you don't get them, of course, and that's because both IEnumerable and IObservable are a sort of a collection, and a collection is special in LINQ and Functional Programming terms because of how you apply functions to it. Let's take a simple predicate lambda, for example.

    var uselessListOfFalseBools = myCollection.Where(item => item.BooleanProperty ==  true)
       .Select(newItem => false);

Here I have a collection of items, each of which has a property named BooleanProperty. I filter for the items where BooleanProperty is true and I create a new (admittedly useless) collection of bool values, each set to false.

Fine. What happens if myCollection is empty?

You already know what happens - nothing happens. The Where operation produces an empty collection and the Select operation is simply never applied. In essence, the pipeline breaks - without throwing any exceptions! - and uselessListOfFalseBools is an empty list.

This, in FP terms, is an elevated value. You're protected from NullReferenceExceptions by virtue of the fact that your values are enclosed in a collection structure.

The same happens with anything that implements IObservable<T>.

    myObservable.Where(item => item.BooleanProperty == true)
       .Subscribe(() => DoFunction());`

DoFunction is only called when the value of the item that ticks through myObservable has a BooleanProperty set to true - otherwise the Subscribe is never applied. If BooleanProperty is false, the "collection" produced by Where is empty.

Wouldn't it be nice if you could do this with any class? If only there was some way you could elevate those classes so that NullReferenceException never happened, operate on them with nice, clean testable pipelines and just have the pipeline break without error if it encountered a null value, or in elevated terms, an empty collection?

I mentioned in a previous post that I'd talk about how to avoid null and Exception as well as Event - events replaced by observables, we did this one first - and this seems like a good time to do that. What follows is not necessary to use ReactiveUI or even System.Reactive. You could even regard it as horribly off-topic for this website if you so chose. My belief, however, is that once you get used to elevated values and the virtues of immutability - we'll talk about this later - which are required for System.Reactive and ReactiveUI, you're going to want the rest of your code to have the same benefits.

Short version - you don't have to read any further but I strongly believe it will benefit you and anyone else who has to maintain your code if you do.

LanguageExt

Let's knock up a perfectly normal, boring class.

    public class Person
    {
        public int Id  { get; set; }
        
        public string FirstName { get; set; }
        
        public string LastName { get; set; }
        
        public bool LikesMarmite { get; set; }
    }

Let's say we want to get a person with an Id of 127 from the database and because we like Linq, we're using EF Core. Although if you're interested, I actually prefer Linq2Db because DbContext isn't thread-safe, but anyway, demo stuff so EF Core it is.

    var myPerson = _dbContext.People().First(person => person.Id == 127);

There he is. Unless I don't have a person with an ID of 127, in which case I'll get an exception. I don't want that. So let's change it a bit.

    var myPerson = _dbContext.People().FirstOrDefault(person => person.Id == 127);

Obviously, we want to do something with this person object, so let's say he's filled in our questionnaire and we have determined that he likes Marmite because he is one of the good people.

    var myPerson = _dbContext.People().FirstOrDefault(person => person.Id == 127);
    myPerson.LikesMarmite = true;

Hang on though. What if we've got something wrong? What if 127 is not the Id of the sensible, well-adjusted person who therefore obviously likes Marmite? What if we just returned a default - a null object? We're going to get an exception. Uh-oh.

At this point, we could reach for try/catch and trap and log the missing Id and all the usual stuff but there's a better way. There's a Functional way. There's LanguageExt. From the GitHub repo...

This library uses and abuses the features of C# to provide a functional-programming 'base class library' that, if you squint, can look like extensions to the language itself. The desire here is to make programming in C# much more reliable and to make the engineer's inertia flow in the direction of declarative and functional code rather than imperative.

I'm not going to go into all the features of LanguageExt here but I'll point out some of the more useful bits you can pick up and immediately roll with. Let's start with Option<T>.

Option<T> is like a collection for a single class. Either it contains a non-null value (the Some condition) or it's empty (the None condition). You can apply linq to Option<T> - and in fact, to all of LanguageExt's elevated classes - so that it's easy to put your work together in pipelines. It also has implicit conversion to Option<MyClass> which makes life much easier. So let's split this up a bit.

    Option<Person> myPerson = _dbContext.People().FirstOrDefault(person => person.Id == 127);

So now I have my Person as an Elevated value. Could be null, could be not null. How to do I deal with that? Well, this is Functional Programming so.... a function?

    private Person SetMarmitePreference(Person person, bool likesMarmite)
        => new Person
           { 
              Id = person.Id,
              Firstname = person.FirstName,
              LastName = person.LastName,
              LikesMarmite = likesMarmite
           };

Okay. You'll note we're returning a new Person. Immutability is a feature of FP and it's great because it's entirely thread-safe. If somebody else is working on Person127, it doesn't matter to us - we've got our own version and only we can touch it.

So how do we use this? Well, you've probably guessed already but...

    Option<Person> person127 = _dbContext.People().FirstOrDefault(person => person.Id == 127);
    var myPerson = person127.Select(person => SetMarmitePreference(person, true));

It's finally safe. Select will never apply SetMarmitePreference to person127 unless it contains a Person. If it's null, nothing happens and myPerson is an Option in the None condition. I like this, but I don't quite like it enough yet. Too many steps. An unnecessary allocation. Let's very quickly refactor the first statement to a function.

   private Option<Person> GetPersonFromDatabaseById(int id)
       => _dbContext.People().FirstOrDefault(person => person.Id == id);

So now what do we have?

Well, now we have this -

   var myPerson = GetPersonFromDatabaseById(127)
                     .Select(person => SetMarmitePreference(person, true));

and that means we have two testable functions, working in a pipeline. Just like you have with an Enumerable or an Observable. We're null-safe and the style is consistent with System.Reactive and ReactiveUI. And I find this is much more important that you'd expect. Consistency may well be the bugbear of little minds - like mine - but damn, it helps when you have to review somebody else's code. Or even come back to your own.

LanguageExt has absolutely loads of useful features. I won't go through them all here but I especially recommend you look into Either<L, R> which helps guard you against Exceptions and Try<T> which takes out all those horrible Try/Catch blocks when you really need Exceptions, like in network code or anything else that might suddenly be unavailable for external reasons. And Validation<T>. Guess what that does.

It's by Paul Louth, it's on Nuget and you should try it out. I think you'll appreciate it.

There are even extensions for Observables!

Code safe out there, folks.


ReactiveUI On The Web with Blazor

Published
Sunday, July 12, 2020
Category
Article
Author
Rich Bryant

I hope by now people are starting to learn about the existence of the ReactiveUI.Blazor package. Blazor means "writing Single Page Apps like Angular or Vue in C#" and it has all the potential in the world. And ReactiveUI supports it. The official samples are here but I don't feel that they really sell the reason why you'd want to do web work with ReactiveUI, and I should know, I wrote them.

Read more...

On Reactive Programming

Published
Friday, July 10, 2020
Category
Article
Author
Rich Bryant

Well, some say the Creator took a handful of sand and - wait, no. Why are we here? Why ReactiveUI?

Read more...

UWP minimum version is now 10.0.17763.0

Published
Monday, May 13, 2019
Category
Release Notes
Author
Glenn Watson

Due to a ongoing issue with Azure DevOps we had to change our minimum version from 10.0.16299 to 10.0.17763.0 for the UWP platform.

Read more...

Splat v7.0.1 released

Published
Tuesday, March 19, 2019
Category
Release Notes
Author
Rodney Littles, II

Splat 7.0.1 is here!

Read more...

ReactiveUI Rebranding

Published
Sunday, January 20, 2019
Category
Announcement
Author
Artyom Gorchakov

ReactiveUI was created by Anaïs Betts whilst working in Office Labs at Microsoft, and released in early 2011. Since that time, ReactiveUI has become a mature framework trusted by Slack, GitHub, Amazon, Elastic and Microsoft, has become a member of the Dot Net Foundation, and actively maintained by the open-source community on GitHub. The work we do is sponsored by our wonderful Backers on OpenCollective.

Read more...

Release notes now on GitHub

Published
Sunday, December 30, 2018
Category
Release Notes
Author
Glenn Watson

Rather than creating a blog entry for every Release we are now going to store the release note exclusively on the GitHub Releases.

Read more...

ReactiveUI v9.5.1 released

Published
Wednesday, December 26, 2018
Category
Release Notes
Author
Glenn Watson

Release 9.5.1 of ReactiveUI is available!

Read more...

ReactiveUI v9.4.1 released

Published
Tuesday, December 4, 2018
Category
Release Notes
Author
Glenn Watson

Release 9.4.1 of ReactiveUI is available!

Read more...

ReactiveUI v9.3.1 released

Published
Tuesday, November 20, 2018
Category
Release Notes
Author
Glenn Watson

Release 9.3.1 of ReactiveUI is available!

Read more...

ReactiveUI v9.2.2 released

Published
Sunday, November 11, 2018
Category
Release Notes
Author
Glenn Watson

Release 9.2.2 of ReactiveUI is available!

Read more...

Removing ReactiveCommand abstract base class

Published
Wednesday, November 7, 2018
Category
Announcement
Author
Rodney Littles, II

The ReactiveUI team has been urging consumers for some time now to move away from the ReactiveCommand abstract class for properties. There are some slight nuiances with type constraints that can sometimes cause run time bugs. Because your property can resolve to an abstract base implementation doesn't mean you should define it that way. We are very adamante about creating a type safe environment where consumers don't have to worry about hidden runtime issues with the framework. RFC: Remove ReactiveCommand abstract base class was raised to address this exact issue.

Read more...