FullStackMark

curiosity-driven development

Learning Unit Testing in ASP.NET Core

This is the follow-up to my last post about IoC and dependency injection. Today, we'll be focusing on unit testing. Since DI and unit testing go hand in hand we had to cover those topics first to lay the foundation for what we'll learn today. If you're not already familiar with IoC/DI then I'd encourage you to go back and check out that post first before you dig into this one.


What is unit testing?

Unit testing simply verifies that individual units of code (mostly functions) work as expected. They allow you to isolate these specific methods/functions and test their behaviors under different conditions and data.

Why bother unit testing?

One big reason is that unit tests make it much easier to change our code while making sure we don't change its behavior (refactoring). This means that properly unit tested code can be heavily refactored/cleaned up so if we happen to break existing functionality we'll know instantly by way of failing tests. This is awesome because it means bugs can't sneak further into our app development. The earlier a bug is identified the less it costs to fix.

Unit tests create a better design

Unit tests help influence our software design by exposing natural decoupling points in our code. If something is awkward or impossible to test it's likely there are tightly coupled dependencies that are causing us grief. When you're designing classes with unit testing in mind you're forced to break your app down into separate, testable components.

Once you get a feel for this you'll never go back to your old process.

In some cases, you almost don't have to think about the design at all. The tests will guide you to ensure the right behavior lands in the right classes/methods and those classes are properly decoupled from each other using interfaces and dependency injection. This has an added side effect of creating focused components that follow the single responsibility principle.

What about test-driven development?

I typically write code in small increments in parallel with my tests and practice what I call test-driven thinking. Test-driven development (TDD) is a different process where tests are written before a line of code is cut - rad! The tests act as a spec whereby you write a test for a non-existent object/function and it initially fails because no code exists yet. Then you write just enough code to get it to pass.

So while TDD is often a motivation for unit testing, unit testing does not require TDD. I want to make that distinction as this can be a point of confusion for folks who are familiar with these terms but may not fully understand how they work together.

Adding a unit test project

A good approach to unit testing in .net is to add your tests in their own class library project completely separate from your application code. So, to get started I added a new .NET Core Class Library project to the existing solution we used in the first post.

Next up, we need to add a unit testing framework - we'll use xUnit as it currently supports .net core and works with the built-in visual studio 2015 test runner. NUnit is another very popular framework - there are differences between the two but neither will change your life for the better in any dramatic way so don't split hairs about which one to go with.

An additional library is required for mocking up some behavior and data within our unit tests. This can be referred to as mocking, stubbing or faking depending on who you talk to but let's not get caught up with semantics. We'll see in a minute how to use moq to mimic behavior of an interface in our test - this is a powerful construct in unit testing.

Finally, we need to add a reference in our unit test project to our application so we have access to the classes we want to test.

For completeness, your project.json should look like this:


{
  "version": "1.0.0-*",

  "dependencies": {
    "moq.netcore": "4.4.0-beta8",
    //http://stackoverflow.com/questions/37288385/moq-netcore-failing-for-net-core-rc2
    "System.Diagnostics.TraceSource": "4.0.0-rc2-24027",
    "NETStandard.Library": "1.6.0",
    "xunit": "2.2.0",
    "dotnet-test-xunit": "2.2.0-preview2-build1029",
    "ASPNetCoreDIAndUnitTesting": "1.0.0-*"
  },

  "testRunner": "xunit",

  "frameworks": {
    "netcoreapp1.0": {
      "imports": [ "netcoreapp1.0", "portable-net45+win8", "dnxcore50" ],
      "dependencies": {
        "Microsoft.NETCore.App": {
          "version": "1.1.0",
          "type": "platform"
        }
      }
    }
  }
}

The important parts are "dependencies:{...}" which brings in the xUnit framework and it's test runner and "testRunner": "xunit" which instructs the dotnet cli we're using xUnit for our tests.

Writing unit tests

Ok, we covered off some good theory on what unit tests are and why we should use them. We got our project provisioned with the xUnit framework so our app code is testable. We're ready to a write a test...

Our first test will target the TeamStatCalculator class in our app. Specfically, the super-complex GetTotalGoalsForSeason() method.


public class TeamStatCalculator
{
  private readonly ITeamStatRepository _teamStatRepository;

  public TeamStatCalculator(ITeamStatRepository teamStatRepository)
  {
     _teamStatRepository = teamStatRepository;
  }

  public int GetTotalGoalsForSeason(int seasonId)
  {
    // get all the team stats for the given season
    var teamStatsBySeason = _teamStatRepository
    .FindAll(ts => ts.SeasonId == seasonId);

    // sum and return the total goals
    return teamStatsBySeason.Sum(ts => ts.GoalsFor);
  }
}

Breaking it down, we can see this method simply queries _teamStatRepository to get the list of team stats for a given season and then relies on linq's Sum() to return the total goals for all the elements...too easy.

One notable thing is that we can see _teamStatRepository is a dependency that gets injected through our constructor. In reality, this repository could be talking to a database, a file or rest api to get its data but the point is it doesn't matter because we've hidden its implementation details behind the ITeamStatRepository interface. We only deal with a contract of its behavior not the concrete details of the class. You'll see why this matters in a few seconds. Side note, if your test code writes to a file, opens a database connection or does something over the network, it's more appropriately categorized as an integration test - but that's a different topic.

Let's see the associated test for this method...


[Fact]
public void GetTotalGoalsForSeason_returns_expected_goal_count()
{
  // ARRANGE 
  var mockTeamStatRepo = new Mock();

  // setup a mock stat repo to return some fake data in our target method
  mockTeamStatRepo
 .Setup(mtsr => mtsr.FindAll(It.IsAny<Func<TeamStatSummary, bool>>()))
 .Returns(new List<TeamStatSummary>
     {
        new TeamStatSummary {SeasonId = 1,Team = "team 1",GoalsFor=1},
        new TeamStatSummary {SeasonId=1,Team = "team 2",GoalsFor=2},
        new TeamStatSummary {SeasonId = 1,Team = "team 3",GoalsFor=3}
     });

  // create our TeamStatCalculator by injecting our mock repository
  var teamStatCalculator = new TeamStatCalculator(mockTeamStatRepo.Object);

  // ACT - call our method under test
  var result = teamStatCalculator.GetTotalGoalsForSeason(1);
 
  // ASSERT - we got the result we expected - our fake data has 6 goals
  we should get this back from the method
  Assert.True(result==6);
}

Unit test structure

Our unit test follows the "AAA" approach where we:

  • Arrange by doing any necessary setup.
  • Act by executing the test - ie. calling the actual method/function and grab its result.
  • Assert by verifying the returned result matches expected results.

We can see the bulk of our test code happens in the arrangement part. Here we're creating a mock of our ITeamStatRepository and defining some custom behavior and data for its FindAll() method. We then inject our mock repo object into TeamStatCalculator when we create it.

Once our setup is complete, the act portion simply calls our target method GetTotalGoalsForSeason(1) to get a result. That's only one little line in our test but if you run the test while debugging you can see the real power and magic in all of this. If you actually step through GetTotalGoalsForSeason() you will see our mock repository object returning the data we made up in our test within our app code! This is IoC/DI in its full glory! We've completely inverted control of creating our repository and can make it do anything we please in our test - let that sink in! πŸ™‚

Finally, in our assertion - we know we have 6 goals in our test data and thus our method should return that if it's working properly.

Running the test in VS test explorer I get a passing green check!

Alternatively, we can run tests from the command line using the new CLI tools. In our project directory simply run the command dotnet test to invoke the test runner from the command line.

Unit testing controllers

Controllers are a big part of an ASP.NET Core application so providing some coverage for them is important to ensure they behave as expected. We typically want our controllers to be thin and free of code directly performing any sort of business logic or data access (this stuff belongs in its own class(es)). So, we're really just verifying how our controller actions behave based on given inputs and the responses they generate based on the operation(s) they perform.

Let's write a test for the Index() method on the HomeController.


public IActionResult Index([FromServices] IGameRepository gameRepository)
{
  var model = new IndexViewModel
  {
    Players = _playerRepository.GetAll().ToList(), // constructor injected
    Games = gameRepository.GetTodaysGames().ToList() // parameter injected
  };

  return View(model);
}

The associated test for this action...


[Fact]
public void Index_returns_viewresult_with_list_of_players_and_games()
{
  // ARRANGE 
  var mockPlayerRepo = new Mock();
          
  mockPlayerRepo.Setup(mpr => mpr.GetAll()).Returns(new List
  {
     new Player {Name = "Sidney Crosby"},
     new Player {Name="Patrick Kane"}
  });

 var mockGameRepo = new Mock();

 mockGameRepo.Setup(mpr => mpr.GetTodaysGames()).Returns(new List
 {
   new Game {
            HomeTeam = "Montreal Canadiens",
            AwayTeam = "Toronto Maple Leafs",
            Date = DateTime.Today},
   new Game {
            HomeTeam = "Calgary Flames",
            AwayTeam = "Vancouver Canucks",
            Date = DateTime.Today},
   new Game {
            HomeTeam = "Los Angeles Kings",
            AwayTeam = "Anaheim Ducks",
            Date = DateTime.Today},
 });

 // player repository is injected through constructor
 var controller = new HomeController(mockPlayerRepo.Object);

// ACT 
// game repository is injected through action parameter
var result = controller.Index(mockGameRepo.Object); 

// ASSERT our action result and model
var viewResult = Assert.IsType(result);
var model = Assert.IsAssignableFrom(viewResult.ViewData.Model);
Assert.Equal(2, model.Players.Count);
Assert.Equal(3, model.Games.Count);
}

Nothing radically different in this test than what we just did in our custom TeamStatCalculator one. We're using "aaa", we mock up some dependencies for PlayerRepository and GameRepository, inject them into our controller then call its Index() action method. The biggest difference is in the assertion where we're looking at the ViewResult and model to make sure they're returning what we expect. Other than that, it's safe to say that writing and structuring tests for custom logic AND controllers is practically the same...sweet! πŸ™‚

Wrapping up

Well friend, if you're still with me - you rock!!

Right now between the last post and what we've just covered I hope you have a clearer picture of how IoC/DI and unit tests all work together in ASP.NET Core to help produce higher-quality software that is easier and faster to test, fix and change.

The best way to truly understand and feel the benefits of these concepts is to put them into action yourself. So, I challenge you to do so in your next project and experience first hand how they can improve your life as a developer.

Thanks for reading and please drop any questions or feedback in the comments below!

Source code

Learning Dependency Injection in ASP.Net Core

This is the first of two posts (update: next post here) focused on removing the mystery around dependency injection and unit testing. The goal of these posts is to demonstrate how we can make loosely coupled, testable applications in ASP.NET Core and the value this adds to our apps and lives as developers. This will mostly benefit developers new to IoC, DI and unit testing.

Before we talk about unit testing in the next post we'll explore dependency injection right now and the role it plays within our software architecture.


What is dependency injection?

DI is a type of Inversion of Control (IoC).

Inversion of Control is just an intimidating term for a group of design principles intended to remove dependencies from your code. It works by offloading the instantiation of dependencies to another module called the container.

A container is essentially a factory that is responsible for providing instances of types that are requested from it.

DI specifically is a type of IoC which allows dependencies (ie. other components and services in your program) to be injected directly from the container into either the constructor or public properties of a class that depends on them.

Let's see how this works with a simple example.


public class CodeEditor
{
  private SyntaxChecker syntaxChecker;

  public CodeEditor()
  {
  this.syntaxChecker = new SyntaxChecker();
  }
}

Instantiating SyntaxChecker by newing it up in the constructor like this creates a hard dependency between CodeEditor and SyntaxChecker because we've literally hard-coded its creation here.

This is not ideal.

For starters, if the author of SyntaxChecker removes that parameterless constructor at a later point in time - our code breaks - not good. This is just the tip of the iceberg. There are a number other issues that dependencies like this introduce which we'll get to shortly.

For now, let's consider a better approach.


public class CodeEditor
{
  private ISyntaxChecker syntaxChecker;

  public CodeEditor(ISyntaxChecker syntaxChecker)
  {
  this.syntaxChecker = syntaxChecker;
  }
}

We've made two small yet powerful changes here. First, we created an abstraction for SyntaxChecker using an interface. This means we're not referencing the concrete implementation anymore, we're just referencing a contract of its behavior.

So we can accept any type of SyntaxChecker here that implements the methods defined in ISyntaxChecker - could be a JavaScriptSyntaxChecker, CSharpSyntaxChecker, PythonSyntaxChecker etc. As long as the class implements everything ISyntaxChecker says it should we're good to go.


// a contract to define the behavior of a syntax checker
public interface ISyntaxChecker
{
  bool IsValid();
  bool GetLineCount();
  bool GetErrorCount();
  ...
}

// a concrete SyntaxChecker implementation focused on JavaScript
public class JavaScriptSyntaxChecker : ISyntaxChecker
{
  
  public JavaScriptSyntaxChecker()
  {

  }

  public bool IsValid()
  {
  // implement JavaScript IsValid() method here...
  }
  
  ... other methods defined in our interface
}

The second big change to CodeEditor is that we got rid of the hard dependency on SyntaxChecker. We replaced the statement to new up a SyntaxChecker in the constructor with a parameter to request an ISyntaxChecker via the constructor. So, clients (or containers as we'll see shortly) creating a CodeEditor have control over which SyntaxChecker implementation to use.


 JavaScriptSyntaxChecker jsc = new JavaScriptSyntaxChecker(); // dependency
 CodeEditor codeEditor = new CodeEditor(jsc);

 CSharpSyntaxChecker cssc = new CSharpSyntaxChecker(); // dependency
 CodeEditor codeEditor = new CodeEditor(cssc);

There it is, the essence of dependency injection. Nothing too magical right?

But it does give us a ton of advantages. Two important ones are:

  • The ability to control the creation of dependencies outside of the classes that use them. Usually, this is done in a central place like an IoC container rather than repeatedly throughout the application.
  • The ability to easily test each class in isolation because we can pass fake or mocked objects into its constructor instead of needing to use a concrete implementation - more on this in the next post.

At this point, I hope you have a clear(er) understanding of how IoC and DI work together with abstractions (interfaces) to create a more loosely-coupled software architecture and some benefits this provides.

Dependency injection in ASP.Net Core

A new feature of ASP.Net Core is that it ships with a simple, lightweight IoC container making dependency injection a first class citizen right out of the box!

This is a big step forward as previous products like WebForms, MVC, SignalR and Web API each had their own mechanisms for using third party containers like Ninject, Autofac, SturctureMap and Castle Windsor.

Note that ASP.NET Core fully supports switching out the built-in IoC provider for one of the others if you require something more feature-rich. The built-in one is designed to be simple, fast and ideal for smaller projects so that's what we'll be focusing on today.

To begin I created a new ASP.NET Core Web Application.

The new project template already comes pre-loaded with the IoC container but if you ever need to add it separately it's part of the Microsoft.Extensions.DependencyInjection NuGet package.

Container concepts

The built-in container in ASP.NET Core is represented by the IServiceProvider interface which supports constructor injection by default.

The types we register with the container are known as services. You register your types with the container in the ConfigureServices method of the Startup class.


// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
  // Add framework services.
  services.AddMvc();

  // registering our custom player repository
  services.AddScoped<IPlayerRepository, PlayerRepository>();

  // registering our custom game repository
  services.AddScoped<IGameRepository, GameRepository>();
}

The IServiceCollection parameter is the collection that stores our registered types. Like other containers, it supports interface matching or creating instances using factory implementations.

We also need to consider the lifetime of the services we're registering. The lifetime of a service in the context of a web app is simply how long the service instance will live during a server request.

The default container supports three lifetimes:

  • ServiceLifetime.Transient - A unique instance will be returned from each object request.
  • ServiceLifetime.Scoped - In ASP.NET Core applications a scope is created around each server request. Instances registered as scope will be shared within a single request. This type of lifetime scope is useful for Entity Framework DbContext objects (Unit of Work pattern) to be shared across the object scope so you can run transactions across multiple objects.
  • ServiceLifetime.Singleton - A single instance is created once and is shared throughout your application’s lifetime.

With our player and game repositories registered, consuming these services in our app couldn't be easier.

In the HomeController I'm using both constructor injection and parameter injection on the Index() action. No manually newing them up, they're just magically available to our controller through the wonders of IoC and DI - sweet! πŸ™‚


public class HomeController : Controller
{
  private readonly IPlayerRepository _playerRepository;

  public HomeController(IPlayerRepository playerRepository)
  {
  _playerRepository = playerRepository;
  }

  public IActionResult Index([FromServices] IGameRepository gameRepository)
  {
  var players = _playerRepository.GetAll(); // constructor injected
  var games = gameRepository.GetTodaysGames(); // parameter injected
  return View();
  }

Typically, you'll pass most of your dependencies through the constructor but in ASP.Net Core the parameter injection feature is neat and worth keeping in mind for objects that might be expensive to spin up or for some reason don't require constructor injection.

Wrapping up

Phew! If you made it this far - you rock!

IoC and DI are abstract concepts which make them tricky to explain but I hope you were able to get some idea of their purpose, benefit and how quickly you can apply them in your ASP.NET Core apps.

In the next post, we will leverage what we learned here by adding some unit tests to really demonstrate the power and value we get from putting our apps together using IoC and DI patterns.

Thanks for reading and please drop any questions or feedback in the comments below!

Source code

A Simple Vocabulary App Using ReactiveUI and Xamarin Forms

These days, reactive programming and its supporting frameworks are a white-hot topic for companies and developers everywhere.

On the web, mobile, desktop or server - reactive programming is emerging as the answer for many new types of problems and use cases previously solved using traditional, imperative programming paradigms.

I'm not going to do a deep dive introduction here so if you're new to the concept of reactive programming I highly recommend you stop reading this and go check out Andre Staltz's excellent introduction before proceeding with this tutorial.

Here are two excerpts I pulled from Andre's tutorial that I found helpful to keep in mind when answering the What and Why behind reactive programming.

What is reactive programming?

Reactive programming is programming with asynchronous data streams.

In a way, this isn't anything new. Event buses or your typical click events are really an asynchronous event stream, on which you can observe and do some side effects. Reactive is that idea on steroids. You are able to create data streams of anything, not just from click and hover events. Streams are cheap and ubiquitous, anything can be a stream: variables, user inputs, properties, caches, data structures, etc. For example, imagine your Twitter feed would be a data stream in the same fashion that click events are. You can listen to that stream and react accordingly.

Why use reactive programming?

Apps nowadays have an abundancy of real-time events of every kind that enable a highly interactive experience to the user. We need tools for properly dealing with that, and Reactive Programming is an answer.

Our app

We're going to build a simple app to help broaden our vocabulary. Similar in concept to flash cards but with some extra features like scoring to track our progress and a bit of a game effect to make it fun. Our implementation will be based on ReactiveUI, which is an MVVM framework that integrates with the Reactive Extensions for .net.

My setup

I'm running Visual Studio 2015 Professional, Update 3 on Windows 10.

Application architecture

I created a new app using the Xamarin Forms PCL project template (Xamarin.Forms.Portable) and structured it using MVVM. ReactiveUI plays very nicely within the MVVM architecture, hence its use in this application. I also implemented a data layer based on SQLite, navigation serivce and a DI-container using autofac to keep our app components nicely decoupled and injectable everywhere. To keep the focus on ReactiveUI I won't go into how I implemented these bits in this guide so please refer to the source code or drop a question in the comments if you'd like to know more.

The PCL project structure.

Data

To supply our app with an adequate list of words I've already provisioned our project with a sqlite database pre-populated with 1000 words. Note, as we're only targeting android for this tutorial I only added the DB to that project.

Let's get reactive

The core concept in reactive programming is the Observable. In a nutshell, observables represent a stream or sequence of data that may or may not have a beginning or an end. When we think about it, many different kinds of data can be modeled in this observable fashion.

  • The classic example: a stock ticker constantly providing updates on fluctuating stock prices
  • Twitter: a never-ending stream of data flows through twitter. Their status API is literally named firehose.
  • Keyboard presses and mouse clicks: events are infinite and we can receive a new signal and piece of data for each one that occurs.

Great - we have a channel or stream to bring data into our application so now what? To make use of these observables we use Subscribers to receive interesting events from our observable like "new data arrived" or "error occurred" or "no more data". As these events occur, our subscriber(s) can react in any number of ways to handle that event accordingly in our program.

I'll mention at this point that it's simply impossible to fully describe such a broad topic like reactive extensions in a few sentences. But the observable/subscriber pattern is the most fundamental piece so a basic understanding will make it easier to follow along with the code we're about to write.

Some interesting code

Our app is so simple it's really just the single screen shown in the gif above. Users are challenged to pick the correct definition of the featured word within 10 seconds. Looking at the code you'll see this view is powered by the WordPickViewModel.cs

Looking at its constructor, we can see there's a fair bit happening here.


  public WordPickViewModel(IWordRepository wordRepository)
        {
            _wordRepository = wordRepository;
            WordOptions = new ObservableCollection();
            CorrectPct = "0%";

            var canRetrieve = this.WhenAnyValue(x => x.CanRetrieve).Select(x => x);
            var canSelect = this.WhenAnyValue(x => x.CanRetrieve).Select(x => !x);

            RetrieveWordCommand = ReactiveCommand.CreateAsyncTask(canRetrieve, async arg =>
            {
                var wordResults = await _wordRepository.GetWords(_rangeFloor,RangeCeiling);

                return wordResults.Select(wr =>
                    new WordOption
                    {
                        Word = wr.Name,
                        Definition = wr.Definition,
                        WordId = wr.Id
                    }).ToList();
            });

            SelectAnswerCommand = ReactiveCommand.CreateAsyncTask(canSelect,async arg =>
            {
                await HandleItemSelectedAsync(arg);
            });

             RetrieveWordCommand
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(wordOptions =>
                 {
                     _timerCancellationToken = new CancellationTokenSource();
                     NextRange();
                     CanRetrieve = false;
                     WordOptions.Clear();

                // randomly determine the word to challenge user with
                var rand = new Random();
                var challengeWord = wordOptions[rand.Next(wordOptions.Count)];
                     ChallengeWord = $"\"{challengeWord.Word}\"";

                foreach (var item in wordOptions)
                {
                    var isAnswer = item.WordId == challengeWord.WordId;
                    item.IsAnswer = isAnswer;
                    item.Image = isAnswer ? "check.png" : "x.png";
                    WordOptions.Add(item);
                }

                TimerCountdown = 10;
                Device.StartTimer(new TimeSpan(0, 0, 1), () =>
                {
                    if (_timerCancellationToken.IsCancellationRequested)
                    { 
                        return false;
                    }
                    if (TimerCountdown == 0)
                    {
                        ProcessAnswer();
                        return false;
                    }
                    TimerCountdown--;
                    return true;
                });
            });

            //Behaviors
            this.WhenAnyValue(x => x.Begin).InvokeCommand(RetrieveWordCommand);
        }

In fact, this is one of the biggest differences I noticed as I started exploring reactive programming. In MVVM, reactive is largely about describing relationships between data properties and adding bits of functional code to react to changes on those properties. As a result, a lot of the declarations for observables, subscribers, events and property changes are done in the constructor. If your requirements involve more heavy-duty logic used within your reactive components that code should be encapsulated in separate classes to keep things loosely coupled and testable. Our app is really small and simple so code for both my reactive declarations and actual functionality is contained in the view model.

Commands as observables

ReactiveUI offers a very rich command api which lets us bind our UI elements to functionality in our view model and do some powerful things. Thinking about our app, the most important command we need is the one to fetch new word definitions from our database when the user taps the "New Word" button. This is handled by the RetrieveWordCommand:


      RetrieveWordCommand = ReactiveCommand.CreateAsyncTask(canRetrieve, async arg =>
            {
                var wordResults = await _wordRepository.GetWords(_rangeFloor,RangeCeiling);

                return wordResults.Select(wr =>
                    new WordOption
                    {
                        Word = wr.Name,
                        Definition = wr.Definition,
                        WordId = wr.Id
                    }).ToList();
            });

Pretty simple stuff here, we make a call to our repository to fetch and return a new list of words - cool. What's even cooler is that reactive commands are also observables meaning they return an observable of the result and not the result itself. This behavior makes them inherently asynchronous so while we do some IO or CPU-bound work our UI can respond accordingly once the task completes without blocking the main thread.

In our app, once we're done fetching some word definitions from our database we do some additional work to pick our target word, set up our view objects and start the countdown timer.


  RetrieveWordCommand
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(wordOptions =>
                 {
                     _timerCancellationToken = new CancellationTokenSource();
                     NextRange();
                     CanRetrieve = false;
                     WordOptions.Clear();

                // randomly determine the word to challenge user with
                var rand = new Random();
                var challengeWord = wordOptions[rand.Next(wordOptions.Count)];
                     ChallengeWord = $"\"{challengeWord.Word}\"";

                foreach (var item in wordOptions)
                {
                    var isAnswer = item.WordId == challengeWord.WordId;
                    item.IsAnswer = isAnswer;
                    item.Image = isAnswer ? "check.png" : "x.png";
                    WordOptions.Add(item);
                }

                TimerCountdown = 10;
                Device.StartTimer(new TimeSpan(0, 0, 1), () =>
                {
                    if (_timerCancellationToken.IsCancellationRequested)
                    { 
                        return false;
                    }
                    if (TimerCountdown == 0)
                    {
                        ProcessAnswer();
                        return false;
                    }
                    TimerCountdown--;
                    return true;
                });
            });

Binding stuff

ReactiveUI offers a rich binding api that makes connecting our view model and UI elements very easy. In the code-behind for WordPickPage.xaml.cs you can see the data and command bindings in the OnAppearing() method.


...
//This is a one-way bind
this.OneWayBind(ViewModel, x => x.WordCount, c => c._wordCountBadge.Text).DisposeWith(_bindingsDisposable);
//This is a command binding
this.BindCommand(ViewModel, x => x.RetrieveWordCommand, c => c._nextWord).DisposeWith(_bindingsDisposable);
...

Another powerful tidbit related to commands is the CanExecute property. These are observables that perform a state check of our data to determine whether or not a command can run.

We use a couple of these checks to determine the proper states for our app to retrieve words and allow the user to select a definition. Both of these rely on the WhenAnyValue method which is again another thing that returns an observable (surprise!) and something I think of as being similar to INotifyPropertyChanged.


...
var canRetrieve = this.WhenAnyValue(x => x.CanRetrieve).Select(x => x);
var canSelect = this.WhenAnyValue(x => x.CanRetrieve).Select(x => !x);
...

Summary

Reactive programming is a deep topic and we're really just scratching the surface here. There's many important aspects I haven't covered here but some key points I hope you can take away are:

  • Observables are the lifeblood of reactive applications and provide streams of data and events with which we can subscribe to and perform any number of additional actions on.
  • In MVVM, commands are really important and ReactiveUI has a rich api with helper methods to keep our command-related code clean and concise.
  • Reactive syntax is fluent and composable. At first sight, I've found it's often pretty easy to reason about the intent of reactive code and the composability of the extensions makes chaining together super-powerful bits of functionality almost too easy.
  • Reactive isn't a be-all-end-all strategy. Carefully consider your functional and usability requirements when determining whether or not reactive is the right approach for your next project. If you're implementing a traditional CRUD-based line-of-business app chances are reactive likely won't offer you much. If you're dealing with real-time, streaming data and/or need to deliver a highly interactive user interface there's a good chance you can leverage reactive extensions to deliver a rich and performant experience for your users.

References

Source code

Right here

Thanks for reading!