Yeah. It keeps getting me. Last time was while I was making what I thought was a clever API change.
A lot of people have their own tool belt of functions, helpers and extensions. I have mine. Plenty of those tool belts have a
.ForEach() extension method. It is really simple and can help with writing more compact simple loops. E.g. compare these to equivalent constructs:
The clever idea
.ForEach() composable (do something later with the collection) by returning the enumerated collection.
Since only the return value was changed (yeah, right) and all existing code and tests did not know about that return value we are safe.
No compiler errors == money. Correct?
If you answered yes to that question you are on your way to disaster and you’ll be greeted with a wonderful runtime error and an angry call from an angry customer.
I was spared the embarrasment because I usually add a small but important adjustment to the equation: No compiler error + green tests == money.
And indeed by tests failed and were vocal about it.
Wait, what? How?
Just by adding that enumerable return I turned that method into a lazy method. Meaning that if there is no further enumeration of the collection, the code won’t ever be executed.
Obvious, right? Once you see the failing tests, it is.
But my brain keeps forgetting that wonderful property of enumerables: laziness. Thanks to the guy that wrote those tests I was reminded.