Author: Pete

Business of Software

Survivorship Bias

XKCD Survivorship Bias CartoonThis week, I was listening to a business podcast and the guest was describing the “techniques for success” that they had used and how they now teach those techniques to others. As I began to wonder how much of this (and all such advice) was attributable to Survivorship Bias and planning this post in my mind, I started to think about what image should go with it. Of course there is a relevant XKCD comic, Randall Munroe thinks of everything first.

I’ve been accused of some Survivorship Bias in the past, too. My ideas around how individuals can become successful programmers through individual learning and not through college is how I got started, but am I establishing too much personal credibility on the fact that I made it through a minefield without stepping on a mine? I didn’t give it too much thought until this week.

If you aren’t sure what Survivorship Bias is, the XKCD above does a great job of explaining it. But, the short “word only” explanation is that Survivorship Bias is a kind of selection bias. In this case, the bias places a great deal of attention and credence on things that made it past some gate or obstacle and ignores the less visible things that didn’t make it past.

One example that I used this week is with “Guaranteed Winners for Monday Night Football”. I don’t know how prevalent this is any more, but it used to be advertised everywhere there was sports content. The basic idea is that you call in and they give you the winner of an upcoming football game, ostensibly so you can bet on it and win. The scam is that they give some portion of the callers one team and one portion of the callers the other team.

One of those teams will win and then those callers, bolstered by their win, will call back. The next time, they pay for a “Guaranteed Pick”. Again, the callers are given both teams fairly evenly. This goes on and on until you have people who have won 10 games in a row thinking that this phone line is worth its weight in gold. They might crow loudly about the powers of prognostication that the picker has. The problem is that this entire scenario forgets about the ever-growing portion of callers who have received a losing pick along the way. That’s Survivorship Bias.

So, is all advice bad? Is all advice a by-product of Survivorship?

As in all things, I think the answer is Yes and No.

In my opinion, the way around this is twofold. First, be very wary of a “lone survivor”. If there is only one voice crying out about a path, look for the 90+% who might have followed the same advice to a bad end. Secondly, if people who follow particular advice seem to always improve and you diligently look and you can’t find a significant population of people that failed with the advice, then it is likely good advice.

The problem is that advice can’t be too specific. Now, I believe that through hard work anyone can improve their circumstances. However, what does that even mean? Not everyone starts on a level playing field, with the same advantages or disadvantages, and from the same starting place. You have to know what success looks like for you.

For example: Yes, you are following the email list building advice, but your email list is 1/1000th the size of the person who sold you that course. Consider the advice and consider the circumstances. First, their market is huge. They are selling business products to wannabe entrepreneurs nationwide (or even worldwide). If you are selling backgammon supplies to the greater Sheboygan, Wisconsin area (nothing against Sheboygan), you aren’t going to be able to reach the same number of people.

As for my personal bias about becoming a self-taught programmer, this also has a caveat. You can only do it if you are the kind of person who will dedicate hours to learning and also to practice. You have to be able to learn from just watching videos or reading rather than interaction. You have to create so many side projects and put so much sample code on GitHub. You have to be diligent to study and work even when you get home from your full-time job and your family is fighting for your time. You have to promise to work after people have gone to bed or before they wake up… something. It is hard to know what to do when no one is telling you what to do.

That leads to the other bias secretly at play. There are the concepts of Self-Serving Bias and Attribution Theory. They are related and the relevant part I want to pick out is that people often attribute positive events to their own character but attribute negative events to external factors (Psychology Today). Likewise, if someone else messes up, it is common to ignore external factors and blame the person’s character or drive or something internal to them. We don’t cut them any slack, but we can cut ourselves all kinds of slack.

What can we do? Just be aware. For certain, tell your story. If you see someone successful, listen to their story. Then, in all things, listen critically. Think critically. Take advice generally and apply it to your specific situation where it fits, throw out what doesn’t. If that doesn’t work, try something else. Rapid iteration and prototyping isn’t just for software, it works for approaches to life’s problems and obstacles, too.

Code Tips

Async Void Cannot Access a Disposed Object

A SinkRecently, I was trying to throw a quick method on a controller to create a user on the fly. I was pretty new into a .Net Core Web API project and I just needed to add a quick user to start to test some of the authenticated API calls that I was creating. So, I wrote code that was very similar to this:

[HttpGet("~/peteonsoftware")]
public async void CreateUser()
{
    var user = new ApplicationUser()
    {
        Email = "me@myserver.com",
        UserName = "me@myserver.com"
    };
    var result = await _userManager.CreateAsync(user, "SomePasswordThatIUsed,YouKnowHowItIs...");
}

When I started it up and made a call to http://localhost:56617/peteonsoftware, I got an error that read:

System.ObjectDisposedException occurred
  HResult=0x80131622
  Message=Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.

I could not figure this out. I would debug and stop on the line. My dependency injection was working and my _userManager was populated via dependency injection and I reviewed documentation and what I was calling should work. I lost a lot of time to this. It turns out that I was the victim of some optimization that .Net is doing for me. Notice that my method is async. Notice also that my method returns void. So, as far as .Net is concerned, it can go ahead and return from my method as soon as it fires off that CreateAsync() call because it doesn’t care about the result and it isn’t returning anything anyway.

I naively thought that my await would keep everything holding on until the method returned. NOPE! I found through research that my method was returning before it was done and everything started cleaning up and disposing. Therefore, when the method went to work, everything was disposed, resulting in my error. When I made the small change of no longer returning void, everything worked.

[HttpGet("~/peteonsoftware")]
public async Task CreateUser()
{
    var user = new ApplicationUser()
    {
        Email = "me@myserver.com",
        UserName = "me@myserver.com"
    };
    var result = await _userManager.CreateAsync(user, "SomePasswordThatIUsed,YouKnowHowItIs...");

    // Yes, I know I could just return above, but I like it to be separate sometimes, don't judge me!
    return result;
}

Now when I call, I get back

{"succeeded":true,"errors":[]}

So, lesson to learn… async void is BAD! Lots of unexpected consequences. Always return something from an async method to ensure that nothing gets cleaned up early.

Podcasts

Podcast Episode 51 – Matthew Groves on Couchbase

Matthew D. GrovesIn Episode 51, we go back to our interview roots and have our first returning guest (who was also our first guest, period), Matthew Groves. Matthew is a Developer Evangelist for Couchbase, Inc. I’ve been following what he’s been doing with Couchbase since joining the company and I was interested to find more about the product. It turns out that Couchbase has some pretty nice features and you’ll want to listen to this episode and find out what’s new.

Links Mentioned in this Show:

Couchbase

Cross Cutting Concerns

Couchbase Blogs

The CouchCase

CodeMash

Matthew Groves’ Original Pete on Software Episode

You can also subscribe to the podcast at any of these places:
iTunes Link RSS Feed

Thanks to all the people who listen, and a special thanks to those who have rated me. I really appreciate it.

The episodes have been archived. Click Here to see the archive page.

SQL

T-SQL IIF

DecisionsRecently, I’ve decided to try to catch up on some things that were “snuck” into SQL Server while I wasn’t paying attention. The first post in this series was about TRY_CONVERT() (which is awesome) and today I want to talk about IIF().

I can’t imagine that there is a single beginner who has written any appreciable amount of SQL queries who at some point didn’t have to Google “how to do an if statement in sql” or ask someone with a little more experience. I certainly know that I had to do that. What you end up with is the CASE statement.

Let’s create a table to work with and populate it with some data.

USE tempdb
GO

IF OBJECT_ID('Customer') IS NULL
BEGIN
	CREATE TABLE dbo.Customer (
		CustomerId INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
		Name NVARCHAR(100) NOT NULL,
		CreditLimit MONEY NOT NULL,
		Active BIT NOT NULL		
	);

	INSERT dbo.Customer (Name, CreditLimit, Active)
	SELECT 'Nike', 10000000.00, 1
	UNION
	SELECT 'Under Armor', 5000000.00, 1
	UNION
	SELECT 'Reebok', 1000000.00, 1
	UNION
	SELECT 'Buster Brown', 10000.00, 0
END
GO

If we select out all of the data from the table now, it should look like this:

Customer Table Data

So, if we were to run a standard CASE statement against the table, it might look something like this. This statement returns the name of all of the customers along with their “Credit Status”. If a credit limit is greater than 1,000,000, then they are Preferred. Otherwise, they are Standard.

SELECT Name, CASE WHEN CreditLimit > 1000000.00 THEN 'Preferred' ELSE 'Standard' END AS CreditStatus
FROM dbo.Customer

This returns the following results.

Results after CASE Statement

T-SQL finally has an if statement of sorts for use in SELECT statements (logical branching IFs have always existed… I used one in my table create script). Those of you with any kind of VBA background (Access, Excel Macros and Formulas, etc) are probably already familiar with IIF(), which stands for “Immediate IF”. The T-SQL version takes three parameters, just as the VBA version does. The first parameter is the conditional, the second is what will display if the conditional is true, and the third is what will display if the conditional is false. Here is that same Credit Status query rewritten to use IIF().

SELECT Name, IIF(CreditLimit > 1000000.00, 'Preferred', 'Standard') AS CreditStatus
FROM dbo.Customer

You can see that the results are the same and the query does look a little cleaner.

Results after IIF Statement

What if you want to do multiple “layers” of the conditional? Nested IIF statements! Take a look at this query:

SELECT Name, 
IIF(CreditLimit > 5000000.00, 'Platinum', 
	IIF(CreditLimit >= 1000000.00, 'Gold', 'Silver')) AS CreditStatus
FROM dbo.Customer

The equivalent CASE statement would look like this:

SELECT Name, 
CASE 
	WHEN CreditLimit > 5000000.00 THEN 'Platinum'
	WHEN CreditLimit >= 1000000.00 THEN 'Gold'
	ELSE 'Silver'
END AS CreditStatus
FROM dbo.Customer

Both of those return a result set like this:
Nested Conditional Results

So, those statements do the same thing. For complicated conditional logic (especially logic that requires 5 or more decisions), I’d much prefer the CASE statement. Nested IIFs gets pretty dirty once you get that far. However, that appears to be an entirely stylistic choice. If you have any strong preference one way or the other, comment and let me know how you feel and why.

Goals

Podcast Episode 50 – The Year(s) in Review

MissedI figured with the year coming to a close that I would take a look back at the goals that I made on this podcast at the beginning of the year. As I went to pull up that episode to find out what I had promised “exactly”, I found out a sad fact…. I made that episode in 2015! Soldiering on, I take a look at *those* goals and talk about what my goals are in 2017 and even if it is worthwhile to make goals if they are going to change. It all culminates in a little Wes Bos lovefest 😉


Links Mentioned in this Show:
Episode 31
Social Network Movie
Episode 33
Wes Bos’ React for Beginners Course
2 Keto Dudes Podcast
Wes Bos’ Site

You can also subscribe to the podcast at any of these places:
iTunes Link RSS Feed

Thanks to all the people who listen, and a special thanks to those who have rated me. I really appreciate it.

The episodes have been archived. Click Here to see the archive page.