Just Lazy Enough.
There’s cases where memoizing a bit of data in memory can make dramatic improvements in performance (like a lookup table that changes infrequently, but is accessed frequently.) We may even find that as long as it’s “eventually consistent”, that’s good enough.
The .net 4.0 framework introduced a brilliant little class called Lazy<T>. With this class, you could pass a function that would get called once when a value was requested, and then would be stored for future requests. This was helpful when you didn’t know exactly when an expensive resource would be needed, or it didn’t make sense to load it at the moment when they system was getting initialized, for example.
One drawback of the Lazy<T> is that it will resolve the value one time, and then keep it for the lifetime of the Lazy instance. That’s where “LazyEnough<T>” might come in handy. The idea of this class is similar, you initialize it in the same way you initialize Lazy<T>, but with one extra (optional) parameter, TimeSpan.
Once initialized, LazyEnough<T> will work almost identically to Lazy<T>, except that each time the TimeSpan elapses, the next call to Value will invalidate the currently memoized value, call the loader Func<T> again, and return the updated value (memoizing it in the process).
https://gist.github.com/4014001
You should note that this class intentionally doesn’t try to minimize the number of calls to the loader, the idea is that you’re getting a huge gain from just reducing the number of calls to the expensive resource, adding locking code for the rare case where multiple threads will contend to load the same resource is overkill.
Anyway, just thought I’d share, hope you enjoy!
Kate and I bought a house! Here are some pictures…
The house is around here, to give you an idea:
More house pictures!
Set for Life
I’ve been meaning to write this post for over a year now, but now seems like an important time to write it.
There’s a common saying: “Set for life,” which usually means “Financially secure for the rest of your life.” Someone winning a Powerball jackpot would be set for life. I think there’s a much more achievable version of “Set for life” that more of us should aspire to: creating a niche in the world where we can do the work we love doing for the rest of our career.
A friend of mine started a SaaS company early in his career. While I don’t know any of the financial details, the process of starting the company, and nurturing it to its current state speaks volumes for his abilities. The company was acquired, and my friend stayed on for a few years, but has recently left to explore new opportunities. The company has, from my perspective, been a success.
Although I’m sure he didn’t win the jackpot, I am also sure that he is set for life. I think he’ll enjoy options to work where, and how he wants for the rest of his career. He knows what it would take to do it again. Imagine if you were in his position, knowing what it takes to make your own way, and having some success behind you to push you forward. I see that as a much more satisfying version of “set for life” than merely winning the Powerball. (Of course, being independently wealthy would be fun, too!)
Here comes some hackneyed cliches: We live in a time where each of us can be “Set for Life,” purely by finding what we’re good at, and creating a niche for ourselves. The costs to start our own thing are in the few hundreds to a few thousands of dollars, plus our time and our talent. Who can’t find a way to put together a few thousand bucks to get their dream started? Who doesn’t want to know what they’re made of? Who doesn’t want to be “Set for life?”
In the next 3 months, find a way to chip away at becoming an entrepreneur. Figure out what you’re better at than anybody else, and then figure out how you can get people to pay you for it. If you do, you’ll be set for life.
Tuples in .net considered…
One of the features that became available in .Net 4.0 was a built in type for a Tuple. Tuples are useful within the scope of a function, where having an ad hoc data structure that holds a set of related values together can make writing an algorithm a little easier. The best part of a feature like this is that you can focus on what your algorithm should be doing, and a little less on the class definitions required to support the algorithm.
The first sign of trouble is when you use a Tuple as a return type. If you’ve spent 5 minutes with them in C#, you will notice how ugly that can get. All of the sudden, you’re trying to figure out what the String value stored in Item1 is, and what the String value store in Item2 is. As projects grow, this can quickly make it impossible for other developers to discover what the reference they’re working with actually represents.
Aside from the main drawback, that you have no idea what the return value from a method is trying to represent, C# 2.0 included a much more intuitive/informative syntax for defining single-use types in algorithms: Anonymous Types. There’s virtually no reason to use a Tuple over an anonymous type within the scope of a method body.
Compare:
Tuple.Create(“bob”, “marley”, 42, true);
With:
new {FirstName = “bob”, LastName = “marley”, Age = 36 , IsMusician = true};
I’ll grant you that the second takes a bit more typing, but we’re not trying to “Save The Characters.” We’re trying to write an algorithm that we can read and debug.
If you later decide to promote the anonymous type so that you can return it from a method, it’s as simple as defining a class with the appropriate properties and changing the new declaration to:
new Person {FirstName = “bob”, LastName = “marley”, Age = 36 , IsMusician = true};
I’ll bet tools like ReSharper even provide this sort of refactoring. I believe that Tuples were added to support better interop between F# programs and C#/VB.Net applications (interesting read on the design of Tuples: http://msdn.microsoft.com/en-us/magazine/dd942829.aspx).
If you’re doing C#-only development, Tuples come at a high cost to code clarity. For the reasons above, I (now) mostly avoid using them (in C#). When I understand how tuples are used in F# a little better, I may change my mind.