When creating unit tests, we come across blocks of code that appear to be difficult to test. But with some thought, we can come up with some interesting solutions. Previously, we took a look at a test helper class that allows us to track changes to properties.
In the last article, we improved our PropertyChangeTracker class so that it works when "all properties" are updated. This time, we'll look at adding a finer-grained timeout.
Articles in this Series
o Tracking Property Changes in Unit Tests
o Update 1: Supporting "All Properties"
o Update 2: Finer-Grained Timeout (this article)
o Update 3: Async Tests
Note: The completed code for this article is in the "Timeout" branch of the GitHub project: jeremybytes/property-change-tracker. (It has also been merged into the master branch with some other updates.)
The Problem: 1 Second Resolution
The shortcoming of our current property change tracker is with the maximum wait time in our "WaitForChange" method:
The parameter is an integer, and it represents seconds. This means that our minimum wait time is 1 second.
This is an *extremely* long time to wait in a unit test. We want our tests to run fast. The faster our tests run, the more frequently we will run them.
Right now we have 3 tests that look at the timeout. This means that we have a minimum of a 3 second runtime for our tests:
In fact, our total run time is 5 seconds:
This doesn't seem like a long run time. But we only have 9 tests here. Once our test suite has several hundred tests, we may be hitting the timeout a dozen times in those tests, and that significantly impacts the running time of our test suite.
Finer-Grained Timeout
Ideally, we want to have much more control over this timeout period. As a start, we'll update the "WaitForChange" method so that it uses milliseconds instead of seconds. This is pretty easy:
The calculations are pretty much the same (although I did refactor it a bit). The result is that our maximum wait (a.k.a. timeout) is now in milliseconds.
DateTime.Now vs. DateTime.UtcNow
Just a quick note: another change to this code is that we use "DateTime.UtcNow" instead of "DateTime.Now". This is a minor optimization.
In the framework code, it turns out that "DateTime.Now" makes a call to "DateTime.UtcNow" and then it adjusts for the local timezone. We can avoid that calculation by just using the UTC time. For practical purposes, this makes no difference in functionality*. But there is a very slight performance difference.
*Exception: We will run into an issue with "DateTime.Now" if we run the unit tests precisely during a Daylight Saving Time switch over.
Breaking Change
We just made a breaking change to our code. Previous calls to "WaitForChange" that used "1" as a parameter will now have a timeout of 1 millisecond instead of 1 second.
Here's one of our tests:
We can see the difference in our results:
Our tests still pass, but our timings are different. This would be an issue if we were testing asynchronous calls (which we'll add in a future article).
Test Fix
Fixing the test is easy, we just need to change the parameter:
Now we have a timeout of 100 milliseconds. When we update all of our tests, we see the results:
Our total run time is now 3 seconds:
And most of that 3 seconds is actually the test runner starting up. So we've accomplished our goal of having a finer-grained timeout for our tracker class.
But lets add one more option before we leave this code.
Overload with TimeSpan
In addition to the millisecond option, we'll add an overload to our "WaitForChange" method that accepts a TimeSpan as a parameter.
Here's our additional method:
The logic is pretty close to our other method, but now we aren't limited to millisecond resolution. We can create whatever timeout we would like.
Additional Unit Tests
To test this new method, we'll create some additional tests. Here is a new test that is in the "Standard Properties" tests (see previous article for details on the test suite):
In this test, we're looking at what happens when our "max wait" has expired (hence, the name of the test). In the set up, we create a TimeSpan that represents 60 milliseconds.
This test was added to the "CallerMemberName" and "nameof()" test classes as well.
Here are the results:
We can see the new results that have run times of "59 ms" each. Our total run time stays the same:
So now we have 2 ways of calling our "WaitForChange" method: with milliseconds or with a TimeSpan.
Coming Up: Additional Tests
We still need some additional tests. As mentioned previously, the primary purpose of our PropertyChangeTracker class is to help us test where we have asynchronous methods updating our properties. So far, all of our tests are synchronous code.
So we'll add some asynchronous tests to make sure that all of this code still works reliably. And with that, we can do some additional validation of the timeouts that we have in place.
Wrap Up
We want our unit tests to run fast. The code that we had limited how fast some of our tests could run. 1-second resolution was just too long to be practical. We could easily update this code to give us millisecond resolution; however, this was a breaking change so we need to update the calling code (in this case, in our tests).
In addition, we added an option to accept an arbitrary TimeSpan. This offers even more flexibility when we use the PropertyChangeTracker in our tests.
Our class is slowly becoming useful in a larger variety of situations. More to come.
Happy Coding!
Friday, February 19, 2016
Tracking Properties in Unit Tests - Update 1: Supporting "All Properties"
When creating unit tests, we come across blocks of code that appear to be difficult to test. But with some thought, we can come up with some interesting solutions. Previously, we took a look at a test helper class that allows us to track changes to properties.
I've found that this code is especially helpful when testing view models that use asynchronous method calls. For more information on this scenario, please see the prior article: Tracking Property Changes in Unit Tests.
Articles in this Series
o Tracking Property Changes in Unit Tests
o Update 1: Supporting "All Properties" (this article)
o Update 2: Finer-Grained Timeout
o Update 3: Async Tests
There were some shortcomings in the original implementation. The code worked just fine in the environment that I created it for, but it falls down once we start trying to use it as a more general tool. Now it's time to address those shortcomings.
To make sure that the changes would work in various scenarios, I created a stand-alone project and a set of unit tests. The code is available on GitHub: jeremybytes/property-change-tracker.
Here are the shortfalls of the original code (as described in the prior article):
Note: The completed code for this article is in the "All Properties" branch of the GitHub project. (It has also been merged into the master branch with some other updates.)
Single Property vs. "All" Properties
When we implement the "INotifyPropertyChanged" interface, our goal is to get the "PropertyChanged" event to fire whenever we update one of our properties. This lets the UI know that the property has been updated, so the data-bound controls will re-bind their values.
For more information on this, check out the previous article that shows different ways to implement this code: CallerMemberName vs. nameof() in INotifyPropertyChanged.
In these examples, we have been passing in a specific property name, but we can also signal that *all* properties have been changed. Here's the documentation for the PropertyChanged event:
So we can pass "null" or "String.Empty" to fire the PropertyChanged event for all properties.
The Problem
The problem is that our PropertyChangeTracker code does not currently support "all properties". Here's the original code:
We have a "notifications" list that holds the names of the properties that have been changed. Then in our "WaitForChange" method, we look for the name of a property. But if "all properties" have been changed, then the string for the specific property will not appear in this list.
Test Classes & Unit Tests
Before making these changes, we'll set up some test classes and tests. Since there are multiple ways of implementing "INotifyPropertyChanged" (as we've seen), I decided to create 3 different test classes. This is technically not necessary because we've seen that the code gets compiled down to the same IL. But I initially approached this from a naive standpoint, so I wanted to "cover the bases".
Standard Properties Class
Inside the "TestHelpers.Tests" project is a "FakeClassStandardProperties" class. This uses quoted strings in the calls to RaisePropertyChanged. Here's a snippet with a sample property:
Then there is also a public method to update "all properties":
The "RaisePropertyChanged" method has a default value for the parameter. If no value is passed in, then "null" is used -- indicating that "all properties" have been changed.
Standard Properties Tests
To test our PropertyChangeTracker, we set up 3 initial tests. First, we look at a single property:
In the first test, we initialize our fake class and then hook up the PropertyChangeTracker. Then we change the "LastName" property and ask our tracker to wait for the "LastName" property to be changed. Since we just changed the property, the tracker will have it in its list of changed items, so it will return "true" immediately.
This scenario is a bit different than described in the original article on the change tracker because we are dealing with synchronous code. We will want to add tests in the future to test with asynchronous code since that's the primary reason for using this test helper. But for now, we'll stick with basic functionality.
In the second test, we initialize our fake class and hook up the tracker, but we do *not* change the property. This means that our "WaitForChange" method will wait for 1 second and then return "false" (meaning the property was not changed within the expected timeframe).
Note: One of our shortfalls of this object is that we have a timeout measured in seconds. This will be addressed in a future update.
Testing "All Properties"
In addition to these 2 tests, we have a third to test "all properties":
This has the same setup, but instead of updating a single property, we call the "NotifyAllProperties" method on our test class.
With our code in its initial state, this test will fail.
Testing with the CallerMemberName Attribute
We have another test class that implements INotifyPropertyChanged using the CallerMemberName attribute. This class is called "FakeClassCallerMemberName". Here's a sample property:
We don't have a quoted string when we call "RaisePropertyChanged" beause we are relying on the compiler to pass "FirstName" into the method. More information on the "CallerMemberName" attribute is available in a prior article: "Using the CallerMemberName Attribute for Better XAML Data Binding".
The method to update "all properties" is a little different:
Since we are using the "CallerMemberName" attribute, we don't want to leave the parameter empty. This would pass in "NotifyAllProperties" as the parameter, which is definitely not what we want.
Instead, we pass in an explicit "null". The "null" will then be passed through to the PropertyChanged event.
Unit Tests with the CallerMemberName fake class
The tests that go along with this fake class are pretty much the same as what we saw with the standard property fake class. So, we won't look at them here. Again, the test that uses the "NotifyAllProperties" method fails.
Testing with the "nameof()" Expression
As you might imagine, there is a third test class that implements INotifyPropertyChanged using the "nameof()" expression. Here's a sample property:
And a method to update "all properties":
Notice that this is the same as the class with standard properties. That's because we "RaisePropertyChanged" has a default value for the parameter, and since we do *not* have the CallerMemberName attribute, we can go back to relying on the default to pass in the "null" value.
Unit Tests with "nameof()"
Again, the unit tests that use this class are pretty much the same as the other tests, so we won't go through them here. As above, the test that uses "NotifyAllProperties" currently fails.
Adding Support for "All Properties"
So we have our tests in place. With our original code, we do get some failures:
This shows us that the tests which call the single properties pass, but the tests which update "all properties" fail.
The reason that the failing tests take 1 second to complete is because they wait for the timeout before returning "false". (Again, we'll address this timeout in a future article.)
Updated Code
I took the simplest path in order to add support for "all properties". I made changes to the PropertyChangeTracker in 2 locations. The first was the constructor:
If we compare this to the original constructor above, we see that there we added a conditional to check to see if the parameter is null or empty. This will handle both a "null" parameter or a "String.Empty" parameter, so this matches the specifications of the PropertyChanged event that we saw above.
As a simple path, I added a magic string to our notifications list: "***ALL***". I'm not a big fan of magic strings, but this code is pretty compact and isolated.
So let's look at the other part of the code: "WaitForChange":
In this code, we have added to the condition of the "while" loop. Instead of just checking for the property name, we also check for "***ALL***".
With this code in place, all of our tests now pass:
Considerations
I mentioned that I'm not a fan of magic strings, so why did I use one? Wouldn't it be better to check for the "all" parameter directly in the notifications list?
The answer is maybe. That's the code that I started with. The constructor would be unchanged from the original, but the "while" conditional looks like this:
With this code in place, all of the tests pass. But I wasn't happy with the readability. This is really a matter of opinion, so I won't recommend one over the other. But I have a preference for the version with the magic string because it's more readable. The class itself is small (only 45 lines of code), and the magic string is isolated (meaning, it doesn't cross class boundaries). So I'm willing to compromise in one area (magic string) to make another area better (readability).
Again, the code for this update is available in the "All Properties" branch on GitHub: jeremybytes/property-change-tracker.
Wrap Up
There was a bit of setup to get our tests in place. But once that was done, it was pretty easy to add our first improvement to the "PropertyChangeTracker" class. Next time around, we'll look at fixing our timeout so that we can have finer-grained values. One second is a really long minimum value, particularly if we have multiple tests that hit that timeout.
Also in the future, we'll look at adding tests that explicitly test our tracker with asynchronous code. This is closer to the real-world use for this test helper. And we may look at potential threading issues as well.
When we're looking to add features to our code, it's important to have tests in place to make sure that we don't break any existing functionality. This let's us move forward confidently and gives us immediate feedback when something goes wrong. And that makes me a faster coder.
Happy Coding!
I've found that this code is especially helpful when testing view models that use asynchronous method calls. For more information on this scenario, please see the prior article: Tracking Property Changes in Unit Tests.
Articles in this Series
o Tracking Property Changes in Unit Tests
o Update 1: Supporting "All Properties" (this article)
o Update 2: Finer-Grained Timeout
o Update 3: Async Tests
There were some shortcomings in the original implementation. The code worked just fine in the environment that I created it for, but it falls down once we start trying to use it as a more general tool. Now it's time to address those shortcomings.
To make sure that the changes would work in various scenarios, I created a stand-alone project and a set of unit tests. The code is available on GitHub: jeremybytes/property-change-tracker.
Here are the shortfalls of the original code (as described in the prior article):
- Missed "All" Property Changed
- The "while" Loop
- Finer-Grained Timeout
- Implementing IDisposable
Note: The completed code for this article is in the "All Properties" branch of the GitHub project. (It has also been merged into the master branch with some other updates.)
Single Property vs. "All" Properties
When we implement the "INotifyPropertyChanged" interface, our goal is to get the "PropertyChanged" event to fire whenever we update one of our properties. This lets the UI know that the property has been updated, so the data-bound controls will re-bind their values.
For more information on this, check out the previous article that shows different ways to implement this code: CallerMemberName vs. nameof() in INotifyPropertyChanged.
In these examples, we have been passing in a specific property name, but we can also signal that *all* properties have been changed. Here's the documentation for the PropertyChanged event:
So we can pass "null" or "String.Empty" to fire the PropertyChanged event for all properties.
The Problem
The problem is that our PropertyChangeTracker code does not currently support "all properties". Here's the original code:
We have a "notifications" list that holds the names of the properties that have been changed. Then in our "WaitForChange" method, we look for the name of a property. But if "all properties" have been changed, then the string for the specific property will not appear in this list.
Test Classes & Unit Tests
Before making these changes, we'll set up some test classes and tests. Since there are multiple ways of implementing "INotifyPropertyChanged" (as we've seen), I decided to create 3 different test classes. This is technically not necessary because we've seen that the code gets compiled down to the same IL. But I initially approached this from a naive standpoint, so I wanted to "cover the bases".
Standard Properties Class
Inside the "TestHelpers.Tests" project is a "FakeClassStandardProperties" class. This uses quoted strings in the calls to RaisePropertyChanged. Here's a snippet with a sample property:
Then there is also a public method to update "all properties":
The "RaisePropertyChanged" method has a default value for the parameter. If no value is passed in, then "null" is used -- indicating that "all properties" have been changed.
Standard Properties Tests
To test our PropertyChangeTracker, we set up 3 initial tests. First, we look at a single property:
In the first test, we initialize our fake class and then hook up the PropertyChangeTracker. Then we change the "LastName" property and ask our tracker to wait for the "LastName" property to be changed. Since we just changed the property, the tracker will have it in its list of changed items, so it will return "true" immediately.
This scenario is a bit different than described in the original article on the change tracker because we are dealing with synchronous code. We will want to add tests in the future to test with asynchronous code since that's the primary reason for using this test helper. But for now, we'll stick with basic functionality.
In the second test, we initialize our fake class and hook up the tracker, but we do *not* change the property. This means that our "WaitForChange" method will wait for 1 second and then return "false" (meaning the property was not changed within the expected timeframe).
Note: One of our shortfalls of this object is that we have a timeout measured in seconds. This will be addressed in a future update.
Testing "All Properties"
In addition to these 2 tests, we have a third to test "all properties":
This has the same setup, but instead of updating a single property, we call the "NotifyAllProperties" method on our test class.
With our code in its initial state, this test will fail.
Testing with the CallerMemberName Attribute
We have another test class that implements INotifyPropertyChanged using the CallerMemberName attribute. This class is called "FakeClassCallerMemberName". Here's a sample property:
We don't have a quoted string when we call "RaisePropertyChanged" beause we are relying on the compiler to pass "FirstName" into the method. More information on the "CallerMemberName" attribute is available in a prior article: "Using the CallerMemberName Attribute for Better XAML Data Binding".
The method to update "all properties" is a little different:
Since we are using the "CallerMemberName" attribute, we don't want to leave the parameter empty. This would pass in "NotifyAllProperties" as the parameter, which is definitely not what we want.
Instead, we pass in an explicit "null". The "null" will then be passed through to the PropertyChanged event.
Unit Tests with the CallerMemberName fake class
The tests that go along with this fake class are pretty much the same as what we saw with the standard property fake class. So, we won't look at them here. Again, the test that uses the "NotifyAllProperties" method fails.
Testing with the "nameof()" Expression
As you might imagine, there is a third test class that implements INotifyPropertyChanged using the "nameof()" expression. Here's a sample property:
And a method to update "all properties":
Notice that this is the same as the class with standard properties. That's because we "RaisePropertyChanged" has a default value for the parameter, and since we do *not* have the CallerMemberName attribute, we can go back to relying on the default to pass in the "null" value.
Unit Tests with "nameof()"
Again, the unit tests that use this class are pretty much the same as the other tests, so we won't go through them here. As above, the test that uses "NotifyAllProperties" currently fails.
Adding Support for "All Properties"
So we have our tests in place. With our original code, we do get some failures:
This shows us that the tests which call the single properties pass, but the tests which update "all properties" fail.
The reason that the failing tests take 1 second to complete is because they wait for the timeout before returning "false". (Again, we'll address this timeout in a future article.)
Updated Code
I took the simplest path in order to add support for "all properties". I made changes to the PropertyChangeTracker in 2 locations. The first was the constructor:
If we compare this to the original constructor above, we see that there we added a conditional to check to see if the parameter is null or empty. This will handle both a "null" parameter or a "String.Empty" parameter, so this matches the specifications of the PropertyChanged event that we saw above.
As a simple path, I added a magic string to our notifications list: "***ALL***". I'm not a big fan of magic strings, but this code is pretty compact and isolated.
So let's look at the other part of the code: "WaitForChange":
In this code, we have added to the condition of the "while" loop. Instead of just checking for the property name, we also check for "***ALL***".
With this code in place, all of our tests now pass:
Considerations
I mentioned that I'm not a fan of magic strings, so why did I use one? Wouldn't it be better to check for the "all" parameter directly in the notifications list?
The answer is maybe. That's the code that I started with. The constructor would be unchanged from the original, but the "while" conditional looks like this:
With this code in place, all of the tests pass. But I wasn't happy with the readability. This is really a matter of opinion, so I won't recommend one over the other. But I have a preference for the version with the magic string because it's more readable. The class itself is small (only 45 lines of code), and the magic string is isolated (meaning, it doesn't cross class boundaries). So I'm willing to compromise in one area (magic string) to make another area better (readability).
Again, the code for this update is available in the "All Properties" branch on GitHub: jeremybytes/property-change-tracker.
Wrap Up
There was a bit of setup to get our tests in place. But once that was done, it was pretty easy to add our first improvement to the "PropertyChangeTracker" class. Next time around, we'll look at fixing our timeout so that we can have finer-grained values. One second is a really long minimum value, particularly if we have multiple tests that hit that timeout.
Also in the future, we'll look at adding tests that explicitly test our tracker with asynchronous code. This is closer to the real-world use for this test helper. And we may look at potential threading issues as well.
When we're looking to add features to our code, it's important to have tests in place to make sure that we don't break any existing functionality. This let's us move forward confidently and gives us immediate feedback when something goes wrong. And that makes me a faster coder.
Happy Coding!
Sunday, February 14, 2016
CallerMemberName vs. nameof() in INotifyPropertyChanged
Last month, we took a look at some of the framework and language changes that make it easier to implement INotifyPropertyChanged in our classes. Two of those changed included the "CallerMemberName" attribute and the "nameof()" expression.
Antoine left a great question since the functionality of "CallerMemberName" and "nameof()" seem so similar:
Review: Using a String Parameter Directly
Let's look at why we want to use either "CallerMemberName" or "nameof()". For this, we'll do a quick review of how we implemented INotifyPropertyChanged before we had these.
This is a typical implementation of INotifyPropertyChanged (although you'll probably notice that we're using the null-conditional operator that we learned about before).
We could then call "RaisePropertyChanged" in our property setter by passing in the name of the property as a string:
This works, but wherever we have quoted strings, we have good places for things to break. For example, if we type the name of the property incorrectly, it will not work. If we change the name of our property, it's likely that our refactoring tool will not change the string, and it will not work.
So we'd like an option where we don't have to use a quoted string for the property name.
Review: Using "CallerMemberName" Attribute
One option is to use the "CallerMemberName" attribute (which was added to the framework in .NET 4.5), we put the attribute into our implementation of INotifyPropertyChanged:
Because the "CallerMemberName" attribute is placed before the first parameter of our "RaisePropertyChanged" method, the name of the calling item will be substituted here. So that means our property setter can look like this:
Notice that we do not pass a parameter to "RaisePropertyChanged". But because we have the attribute on the parameter, the string "FirstName" (the name of our property) is passed in automatically.
This fixes our initial problem because we no longer have a quoted string to worry about.
For more information on the "CallerMemberName" attribute, see "Using the CallerMemberName Attribute for Better XAML Data Binding".
Review: Using the "nameof()" Expression
A new option that we got with C# 6 (and the Visual Studio 2015 compiler) is the "nameof()" expression. To use this, we don't need to do anything special with our implementation of "INotifyPropertyChanged":
Notice that this implementation is exactly the same as our first example where we use the string parameter directly.
But instead of using a string parameter, we use the "nameof()" expression in the property setter:
When we use "nameof(FirstName)" in our code, it will pass the string "FirstName" as a parameter to "RaisePropertyChanged", so we get the correct value. And this has the added benefit of not being a quoted string.
This means that if we type "FirstName" incorrectly, we will get a compiler error. In addition, if we rename the property, our refactoring tools will automatically update the "nameof()" expression as well.
So why do I prefer "nameof()" to "CallerMemberName"?
Are There Performance Differences?
The first thing to do is look at performance. It turns out that all three of these implementations generate the same compiled code.
To take a look at the sample code, go to the "property-change-tracker" project on GitHub: jeremybytes/property-change-tracker. Inside of the "TestHelpers.Tests" project, there are classes that have all three implementations:
FakeClassStandardProperties
The "FakeClassStandardProperties" uses the quoted string parameters. If we look at the IL (intermediate language) that the compiler generates for the "FirstName" property, we see this code:
(Just a snippet). Notice the string "FirstName". This quoted string is used as the parameter for the next line, which is a call to "RaisePropertyChanged".
That's not much of a surprise, but let's look at the other classes.
FakeClassCallerMemberName
The "FakeClassCallerMemberName" uses the "CallerMemberName" attribute like we saw above. Let's look at the IL that is generated by the compiler:
This also has the quoted string "FirstName" which then gets used as a parameter for "RaisePropertyChanged". The compiler generates the same code as if we pass in the string directly.
So this means that there is no performance difference (at least at runtime), when we use the "CallerMemberName" attribute in this sceneario.
FakeClassNameOf
The "FakeClassNameOf" uses the "nameof()" expression like we saw above. Here's the IL that's generated:
Again we see the "FirstName" quoted string in our IL.
So this means that there is no performance difference if we use the "nameof()" expression in this scenario.
With no performance differences, why do I prefer "nameof()" over "CallerMemberName"? Let's take a look at another scenario: calculated properties.
Consistency and Calculated Properties
I've written a lot of user-facing applications. And quite often, these applications would have calculated properties -- properties that were based on 1 or more other properties. Here's an example:
If we have an order form that has both "Quantity" and "Price" properties, then we may also want a "TotalPrice" property that is calculated from these values.
In this case, if the "Quantity" is updated, then I want the "TotalPrice" property to be recalculated. In our data binding world, this means that we also need to call "RaisePropertyChanged" for our "TotalPrice" property.
Using the CallerMemberName Attribute
If we use the "CallerMemberName" attribute in this scenario, then our "Quantity" property may look like this:
The first "RaisePropertyChanged" (without a parameter), will get "Quantity" passed in. But for the second call to "RaisePropertyChanged", we need to explicitly pass a parameter so that we can also raise the PropertyChanged event for "TotalPrice".
Now, we know that using a hard-coded string here is not a good idea. That's the whole reason we want to use one of these other features. So, it makes more sense to update the code like this:
So the first call to "RaisePropertyChanged" (without the parameters) still raises the PropertyChanged event for "Quantity", but then the second call will raise it for "TotalPrice". And again, we get the benefits of not using a hard-coded string here.
Consistency with the nameof() Expression
And this is where I want to take things one step further. If I only have *one* call to "RaisePropertyChanged", then I don't have to do much thinking -- of course, this will reference the current property.
But when I have *two* calls to "RaisePropertyChanged", and one of them doesn't have any parameters, I need to start thinking a little more. Instead of this, I'd rather just use the "nameof()" expression for both calls.
This gives my brain something that is really easy to process. Without having to think about details, I know that this raises the PropertyChanged event for both "Quantity" and "TotalPrice".
Wrap Up
The "CallerMemberName" attribute and the "nameof()" expression both give us the same key benefits: (1) they eliminate the quoted string in our properties, and (2) they don't affect runtime performance.
But once we start to look at other scenarios -- like having calculated properties -- we see that "nameof()" can give us consistency in our properties that makes them easier to read and understand. And when we're dealing with code, human readability is a key feature.
In the applications I've spent most of my career with, calculated properties are pretty common. Because of that, I prefer the "nameof()" expression. But if you have classes that have no calculated properties (which is common when using entity classes), you may get better readability by using the "CallerMemberName" attribute.
A big part of making these types of decisions is to understand our environment. This helps us make the right decision for our particular application.
Happy Coding!
Antoine left a great question since the functionality of "CallerMemberName" and "nameof()" seem so similar:
I don't see the point of using nameof() instead of the CallerMemberName though, is it about performance?Let's take a closer look, first to see if there are any performance differences, and then see an example of why I prefer to use "nameof()": calculated properties.
Review: Using a String Parameter Directly
Let's look at why we want to use either "CallerMemberName" or "nameof()". For this, we'll do a quick review of how we implemented INotifyPropertyChanged before we had these.
This is a typical implementation of INotifyPropertyChanged (although you'll probably notice that we're using the null-conditional operator that we learned about before).
We could then call "RaisePropertyChanged" in our property setter by passing in the name of the property as a string:
This works, but wherever we have quoted strings, we have good places for things to break. For example, if we type the name of the property incorrectly, it will not work. If we change the name of our property, it's likely that our refactoring tool will not change the string, and it will not work.
So we'd like an option where we don't have to use a quoted string for the property name.
Review: Using "CallerMemberName" Attribute
One option is to use the "CallerMemberName" attribute (which was added to the framework in .NET 4.5), we put the attribute into our implementation of INotifyPropertyChanged:
Because the "CallerMemberName" attribute is placed before the first parameter of our "RaisePropertyChanged" method, the name of the calling item will be substituted here. So that means our property setter can look like this:
Notice that we do not pass a parameter to "RaisePropertyChanged". But because we have the attribute on the parameter, the string "FirstName" (the name of our property) is passed in automatically.
This fixes our initial problem because we no longer have a quoted string to worry about.
For more information on the "CallerMemberName" attribute, see "Using the CallerMemberName Attribute for Better XAML Data Binding".
Review: Using the "nameof()" Expression
A new option that we got with C# 6 (and the Visual Studio 2015 compiler) is the "nameof()" expression. To use this, we don't need to do anything special with our implementation of "INotifyPropertyChanged":
Notice that this implementation is exactly the same as our first example where we use the string parameter directly.
But instead of using a string parameter, we use the "nameof()" expression in the property setter:
When we use "nameof(FirstName)" in our code, it will pass the string "FirstName" as a parameter to "RaisePropertyChanged", so we get the correct value. And this has the added benefit of not being a quoted string.
This means that if we type "FirstName" incorrectly, we will get a compiler error. In addition, if we rename the property, our refactoring tools will automatically update the "nameof()" expression as well.
So why do I prefer "nameof()" to "CallerMemberName"?
Are There Performance Differences?
The first thing to do is look at performance. It turns out that all three of these implementations generate the same compiled code.
To take a look at the sample code, go to the "property-change-tracker" project on GitHub: jeremybytes/property-change-tracker. Inside of the "TestHelpers.Tests" project, there are classes that have all three implementations:
FakeClassStandardProperties
The "FakeClassStandardProperties" uses the quoted string parameters. If we look at the IL (intermediate language) that the compiler generates for the "FirstName" property, we see this code:
(Just a snippet). Notice the string "FirstName". This quoted string is used as the parameter for the next line, which is a call to "RaisePropertyChanged".
That's not much of a surprise, but let's look at the other classes.
FakeClassCallerMemberName
The "FakeClassCallerMemberName" uses the "CallerMemberName" attribute like we saw above. Let's look at the IL that is generated by the compiler:
This also has the quoted string "FirstName" which then gets used as a parameter for "RaisePropertyChanged". The compiler generates the same code as if we pass in the string directly.
So this means that there is no performance difference (at least at runtime), when we use the "CallerMemberName" attribute in this sceneario.
FakeClassNameOf
The "FakeClassNameOf" uses the "nameof()" expression like we saw above. Here's the IL that's generated:
Again we see the "FirstName" quoted string in our IL.
So this means that there is no performance difference if we use the "nameof()" expression in this scenario.
With no performance differences, why do I prefer "nameof()" over "CallerMemberName"? Let's take a look at another scenario: calculated properties.
Consistency and Calculated Properties
I've written a lot of user-facing applications. And quite often, these applications would have calculated properties -- properties that were based on 1 or more other properties. Here's an example:
If we have an order form that has both "Quantity" and "Price" properties, then we may also want a "TotalPrice" property that is calculated from these values.
In this case, if the "Quantity" is updated, then I want the "TotalPrice" property to be recalculated. In our data binding world, this means that we also need to call "RaisePropertyChanged" for our "TotalPrice" property.
Using the CallerMemberName Attribute
If we use the "CallerMemberName" attribute in this scenario, then our "Quantity" property may look like this:
The first "RaisePropertyChanged" (without a parameter), will get "Quantity" passed in. But for the second call to "RaisePropertyChanged", we need to explicitly pass a parameter so that we can also raise the PropertyChanged event for "TotalPrice".
Now, we know that using a hard-coded string here is not a good idea. That's the whole reason we want to use one of these other features. So, it makes more sense to update the code like this:
So the first call to "RaisePropertyChanged" (without the parameters) still raises the PropertyChanged event for "Quantity", but then the second call will raise it for "TotalPrice". And again, we get the benefits of not using a hard-coded string here.
Consistency with the nameof() Expression
And this is where I want to take things one step further. If I only have *one* call to "RaisePropertyChanged", then I don't have to do much thinking -- of course, this will reference the current property.
But when I have *two* calls to "RaisePropertyChanged", and one of them doesn't have any parameters, I need to start thinking a little more. Instead of this, I'd rather just use the "nameof()" expression for both calls.
This gives my brain something that is really easy to process. Without having to think about details, I know that this raises the PropertyChanged event for both "Quantity" and "TotalPrice".
Wrap Up
The "CallerMemberName" attribute and the "nameof()" expression both give us the same key benefits: (1) they eliminate the quoted string in our properties, and (2) they don't affect runtime performance.
But once we start to look at other scenarios -- like having calculated properties -- we see that "nameof()" can give us consistency in our properties that makes them easier to read and understand. And when we're dealing with code, human readability is a key feature.
In the applications I've spent most of my career with, calculated properties are pretty common. Because of that, I prefer the "nameof()" expression. But if you have classes that have no calculated properties (which is common when using entity classes), you may get better readability by using the "CallerMemberName" attribute.
A big part of making these types of decisions is to understand our environment. This helps us make the right decision for our particular application.
Happy Coding!
Labels:
CallerMemberName,
INotifyPropertyChanged,
Properties
Sunday, January 31, 2016
Speaker Tip: Start Your Timer Now!
Many speakers use a timer. This helps you stay on track and not run over. I know some speakers who set up a tablet or phone with a countdown timer. A few years ago, I picked up a Logitech presentation remote with a built-in timer (it's a bit well-worn now):
I like this remote because it buzzes at me when my time starts to run down. But when I was learning to use it, I made a big mistake. I would set it for 1 hour (or however long the presentation was supposed to be), but then I would forget to start it.
Then I picked up an awesome piece of advice (I heard it from Kathleen Dollard):
This means that you start the timer while you're thinking about it -- because it is way too easy to forget to start it when you're worrying about starting your presentation. As an added bonus, it helps you remember when you're supposed to start talking.
Since I started doing this, I've never forgotten to start my timer.
Happy Speaking!
![]() |
| 1 hour talk (don't do this) |
Then I picked up an awesome piece of advice (I heard it from Kathleen Dollard):
Don't set the timer for the length of the talk. Set it for how long until the talk ends from now.So if the talk is one hour long, and it starts in 7 minutes, set the timer for 1:07 and then start it now.
![]() |
| 1 hour talk that starts in 7 minutes (do this!) |
Since I started doing this, I've never forgotten to start my timer.
Happy Speaking!
Saturday, January 30, 2016
February 2016 Speaking Engagements
I'll be speaking at a number of user groups in February. Be sure to stop by if you get a chance.
Tuesday, February 2, 2016
LA C#
Pasadena, CA
Meetup Link
o Unit Testing Makes Me Faster: Convincing Your Boss, Your Co-Workers, and Yourself
Wednesday, February 3, 2016
So Cal Dot NET
Buena Park, CA
Meetup Link
o I'll Get Back to You: Understanding Task, Await, and Asynchronous Methods
Tuesday, February 9, 2016
Ontario C#
Ontario, CA
Meetup Link
o I'll Get Back to You: Understanding Task, Await, and Asynchronous Methods
Wednesday, February 10, 2016
vNext OC
Newport Beach, CA
Meetup Link
o DI Why? Getting a Grip on Dependency Injection
Thursday, February 25, 2016
DotNet Group.org
Las Vegas, NV
Meetup Site
o Learn the Lingo: Design Patterns
Past Events
I stayed pretty busy in January -- mostly because I was traveling (on the road for 15 days).
First, I headed to CodeMash in Sandusky, OH. This was my first opportunity to go to CodeMash, and I stayed pretty busy throughout the week. There were tons of people to talk to and lots of great sessions. I had a good time presenting on how to get the right level of abstraction in our applications:
I also built a really sad robot in the NodeBots workshop:
NDC London was a really awesome conference. I had a lot more people attend my presentation on Task and Await than I was expecting.
I had a really great time (as usual). Thanks to folks on Twitter for the pictures (@ChrisAnnODell, @jakegreenwood, @jplebre):
I was also very happy to see the response:
This past week, I went to Riverside, CA to speak at IE.NET. I had a great time talking about one of my favorite topics: Interfaces.
Upcoming Events
My calendar for the rest of the year is starting to fill in. At the end of March, I'll be at Code PaLOUsa in Louisville, KY. In May, I'll be at Visual Studio LIVE! Austin in Austin, TX. And I've been invited to speak at NDC Oslo in June in Oslo, Norway. (My picture is currently on the front page!)
In addition, I'll be speaking at user groups in Southern and Central California. If you'd like me to speak at your Meetup or developer event, be sure to drop me a note. I've got tons of topics that I'm passionate about, and I'm adding to the list all the time.
I hope to see you at an upcoming event.
Happy Coding!
Tuesday, February 2, 2016
LA C#
Pasadena, CA
Meetup Link
o Unit Testing Makes Me Faster: Convincing Your Boss, Your Co-Workers, and Yourself
Wednesday, February 3, 2016
So Cal Dot NET
Buena Park, CA
Meetup Link
o I'll Get Back to You: Understanding Task, Await, and Asynchronous Methods
Tuesday, February 9, 2016
Ontario C#
Ontario, CA
Meetup Link
o I'll Get Back to You: Understanding Task, Await, and Asynchronous Methods
Wednesday, February 10, 2016
vNext OC
Newport Beach, CA
Meetup Link
o DI Why? Getting a Grip on Dependency Injection
Thursday, February 25, 2016
DotNet Group.org
Las Vegas, NV
Meetup Site
o Learn the Lingo: Design Patterns
Past Events
I stayed pretty busy in January -- mostly because I was traveling (on the road for 15 days).
First, I headed to CodeMash in Sandusky, OH. This was my first opportunity to go to CodeMash, and I stayed pretty busy throughout the week. There were tons of people to talk to and lots of great sessions. I had a good time presenting on how to get the right level of abstraction in our applications:
![]() |
| At CodeMash talking about "Abstract Art" |
As if going to one conference isn't exhausting enough, I hopped on a plane and flew from Ohio to London for NDC London. It was my first time in London, so I took a few days to go around the city. I got to see things that were pretty amazing, including the National Gallery, Trafalgar Square, Tower Bridge, the British Museum (including seeing the Rosetta Stone!), standing on the Prime Meridian at Greenwich, and walking across the London Bridge. This means that I've walked across *both* London Bridges -- the one in Lake Havasu City and the one in London.Built a rather sad robot at #CodeMash nodebots. Not bad for a first try. I guess I need some practice. pic.twitter.com/bmkSci3P9U— Jeremy Clark (@jeremybytes) January 7, 2016
NDC London was a really awesome conference. I had a lot more people attend my presentation on Task and Await than I was expecting.
![]() |
| A full room at NDC London |
![]() |
| At NDC London talking about Task and Await |
— Anthony Chu (@nthonyChu) January 15, 2016
The total counts for my session were 157 Green, 7 Yellow, and 0 Red.This past week, I went to Riverside, CA to speak at IE.NET. I had a great time talking about one of my favorite topics: Interfaces.
![]() |
| At Inland Empire .NET in Riverside, CA |
Upcoming Events
My calendar for the rest of the year is starting to fill in. At the end of March, I'll be at Code PaLOUsa in Louisville, KY. In May, I'll be at Visual Studio LIVE! Austin in Austin, TX. And I've been invited to speak at NDC Oslo in June in Oslo, Norway. (My picture is currently on the front page!)
In addition, I'll be speaking at user groups in Southern and Central California. If you'd like me to speak at your Meetup or developer event, be sure to drop me a note. I've got tons of topics that I'm passionate about, and I'm adding to the list all the time.
I hope to see you at an upcoming event.
Happy Coding!
Sunday, January 3, 2016
The Evolution of INotifyPropertyChanged
When we implement the INotifyPropertyChanged interface, it's pretty common for us to copy code from a previous implementation or use a shared base class. What we don't normally do is review the code that we've been reusing.
But there are some features in .NET 4.5 and 4.6 that we can use to improve our implementation. Let's take a look at those to see how we can reduce our code without reducing functionality or safety.
Update: As Andrew points out in the comments; this article previously used the incorrect terminology for the null-conditional operator "?.". This has been corrected.
A Bit of Background
I really love data binding in XAML; it's extremely flexible and powerful. But in order for data binding to work appropriately, we need to implement the INotifyPropertyChanged interface in our data classes.
Original Implementation
The INotifyPropertyChanged interface only has a single member: the PropertyChanged event. To make it easier to raise this event, it's pretty common to create a helper method. Common names for this are "OnPropertyChanged" or "RaisePropertyChanged" (I prefer "RaisePropertyChanged").
So here's an implementation that I use to use:
This shows our helper method (RaisePropertyChanged) that takes the property name as a string. This is used to create the event args and then invoke the event.
This notifies the UI that anything bound to this property needs to be updated. If the event is called with a "null" parameter, then it is the same as notifying that all the properties have been updated.
To raise the event, we call "RaisePropertyChanged" in the setter for our properties:
If the value of the property has changed, then we set the property and then raise the event using a string value for the parameter.
Safer Implementation
This code worked, but it can be improved. First, let's look at it from a thread-safety perspective. It's possible that the PropertyChanged event could be updated in between the null check and the code to invoke the event.
To make things safer, we should use an intermediate variable:
By using the "handler" variable, we create a copy the PropertyChanged event. Since this is a local variable, we know that it will not be updated in between the null check and the invocation of the event.
This gives us a thread-safe implementation of our "RaisePropertyChanged" method. (Again, thanks to Brian Lagunas for pointing this out to me.)
Improvements with .NET 4.5
The previous code works, and it will continue to work, but it does have some shortcomings. First is the use of the string parameter.
Hard-coded strings are rarely a good idea. If we happen to type the string incorrectly, then the data binding will not work as expected. This is especially frustrating to debug because there are no runtime errors; the UI elements are simply not updated like we want them to be.
In addition, if we change the name of our property, we need to make sure to update the string as well. Refactoring tools have gotten better; many of them have the option to update strings and comments when we rename a property. But it's possible to miss updating the string parameter.
Using the CallerMemberName Attribute
In .NET 4.5, we got a new attribute that can help us with our string problem: CallerMemberName. You can get a full description of how it works here: Using the CallerMemberName Attribute for Better XAML Data Binding.
The short version is that we can add the attribute to our INotifyPropertyChanged implementation:
Notice the attribute before the parameter. This value will automatically be populated with the name of the object calling this method.
Note: This is the non-thread-safe version of the code (it's taken from the example code in the article mentioned above). We should add the intermediate variable to make things safer.
With this new attribute in place, we can now update our properties as follows:
Notice that when we call "RaisePropertyChanged", we no longer pass in a parameter. Instead, we rely on the fact that "ProgressPercentage" (the name of our property) will automatically be passed because of the "CallerMemberName" attribute.
This gives us the advantage of no longer having a hard-coded string in our code. So we don't have to worry about typos or missed updates if we rename things.
Improvements with Visual Studio 2015
The previous code works (and will continue to work), but there are a couple of new features that came in with C# 6 that we can use. Since this is language/compiler related, we can use these with earlier version of .NET as long as we use the Visual Studio 2015 compiler to build the code.
"nameof" Expression
The "nameof" expression can get us the string name of a variable, type, or member. This is new in C# 6. Check out MSDN for more information: nameof (C# and Visual Basic Reference).
This lets us create our properties like this:
Instead of passing a hard-coded string to "RaisePropertyChanged", we use "nameof" to generate the string for us. The end result is the same: we will pass the string "ProgressPercentage" to our method. The difference is that we will get a compile-time warning if we typo "ProgressPercentage" since this references the property.
In addition, if we use a refactoring tool to rename our property, the reference in "nameof" will get updated as well.
Using "nameof" will work with or without the "CallerMemberName" attribute.
Null-Conditional Operator
Another feature of C# 6 that we can use is the null-conditional operator (also called the "Elvis operator"). This takes of the form of "?.", and it combines a method or property reference with a null check.
Let's look at our INotifyPropertyChanged implementation to see how this operator works:
Compared to:
If the "PropertyChanged" event is null (meaning there are no event handlers hooked up to it), then everything after the "?." is ignored.
If "PropertyChanged" is not null, then the "Invoke" method is called. Note: calling "Invoke" explicitly is the equivalent of calling "PropertyChanged" with the parameters in the prior example.
The best thing about the null-conditional operator is that it is thread safe. This means that we no longer need the intermediate variable that we use earlier. So we end up with a very compact method that is thread safe.
Combining Features
We can also combine the "CallerMemberName" attribute with the null-conditional operator. Whether we do this depends on how we want to do our property code: either using no parameter or the "nameof" expression.
Reviewing Implementations
It's really easy for us to keep using the code that we're comfortable with. The "INotifyPropertyChanged" interface is especially prone to this. It is treated like boiler-plate code that has a consistent implementation. Because of this, we don't often review the code (as long as is continues to work).
I've described a very simple implementation here. Often people will use a base class or more involved implementation to make it easier to create properties. You can check out Dan Rigby's series of articles for some options on that.
From time to time, we should take a look at our boiler-plate implementations to see if they can be improved. In the case of "INotifyPropertyChanged", the "nameof" expression makes our code less brittle and easier to maintain. In addition, we can use the null-conditional operator to improve readability while still maintaining thread safety.
We'd never know about this without taking time for review.
Happy Coding!
But there are some features in .NET 4.5 and 4.6 that we can use to improve our implementation. Let's take a look at those to see how we can reduce our code without reducing functionality or safety.
Update: As Andrew points out in the comments; this article previously used the incorrect terminology for the null-conditional operator "?.". This has been corrected.
A Bit of Background
I really love data binding in XAML; it's extremely flexible and powerful. But in order for data binding to work appropriately, we need to implement the INotifyPropertyChanged interface in our data classes.
Original Implementation
The INotifyPropertyChanged interface only has a single member: the PropertyChanged event. To make it easier to raise this event, it's pretty common to create a helper method. Common names for this are "OnPropertyChanged" or "RaisePropertyChanged" (I prefer "RaisePropertyChanged").
So here's an implementation that I use to use:
![]() |
| Original Implementation (could be better) |
This shows our helper method (RaisePropertyChanged) that takes the property name as a string. This is used to create the event args and then invoke the event.
This notifies the UI that anything bound to this property needs to be updated. If the event is called with a "null" parameter, then it is the same as notifying that all the properties have been updated.
To raise the event, we call "RaisePropertyChanged" in the setter for our properties:
![]() |
| Original Property Implementation (pre .NET 4.5) |
If the value of the property has changed, then we set the property and then raise the event using a string value for the parameter.
Safer Implementation
This code worked, but it can be improved. First, let's look at it from a thread-safety perspective. It's possible that the PropertyChanged event could be updated in between the null check and the code to invoke the event.
To make things safer, we should use an intermediate variable:
![]() |
| Safer Implementation (pre .NET 4.5) |
By using the "handler" variable, we create a copy the PropertyChanged event. Since this is a local variable, we know that it will not be updated in between the null check and the invocation of the event.
This gives us a thread-safe implementation of our "RaisePropertyChanged" method. (Again, thanks to Brian Lagunas for pointing this out to me.)
Improvements with .NET 4.5
The previous code works, and it will continue to work, but it does have some shortcomings. First is the use of the string parameter.
![]() |
| Original Property Implementation (pre .NET 4.5) |
Hard-coded strings are rarely a good idea. If we happen to type the string incorrectly, then the data binding will not work as expected. This is especially frustrating to debug because there are no runtime errors; the UI elements are simply not updated like we want them to be.
In addition, if we change the name of our property, we need to make sure to update the string as well. Refactoring tools have gotten better; many of them have the option to update strings and comments when we rename a property. But it's possible to miss updating the string parameter.
Using the CallerMemberName Attribute
In .NET 4.5, we got a new attribute that can help us with our string problem: CallerMemberName. You can get a full description of how it works here: Using the CallerMemberName Attribute for Better XAML Data Binding.
The short version is that we can add the attribute to our INotifyPropertyChanged implementation:
![]() |
| Implementation with CallerMemberName Attribute (.NET 4.5) |
Notice the attribute before the parameter. This value will automatically be populated with the name of the object calling this method.
Note: This is the non-thread-safe version of the code (it's taken from the example code in the article mentioned above). We should add the intermediate variable to make things safer.
With this new attribute in place, we can now update our properties as follows:
![]() |
| Property Implementation with CallerMemberName (.NET 4.5) |
Notice that when we call "RaisePropertyChanged", we no longer pass in a parameter. Instead, we rely on the fact that "ProgressPercentage" (the name of our property) will automatically be passed because of the "CallerMemberName" attribute.
This gives us the advantage of no longer having a hard-coded string in our code. So we don't have to worry about typos or missed updates if we rename things.
Improvements with Visual Studio 2015
The previous code works (and will continue to work), but there are a couple of new features that came in with C# 6 that we can use. Since this is language/compiler related, we can use these with earlier version of .NET as long as we use the Visual Studio 2015 compiler to build the code.
"nameof" Expression
The "nameof" expression can get us the string name of a variable, type, or member. This is new in C# 6. Check out MSDN for more information: nameof (C# and Visual Basic Reference).
This lets us create our properties like this:
![]() |
| Property Implementation with "nameof" Expression (.NET 4.6) |
Instead of passing a hard-coded string to "RaisePropertyChanged", we use "nameof" to generate the string for us. The end result is the same: we will pass the string "ProgressPercentage" to our method. The difference is that we will get a compile-time warning if we typo "ProgressPercentage" since this references the property.
In addition, if we use a refactoring tool to rename our property, the reference in "nameof" will get updated as well.
Using "nameof" will work with or without the "CallerMemberName" attribute.
Null-Conditional Operator
Another feature of C# 6 that we can use is the null-conditional operator (also called the "Elvis operator"). This takes of the form of "?.", and it combines a method or property reference with a null check.
Let's look at our INotifyPropertyChanged implementation to see how this operator works:
![]() |
| Original Implementation (could be better) |
Compared to:
![]() |
| Implementation with "?." (.NET 4.6) |
If "PropertyChanged" is not null, then the "Invoke" method is called. Note: calling "Invoke" explicitly is the equivalent of calling "PropertyChanged" with the parameters in the prior example.
The best thing about the null-conditional operator is that it is thread safe. This means that we no longer need the intermediate variable that we use earlier. So we end up with a very compact method that is thread safe.
Combining Features
We can also combine the "CallerMemberName" attribute with the null-conditional operator. Whether we do this depends on how we want to do our property code: either using no parameter or the "nameof" expression.
Reviewing Implementations
It's really easy for us to keep using the code that we're comfortable with. The "INotifyPropertyChanged" interface is especially prone to this. It is treated like boiler-plate code that has a consistent implementation. Because of this, we don't often review the code (as long as is continues to work).
I've described a very simple implementation here. Often people will use a base class or more involved implementation to make it easier to create properties. You can check out Dan Rigby's series of articles for some options on that.
From time to time, we should take a look at our boiler-plate implementations to see if they can be improved. In the case of "INotifyPropertyChanged", the "nameof" expression makes our code less brittle and easier to maintain. In addition, we can use the null-conditional operator to improve readability while still maintaining thread safety.
We'd never know about this without taking time for review.
Happy Coding!
Labels:
CallerMemberName,
INotifyPropertyChanged,
Properties
Friday, January 1, 2016
Being Present
Sometimes we make decisions unconsciously, but we'll read an article or someone says something that makes us reflect on those decisions. I've recently come across one of those decisions, and I'm looking for ways to follow it consciously.
So this is not really a resolution, but it's more of a continued intention:
Background
I started speaking back in January 2010. That first year, I spoke at 8 events and only 1 of those events was outside Southern California. In 2015, I spoke at 28 events, and 13 of those were outside So Cal. So I was on quite a few airplanes and away from home a bit more than usual.
During those 6 years, my interaction with other speakers has also changed. When I originally started, my circle included primarily local speakers -- folks who would speak at 2 or 3 events a year in their local development community. As time went on, my circle grew to include regional speakers and folks who travel to major events in the US. And in the last couple years, my circle has grown to include people who speak across the US and internationally, and they spend much more time on airplanes than I do.
I've noticed a few things this past year that helped me focus my priorities.
Before going any further, I want to put in a disclaimer. I've been thinking about this article for quite a while, and I've had trouble figuring out how to write it. One reason is that I'll be referring to behaviors of some other speakers. I don't want this to come across as disparaging of those behaviors. Everyone is different and has different priorities. I'm making my decisions based on my own priorities.
Not Available
One of the things I've run across several times this year are speakers who fly in, do their presentations, and then fly out.
I always go through the speaker list for any event that I'm speaking at, and I make notes of folks that I've wanted to meet and talk to. I figure that we'll be around the same conference for 3 or 4 (usually very long) days, so I should have a chance to meet at some point, even if just for a few minutes.
But then the only place I'll see that person is during their presentation. And I don't usually go up after presentations because I want to give other folks a chance to talk to the speaker -- I'll wait for another opportunity. Unfortunately, that opportunity doesn't come.
Now obviously, that's a bit selfish of me because I'm thinking about my own disappointment. But I compare that to my priorities and what I what kind of accessibility I want people to have to me.
The reasons for the inaccessibility are many. Some speakers are horrendously busy -- sometimes doing 2 events the same week. Some speakers want to minimize time away from home and family (which is an awesome priority). Some speakers are not comfortable talking to people when they're not on stage. Some speakers have time-sensitive work to do while they are at an event.
Again, I don't want to disparage these decisions or priorities. I'm just using them as a reference point for my own priorities.
Talking to Other Developers
I've made it a big priority to talk to other developers. It was difficult for me to do the first few times, but I've seen so many benefits that I push down my discomfort and shyness to talk to people whenever I'm at a developer event.
And I've been doing my best to encourage other developers to give it a try: Becoming A Social Developer: A Guide for Introverts (and the podcast, and the website).
Especially Important for Speakers
I think this concept is especially important for speakers. There's a tendency for conference attendees, especially at professional conferences, to think of the speakers as special or gurus or geniuses. I know that I used to think of speakers this way (when I was just an attendee).
But speakers are just people who share things that they know. And just because we talk intelligently or authoritatively on one topic doesn't mean that we can do the same thing with *any* topic -- and I think that's the major misconception.
Joe Guadagno (@jguadagno) wrote an article about this earlier this year: Speakers are not Idols. The vast majority of speakers that I know and interact with are like this. They are developers who like to share what's made them successful. But they aren't perfect, and they really aren't that much different from the majority of attendees.
As a speaker, I want to make sure that people are comfortable talking to me. And often, that involves me going up to talk to people in the hallway or lunch line.
Not Available at an Event
I didn't realize how important this was to me until earlier this year. I spoke at a corporate event, and I came in, did my presentation, and left. That was the organizer's choice; if it were up to me, I would have loved to hang around for lunch (which was right after my presentation) to have a chance to speak to the attendees. I didn't realize how much I missed that interaction until I was back at my car. Something just felt really incomplete.
Being Present
My intention is to be present at every event that I speak at:
Tough Decisions
This means that I will have to make some tough choices. But I'm okay with that.
Missing Events
This past year, I missed the So Cal Code Camp in Los Angeles. The event was on a Saturday & Sunday, and I was flying to another event on Sunday morning. I thought about attending part of the event (just on Saturday). But I decided against it.
It was a tough decision. But I knew that if I went, I wouldn't really be "present". I would be thinking about my travel plans and packing and the next event. I could have "given my presentations and left", but that's not the impression I want to leave with people.
I wish I could have gone to the event, but I don't regret my decision.
Reduced Opportunities
One thing that helped me get some perspective was a tweet sent out by Cory House (@housecor) earlier this year. It's an article from 2009 from Derek Sivers, but it's still very relevant: No more yes. It's either HELL YEAH! or no.
After reading this article, I did start to change my behavior. Since I've started speaking, I've been trying to expand my reach (meaning, speaking at larger events in different parts of the country/world). Part of my strategy was to take the shotgun approach: send in proposals to as many conferences as I can and speak at any opportunity that comes up.
But I've since focused my approach:
Fewer Events
This also means that I may be at fewer events. Multi-day or week-long conferences take up more time and effort, so I may end up doing fewer of them. But at the same time, this gives me an opportunity to focus on the people who will get the most out of my presentations. So I'm looking for an overall positive outcome.
Awesome Experiences
In 2015, I had some really awesome experiences. Fortunately, every event I had a chance to go to was something I was excited about. And I did turn down an opportunity to speak that wasn't as exciting (turning down a speaking opportunity was something new to me).
Everything that I have on my calendar for this year is something I'm excited about. This month, I'm going to CodeMash. This is a conference that I've heard great things about, and I've wanted to go for several years. (It's hard to believe that it's next week.) And the week after, I'm headed to NDC in London. Again, NDC is a conference that I've heard really good things about, and I'm excited about getting the opportunity to speak and attend.
A Great Year of Being Present
I'm really looking forward to this year. There are a lot of events that I'm excited about. I won't get into all of them (and that will be a big disappointment). But for the events I do attend, I will be present -- available to talk to as many people as possible.
This isn't really a change in my behavior, just an intentional focus. It's always good to review what we've been doing, figure out where we want our priorities, and adjust as necessary.
Happy Coding!
So this is not really a resolution, but it's more of a continued intention:
I will be present at every event.What does this mean? As a speaker, I will be present for the entire event so that I have plenty of time for interaction with other people (and also time to learn new things from other speakers (and attendees)).
Background
I started speaking back in January 2010. That first year, I spoke at 8 events and only 1 of those events was outside Southern California. In 2015, I spoke at 28 events, and 13 of those were outside So Cal. So I was on quite a few airplanes and away from home a bit more than usual.
During those 6 years, my interaction with other speakers has also changed. When I originally started, my circle included primarily local speakers -- folks who would speak at 2 or 3 events a year in their local development community. As time went on, my circle grew to include regional speakers and folks who travel to major events in the US. And in the last couple years, my circle has grown to include people who speak across the US and internationally, and they spend much more time on airplanes than I do.
I've noticed a few things this past year that helped me focus my priorities.
Before going any further, I want to put in a disclaimer. I've been thinking about this article for quite a while, and I've had trouble figuring out how to write it. One reason is that I'll be referring to behaviors of some other speakers. I don't want this to come across as disparaging of those behaviors. Everyone is different and has different priorities. I'm making my decisions based on my own priorities.
Not Available
One of the things I've run across several times this year are speakers who fly in, do their presentations, and then fly out.
I always go through the speaker list for any event that I'm speaking at, and I make notes of folks that I've wanted to meet and talk to. I figure that we'll be around the same conference for 3 or 4 (usually very long) days, so I should have a chance to meet at some point, even if just for a few minutes.
But then the only place I'll see that person is during their presentation. And I don't usually go up after presentations because I want to give other folks a chance to talk to the speaker -- I'll wait for another opportunity. Unfortunately, that opportunity doesn't come.
Now obviously, that's a bit selfish of me because I'm thinking about my own disappointment. But I compare that to my priorities and what I what kind of accessibility I want people to have to me.
The reasons for the inaccessibility are many. Some speakers are horrendously busy -- sometimes doing 2 events the same week. Some speakers want to minimize time away from home and family (which is an awesome priority). Some speakers are not comfortable talking to people when they're not on stage. Some speakers have time-sensitive work to do while they are at an event.
Again, I don't want to disparage these decisions or priorities. I'm just using them as a reference point for my own priorities.
Talking to Other Developers
I've made it a big priority to talk to other developers. It was difficult for me to do the first few times, but I've seen so many benefits that I push down my discomfort and shyness to talk to people whenever I'm at a developer event.
And I've been doing my best to encourage other developers to give it a try: Becoming A Social Developer: A Guide for Introverts (and the podcast, and the website).
Especially Important for Speakers
I think this concept is especially important for speakers. There's a tendency for conference attendees, especially at professional conferences, to think of the speakers as special or gurus or geniuses. I know that I used to think of speakers this way (when I was just an attendee).
But speakers are just people who share things that they know. And just because we talk intelligently or authoritatively on one topic doesn't mean that we can do the same thing with *any* topic -- and I think that's the major misconception.
Joe Guadagno (@jguadagno) wrote an article about this earlier this year: Speakers are not Idols. The vast majority of speakers that I know and interact with are like this. They are developers who like to share what's made them successful. But they aren't perfect, and they really aren't that much different from the majority of attendees.
As a speaker, I want to make sure that people are comfortable talking to me. And often, that involves me going up to talk to people in the hallway or lunch line.
Not Available at an Event
I didn't realize how important this was to me until earlier this year. I spoke at a corporate event, and I came in, did my presentation, and left. That was the organizer's choice; if it were up to me, I would have loved to hang around for lunch (which was right after my presentation) to have a chance to speak to the attendees. I didn't realize how much I missed that interaction until I was back at my car. Something just felt really incomplete.
Being Present
My intention is to be present at every event that I speak at:
- I will be onsite for the duration of the event.
- I will make myself as available as possible.
- Even if I need to get work done in the speaker room, I will be out in the hallways during session breaks.
- This also means that I will be available at the noisy, crowded receptions that clash with my introvert nature (although I reserve the right to find a small group of people to go have coffee with in a quieter location).
Tough Decisions
This means that I will have to make some tough choices. But I'm okay with that.
Missing Events
This past year, I missed the So Cal Code Camp in Los Angeles. The event was on a Saturday & Sunday, and I was flying to another event on Sunday morning. I thought about attending part of the event (just on Saturday). But I decided against it.
It was a tough decision. But I knew that if I went, I wouldn't really be "present". I would be thinking about my travel plans and packing and the next event. I could have "given my presentations and left", but that's not the impression I want to leave with people.
I wish I could have gone to the event, but I don't regret my decision.
Reduced Opportunities
One thing that helped me get some perspective was a tweet sent out by Cory House (@housecor) earlier this year. It's an article from 2009 from Derek Sivers, but it's still very relevant: No more yes. It's either HELL YEAH! or no.
After reading this article, I did start to change my behavior. Since I've started speaking, I've been trying to expand my reach (meaning, speaking at larger events in different parts of the country/world). Part of my strategy was to take the shotgun approach: send in proposals to as many conferences as I can and speak at any opportunity that comes up.
But I've since focused my approach:
Rather than applying to "any conference that will take me", I've narrowed it down to "conferences that I want to attend".This makes things a bit harder. If you get rejected from a conference you really didn't want to go to, then it's not a big deal. But if you get rejected from a conference you really wanted to attend, then it's a heavy blow. But ultimately, this is better for me, and it's better for my potential audience.
Fewer Events
This also means that I may be at fewer events. Multi-day or week-long conferences take up more time and effort, so I may end up doing fewer of them. But at the same time, this gives me an opportunity to focus on the people who will get the most out of my presentations. So I'm looking for an overall positive outcome.
Awesome Experiences
In 2015, I had some really awesome experiences. Fortunately, every event I had a chance to go to was something I was excited about. And I did turn down an opportunity to speak that wasn't as exciting (turning down a speaking opportunity was something new to me).
Everything that I have on my calendar for this year is something I'm excited about. This month, I'm going to CodeMash. This is a conference that I've heard great things about, and I've wanted to go for several years. (It's hard to believe that it's next week.) And the week after, I'm headed to NDC in London. Again, NDC is a conference that I've heard really good things about, and I'm excited about getting the opportunity to speak and attend.
A Great Year of Being Present
I'm really looking forward to this year. There are a lot of events that I'm excited about. I won't get into all of them (and that will be a big disappointment). But for the events I do attend, I will be present -- available to talk to as many people as possible.
This isn't really a change in my behavior, just an intentional focus. It's always good to review what we've been doing, figure out where we want our priorities, and adjust as necessary.
Happy Coding!
Subscribe to:
Posts (Atom)























































