The Stochastic Game

Ramblings of General Geekery

Posts tagged with 'programming'

PHP is fucked up

You may be shocked by what I’m about to say but here it is: PHP is fucked up.

Well, duh

Oh, no. Wait. No you’re not shocked. You already knew it.

Today’s topic: namespaces.

Read more...

The extension method trick

If you’ve been writing C# code lately you should be pretty familiar with extension methods: it’s a nice compiler feature added to C# 3.0 which lets you “attach” methods to an existing type.

So for instance, if you define the following extension method:

    static class ConsoleExtensions
    {
        public static void WriteReversed(this TextWriter writer, string message)
        {
            writer.WriteLine(new string(message.Reverse().ToArray()));
        }
    }
 

You can write:

    Console.Out.WriteReversed("hello world!");
 

You effectively “extended” the TextWriter type with a new WriteReversed method in which you get a pseudo-this reference. Before extension methods, these types of methods would have been in a ConsoleHelper class of some kind — a lot less discoverable for the clients of your library.

Now, the (not so-)peculiar thing about it is that the pseudo-this variable can be null. Indeed, since this whole feature is only syntactic sugar, as they say, it’s just a more elegant way to write the following, which is a plain old function call:

    ConsoleExtensions.WriteReversed(Console.Out, "hello world!");
 

But it means it would look like you’re calling a method on a null object without getting slapped in the face with the infamous NullReferenceException.

slap!

You just need to add some simple parameter validation code to your extension method:

    static class ConsoleExtensions
    {
        public static void WriteReversed(this TextWriter writer, string message)
        {
            if (writer != null)
                writer.WriteLine(new string(message.Reverse().ToArray()));
        }
    }
 
    TextWriter writer = null;             // woah, are you crazy!?
    writer.WriteReversed("hello world!"); // woah, this is crazy!!
 

This trick can be pretty useful if you have an API that aims to be as minimalist as possible for the user and null is a valid case for one of the objects exposed publicly. You can already handle this with various well known techniques like wrapping or the NullObject pattern, but the extension method is a nice new alternative that’s enough in some cases and requires a minimum of code.

I’ve seen that trick used only once so far, in the excellent MvcMiniProfiler:

    using (MiniProfiler.Current.Step("Getting the answer to the ultimate question"))
    {
        var result = DeepThought.Compute();
        ViewBag.UltimateAnswer = result;
    }
 

Here, it’s totally OK if you disabled profiling in your web application, which means MiniProfiler.Current would return null. That’s because the Step() method is an extension method that checks for a null value provided as “this”, and doesn’t do much in that case.

Sure, they could have abstracted the profiler behind an IProfiler interface and have the MiniProfiler.Current return a NullProfiler when profiling is disabled, or something like that, but that would have been a lot more code than just using an extension method.


Formatting mongo output

If you’re working with MongoDB’s mongo command line tool and you often see yourself reading through this:

> db.contactInfos.find({"source":ObjectId("4e39da93058cfe28a039b546")})

{ "_id" : ObjectId("4e6e9a9f058cfe01dc1bcded"), "source" :ObjectId("4e39da93
058cfe28a039b546"), "sourceId" : "754731", "sourceUserName" : "loudej", "ful
lName" : "Louis DeJardin", "description" : "A software guy on the ASP.NET te
am and author of Spark", "avatarUrl" : "http://a2.twimg.com/profile_images/1
161371928/DSC01367_normal.jpg", "websiteUrl" : "http://louis.dejardin.org",
"location" : "Kenmore, WA", "friendCount" : 97, "followerCount" : 1428 }
{ "_id" : ObjectId("4e6e9a9f058cfe01dc1bcdf3"), "source" : ObjectId("4e39da9
3058cfe28a039b546"), "sourceId" : "16925866", "sourceUserName" : "sebastienr
os", "fullName" : "Sébastien Ros", "description" : "", "avatarUrl" : "http:/
/a1.twimg.com/profile_images/1074060902/f71ee9e786d8340a5eb08dd6154c2095_1__
normal.jpeg", "websiteUrl" : "http://about.me/sebastienros", "location" : "S
eattle", "friendCount" : 18, "followerCount" : 142 }
{ "_id" : ObjectId("4e6e9a9f058cfe01dc1bcdf4"), "source" : ObjectId("4e39da9
3058cfe28a039b546"), "sourceId" : "768197", "sourceUserName" : "haacked", "f
ullName" : "Phil Haack", "description" : "This bio is not true.", "avatarUrl
" : "http://a2.twimg.com/profile_images/1315393964/image_normal.jpg", "websi
teUrl" : "http://haacked.com/", "location" : "Bellevue", "friendCount" : 225
, "followerCount" : 15947 }

…then you may want to add toArray() at the end of your line:

> db.contactInfos.find({"source":ObjectId("4e39da93058cfe28a039b546")}).toArray()

[
    {
        "_id" : ObjectId("4e6e9a9f058cfe01dc1bcded"),
        "source" : ObjectId("4e39da93058cfe28a039b546"),
        "sourceId" : "754731",
        "sourceUserName" : "loudej",
        "fullName" : "Louis DeJardin",
        "description" : "A software guy on the ASP.NET team and author of Spark",
        "avatarUrl" : "http://a2.twimg.com/profile_images/1161371928/DSC01367_normal.jpg",
        "websiteUrl" : "http://louis.dejardin.org",
        "location" : "Kenmore, WA",
        "friendCount" : 97,
        "followerCount" : 1428
    },

    {
        "_id" : ObjectId("4e6e9a9f058cfe01dc1bcdf3"),
        "source" : ObjectId("4e39da93058cfe28a039b546"),
        "sourceId" : "16925866",
        "sourceUserName" : "sebastienros",
        "fullName" : "Sébastien Ros",
        "description" : "",
        "avatarUrl" : "http://a1.twimg.com/profile_images/1074060902/f71ee9e786d8340a5eb08dd6154c2095_1__normal.jpeg",
        "websiteUrl" : "http://about.me/sebastienros",
        "location" : "Seattle",
        "friendCount" : 18,
        "followerCount" : 142
    },
    {
        "_id" : ObjectId("4e6e9a9f058cfe01dc1bcdf4"),
        "source" : ObjectId("4e39da93058cfe28a039b546"),
        "sourceId" : "768197",
        "sourceUserName" : "haacked",
        "fullName" : "Phil Haack",
        "description" : "This bio is not true.",
        "avatarUrl" : "http://a2.twimg.com/profile_images/1315393964/image_normal.jpg",
        "websiteUrl" : "http://haacked.com/",
        "location" : "Bellevue",
        "friendCount" : 225,
        "followerCount" : 15947
    }
]

Much more readable, isn’t it? The only problem is that mongo will, by default, return only the first 20 hits of a query (it will write “has more” at the bottom to indicate that, well, there’s more). The toArray() method, however, will get everything and print it out. This could mean printing a lot of stuff, so you may want to stick a limit(20) in between if you’re not sure:

> db.contactInfos.find({"source":ObjectId("4e39da93058cfe28a039b546")}).limit(20).toArray()

IEnumerable is awesome

I’ve always thought that one of the most underrated features of C# is the yield statement and its companion, IEnumerable<T>. It may be because I’m working a lot with people coming from an exclusively C++ background — it takes some time to adapt to a new language with new paradigms, especially when that language can look a lot like “C++ without delete!” at first. But there are so many wonderful constructs in C# (especially in the past couple versions) that it’s a shame when people keep writing code “the old way”…

That’s why I’m going to write a few “101” articles I can refer my co-workers to (hi co-worker!).

Awesome!

It starts (after the jump) with how yield+IEnumerable is awesome.

Read more...