Skip to content

Commit

Permalink
Switch to fenced code blocks.
Browse files Browse the repository at this point in the history
  • Loading branch information
munificent committed Feb 12, 2015
1 parent 7b77c35 commit 104a194
Show file tree
Hide file tree
Showing 59 changed files with 1,158 additions and 1,139 deletions.
5 changes: 4 additions & 1 deletion _config.yml
@@ -1,6 +1,6 @@
permalink: /:year/:month/:day/:title
highlighter: pygments
markdown: kramdown
markdown: redcarpet

exclude: [
TODO,
Expand All @@ -11,6 +11,9 @@ exclude: [
Gemfile.lock
]

redcarpet:
extensions: ["smart"]

# Custom variables:
disqus: "journal-stuffwithstuff"

Expand Down
4 changes: 2 additions & 2 deletions _drafts/a-fake-post.md
Expand Up @@ -12,7 +12,7 @@ This is a fake post to check out all of the different kinds of formatting that n

Here is a code block with the maximum code width (70 characters):

{% highlight java %}
```java
1 2 3 4 5 6 7
1234567890123456789012345678901234567890123456789012345678901234567890
class Parser {
Expand All @@ -35,7 +35,7 @@ class Parser {
private final Map<TokenType, PrefixParselet> mPrefixParselets =
new HashMap<TokenType, PrefixParselet>();
}
{% endhighlight %}
```

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed luctus suscipit elit mattis blandit. Sed dolor metus, fermentum vitae vestibulum ut, sollicitudin at tortor. Donec ac lobortis tortor. Proin id magna nisl. Pellentesque porttitor rutrum orci non dignissim. Morbi eros tortor, ultrices id aliquet quis, commodo ut purus. Suspendisse eget nunc lacus. In id sodales tortor.

Expand Down
60 changes: 32 additions & 28 deletions _posts/2008-02-09-c-extension-methods-not-just-for-breakfast.md
Expand Up @@ -22,7 +22,7 @@ created by an external developer (read "Microsoft"). We'll pick String because
[everyone](http://weblogs.asp.net/scottgu/archive/2007/03/13/new-orcas-language-feature-extension-methods.aspx) [else](http://www.developer.com/net/csharp/article.php/3592216) [does](http://msdn2.microsoft.com/en-us/library/bb383977.aspx). Let's say you want a method to tell if a
string contains only letters. Here's how you'd normally do it:

{% highlight csharp %}
```csharp
public static class StringUtils
{
public static bool IsAlpha(string text)
Expand All @@ -34,21 +34,21 @@ public static class StringUtils
return true;
}
}
{% endhighlight %}
```

That works, but the calling convention is kind of lame:

{% highlight csharp %}
```csharp
bool isAlpha = StringUtils.IsAlpha(someString);
{% endhighlight %}
```

Not only is it backwards from normal "noun.verb" OOP syntax, it's got this
useless "`StringUtils`" in there. Worse, your users have to *know* that
`StringUtils` even exists before they can find the method. `IsAlpha` is no
longer an easily discoverable property of all strings. So here's the fancy C#
3.0 way using an extension method:

{% highlight csharp %}
```csharp
public static class StringUtils
{
public static bool IsAlpha(this string text)
Expand All @@ -61,14 +61,14 @@ public static class StringUtils
return true;
}
}
{% endhighlight %}
```

Not much different right? Just add a little `this` in the declaration. The
difference is in the calling convention:

{% highlight csharp %}
```csharp
bool isAlpha = someString.IsAlpha();
{% endhighlight %}
```

Much better. So this is about as far as I think most people get with them.
"Extension method" = "friendlier calling convention." Now let's see if there
Expand All @@ -84,7 +84,7 @@ Maybe your classes already have distinct base classes for good reasons.
Here's what I'm talkin' about. Let's say you're writing a game and you've got
something like this:

{% highlight csharp %}
```csharp
public interface IPosition
{
float X { get; }
Expand All @@ -93,20 +93,20 @@ public interface IPosition

public class Monster : Actor, IPosition { /* implementation... */ }
public class Treasure: Item, IPosition { /* implementation... */ }
{% endhighlight %}
```

Often, you want to look through a collection of these to find the first one at
a given position.

The normal solution is to just derive your own collection and implement it
there:

{% highlight csharp %}
```csharp
public class MonsterCollection : List<Monster>
{
public Monster GetAt(IPosition pos) { /* ... */ }
}
{% endhighlight %}
```

The problem is you've now got to derive a new collection for every class with
a position and copy `GetAt()` in every one. Sure you could do an abstract
Expand All @@ -118,7 +118,7 @@ Extension methods to the rescue! You can define extension methods *on
interfaces*. In fact, you can even define them on *generic* interfaces. Like
`IEnumerable<T>`. Ooh!

{% highlight csharp %}
```csharp
public static class IPositionExtensions
{
public static T GetAt<T>(this IEnumerable<T> col,
Expand All @@ -131,29 +131,29 @@ public static class IPositionExtensions
return default(T);
}
}
{% endhighlight %}
```

Now you can do:

{% highlight csharp %}
```csharp
List<Monster> monsters = new List<Monster>();
monsters.GetAt(1.0f, 2.0f);
{% endhighlight %}
```

Along with:

{% highlight csharp %}
```csharp
Stack<Treasure> treasures = new Stack<Treasure>();
treasures.GetAt(1.0f, 2.0f);
{% endhighlight %}
```

Heck, even:

{% highlight csharp %}
```csharp
Dictionary<string, Monster> monsters =
new Dictionary<string, Monster>();
monsters.Values.GetAt(1.0f, 2.0f);
{% endhighlight %}
```

This means **you can define methods that say, "if this class provides this
capability, then it also has this capability"**. Whoawesome!
Expand All @@ -176,11 +176,15 @@ At the concept level, it's good advice, until you run into some issues:

1. You've just **changed the user's calling convention because of an implementation detail**. The fact that you can implement a method just using the public interface of the class is a facet of its *implementation*, just the kind of detail that encapsulation is supposed to *hide*. But now the user is forced to deal with that distinction because sometimes they call (in C#):

foo.Bar(); // needs access to private members
```csharp
foo.Bar(); // needs access to private members
```

and sometimes it's:

FooHelper.Bar(foo); // doesn't need access to private members
```csharp
FooHelper.Bar(foo); // doesn't need access to private members
```

2. You also **threw away discoverability**. Users expect to find the capabilities of an object through the instance methods of that object. You can save a lot of time reading MSDN by just typing `foo.` and seeing what it lets you do. Shunting stuff over in a separate class means users need to know about it and seek it out.

Expand All @@ -207,7 +211,7 @@ rest of your code is dumb.

For example, let's say we have a monster. (Who wouldn't want a pet monster?)

{% highlight csharp %}
```csharp
namespace Engine
{
public class Monster
Expand All @@ -222,7 +226,7 @@ namespace Engine
}
}
}
{% endhighlight %}
```

This class defines what a monster *is* in the abstract data sense. We want to
isolate it from anything specific to UI or rendering because while *right now*
Expand All @@ -232,16 +236,16 @@ future. That change shouldn't affect the engine one bit.
But our uber-modern ASCII UI needs to know what character to use to draw a
given monster. Ideally:

{% highlight csharp %}
```csharp
public void Draw(Monster monster)
{
Console.WriteLine(monster.Character);
}
{% endhighlight %}
```

So we can solve this like this:

{% highlight csharp %}
```csharp
namespace UI
{
public static class MonsterExtensions
Expand All @@ -255,7 +259,7 @@ namespace UI
}
}
}
{% endhighlight %}
```

Now code that is using the UI namespace sees `GetCharacter()` as an intrinsic
capability of monsters, but code that only uses the engine doesn't. And since
Expand Down

0 comments on commit 104a194

Please sign in to comment.