Friday, November 30, 2007

Powershell Sanity: dir/s

After trying to type it over 10 times, I finally added it to my profile:

function Find-Files-Recursive($includes)
get-childitem -r -i $includes | % {$_.FullName}
Set-Alias dir/s Find-Files-Recursive

Monday, November 26, 2007

Using Bookmarks in Visual Studio For Fast Source Code Jumping

Here's a quick tip to boost your source code browsing speed:

If you need to constantly go back and forth between a few spots in code, place (toggle) a bookmark by pressing CTRL+B+T , then you can always go to the next bookmark by pressing
CTRL+B+N or to the previous bookmark by pressing CTRL+B+P

UPDATE: As simontew points out in the comments, the exact key mapping depends on your mappings. See this article for more details.

Tuesday, November 20, 2007

MZ, BSJB, and the Joys of "Magic" Constants in Managed Assemblies.

When I was 10 or so, I thought you could open up a .EXE in a text editor and do meaningful work with it if you only knew some magical secret. I noticed that all EXEs started with the letters "MZ" as in the CMD.EXE example above, but that's as far as I got.

A few years later, I read this article in the special 20th anniversary edition of Byte Magazine that let me know that "MZ" stood for the initials of Mark Zbikowski who designed the MS-DOS executable file format. Needing some magic number to identify bits as an executable, what better choice than your own initials (in Mark's case 0x4D5A)? This is actually very common knowledge that won't get you points at your next nerd dinner.

However, today I will share a point generating piece of knowledge (well for at least a year or so)... Without further ado:

In every piece of managed code, you'll find the four bytes (little-endian DWORD) of 0x42534A42, (of course, in big-endian 0x424A534A). This corresponds to the start of the "General Metadata Header" of an assembly.

The initials correspond to Brian Harry, Susan Radke-Sproull, Jason Zander, and Bill Evans who were part of the team in 1998 that worked on the CLR.

I discovered this gem while reading page 76 of Expert .NET 2.0 IL Assembler. After googling for it though it appears that it's been covered elsewhere too.

With this knowledge, you could write a very simple program that checked to see if a file was a .NET assembly by looking for a start of "MZ" that also contained "BSJB." It looks like the first "virus" that targeted .NET took advantage of this fact.

Now, where can I put "JDM"?

Thursday, November 15, 2007

"Accidence" Improvements: Ninotech Path Copy

Robert Glass, in a reflection on Fred Brooks' Famous "No Silver Bullet" (NSB) essay, wrote in 1988:

"So what, in retrospect, have Parnas and Brooks said to us? That software development is a conceptually tough business. That magic solutions are not just around the corner. That it is time for the practitioner to examine evolutionary improvements rather than to wait -- or hope -- for revolutionary ones.

Some in the software field find this to be a discouraging picture. They are the ones who still thought breakthroughs were near at hand.

But some of us -- those of us crusty enough to think that we are realists -- see this as a breath of fresh air. At last, we can focus on something a little more viable than pie in the sky. Now, perhaps we can get on with the incremental improvements to software productivity that are possible, rather than waiting for the breakthroughs that are not likely to comes."

So, while the real bang for the buck will come in attacking what Brooks calls the "essence" of software complexity rather than "accidence" (e.g. like intellisense), it's still important to get the accidence stuff down to taking as little time as possible. That's because accidence stuff adds up.
All that to say that I really dig "Path Copy." Simply right click on a file in Explorer and it will let you copy the path to your clipboard. How many times have you needed to add a path to your environment variable? How'd you do it? Did you right click and do a properties and then copy and paste? Did you shell out and do a mark and copy? I doubt it was faster than using Path Copy. This is also a really great tool for putting links into an email about a file on a server like file://myserver/really/weird/and/long/directory/to/some/obscure/file.txt

The time savings adds up. It sort of reminds me of the time when Steve Jobs was trying to convince Andy Hertzfeld to reduce the boot time of the first Mac. If Steve were to sell the tool, it'd be like this: "Think about it, every time you use it you probably save 5 seconds. Say you need to do that two times a day. That's 10 seconds a day, or around 42 minutes a year! Do you know how many MILLIONS of developers need to do this each day? Let's say a measly 5 million do, that's about 400 years or FIVE LIFETIMES. If people just used Path Copy, we could save 5 lives!! Stop wasting time! Install it today, save a life!"

OK, if we can't get Steve's salesmanship, maybe we could cajole Scott Hanselman to add it to his great list of tools.

Now go, install it already -- save a life!

UPDATE: It appears that Vista has this built in. Simply hold down shift and then right click on a file and then "Copy as Path." Read here for more.

Sunday, November 11, 2007

Attack of the mutations, or why do we accept crazy statements like x=x+1?

I'll never forget walking into a room one day in my days before learning algebra and seeing something like "2x + 4 = 10" and after thinking for a minute, proudly exclaiming: "Finally, I figured out all this algebra stuff, X is just a fancy way of saying 3! I'm a genius!"

Well, my hopes were dashed when my sister told me that the value of X changed depending on the problem. Gee, wouldn't it be nice if X really was always one value, like, say 3? In a math problem, this is the case. If the variables could change on a whim -- that'd be maddening! Or would it? Some of the first programs we write are like this:

static void Main()
    Console.Write("Value to compute factorial of: ");
    int n = int.Parse(Console.ReadLine());
    int x = 1;
    while (n > 1)
        x = x * n--;
    Console.WriteLine("Result: {0}", x);

But, if we think about the line "x = x * n" mathematically, we must first assume that x cannot be zero, and then conclude that n must be 1. But this clearly isn't the case. Something odd is going on! The fact of the matter is that our world is changing, or dare I say, mutating.

To be honest, I never really even thought this was weird until I was reminded of the situation while listening to a comment made by Erik Meijer in a recent interview. My acceptance of the situation is perhaps due to me learning BASIC before I really even knew what algebra was. I treated variables as magical buckets that stored things and this just made sense once I "got the hang of it."

But do programming languages fundamentally require people to temporarily forget the math way and reprogram their mind? By no means! Anyone who has used a functional language like Haskell knows that there is another way. That is, if X is 3, it will always be 3. None of this "x = x + 1" nonsense.

Despicable? Restrictive? Hardly. While it might require you to think more from a math perspective, it's probably a good thing in the end. While putting a watch window up on "x" in the C# example would be of some interest to verify the algorithm as you kept seeing "x" change. Putting a watch window on "x" would be quite boring, sort of like doing price checks at the "Everything's a Dollar" store, since "x" cannot change. It'd be so boring, that having a watch window would be almost worthless. That's another way of saying, it's not needed.

No debugger required? Well, that's at least worth another look, right? How much time do you spend pressing F10 and F11 while watching yellow lines move and stopping on red dots?

Having assurance that things don't magically change underneath you also lets you break up a task into many pieces if there are no dependencies to worry about. In other words, no fear about stepping on someone's toes. Why, if you're smart about it, there's nothing stopping you from breaking things up into billions of little pieces and having tens or even hundreds of thousands of dancers moving freely without fear of their toes being harmed. That sure would be powerful: less debugging time and being able to harness the power 80+ core chips that are coming.

These are just two reasons: unchanging (immutable) variables and beautiful support for concurrency are driving me to start to at least look at F# and Erlang. This is true even given the fact that clever solutions for the imperative languages (e.g. C#) are going to come mainstream in a year or two.

Giving up something that I thought was fundamental to programming like changing a variable can actually lead to extra power. This isn't new, we've already seen what can happen when you "force" your programming train to stay on the smooth, but albeit restricted path of Rails.

Thursday, November 8, 2007

Putting the Towers of Hanoi to Use on Backups

I needed to regularly backup some data to a zip file in another directory. The problem was that the data changed daily and the size started to be an issue so that I couldn't keep all the backups.

So what files do you delete and when? Ideally, you'd like to be able to recover from most errors. This includes the error where something has been wrong for a month and you need to recover from that one as well. (It also includes the "OH NO! I DELETED HALF THE FILE!" errors where you need a very fresh copy).

After some searching, I stumbled across a rather clever solution that apparently some backup programs implement: use the optimal Tower of Hanoi solution. If you recall, the Tower of Hanoi problem is typically stated where you have three poles and some discs of decreasing size. You need to move the stack of discs from one pole to another so that no bigger disc is ever on top of a smaller disc. One good solution is to always move the smallest disc every 2^1 moves, the next smallest disc every 2^2 moves, the third smallest every 2^3 moves, etc. The picture from Wikipedia above shows this quite well.

Imagine that the discs are backup tapes. Each time you "move" the tape represents when you perform a backup using that tape. It gives a nice exponential staggering which works pretty good in practice. Working with zip files is similar, just delete files that don't match the exponential factor (well, there is some rounding involved). The math works out because a file that is 8 days old was around at the 4 day mark and at the 2 day mark. However, a file that is 6 days old wouldn't make it because it isn't a power of two.

So imagine it's 11/8/2007. You'd have a directory of backups like this:


Recent history is very backed up, but it thins out over time where it becomes less useful. It's a nice trade off of having backups, but saving space.

Who knew? The Towers of Hanoi are actually useful!

Friday, November 2, 2007

Blogosphere.WriteLine("Hello World");


I really like developing software. Ever since my first lines of code on the green screen of an Apple IIe, it's always fascinated me to be able to think of something in my head and then be able to "code" it.
20 GOTO 10

The fascination started with Applesoft BASIC, which led to GW-BASIC on my first home 386 computer complete with Windows 3.0 and a turbo button too! You should have seen my joy when I found the "PLAY" command (much to the dismay of anyone who actually ran the programs).

After awhile, I felt that .BAS files were for wimps. True men made .EXEs whose first two bytes were MZ followed by a odd heart shape. I was convinced it was black magic at the time. Where were the line numbers? I didn't know, but it sure was a magical day when I found QB4.5.

QB4.5 could "compile" my code. To me, that was elite speak for "make me a true man and give me an EXE from my code!" Which, to the first approximation is still true.

After several years and hundreds of pages of dot-matrix printed code later, I became visual with VB3 and then VB4. It was quite different from my glory QB4.5 days. The mouse actually did something useful. To be honest, I really didn't write much VB code because we got a new computer (Pentium 100MHz/Windows 95) and I discovered the Internet.

Ah yes, the Internet. Back in the days of IE 2.0 and SLIP/PPP connections at blazing dialup speeds. Actually, I didn't need much speed since I spent most of my time on IRC in places like "#VisualBasic". Probably the best find all year was when I was able to download a trial edition of Delphi 2.0.

Everything was new again. I had to learn something called Pascal (or at least a dialect) of it. But it was worth it my friend. Not only could Delphi make EXEs, but it let you do some sewing with threads. The culmination of all of this was learning how to write a web server and actually implementing as much of RFC 2616 as I could. While other web servers were experiencing things like buffer overflows, I was all smug because I didn't write anything that had the word buffer in it.

Well, that thinking worked until I learned that Delphi's string class did in fact use buffers, albeit sometimes unsafely. You learn.

What more to the software world could there be? Surely all I needed was to get a piece of paper at a college saying that I knew all there was to know about computers.


Purdue taught me that I didn't know that much at all, and more importantly I never would. And that was o-k. I wasn't as good as my high school hot-shot mentality thought I was. This lesson was worth every dime I paid to the school.

Years of pointers, recursion, karnaugh maps, asymptotic analysis, static single assignment, flip flops, programming languages named after coffee, and more taught me that there was a lot more out there that I probably never would have dived into on my own had I continued on my high school path.

Having my middle and high school pride destroyed was a good thing. As a matter of fact, it keeps things interesting. Every day I get to learn something that I didn't know before.

That's what this blog is about: little bits and pieces of things picked up along the way that I think are interesting.

What's your story? How did you get involved in software? The best part about blogs is the interaction. I hope you (whoever you are) participate. Tell me when a post stinks or wastes your time and how I can make it better. I hope to make this blog interesting to you. My plan is to take the good lessons from guys like Joel, Hanselman, Atwood, and the 160 or so others on my feed list.

Let the conversation begin!