Showing posts with label interesting. Show all posts
Showing posts with label interesting. Show all posts

Monday, May 12, 2008

Why I hate Frameworks: from hammer to "general-purpose tool-building factory factory factory"

A recent discussion with a smart guy reminded me of an article I read years ago. I wanted to think I read it on Joel on Software. I wanted to think it had something to do with "hammer factories".

Google did the rest.

The write-up, Why I Hate Frameworks comes from Joel's discussion group. Written by Benji Smith.

"So, instead, we started selling schematic diagrams for hammer factories, enabling our clients to build their own hammer factories, custom engineered to manufacture only the kinds of hammers that they would actually need."

"Let me guess. You don't sell those anymore."

"Nope. Sure don't. As it turns out, people don't want to build an entire factory just to manufacture a couple of hammers. Leave the factory-building up to the factory-building experts, that's what I always say!!"

Like most good content on the internet, brilliant and hilarious.

Monday, March 17, 2008

IE8, Standards, and Joel is Scary Brilliant

By Joel, I mean Joel Spolsky. Not only does he have great taste in presidential candidates, but he's a person everyone in technology should be reading.

It's good to have idols, I think. I dream of having the perspective and wisdom to write like this.

The IE 8 team is in the process of making a decision that lies perfectly, exactly, precisely on the fault line smack in the middle of two different ways of looking at the world. It’s the difference between conservatives and liberals, it’s the difference between "idealists" and "realists", it’s a huge global jihad dividing members of the same family, engineers against computer scientists, and Lexuses vs. olive trees.

Of course he's talking about how IE8 will handle web standards when so much of the world expects IE to work the way it has always worked. Is there a solution? According to Joel:

There is no solution. Each solution is terribly wrong. Eric Bangeman at ars technica writes, "The IE team has to walk a fine line between tight support for W3C standards and making sure sites coded for earlier versions of IE still display correctly." This is incorrect. It’s not a fine line. It's a line of negative width. There is no place to walk. They are damned if they do and damned if they don't.

His Martian headset analogy is just a bit forced, but totally forgiven. The write-up is brilliant and fascinating.

Like Joel, I'm going to sit back with some popcorn.

...it will be really, really entertaining to watch...

Wednesday, March 12, 2008

Consolas: the Coder's Font

Consolas is one of a set of new ClearType fonts that shipped as part of Windows Vista and Office 2007.

It's absolutely beautiful. I love to code in it.

The problem: no applications seem to be smart enough to use it by default. In this post, I'll go through all the places I use monospaced fonts

Visual Studio

Tools->Options->Environment->Fonts and Colors

Set "Plain Text" under "Display Items" to Consolas.

image

Firefox

Tools->Options

Under the Content tab, in the "Fonts & Colors" box, pick "Advanced". In Monospace, pick Consolas.

image

Internet Explorer

Tools->Internet Options

General tab, under Appearance, pick 'Fonts'.

Under "Plain text font:" pick Consolas.

image

.NET Reflector

View->Options

Under 'Appearance', 'Code Font': Consolas.

image

CMD.EXE

(Thanks to Walter for pointing this out to me.)

Yes, even the command window. If you're running Vista, make sure to run this command 'elevated'. You'll have to restart your machine before the setting takes effect.

reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont" /v 00 /d Consolas

image

Next, right click on the command window header and pick 'Properties'. You'll probably want to up the font size, too.

image

And there you go. All your most important applications using the nicest monospaced font.

Happy hacking!

Friday, March 7, 2008

iPhone makes me a better person

...or at least it makes me feel that way.

Let's rewind.

When I moved to Seattle in 2002, I had a simple, "candy bar" Nokia phone. I could barely text message with it, but it worked.

My first Windows Mobile phone was the Audiovox SMT5600--a fancy name for the HTC Typhoon. I could sync calendar and contacts over the air with Exchange. I could T9 through my address book.

I felt like I jumped 18 months into the future. I got the upgraded version of the Typhoon (with the weird bump on the top). It ran a newer version of Windows Mobile. It had a prettier screen. Let's say I jumped forward another 6 months.

Then I went BlackJack. Bigger screen. Keyboard. A reasonable browsing experience, at least for GMail. Maybe a jump of a year into the future.

After a brief stint, I managed to loose my BlackJack, and went to BlackJack 2. Slicker look. Newer version of Windows Mobile. Maybe a 6 month jump.

Fast-forward to Sunday. I was snowboarding with some friends. My phone was in my pocket. My pocket was open. I was in the terrain park. I lot my phone.

Damn.

So I go back to the AT&T store. And the iPhone stand starts calling to me.

I have many friends with iPhone.

Both of my brothers have one.

I get one.

It's been less than a week.

Easily a 5 year jump. I feel like I'm living in the future. The thing freakin' rocks. It makes the BlackJack2 look like a joke.

Not only have I ditched Windows Mobile, I've ditched Zune. I've gone to buying MP3s from Amazon's store. Instant gratification. No expiration. No DRM.

This is the future.

It flawlessly syncs with Outlook on my desktop. (I have a friend who's been trying to get it to work with her BlackJack for months.) The experience with iTunes is great. Maps, Email, SMS, all clean and beautiful.

With the announcement of the SDK and Enterprise support (over-the air sync with Exchange, etc) I can't imagine a better setup for a phone.

I'm sure Google will have a cool offer with Android. I'm sure MS is sweating bullets and cranking on some interesting stuff. At least I hope so.

In the end, the bar has been raised--by a lot. All mobile users will benefit in the long-run by the existence of iPhone.

Especially those that have one.

I couldn't imagine going back.

Let me say it again: wow.

Thursday, February 21, 2008

Dump Evite

Cross-post from my personal blog.

This article from the January Wired got me started:

An email arrives announcing a fete, but it's short on deets. You're forced to click to an ad-choked Web page, then another to RSVP, and then back to the first to see the info again. That faint sound you hear? It's coins tumbling into the pockets of media conglomerate IAC/InterActiveCorp, which acquired the site in 2003.

It's been 2 days since I read the article and I've received 4 evites. It's time to put a stop to this.

The article recommends Socializer as an alternative, but it's way too heavy for my taste. The sign-up experience should be almost invisible.

What I want:

  • Painless sign-up
  • Time and location details in the email
  • +1 if it includes a link to a map
  • +1 if the map link is to Google Maps
  • +1 if a calendar file is attached for us Gmail/Outlook users.
  • Super-clean user experience.

image

Invitastic nails it. There are no crazy custom themes or anything and I'm fine with that. Kudos to the Jackson Fish Market folks.

image

Goovite also looks promising. It includes the ability to offer a number of possible meeting times and allow a discussion about when.

Progress rocks!

Wednesday, January 30, 2008

WPF Set: Now in 3D!

I last discussed Set about 3 weeks ago. At the time, my implementation was based on buttons. It worked fine, but when I saw how it looked on a friend's machine running the 'classic' theme I was appalled.

I got thinking: there has to be a way to make this game more interesting.

The answer: 3D and gratuitous animation.

The address for the XBAP hasn't changed: http://j832.com/workBlogFiles/WpfSet/

WPF Set - 3D!

The source code has been checked-in to my SVN repository. The code files actually live under J832.Wpf.BagOTricksApp, but you can build and play with the stand-alone app by loading the J832.WpfSet solution file. (Thank you, CSProj file linking feature.)

Cool stuff:

  • The listbox on the right that displays the matched sets now uses AnimatingTilePanel.
  • First use of the new WPFUtil class, which exposes a set of Animate methods. These basically formalize and abstract my simple attraction-based physics model. I support 1-dimensional (double), 2-dimensional (Point/Vector), and 3-dimensional (Point3D/Vector3D) animation. Check out ZapScroller and AnimatingTilePanel in the source to see the other places these are used.
  • I've also added some helper extension methods to WPFUtil. Very useful.
  • Implemented a couple of super-simple 3D components: ButtonBase3D and ToggleButton3D. An interesting exercise. Hoping to move FlipTile3D to these in the future.

Not cool stuff:

  • Keyboard accessibility has evaporated. With the previous implementation, you could tab around to the buttons and press spacebar to select/unselect a "card". More work than I signed up for in this iteration, but something to keep in mind.
  • WPF handles z-order great in 3D unless you have transparency in your textures. Take a look at the corners of raised cards. Very frustrating. The only work-around is to manually re-order the child elements. Lame.
  • Perf is great...on my super fast workstation. Even on my relatively beefy laptop, I notice some glitching when things are moving around. Ideally, I'd detect machines hardware limitations and degrade the animations. I should probably offer a "turn off the fancy stuff" check box. Eh, V3.

This will of course be included in the next drop of the full bag-o-tricks, but I thought it was cool enough to share out-of-band.

Have fun.

Friday, January 18, 2008

Recursion, Linq, etc. - 3rd Times the Charm

The joke about Microsoft is that it always takes them three times to get it right.

If you look at my posts on the game Set in WPF, it would seem I follow the same pattern.

Well, here I go again.

Let's start simple: I have a path to a directory and I want to enumerate over all of it's subdirectories recursively. To be super concrete:

string[] startPaths = new string[] { @"D:\j832_svn\PublicSoftware\" }; 
IEnumerable<string> subPaths = SelectRecursivePaths(startPaths);

Easy enough.

What's the scenario-specific implementation of SelectRecursive? Well, our friend System.IO.Directory provides what we need.

private static IEnumerable<string> SelectRecursivePaths(IEnumerable<string> paths)
{
    foreach (string path in paths)
    {
        yield return path;
        foreach (string subPath in SelectRecursivePaths(Directory.GetDirectories(path)))
        {
            yield return subPath;
        }
    }
}

This code does the job for doing an in-order, recursive traversal of all of all of the directories. But it isn't very Linq-ish, is it?

Getting Linq-ish: SelectRecursiveSimple

Could there be a way to extract out the call to Directory.GetDirectories such that this method could be used over any homogenous, hierarchical structure? Yup.

public static IEnumerable<TSource> SelectRecursiveSimple<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, IEnumerable<TSource>> recursiveSelector)
{
    foreach (TSource element in source)
    {
        yield return element;
        foreach (TSource subElement in recursiveSelector(element).SelectRecursiveSimple(recursiveSelector))
        {
            yield return subElement;
        }
    }
}

Now we change the call site to embody the call to GetDirectories:

IEnumerable<string> subPaths = startPaths.SelectRecursiveSimple(path => Directory.GetDirectories(path));

I love lambda expressions and extension methods.

With me so far?

Getting Clever: SelectRecursiveClever

Now we go back to my clever idea from Tuesday and Wednesday about flattening recursion. The code I ended up with:

public static IEnumerable<TSource> SelectRecursiveClever<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, IEnumerable<TSource>> recursiveSelector)
{
    Stack<TSource> stack = new Stack<TSource>();
    source.Reverse().ForEach(stack.Push);
    while (stack.Count > 0)
    {
        TSource current = stack.Pop();
        yield return current;
        recursiveSelector(current).Reverse().ForEach(stack.Push);
    }
}

Note: ForEach is an extension method I created that does what Array.ForEach does: calls an Action<T> delegate on each item. In this case, pushing every item in the sequence into the stack.

Now the caller-side behavior of this is exactly the same as the "simple" version above. The implementation tries to be "clever" though, by discarding the "naive" use of recursion by replacing the call stack with a local stack. I was quite proud of this implementation. As I said on Tuesday:

If you can flatten a recursive implementation, you will have a better understanding of what's really going on under the covers.

Gulp. Perhaps I spoke to soon.

The Problem with Clever

I showed a co-worker this code. It took a bit of work to explain the use of .Reverse(). Stacks are Last-in-first-out, so if you want to get the first item out first, you have to put it in last.

Explaining this hurt my head a bit. In the "simple"--read "naive"--implementation, one didn't have to reverse the enumeration. Why should the flattened version be different?

The answer: it shouldn't.

At some point in the "clever" implementation, every item is on the stack. This means if you have a very wide tree, the stack could grow to be huge.

Imagine your recursiveSelector is smart about not loading all items at a given level into memory at one time--the benefit of sequences, right? It doesn't matter, because SelectRecursiveClever will load everything in one level into a stack. It trades the potential benefit of a smaller call stack with the potential blow-up of your working set when iterate over a folder with 10,000 sub-folders.

Oops.

You have to keep track of your depth in the recursion somewhere: either the runtime stack or your own stack.

But all you have to keep track of is where you are in each sequence at each level. You don't have to queue up all of the items at a given level.

Turns out the CLR has this obscure feature to handle this: IEnumerator<T>.

Yeah, not so obscure.

It's actually what the simple version of this code does. When you call down into the nested SelectRecursiveSimle, an IEnumerator<T> will be waiting patiently at the the current spot for the call to return.

Getting Smart(er): SelectRecursive

The code is more ugly, but it also does a better job of illuminating what is happening in the truly recursive, "simple" version.

public static IEnumerable<TSource> SelectRecursive<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, IEnumerable<TSource>> recursiveSelector)
{
    Stack<IEnumerator<TSource>> stack = new Stack<IEnumerator<TSource>>();
    stack.Push(source.GetEnumerator());

    while (stack.Count > 0)
    {
        if (stack.Peek().MoveNext())
        {
            TSource current = stack.Peek().Current;
            yield return current;
            stack.Push(recursiveSelector(current).GetEnumerator());
        }
        else
        {
            stack.Pop();
        }
    }
}

2008-01-19: Turns out this code is wrong, too.

The stack now holds on to what it should: the IEnumerator<T> at each level. The while loop runs through IEnumerator<T>.MoveNext(), going deeper with every stack.Push() until there are no more items and then "returning" with stack.Pop().

Popping the stack

It's pretty easy to implement a recursive construct using Linq. The first "simple" implementation works great and it's really useful when partying over the file system or any other hierarchy.

I still claim that flattening recursive code is a good thing to do for reasons I mentioned on Tuesday.

Just make sure you do it correctly.

Put another way: pay attention to your masters.

If you can't be smart, be simple.

Don't ever be clever.

Clever will burn you.

 

Happy hacking.

 

kick it on DotNetKicks.com

PS: SVN has been updated again with the latest code. Hopefully the last time I'll touch RecursiveSelect for a while.

Wednesday, January 16, 2008

Flattening recursive algorithms with Linq

I wake up this morning to find a comment from Stefan regarding my post yesterday about flattening recursion:

In the future version of C# we may receive a new language construct yield foreach which will eliminate this problem. Read this paper by Erik Meijer or this blog post by Wes Dyer if you are interested.

Ironically, I had read the paper and associated blog post last week.

And it got me thinking: could I abstract out my recursive traversal?

Even better: could I abstract it out in a way that was Linq-friendly?

The answer to both: oh yeah.

Check out the browser-friendly source here.

Now the code to find all of the selected directories becomes

SubDirectories
.SelectRecursive(directory => directory.SubDirectories)
.Where(directory => directory.IsSelected);

How's that for straight-forward?

Note 1: The savvy reader will notice that the third implementation is now like the original: the target node is not included in SelectedDirectories if it is selected. I like this more.

Note 2: Since I made SelectRecursive more general, I'm not quite as efficient about creating a bunch of enumerable instances. I still (likely) save a lot in call stack space and having a general implementation is pretty cool.

Note 3: You'll notice that SelectRecursive handles the case where there recursiveSelector returns null. This is different than how default extensions like SelectMany work. It made my usage in this scenario cleaner, but it's important to note. Or not. This bothered me for reasons I'll go into in another post. The code as checked-in now throws if null is returned. These subtle implementation details can cause headaches later.

As I mentioned yesterday, you can get the full source code from my SVN repository. The new methods extension methods have been added to Extensions.cs in J832.Common.

Happy recursive Linq-ing!

Tuesday, January 15, 2008

Flattening recursive algorithms is like taking the stairs...

...it's rarely necessary, but you'll be better for it.

Okay, a forced analogy.

2008-01-19: I've learned a lot since Tuesday. Please read!

I'm sure many remember their first algorithms class and their first introduction to recursion: the infamous Tower of Hanoi problem. I'd been coding for a while when I was presented with this puzzle and wondered (probably out loud), "Why don't we use a more concrete example, like the file system?"

I guess I've always been more of a software engineer than a computer scientist.

While the idea of recursion is useful in many situations, the costs are rarely discussed. As our friends at Wikipedia mention:

...in today's programming languages, the stack space available to a thread is often much less than the space available in the heap, and recursive algorithms tend to require more stack space than iterative algorithms.

Well said.

I was hacking on some work stuff that required recursion-- specifically flattening a hierarchy. I realized I'd done this before, in the bag-o-tricks. I also realized how expensive it was.

Call stack for recursive function call

Not only was I paying in call stack space for every nested call, but I was also allocating a lot of enumerators.

Code for the SelectedDirectories getter.

if (m_directories != null)
{
    foreach (SelectableDirectory sd in m_directories)
    {
        if (sd.IsSelected)
        {
            yield return sd;
        }
        foreach (SelectableDirectory sd2 in sd.SelectedDirectories)
        {
            yield return sd2;
        }
    }
}

So how does one improve this? Replace the call stack with your own stack.

Stack<SelectableDirectory> directoryStack = new Stack<SelectableDirectory>();
directoryStack.Push(this);
while (directoryStack.Count > 0)
{
    SelectableDirectory currentDir = directoryStack.Pop();
    if (currentDir.m_directories != null)
    {
        for (int i = (currentDir.m_directories.Count - 1); i >= 0; i--)
        {
            directoryStack.Push(currentDir.m_directories[i]);
        }
    }
    if (currentDir.IsSelected)
    {
        yield return currentDir;
    }
}

The savvy reader will notice that the second implementation is slightly different: the target node is included if it is selected. Just a detail.

So, what has improved? Only one enumerator is created. The call stack space for the recursion is also eliminated. The cost is the creation of the local Stack<> to keep track of the location in the hierarchy, which is likely much smaller than the space required for a call stack frame.

Since we want to keep the original order of items returned, we also have to Push each level of directories into the Stack in reverse order, so that the Stack returns them in the original order.

Now how does this match up with our masters?

It's certainly less readable. Since the code's not documented, it would probably take longer for even a savvy dev to figure out what's going on. This means it's less maintainable--certainly a negative.

On the plus size, the scalability of this algorithm is now limited by the size of the heap, which is much larger than the call stack. This only matters if one plans to parse very deep directory structures, though.

Another plus is likely performance, since fewer objects are instantiated and the cost of manipulating a local Stack<> is likely much cheaper than churning the call stack. I say 'likely' because I'm not really sure. I should absolutely measure the performance to be certain. Even then, the perf gain is likely trivial unless this code is called a lot. In that case, it might make sense to cache the result of the method.

In the end (and as always), context really matters. I think this is a good exercise to understand the costs and to challenge one's understanding of recursion. If you can flatten a recursive implementation, you will have a better understanding of what's really going on under the covers--something that is always useful.

Happy hacking!

Note: the updated code for Folder Picker has been committed to the bag-o-tricks directory in my SVN repository. You can take a look at the old implementation using Tortoise. Right-click on Data.cs in the shell. Pick 'Show log' out of the Tortoise menu. Then right-click on revision 58 and pick 'Update item to revision'.

Update to revision

Saturday, December 29, 2007

When you code, do you know your Master(s)?

Master Chief - Everyone's MasterThere are a whole set of blog posts floating around my head. Discussions of immutability, pre-condition checking, etc. I realized I needed to cover a meta-topic first: the notion of "masters" while programming.

This is a concept I think everyone has, but for most, it remains fuzzy, undefined and un-discussed--which is fine, if you work by yourself.

As I've dived into the software engineering role in the last few months, I've been required to justify my implementation decisions and opinions with co-workers. Given the seemingly limitless ways in which one could solve a given problem with a file full of curly braces and semi-colons, why did I choose the approach I did? Why do I want to change a bunch of existing code? Why am I asking my colleagues to change how they write software?

When it's a simple matter of "does it work or not" there isn't much of a problem, but as many know, writing solid code goes well beyond getting things to build and run.

So, what drives how you write software? When you are at a cross roads (with a co-worker or even with yourself) about how to approach implementation, what guides your discussion? These are your masters.

Examples:

  • Minimize code size
  • Minimize code complexity
  • Minimize unnecessary code churn
  • Maximize code readability
  • Maximize correctness
  • Maximize robustness
  • Maximize flexibility
  • Maximize code maintainability
  • Maximize CPU performance characteristics
  • Maximize Memory performance characteristics
  • Maximize API ease-of-use
  • Maximize the chance another dev will use an API correctly (see Pit of Success)
  • Opt for immutable data structures
  • Opt for thread-safe data structures and APIs
  • Verify pre-conditions
  • Follow design guidelines
  • Get it done yesterday!

And none of these have anything to do with solving the problem at hand. They are, for lack of a better term, taxes. Well, except for get it done yesterday.

Some observations:

1) Many (Most? All?) of the masters conflict with at least one other master. CPU vs Memory performance is a trade off for many algorithms. Performance optimizations often hurt code readability. API ease-of-use often bumps up against immutability and thread safety. Therefor...

2) Context really matters. This is an important point to bring up when discussing with co-workers. In this situation, which master is most important?

3) When making your case in a disagreement, make it in terms of the masters you are prioritizing in a given situation. If someone doesn't understand the importance of--say--immutability, you'd better be able to articulate it.

4) Speaking in terms of masters makes everyone a lot more sane. How often have implementation discussions turned into irrational arguments? Using a master-focused format, I've found disagreements turn into pretty simple cases of a disagreement about the relative importance of two masters. Other times, it's a matter of agreeing on an exception to general rule. "While in general, Master A is more important than Master B, in this situation, we should prioritize B because of X, Y, Z..."

5) "Fake" masters get exposed--vices wearing the mask of a real master. This is amazingly important, too. Lazy often wears the mask of code size or get it done yesterday. Clever often wears the guise of unnecessary flexibility or performance improvements, while increasing code complexity and decreasing code readability. (I'm often guilty of this.)

So...

Next time you are struggling with several valid ways to implement something, make the mental check-list: what masters am I serving with each implementation? What masters are really important in this situation?

Next time you disagree with a co-worker about an implementation, ask yourself: what masters is she arguing for? What masters am I arguing for? What masters really matter? Maybe step back a bit and talk through your respective masters and make sure you both understand before you dig in.

Next time you are trying to get it done yesterday, ask yourself: am I just being lazy? :-)

Happy hacking...

Note 1: Huge props to my co-worker, David Potter. A more brilliant, friendly, and fun colleagues I could not ask for. We've been using this master-focused mind set for weeks now and it makes collaborating a blast.

Note 2: I always get a little nervous posting these long, pseudo-philosophical rants with no source code. As always, if you write a comment saying you read this far (and you don't think I'm crazy) you'll make my day.

Thursday, December 20, 2007

Bag-o-Tricks Christmas Edition

Here's a token gift from me to you. An update to the bag-o-tricks. No earth-shattering features, but a bunch of clean-up. I've made everything work under VS 2008 and rolled up a bunch of common files under a 'common' assembly.

I've renamed the assemblies so it's easy to keep track of what comes from me--everything starts with J832.

I've also done some tweaking so that, by default, images are picked up from the users image folder on XP. You can still override this with a command line parameter.

As I hinted to with my post about TortoiseSVN, I've also put all of my code up on an SVN share: j832.com/PublicSoftware.

I'll try to make sure that the bits I check-in are at least building, but no promises. If you want to fix any bugs and send me the patch, I'd love to try it out. Promise that it's your own code and that you're willing to license your work under the MIT License. You can find my email address on my blog.

Happy hacking and happy holidays!

Monday, December 10, 2007

TortoiseSVN Rocks!

Yes, I'm considering writing a book: "Kevin Explores Things That Rock".

My company uses Perforce for source control. It works pretty well (although there is no shell integration and the Visual Studio integration is a bit flaky.)

I have my own projects on the side that I'd like to managed with source control. These are both code projects and non-code (poetry, screen plays, other writing) projects. Like I said, anything that I want backed-up, synced and versioned.

If you're like me, you share a set of conflicting tendencies.

  • First, a tendency to have many machines that you work on.
  • Second, a tendency to be paranoid about keeping important data backed-up and protected with good redundancy.
  • Third, a tendency to hate redundancy! This goes along with SPOT. I hate when things get out of sync. I hate having things spread all over a bunch of machines.

Using a source control system helps a lot with this (especially if you're dealing with text-based data formats).

In the world of OSS, Subversion (SVN) is a big player in source management. It's supported by SourceForge. It's used by a mountain of OSS projects. And (drum roll) it has an amazing Windows shell extension: Tortoise.

  • Step one: install.
  • Step two: make directory somewhere on your machine.
  • Step three: right-click and pick "SVN Checkout..."
  • Step four: type in the URL of a public SVN repository. There are many out there. Check the list above.
  • Step five: laugh at how easy it all is.

Tortoise supports the creation of patches. Renaming and branching. It even has great shell indicators so you know what's checked-in and what's pending check-in. (It works great on XP. So-so on Vista.)

Take a look at TortoiseSVN.

If you're looking for hosting for your SVN repository, check out DreamHost.

Happy Hacking...and don't forget to build an test before you check-in. :-)

Tuesday, December 4, 2007

In search of DRY SPOT

I realized there is a concept I come back to often in a lot of my software implementation and in a lot of my discussions. It goes by two common acronyms that are pretty much interchangeable.

DRY: Don't Repeat Yourself.
SPOT: Single Point of Truth.

DRY is articulated in the book The Pragmatic Programmer, although Eric Raymond likes to call it SPOT.

How does this exist in our world of C# and .NET? Well, every time you define a private const string or private const int instead of sprinkling magic values all over your code, every time you generate documentation from your source files, every time you develop a clever data structure to represent both the execution and the description of a process, you are practicing SPOT.

Quite often, my SPOT will live in a static class Util that I create for almost all of my software projects. If I have one way to handle errors, one pay to deal with collection, one way to handle user input, centralizing it makes bug fixing so much easier. It actually minimizes bugs in a lot of cases, which minimizes the need to fix them.

If you haven't heard of these concepts, they are great to add to your software vocabulary.

For many, I'm sure the idea has always been floating around, just without a good name.

Now you have a good shorthand when you are mocking someone else's code.

Happy hacking!

Saturday, November 3, 2007

The event pattern in C# and funny coincidence

On Thursday, I wrote about the importance of software patterns, specifically the event pattern in C#.

That very afternoon I was going through some code written by a co-worker that leveraged this pattern.

To keep things simple, let's imagine it was like this.

public event EventHandler NewMessage;

protected virtual void OnNewMessage(MessageEventArgs args)
{
EventHandler handler = NewMessage;
if(handler != null)
{
handler(this,args);
}
}

protected virtual void OnNewMessage(string message)
{
EventHandler handler = NewMessage;
if(handler != null)
{
handler(this,new MessageEventArgs(message));
}
}

Pretty straight forward, right? See the problem?

This gets to the core of why understanding a pattern deeply is important. The pattern of having a protected virtual OnFoo method for your Foo event is to ensure that a subclass can peek at the event before it's fired. The implementation above will require the subclass to not only override both methods, but to understand that she must override both methods to make sure all raised events are captured.

This is making the job of the subclass writer much harder and likely more error prone.

I'm not saying one should get rid of the helper method. It's fine. It just needs to be tweaked.

protected void OnNewMessage(string message)
{
OnNewMessage(new MessageEventArgs(message));
}

First, get rid of the virtual flag. This should be callable from a subclass, but there should only be one method to override.

Second, call the 'real' virtual method from the helper. This ensures that anyone who overrides OnNewMessage will get the desired result.

A clever developer might not like this, because she wants to avoid allocating the EventArgs unless there actually are handlers to call. Clever optimization, but it breaks the pattern.

Make sense?

Happy hacking.

Friday, November 2, 2007

Former MS co-workers done well: Amar & Robby [Videos]

Amar was my GPM (manager's manager) in the Longhorn days. (Yes, back when Vista had a lot more managed code and was going to change the world.)

He's one of the stars in the intro video for Google's openSocial. (Look for the Indian guy in the Brazilian soccer jersey.)

I can't wait to start hacking on this stuff.

The last time you may have seen him on video was when he was GPM of the RSS team at Microsoft. (Interviewed by Scoble, none the less. A lot can change in three years, huh?)

Robby is on channel9 again, chatting the goodness of the 'integrator' role in WPF/Silverlight development. He's a main guy at identity mine these days.

Robby and I worked together on the WPF team in the v1 days. The last time you may have seen him on channel9 was with yours truly. Although I'd rather forget the topic. :-)

Friday, October 5, 2007

I'll avoid any reference to rats and ships

On Monday, Fil made a note on Facebook listing the ~10 people he knew who had left MS this year. After a couple days and a few additions from friends, it was up to 16.

Earlier today I stumbled upon Rory's announcement.

Then I discovered Danny's post.

Wow.

Maybe it's just that time of year.

Maybe it's that departures are more visible these days.

To use Microsoft's favorite overloaded statement: interesting.