Saturday, 28 October 2017

C++ 2017

Wahooo!!! C++ 17 has now been published as an ISO standard!!

I haven't used C++ for a long time as C# is my daily driver these days. But I will always remember when I moved from C++ to C#, being so much more productive as the language was a more safer environment and there was less things you had to worry about.

However, I always try to keep up-to-date with news over in the C++ camp. The C++ language will always have a special place in my heart and I have plenty of war stories and battle scars!. Yes, C++ is an overly complicated language with years of baggage but with every new feature that is added there is less and less sharp bits to impale yourself on.

The only thing I would like the standards committee to do is actually remove old/legacy features from the language. And maybe provide a compiler switch to enable them for backwards compatibility. This would mean you have to opt-in to use those legacy features. Unfortunately I don't think this will ever happen.

Of course, there was a time when C++ languished but that all changed in 2011 with C++11. It added so many features to the language like lambdas and auto, unique pointer and shared pointer that it changed the way you code. For example, now, when coding C++ they say if you're writing "new" or "delete" you're doing it wrong! Instead you should be using make_shared() or make_unique() which means you don't have to worry about memory leaks (as much).

C++ 20

What piqued my interest is what is coming down the pipe for C++20 and beyond. Big things are brewing in the C++ world and C++ 20 is where all the big action is. It's 3 years away but it promises:

Okay, so I kinda snuck metaclasses in that list. It might be a little too early for them to make the cut for C++20. But a guy can dream can't he?

The biggest problem I have with C++ at the moment is the #include header system. It's soo old and antiquated. Coming from Java or C# where they have a module system the #include system is painful. But hopefully C++20 will fix that with it's new module system (And then maybe we can get an official package manager).

C++ Core Guidelines

However, the thing about C++ is it's as "old as god's dog" which means when searching on the internet, you need to make sure you are reading about the latest stuff. While there maybe less sharp pointy bits, for the most-part the old stuff is still there and you need to know what to avoid!

You don’t want to be reading old out-of-date information. Thankfully the C++ guys (Bjarne & Herb) are working on the C++ Core Guidelines. Apparently, these Guidelines are a "set of rules designed to help you write modern, safe C++ – saving you time and effort as well as making your code more reliable." Microsoft even have a nuget package add-in for Visual Studio that performs code analysis to check your code for compliance!

Wrapping Up

In a world where we have modern, new and shiny languages like Rust, Swift & Kotlin you'd be forgiven for thinking there is no place for C++. That it's time to retire the old dog and put her out to pasture (tounge == in-cheek). Of course, we know that's not the case when we are talking about a language as important as C++. It's just good to see that C++ is alive and well and I am watching with interest to see how the language continues to evolve.


Contact Me:  ocean.airdrop@gmail.com

Friday, 27 October 2017

INotifyPropertyChanged & Fody

We all know what the INotifyPropertyChanged interface does. It can be used to raise an event when a property of a class changes. Then in another section of code we can subscribe to these events and perform certain actions based on the application needs. It's all very cool but also old hat and pedestrian.

But the thing with this interface is that you can end up writing a lot of boiler plate code! For example, take this simple person class:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
}

It's nice. It's neat.. All is good with the world. But then you decide you want to be notified when one of the fields in the class is changed, so we introduce the INotifyPropertyChanged interface. Suddenly, for every property we find ourselves expanding the above code like this:

private string m_firstName;
public string FirstName
{
    get
    {
        return m_firstName;
    }
    set
    {
        OnPropertyChanged("FirstName", m_firstName, value);
        m_firstName = value;
    }
}

For every property you need to include a backing field, then fill in the getter and setter functions yourself and in the setter field ensure you raise the property changed event handler.. Geez! If you need to add this to a number of objects within a sizeable project, the work can quickly become monotonous.

The full class definition now looks like this:

class PersonNotify : INotifyPropertyChanged
{
    private string m_firstName;
    public string FirstName
    {
        get { return m_firstName; }
        set
        {
            OnPropertyChanged("FirstName", m_firstName, value);
            m_firstName = value;
        }
    }

    private string m_lastName;
    public string LastName
    {
        get { return m_lastName; }
        set
        {
            OnPropertyChanged("LastName", m_lastName, value);
            m_lastName = value;
        }
    }

    private DateTime m_dateOfBirth;
    public DateTime DateOfBirth
    {
        get { return m_dateOfBirth; }
        set
        {
            OnPropertyChanged("DateOfBirth", m_dateOfBirth, value);
            m_dateOfBirth = value;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName, object before, object after)
    {
        if (PropertyChanged != null)
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

This is the situation I was in when I thought to myself “surely there must be a better way?”. And, in the internet age, if you can think of it, chances are someone else has already implemented it!

Enter Fody! You can find the nuget package here and install it with nuget like this:

Install-Package PropertyChanged.Fody 

It’s a great little utility which, at compile time, looks for classes that implement the INotifyPropertyChanged interface and implements the backing fields for each property of your class as well as raising the event for you.

With fody installed we can now revert back to our original class with just a couple of small modifications:

public class Person : INotifyPropertyChanged
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName, object before, object after)
    {
        if (PropertyChanged != null)
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

In the code above we have implemented the INotifyPropertyChanged interface and added a small bit of code to raise an event when any of the properties change.

Side note: In my final code I also extract the event and OnPropertyChanged handler into a central base class which cleans up all the model classes that derive from it.

Now, when you build it you will see this output in the Visual Studio build window:

1>------ Build started: Project: FodyTest, Configuration: Debug Any CPU ------
1>    Fody: Fody (version 2.0.0.0) Executing
1>      Fody/PropertyChanged:    No reference to 'PropertyChanged' found. References not modified.
1>    Fody:   Finished Fody 52ms.
1>    Fody:   Skipped Verifying assembly since it is disabled in configuration
1>    Fody:   Finished verification in 0ms.
1>  FodyTest -> C:\OceanAirdrop\TempCode\FodyTest\FodyTest\bin\Debug\FodyTest.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Now that’s nice and saves us a lot of work. Here's the full implementation:

class Program
{
    static void Main(string[] args)
    {
        var p = new Person();
        p.PropertyChanged += PropertyChangedEvent;
        p.FirstName = "Berty";
        p.LastName = "Burnstein";
        p.DateOfBirth = DateTime.Now;
    }

    private static void PropertyChangedEvent(object sender, PropertyChangedEventArgs e)
    {
        var propertyChanged = (OceanAirdropPropertyChangedArgs)e;
        Trace.WriteLine(string.Format("{0} changed from {1} to {2}.", 
        propertyChanged.PropertyName, propertyChanged.Before, propertyChanged.After));
    }
}

// Create your model objects as normal, but derive from BaseData and INotifyPropertyChanged
public class Person : BaseData, INotifyPropertyChanged
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
}

// Create a base class that implements the INotifyPropertyChanged interface and raises the event
public class BaseData : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName, object before, object after)
    {
        if (PropertyChanged != null)
            PropertyChanged.Invoke(this, new OceanAirdropPropertyChangedArgs(propertyName, before, after));
    }
}

// Create own event args that capture property value before and after!
public class OceanAirdropPropertyChangedArgs : PropertyChangedEventArgs
{
    public OceanAirdropPropertyChangedArgs(string propertyName) : base(propertyName) { }

    public OceanAirdropPropertyChangedArgs(string propertyName, object before, object after) : base(propertyName)
    {
        Before = before; After = after;
    }
    public virtual object Before { get; }
    public virtual object After { get; }
}

So there we have it. I have written this blog post as a reminder for me, the next time I need to implement notification changes in another project. Fody is a nice little utility to be aware of and kept in our software toolbox.


Contact Me:  ocean.airdrop@gmail.com

Popular Posts

Recent Posts

Unordered List

Text Widget

Pages