Friday, 1 December 2017

Unit Test Fixtures

Almost ten years ago, I bought and read Gerard Meszaros’ xUnit Test Patterns, Refactoring Test Code. It is very comprehensive and seeks to document all the common test design patterns. Meszaros uses italics to indicate named patterns, and I'll follow that convention here.

The unit test framework I’ve used the most with .NET is NUnit. One quirk that I’m just beginning to understand better is the difference between Testcase Class and Fixture.

My confusion lies with how NUnit requires that classes which contain test methods, be decorated with the TestFixture attribute. I always assumed that this meant the class was "the fixture", but no!

Meszaros defines them as follows:
(I) use ‘test fixture’ or just ‘fixture’ to mean ‘the pre-conditions of the test’ and Testcase class to mean ‘the class that contains the Test Methods and any code needed to set up the test fixture’. (xUnit Test Patterns p.59)

The key thing is that while NUnit defaults to the Testcase Class per Fixture, you can do things differently.

Take a look at one of the unit test projects from the Cake project.
Cake.NuGet.Tests project structure

Notice how they’ve separated the Fixture classes and the Testcase classes into separate folders.

Here’s one of the test methods from the NuGetPackageInstallerTests class. Note how concise and uncomplicated it is. You can look at this method and very quickly understand what it’s testing.

public void Should_Be_Able_To_Install_If_Scheme_Is_Correct()
    // Given
    var fixture = new NuGetPackageInstallerFixture();
    fixture.Package = new PackageReference("nuget:?package=Cake.Core");

    // When
    var result = fixture.CanInstall();

    // Then

Now let’s look at the fixture class – NuGetPackageInstallerFixture

internal sealed class NuGetPackageInstallerFixture
    public ICakeEnvironment Environment { get; set; }
    public FakeFileSystem FileSystem { get; set; }
    public IProcessRunner ProcessRunner { get; set; }
    public INuGetToolResolver ToolResolver { get; set; }
    public INuGetContentResolver ContentResolver { get; set; }
    public ICakeLog Log { get; set; }

    public PackageReference Package { get; set; }
    public PackageType PackageType { get; set; }
    public DirectoryPath InstallPath { get; set; }

    public ICakeConfiguration Config { get; set; }

    public NuGetPackageInstallerFixture()
        Environment = FakeEnvironment.CreateUnixEnvironment();
        FileSystem = new FakeFileSystem(Environment);
        ContentResolver = Substitute.For<INuGetContentResolver>();
        Log = Substitute.For<ICakeLog>();
        Config = Substitute.For<ICakeConfiguration>();

        ToolResolver = Substitute.For<INuGetToolResolver>();
        ToolResolver.ResolvePath().Returns(new FilePath("/Working/tools/nuget.exe"));

        Package = new PackageReference("nuget:");
        PackageType = PackageType.Addin;
        InstallPath = new DirectoryPath("./nuget");

        ProcessRunner = Substitute.For<IProcessRunner>();
        ProcessRunner.When(p => p.Start(Arg.Any<FilePath>(), Arg.Any<ProcessSettings>()))
            .Do(info => FileSystem.CreateDirectory(InstallPath.Combine(Package.Package.ToLowerInvariant()).Combine(Package.Package)));

    public void InstallPackageAtSpecifiedPath(DirectoryPath path)
        ProcessRunner.When(p => p.Start(Arg.Any<FilePath>(), Arg.Any<ProcessSettings>()))
            .Do(info => FileSystem.CreateDirectory(path));

    public NuGetPackageInstaller CreateInstaller()
        return new NuGetPackageInstaller(FileSystem, Environment, ProcessRunner, ToolResolver, ContentResolver, Log, Config);

    public IReadOnlyCollection<IFile> Install()
        var installer = CreateInstaller();
        return installer.Install(Package, PackageType, InstallPath);

    public bool CanInstall()
        var installer = CreateInstaller();
        return installer.CanInstall(Package, PackageType);

As described in xUnit Test Patterns, this Test Fixture has everything we need in place to exercise the SUT (system under test). It instantiates both the SUT and all its dependencies, and also provides helper methods that are called by the Test Methods. Without this, all of the setup and configuration code would have lived in the Testcase class (NuGetPackageInstallerTests). This looks like an example of the Transient Fresh Fixture pattern.

If you want to get another perspective on using test fixtures, I’d also recommend taking a look at Mark Seemann’s Advanced Unit Testing course on Pluralsight

Monday, 27 November 2017

Enterprise Service Bus libraries for .NET – Rebus

One in a series of posts giving a quick overview of ESB libraries for .NET

Rebus describes itself as "a lean service bus implementation for .NET".


POCO classes


Use an instance of IBus to publish.

activator is an implementation of IHandlerActivator - either BuiltinHandlerActivator or an adapter class for your particular IoC container.

activator.Bus.Publish(new DateTimeMessage(DateTime.Now)).Wait();


Handlers implement IHandleMessages<T>

public class PrintDateTime : IHandleMessages<DateTime>
    public async Task Handle(DateTime currentDateTime)
        Console.WriteLine("The time is {0}", currentDateTime);

And register a subscription


Sunday, 26 November 2017

Enterprise Service Bus libraries for .NET – Shuttle ESB

One in a series of posts giving a quick overview of ESB libraries for .NET

Shuttle ESB describes itself as a "free .NET open-source enterprise service bus". It supports a good range of transports and integrates with a number of IoC containers.


A POCO class


Publish using IServiceBus. You'll also make use of static methods from the ServiceBus class.

using (var bus = ServiceBus.Create(resolver).Start())
    bus.Publish(new MemberRegisteredEvent
        UserName = "Mr Resistor"


A handler implements IMessageHandler

public class MemberRegisteredHandler : IMessageHandler<MemberRegisteredEvent>
    public void ProcessMessage(IHandlerContext<MemberRegisteredEvent> context)
        Console.WriteLine("[EVENT RECEIVED] : user name = ‘{0}’", context.Message.UserName);

You also need to tell the subscription manager that you want to subscribe to a particular event. resolver is a wrapper class for your specific container.


Monday, 20 November 2017

Enterprise Service Bus libraries for .NET – Nimbus

One in a series of posts giving a quick overview of ESB libraries for .NET

Nimbus primarily supports the Azure Service Bus as a transport, so if your application is going to run in Azure, then this could be a good choice.


Event messages should implement IBusEvent


Publish with an instance of IBus

_bus.Publish(new NewOrderReceived {CustomerName = "Ricky Bobby"});


Handle events by implementing IHandleMulticastEvent

public class ListenForNewOrders : IHandleMulticastEvent
    public async Task Handle(NewOrderReceived busEvent)
        Console.WriteLine("I heard about a new order from " + busEvent.CustomerName);
        //Do more stuff

Wednesday, 15 November 2017

Enterprise Service Bus libraries for .NET – MassTransit

One in a series of posts giving a quick overview of ESB libraries for .NET

MassTransit is an open-source library which apparently began as a response to some perceived deficiencies in the version of NServiceBus that was around in 2007. The project did a major rewrite in 2014, introducing async support and switching from MSMQ to RabbitMQ as the preferred transport.


Messages are POCO classes. There is no requirement to inherit from any base class or implement a specific interface.


Messages are published using IPublishEndpoint, which is provided by ConsumeContext for consumers or by the IBus interface

public async Task NotifyOrderSubmitted(IPublishEndpoint publishEndpoint)
    await publishEndpoint.Publish<OrderSubmitted>(new
        OrderId = "27",
        OrderDate = DateTime.UtcNow,


A subscribing class (or consumer) implements the IConsumer<T> interface.
public class UpdateCustomerConsumer :
    public async Task Consume(ConsumeContext<UpdateCustomerAddress> context)
        await Console.Out.WriteLineAsync($"Updating customer: {context.Message.CustomerId}");

        // update the customer address

A consumer needs to be connected to an endpoint to receive messages

var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
    var host = cfg.Host(new Uri("rabbitmq://localhost/"), h =>

    cfg.ReceiveEndpoint(host, "customer_update_queue", e =>

Tuesday, 14 November 2017

Enterprise Service Bus libraries for .NET – NServiceBus

One in a series of posts giving a quick overview of ESB libraries for .NET

Originally an open-source library developed by Udi Dahan, the licensing was changed after version 2 to put it on a more commercial footing, and the software is now developed and supported by Udi’s company – Particular Software. The source code remains on Github.

NServiceBus is a tried and tested library. It has grown a lot since it's humble beginnings and now is once part of a suite of tools and libraries for building distributed applications. It's no surprise that Udi Dahan just happens to be highly regarded as an expert in distributed software architecture.


Messages need to either implement a marker interface or use defined conventions.
namespace Domain.Messages
  public class UserCreatedEvent : IEvent
    public string Name { get; set; }
var conventions = endpointConfiguration.Conventions();

 type =>

       return type.Namespace == "MyNamespace.Messages.Events";


You can publish an event from within another handler or when you create an endpoint.
This example shows publishing an event from an endpoint:

var endpointInstance = await Endpoint.Start(endpointConfiguration)
    await endpointInstance.Publish(new MyEvent())


To handle an event, implement IHandleMessages<T>

public class UserCreatedHandler : IHandleMessages<UserCreatedEvent>
  public Task Handle(UserCreatedEvent message, IMessageHandlerContext context)
  { … }

NServiceBus will automatically locate handlers by looking for implementations of IHandleMessages<T>

Sunday, 5 November 2017

Enterprise Service Bus libraries for .NET

As a software application becomes larger, you may want to break it into separate parts, both to manage complexity but also to aid scalability. But if you break an application apart, how will the separate parts communicate? One approach is to employ messaging using a publish/subscribe (pub/sub) bus.

A few years ago, I worked on an application that used NServiceBus just for this purpose, but I thought it would be useful to survey the .NET landscape to find out what’s available today.

Here’s a summary of the libraries I’ll be looking at over the next few blog posts:




Minimum Framework



NServiceBus v6

Azure Service Bus, In-memory?, MSMQ, RabbitMQ, SQL Server





Azure Service Bus, In-memory, RabbitMQ


Apache 2.0

GreenPipes (>= 1.2.0)

NewId (>= 3.0.1)

Newtonsoft.Json (>= 10.0.3)

Newtonsoft.Json.Bson (>= 1.0.1)


Azure Service Bus



Microsoft.WindowsAzure.ConfigurationManager (= 2.0.3) Nimbus.InfrastructureContracts (>=

Nimbus.MessageContracts (>=

WindowsAzure.ServiceBus (>= 2.1.3 && <= 2.1.4)


MSMQ, RabbitMQ, SQL Server



Shuttle.Core.Infrastructure (>= 8.0.6)


Azure Service Bus, MSMQ, RabbitMQ



Newtonsoft.Json (>= 9.0.1)

These libraries range from the relatively simple and tightly focused to the complete ‘enterprise-level’ configurable, extensible and/or fully supported.

Some of these libraries distinguish between an ‘event’ (notify subscribers that something has happened) and a ‘command’ (tell subscribers that they should perform an action). Some support long-running business processes, often known as ‘sagas’. Some support distributed transactions. Some use dependency injection and can integrate with an inversion-of-control container.

And because the feature sets vary so widely, I’ll just be highlighting how each library implements publishing an ‘event’ message, and how you subscribe to these messages.

Tuesday, 17 October 2017

Conditionally format rows in Excel depending on date range

Sometimes I get asked Excel questions. This is one of those times!

Given a spreadsheet with rows that contain a start and finish date, format the rows in the past, present and future in different colours, so that it looks like this:

Spreadsheet showing rows with different colours

I initially tried using a formula with Excel’s Conditional Formatting feature. Despite this being the recommended solution in some search results, I just found it set the one format for all the rows – not what I wanted. This post by Joseph D’Emanuele put me on the right track.

Here’s what I ended up doing:

  1. Add a new column next to your existing data
    Spreadsheet with extra Status column added
  2. In the first cell of this new column, insert the formula
    =IF(B2 < TODAY(), "Past", IF(A2 > TODAY(), "Future", "Current"))
  3. Copy this formula down to the remaining rows. eg.
    Spreadsheet with Status column populated
  4. Now select all the rows you want to format (for me that’s A2:D5)
  5. On the Home menu tab, select Conditional Formatting, then Manage Rules
  6. You will add 3 rules – one for each status.
  7. Click New Rule
  8. Select Use a formula to determine which cells to format
  9. In Format values where this formula is true, enter =INDIRECT("D" &ROW()) = "Future"
  10. Click Format and choose the desired formatting to apply for Future dates
  11. Click OK and repeat adding new rules for “Current” and “Past”
  12. You should end up with something like this:
    Excel's Conditional Formatting Rules Manager dialog box
  13. Click OK and you should have rows formatted different colours depending on whether the start/finish date is in the past, current or in the future!
  14. You can optionally choose to hide the Status row if you’d rather not see it all the time.

Note that the formula in the conditional formatting (=INDIRECT("D" &ROW()) = "Future") is hard-coded to the column – “D” in my case. If you move data around, you’ll need to update this to refer to the new column letter.

Friday, 1 September 2017

On the NBN

We switched over to the NBN at home a couple of months ago. Unfortunately since the last change of Government in Australia, it appears that all NBN rollouts are getting fibre to the node (FTTN) rather than original plan of fibre to the premises (FTTP). So with the node servicing our neighbourhood being a fair distance from our house, it looks like the best we can expect for the foreseeable future is ~40MB. That is a 4x increase on what we used to get with ADSL2+, but it is a shame we can’t get the full 100MB if we wanted to pay for it.

40MB isn’t too bad – I know of others that are only getting 20 (and there’s stories of some that switch over from ADSL to get a slower speed than what they used to have). Just seems a lost opportunity that if everyone had got fibre, I’m sure that would be capable of being upgraded in the future to even beyond 100MB.

Wednesday, 30 August 2017

ShaggyMax screen protectors

My old laptop ended up getting a really scratched display. The keyboard obviously had been rubbing against the glass for a while, which was a shame. I think this was made worse because the only thing separating them was two rubber feet that had come loose after a few years.

My new laptop has a different design with a small rubber strip that goes all the way around the edge, which seems to do a better job. Nevertheless, I did want to get something that would help protect the display and reduce the chance of scratches.

A bit of Googling came up with a few options. A call out to Twitter ended up with an in-person response from Ryan showing me he’d got a ShaggyMax-brand protector for his brand new 9560 (the newer version of my 9550).

That was good enough for me, so I’ve now got my own!

I bought a 15.4” Laptop Screen Protector. You can buy them through Amazon, or direct from their website. Here’s what it looks like on my laptop:

Laptop with screen protector covering keyboard

It’s a microfibre cloth that is thin enough that it doesn’t interfere with closing the lid, but hopefully will be thick enough to softly cushion and protect the glass. So far, so good.

Saturday, 26 August 2017

NDC Sydney 2017

Delegate badgeMy second time attending NDC Sydney, and this was extra special as I’d been accepted as a speaker. I was excited and pretty nervous!

I flew over Tuesday evening. It was quite windy with a fair bit of turbulence on the flight. A decent tailwind meant even though we left Adelaide late, we still got into Sydney on time.


Jennifer MarsmanThe conference kicked off with a keynote from Jennifer Marsman talking about using EEG and Machine Learning to perform lie detection (on her husband!). Not sure about the lie detection, but I do like the application of EEG to enable things like controlling a wheelchair, and it was useful to learn about the different kinds of algorithms and models you used for different types of problems.

Barry DorransBarry Dorrans walked through a bunch of security vulnerabilities that had been discovered in .NET. Some subtle causes and a few things to watch out for in your own code.

Edith HarbaughEdith Harbaugh gave a good overview of using feature flags. She is from Launch Darkly, a company that provides ‘feature flags as a service’, though her talk was more general. One point she made was that feature flags can be dynamic – something that can be changed at runtime, not just a config setting that is set at startup.

Damian EdwardsDamian Edwards raced through what’s new in ASP.NET Core. This is looking pretty good.

Bart De SmetBart De Smet is a guru of .NET and CLR internals. I've watched some of his Pluralsight courses already. This talk on C# internals was fascinating.

20170816_062053378_iOSFilip Ekberg dug into asynchronous programming.

20170816_074407961_iOSRounding out the day with Jimmy Bogard doing CI with Azure.
20170816_103047694_iOSWednesday evening there was a cruise on Sydney harbour. It was a little chillier than the last time I’d been out, but nice food and great to socialise with other attendees.


20170816_230056563_iOSFirst thing Michele Bustamante stepped through using Docker.

Then it was my talk on using Chocolatey and Boxstarter! All my demos went off without a hitch and there were lots of questions from the audience. I think the early attendees appreciated the bonus chocolate frogs too.
Thanks to Ben for coming along and being a friendly face in the front row (and taking the photo!)

I hung around because Bart De Smet was up after me diving in to a bunch of areas of .NET to watch out for when you really care about performance.

Steve SandersonSteve Sanderson showed off some nice options available now in ASP.NET Core.

Richard CampbellThe one and only Richard Campbell with a history lesson about .NET. Informative and entertaining.

Dina GoldshteinDina Goldshtein on self-monitoring apps. Some interesting ways to do logging and diagnostics.

Finally a bit more Michelle Bustamante with more Docker – this time looking at some of the orchestration tools.

Thursday evening there was a social evening, including a bunch of pretty funny “short stories about failure” from some of the speakers. Some people partied on late into the night, but I retired early.


Nick BlumhardtNick Blumhardt gave a great talk introducing SeriLog and structured logging.

Kylie HuntKylie Hunt talked about dealing with problem bosses. A mix of good suggestions and sharing personal experiences.
Maybe I’m just an old fuddy-duddy, but personally I’m less impressed by speakers at conferences that need a swear jar.

Laura Bell Laura Bell had some good content on building in security.

Cosmo robot with Lars KlintLars Klint did a really interesting talk about Cosmo – a little programmable robot.
Jimmy PelletierLast talk I caught was from Jimmy Pelletier on how his team introduced micro services into their architecture.

There was the option of attending PubConf after the main conference had finished, but I’d already made plans to catch up with some old Adelaide friends who are now living in Sydney. It was really great to spend Friday evening and Saturday with them before my flight home in the late afternoon.

Here’s a pretty waterfall that I saw on Saturday when we went out for a walk. It's been dry in Sydney recently, so imagine what it would be like after a bit of rain.

All in all, again NDC Sydney didn’t disappoint and I can only hope it continues to grow and get better next year. There were quite a few times where I was spoiled for choice. I'll be looking forward to catching up on missed sessions when the recordings are published in a few weeks. It was great to see the Adelaide contingent growing from 2 last year to 9 (that I know of). The word is getting out that this is THE developer conference you should attend!

Saturday, 24 June 2017

Running SQL Server Configuration Manager without SQL Server installed

I like to have SQL Server Management Studio (SSMS) installed as part of my standard development environment. Usually this is because I also have an instance of SQL Server Developer or Express Edition installed, but not always.

One thing I noticed with the separate distribution of SSMS is that it also includes all the other management tools that used to be bundled with the server, like SQL Server Configuration Manager.

I wanted to change the SQL Client configuration settings and Configuration Manager is the tool I’d use to do that. But when I fired it up (it’s named SQL Server vNext CTP2.0 Configuration Manager in the latest release of SSMS), I’ve been greeted with this message:

Error dialog from SQL Server Configuration Manager

I don’t see this problem when an instance of SQL Server is installed though.

The fix is documented in KB 956013. I ran the following from an elevated command prompt:

mofcomp "%programfiles(x86)%\Microsoft SQL Server\140\shared\sqlmgmproviderxpsp2up.mof"

Now SQL Server Configuration Manager starts up without error

Oh, and the easiest way to install SSMS is to use Chocolatey!

choco install sql-server-management-studio

Monday, 15 May 2017

TypeScript tsconfig.json being ignored in C# project

TL;DR - Make sure your tsconfig.json file has the Build Action set to Content

I have some TypeScript files included in a .NET project. I added the Microsoft.TypeScript.MSBuild NuGet package to the project to enable the TypeScript compiler to transpile the .ts files to JavaScript. All was good until I wanted to set some compiler options using the tsconfig.json file. I created this file but every time I compiled the project it didn’t do anything different.

I almost pulling out my hair in frustration, so I decided to dig in deeper to find out why this was happening.

First, I ran msbuild with detailed logging. That showed up the following line just before the CompileTypeScript target was run:

Target "PreComputeCompileTypeScriptWithTSConfig" skipped, due to false condition; ('@(ConfigFiles)' != '') was evaluated as ('' != '').

A bit more digging led me to packages\Microsoft.TypeScript.MSBuild.2.3.1\tools\net45\Microsoft.TypeScript.targets – This defines that PreComputeCompileTypeScriptWithTSConfig target which is looking for @(ConfigFiles), which in turn is set in target FindConfigFiles. That target calls the FindConfigFiles task that is in TypeScript.Tasks.dll.

Firing up JetBrains dotPeek to reflect on the code for FindConfigTasks shows that it uses the ContentFiles property to look for existing tsconfig.json files, and that property is set to @(Content) in the targets file.

Jumping back to my project, I notice this:

Screenshot of tsconfig.json and Build Action set to None

Ah haa! Let’s set that Build Action to Content and try again..

Yes! Building the project shows tsc.exe being passed the --project parameter pointing to the tsconfig.json file!

Friday, 5 May 2017

Speaking at NDC Sydney 2017

Well this happened!

Congratulations message

Yes, my talk “Life is like a Box of Chocolate(y)” was accepted for NDC Sydney!

I’ll be speaking about using Chocolatey and BoxStarter as a way of scripting out the configuration of your developer workstation. You might think of these as more “IT” tools, but I want to show developers how easy they are to use.

Combined with Windows 10’s Reset, this means you can rebuild your Windows environment in a matter of minutes, allowing you to apply the “cattle, not pets” approach to your own PC.
NDC Sydney banner

Last year I attended NDC as a volunteer crew member and afterwards said that “this is THE developer event in Australia”.

So go have a look at the speakers and sessions. I reckon it’s a pretty compelling line-up, and if you register before Sunday 14th May, you can take advantage of early bird prices.

I hope to see you there!

Sunday, 16 April 2017

Someone has created a Facebook profile using your name and photo

One in a series of posts on Facebook Security and Privacy

First off, don’t panic! Unless you have a really poor password, it’s unlikely that you have been hacked. Instead an annoying person has just created a new Facebook account, copied your profile picture and name, and is presumably now going through your friend list asking to become friends, and confusing all your friends who thought you were already their friend.

What can you do?

Use the Facebook “Report” function to ask Facebook to delete the fake account.

  1. Open the fake profile page (Just click on the name)
  2. Click on the ‘…’ button (to the right of the Message button), then click Report.
  3. Select Report this profile and click Continue
  4. Select They're pretending to be me or someone I know and click Continue
  5. Select Me and click Continue
  6. Select Submit to Facebook for Review
  7. Usually within a matter of hours, someone at Facebook will review the details and shut down the offending account.

How can you reduce the risk of this happening?

Review your Facebook privacy and sharing settings to stop non-friends from seeing your friends list and your profile photo.

Enable Two Factor Authentication to reduce the risk of your actual Facebook account being really compromised.

Setting your Facebook privacy and sharing

One in a series of posts on Facebook Security and Privacy

If you use Facebook, you should take the time to review your privacy settings and be deliberate about what details you share with the public (as distinct from just your friends). Setting this appropriately can help prevent annoying people from creating fake Facebook accounts that have the same profile photo and name as you, and that then try to trick all your Facebook contacts into become friends with them.

There’s no one answer to setting privacy settings. Some people might be quite happy to share everything with everyone whereas others will prefer to keep things strictly between friends. The important thing is that you understand and are comfortable with what you’re sharing to whom.

To review your general privacy settings

  1. Click on the drop-down menu on the top right in Facebook in your web browser
  2. Click Settings
  3. On the left, click Privacy
  4. Review the settings and change to your preference if necessary.

To restrict who can see your profile picture

  1. Go to your Facebook profile (click on your name in the top menu bar in Facebook in your web browser)
  2. Click on your profile photo
  3. To the right of the photo, click on the icon next to the date
    Reviewing profile picture sharing settings
  4. Review the current setting and change to your preference if necessary. Choosing a non-public option will reduce the risk of someone copying your profile photo. On the other hand it will make it harder for potential friends to find you.

To restrict who can see your friends

  1. Go to your Facebook profile
  2. Click on Friends
  3. Click on the ‘Pencil’ icon (Manage)
  4. Click Edit Privacy
    Facebook Friend Privacy
  5. Review the current settings. Choosing a non-public option will reduce the risk of someone pretending to be you trying to contact all your friends.

Don’t just accept the defaults, be deliberate and intentional about exactly how much and to who you are sharing your Facebook information with.

Securing your Facebook account with Two Factor authentication

One in a series of posts on Facebook Security and Privacy

You should consider enabling Two Factor Authentication (often shortened to 2FA) for logging in to Facebook. This means in addition to having a unique password for Facebook (that you don’t use for any other online services), you also have to enter a (usually) 6 digit code (or receive a SMS text message) to confirm that it really is you signing in.

The two factors in “two factor” are 1) your password and 2) the 6 digit code.

The clever thing is that the 6 digit code changes every 30 seconds, so it’s no good writing it down as it will be out of date very quickly.

If you have a smart phone or tablet

  1. Install an authenticator app on your device.
    I recommend (and use) the Microsoft Authenticator app (which is available for iOS, Android and Windows Phone), but there’s other options including Google Authenticator and Authy.
  2. Open Facebook in your web browser (preferably on a different device to your smartphone)
  3. Go to Settings, then Security and then Login Approvals
    Facebook Security Settings
  4. In the Code Generator section, click on third-party app.
  5. A QR Code (like a barcode) appears.
  6. On your smartphone, open the Microsoft Authenticator app
  7. Click on ‘+’ to add a new account
  8. Choose Other
  9. Hold your smartphone in front of your computer’s web browser so that the phone’s camera can scan the QR Code.
  10. It should automatically scan the code and add a new account entry for Facebook. eg.
    Microsoft Authenticator
  11. Note the 6 digit number now being displayed on your phone.
  12. Also notice there’s a countdown timer displayed next to this number. When this timer reaches zero, the number will expire and a new number will be displayed.
  13. Switch back to your web browser and enter this number in the confirmation field and press Confirm
  14. Click Enable to allow Login Approvals.
  15. Click on Get Codes
  16. Enter your password
  17. Print out these codes and keep them in a safe place. You can use these codes as a last resort if you lose access to the Authenticator app (eg. your phone drops in the toilet)
  18. It is also a good idea to provide your mobile phone number as a fall back in case you lose access to the Authenticator app (eg. you accidentally deleted it).

From now on, each time you log in to Facebook from a new device you will need to provide the current 6 digits from the Authenticator app as additional proof of identity. If you use some devices regularly, you can then choose not to require two factor authentication in the future.

If you use the Facebook App on your device, that can also function as an authenticator app. The downside to using this is that it only works for Facebook, whereas an app like Microsoft Authenticator can work with many online services.

These include Amazon, Dropbox, Facebook, GitHub, Google accounts, Microsoft Accounts, Mailchimp, Twitter and others. Always choose to enable 2FA for any online services you use. Many banks and financial institutions are also using similar systems.

If you have a mobile phone

  1. Open Facebook in your web browser (preferably on a different device to your smartphone)
  2. Go to Settings, then Security and then Login Approvals
  3. In the Text message (SMS) section, if there is no number listed click on Add phone number
  4. Follow through confirming the phone number

From now on, when you log in to Facebook you’ll receive a SMS text message with a code. You’ll then need to provide that code in addition to your password. If you use a device regularly, you can tell Facebook not to prompt for 2FA again.

Using 2FA with text messages is much better than not using 2FA at all, but it isn’t quite as secure as using an authenticator app. If you can’t use an app then do enable 2FA using SMS. Some services even support non-mobile numbers by reading out the code instead of as a text message.

You just received a friend request on Facebook from someone who’s already a friend

One in a series of posts on Facebook Security and Privacy

First off, don’t panic! Almost certainly your friend has not “been hacked”. Instead an annoying person has just created a new Facebook account and copied your friend’s profile picture and name, and is presumably now going through their friend list asking to become friends.

What can you do?

Use the Facebook “Report” function to let your friend know.

  1. Open the fake profile page (Just click on the name. Don’t click on Confirm Request!)
  2. Click on the ‘…’ button (to the right of the Message button), then click Report.
    Facebook Report
  3. Select Report this profile and click Continue
  4. Select They're pretending to be me or someone I know and click Continue
  5. Select Someone I know and click Continue
  6. Select Message your friend
  7. Type in your friend’s name. Your friend’s existing Facebook profile should be listed.
  8. Click Send.
  9. You friend will receive a Facebook message with a link to the offending profile and they can follow it up by reporting it to Facebook.

If you’re particularly concerned, at step 6 you can also choose Submit to Facebook for Review. You will then be asked to select your friend’s real Facebook profile and send it off to Facebook.

Facebook security and privacy

I’ve had a number of friends on Facebook suffer the annoyance of having ‘fake’ accounts using the same name and profile picture to impersonate them and contacting all their friends asking to be friends.

It’s frustrating and annoying for everyone concerned. The victim who is being impersonated often also wonders if their Facebook account “has been hacked!”. Usually this is not the case, but I thought it would be helpful to write down some suggestions to help reduce the risk and help you feel more safe using Facebook.

Topics in this series:

Let me know in the comments if there’s anything else I should cover.

Tuesday, 4 April 2017

MVP Community Connection 2017

Microsoft SignageFriday morning I took the day off of work so I could fly over to Sydney to take part in a gathering of Australian Microsoft MVPs. Friday afternoon there was a networking/”unconference” event held at Microsoft’s North Ryde campus.


Microsoft, North Ryde

Later we travelled back to Darling Harbor to have some fun at Strike, trying out their Escape Rooms (lots of fun).

Darling Harbour

The next morning we gathered for breakfast followed by a full day of speakers and workshops. Everyone got these really nice cards of appreciation with personalised Lego mini-figures. Not sure that my hair is brown, but then I’m not really sure what colour it is – the days of being blonde, or even ‘dirty’ blonde are well behind me Smile

Card with "Thankyou for being awesome"

During the afternoon, I was asked to do a short presentation about running a user group. I can tell you I was more than a little bit nervous getting up in front of such an experienced group of people, but I think it went ok.

Early Sunday morning, I flew back home. All in all a great time catching up with friends and learning a lot.

Saturday, 25 February 2017

Richard’s Technical Debt

These are my notes from listening to the recording of Richard Banks’ talk The Technical Debt Prevention Clinic that he gave recently at the Microsoft Ignite Australia 2017 conference.

TL; DR - This is a really compelling talk. Go watch it, and share it with your colleagues!

My notes and highlights follow. These are not a substitute for watching/listening to the talk, and the best thing (if you ever get the opportunity) would be to see Richard deliver this in person.

Technical debt

  • Is design complexity + cognitive load. Is NOT quick & dirty code
  • Bad code is not technical debt, it’s just bad code
  • Quantifying – look at trends over time
  • Don’t
    • do a “technical debt sprint”
    • Rewrite
  • Do
    • “Boy Scout Rule”


  • Micro-refactoring – do anytime
  • Macro-refactoring – plan and only do one at a time to limit disruption to team
  • Both should have tests in place – ideally behavioural tests (so you’re testing the behaviour not the implementation)

Feature flags

  • Really useful
  • Still need to be managed properly


  • Be Professional – you don’t need permission to do your job properly
  • Have a Definition of Done and stick to it.
  • Automate everything you can
    • tests
    • code styles/rules
  • Change Team Culture

Code Reviews (suck)

  • Traditional code reviews often don’t work well for a number of reasons
  • Try doing peer refactoring
  • Or pair programming when it is “strong-style” where both people are engaged.
    • Put the mouse away!
  • Mob programming – maximise team intelligence
  • Experiment and find out what works for your team

Other tips

  • Avoid branching if possible. If not possible make it short-lived. This is because merging is costly
  • Premature optimisation
  • Resist temptations
  • Shared learning
  • Run hackathons
  • Adhere to that Definition of Done


Technical debt can be a good thing, but bad code never is.

Friday, 10 February 2017

Skeet, Cogan and VS 2017 launch date announced

It’s been a busy week!

On Wednesday evening we hosted the regular monthly meeting of the Adelaide .NET User Group in the Adelaide offices of RL Solutions. Our speaker was to be Jon Skeet talking about C# 7, joining us remotely from the UK. This involved a bit of logistical planning, including getting in enough seats for the expected crowd, getting a good PA (thanks Tom!), borrowing a nice data projector (thanks Keith!) and making sure everyone could get into the building after hours (thanks Vic!).

Jon Skeet, wrapping up presentationThere were a few gotchas along the way – I’d remembered the front door to our building closes at 6pm, but forgot that the lifts required a security card from 5.30pm. Then my laptop decided to freeze its screen when I reconnected the data projector and tried to launch PowerPoint as we were about to start. We got everyone upstairs and I rebooted my laptop and Jon was able to present his talk. I then realised that the pizzas were going to be delivered too early. So a quick change of schedule to introduce a 5 minute interval in the middle of the talk so everyone could grab some food before continuing on with part 2. Not to mention Tom running out to get some disposable plates as I’d overlooked those too.

But in the scheme of things, they were all pretty minor. All in all, I think it was a pretty successful night and I think lots of positive comments about Jon’s talk and also our office (the bar was especially popular!)

We recorded the Hangout so you can watch Jon’s presentation:

Adam Cogan presentingFriday afternoon is not when we’d normally have a user group meeting, but Adam Cogan was keen to visit and give us a preview of his Ignite Conference talk on What’s New in Visual Studio 2017 and Visual Studio Code.
The timing of Adam’s talk turned out to be quite good, as Microsoft have just announced the release date for Visual Studio 2017. Set your alarms for 2.30am on March 8th (Adelaide time) for a live streaming launch event.

I’ve already got two speakers (Ben Laan on Load Testing and Bronwen Zande on HoloLens) lined up for March, so I think we’ll make April’s meeting our local Adelaide launch event for VS 2017 (combined with Jack Ni on IoT).

It’s going to be a busy year!

Monday, 23 January 2017

Tour Down Under 2017

It’s that time of the year again when bicycles take over the streets of Adelaide and nearby country South Australia. The Tour Down Under is in town, and that also means the Friday is also the BUPA Challenge Tour. This gives us mere mortals a chance to ride the same course as the professionals, complete with supported rest and refuel stops all along the way.

Map from Mt Pleasant to Campbelltown

Usually I ride with my dad and we do the full distance, but this year my son decided he’d like to take part for the first time. So while dad still started at Norwood, we chose to do the shorter 60km distance starting at Mt Pleasant and finishing at Campbelltown.

Carson had previously done a few rides with me and the other Mud, Sweat & Gears riders down to McLaren Vale (a confortable 30km ride from our place), so I was pretty confident he’d be up to the longer distance, given plenty of breaks along the way.

Our family friend Jane also joined us for the ride (as well as giving us a lift to our starting location at Mt Pleasant).

The three of us taking a break at the top of a hillThe day started off cool and overcast, a huge relief from the high temperatures we’d had in the previous days. There’d also been a decent thunderstorm overnight. A small amount of drizzle hung around for the first part of the ride, but nothing too annoying.

We made good use of the rest stops along the way to get refreshments and make use of the ‘conveniences’.

We also had a bonus visit to the bakery in Lobethal. A welcome boost.

Carson's bike getting some mechanical attentionAt one stop, we did an adjustment to Carson’s seat pole – turns out he’s been growing a bit and those legs wanted a bit more room to stretch out Smile. Later on at the Cudlee Creek stop, we were just about to head off when he noticed that his rear brake was not working properly. The main rest stops also have resident bike mechanics, so we immediately went over to get it looked at. This brake had played up in a similar way a few months ago and I thought I’d resolved the problem. I was encouraged that the mechanic tried exactly the same things that I had done myself previously. He managed to get it working so it would get us safely to the finish (which was a fair bit of downhill, so having good brakes was critical), but recommended we take it in to get serviced as there’s obviously something not quite right.

Riding along the road

The final ride down to the finish went well and the three of us even got a chance to ride arm-in-arm under the finish archway, much to the appreciation of the crowd. The finish line was right next to Foxfield Oval with the huge gum trees lining the road. That made it the ideal place to stay and wait for the professional teams to come sprinting in.

Pro riders racing to the finish

All in all a great day. Super proud of Carson for riding 60km (as Jane pointed out, every km after the 30km mark was a PB!). Also nice to finish the ride and not feel completely wrecked too!

Sunday, 1 January 2017

2016 in review

It’s the first day of 2017, so a good time to reflect on the year just past.


A couple of friends have commented either “You’ve travelled a lot this year” or “where are you travelling to next?”. My first reaction was surprise – I don’t travel a lot do I?

Well ok, that was a few trips. But no future travel plans at this stage.


I won’t dwell on this too much but the health challenges continue for some members. Some of you know me well enough to know the details.

The kids did well at school (I’m sure better than I ever did!). They’re all growing up fast too.

We did have a couple of sad losses – Princess Layer (one of our bantam hens) and Guido (a goldfish) both passed away. Layer died quite suddenly of unknown causes (maybe snake or spider bite). We held a little burial ceremony in the backyard for her.

I’ve got a couple of weeks off over the Christmas break. Nice to spend time at home with the family, do a bit of gardening/weeding, a few bike rides and take it easy.


We planted new cherry, apricot and nectarine trees. Looking forward to seeing them fruit in years to come.

I finally finished the chicken run, so we can let the chooks out of their shed into the run during the day, and not worry about foxes or the odd stray dog. If we’re home, we usually let them out of the run to roam around the backyard anyway.


I got a new laptop, and more recently a new phone. The girls got iPads for Christmas so all three kids now have them. As annoying as it is to set up, at least the Apple Family Sharing means we can share single app purchases amongst all the devices. I say annoying as from my experience the ‘app approval’ part only works if a parent also has an Apple device.

Maybe updating to an XBox One S as a late family Christmas present?

Also on the radar is one of these Ubiquiti UniFi AP AC Lite WiFi access points. We have a few reception dead spots around the house that I think could be fixed by one of these.

Don’t think I’m buying new toys/technology all the time! Like most families we have a limited budget so these purchases only happen when absolutely necessary and we’ll get as much use out of them as we can.

Apparently in a few months our suburb will have the NBN. I’ll be looking closely at my options when that becomes available.

.NET and dev things

I’m in my second year as a Microsoft MVP. I’ve really appreciated the opportunities this has given me to participate and learn more. It’s also opened some doors particularly in regards to the Adelaide .NET User Group, which I help run.

The group continues to meet monthly and enjoys good attendances. It would be great to have some other members step up and get more involved with the organising and possibly allow us to run a “DDD Adelaide” event too.

This year I became a volunteer moderator for Chocolatey. I’ve been a fan of Chocolatey for a number of years now (my “Let’s get Chocolatey” t-shirt from supporting their KickStarter is a favourite), and it’s nice to be able to help share the load of moderating new package submissions.

Microsoft has changed considerably as a company over recent years. I really like their approach to doing much more in the open (including developing many products as open source on Github) and working with (instead of against) Linux and other platforms. The way .NET is evolving, together with new innovations like TypeScript gives me confidence that they’re heading the the right direction.


I don’t generally write about the details of my day-to-day work at RL Solutions, but it has been a busy year and 2017 looks to be no different. The consistent highlight is the people I work with. We recently advertised for a graduate developer to join our Adelaide team. It’s good to be growing (and also I can finally pass on the “new guy” mantle).

I’m sure I’ve missed some things, but that will do for now. Happy New Year!