One's mind should be pretty clear when programming. I'm a decent enough programmer, but I'm not a bad-ass programmer. At least not anymore. Back in the day, before so many things happened in my life, when I was sleeping a full 8 hours, I could code some nice stuff. Now it's just a miracle it compiles. When it does. I also tend to, um, not think. At all.
I have been looking into OpenID lately, I was pleased they had made a .NET compatible OpenID library available (Andrew Arnott has wrapped it in a nice ASP.NET 2.0 Web Control). I was thinking I'd add OpenID support to our Desi Office's Server as a Proof of Concept, as our authentication system is pluggable. It'll be a nice demo, as our CardSpace one already works great. I went and download the .NET OpenID Library preparing for a few hours of tedious work.
* Shiv`s Tangent
Right now the best and easiest way to write Boo is to use SharpDevelop, the Open Source IDE. Boo is a first-class language within SharpDevelop, along side VB and C#, and includes all the usual good stuff like debugging and what-not.
The OpenID .NET Library, as I said, is written in Boo, very likely because the original library was written in Python and Boo offered not only a clear porting direction, but also made the developer comfortable. More on this later guys. I figured this evening I'd "port" the Boo source for this library over to a "proper C# library" so the masses wouldn't have to sweat Boo. This experience let me through the :>
1. SHOCK
I was of course, like any religious zealot C# programmer, shocked and offended and looked on with disbelief that anyone would use any language that wasn't the One True Way® to produce perfectly viable and runnable IL. Microsoft's whole multi-language, single-runtime was just to prove a point to the Java guys right? I looked at the code with disdain
Shock is often accompanied by numbness...
No curly braces? Duck typing? Is this how these people live and code? Freaks. Toy Languages, man, toy languages.
2. Denial
At this point, I don't think it'll be hard to port this. The library includes NUnit Tests, but as the library is structured with a lot of things marked internal to the assembly, there's two libraries. The main one, and the test one - but the code is also compiled into the test assembly. I started marking things public, and separated the two.
I've already missed the forest for the trees here, and I'm happily stepping on butterflies in my quest for the big game.
My goal was to use the Test library, as is, to test my glorious new C# library - the one I hadn't started yet. If the same tests passed on my C# version, shiny. I started poking around the code, trying to get an idea on where to start. The library includes a Server and an Consumer, and since I just needed the Consumer in the short term, I figured I start there.
3. Bargaining
There's not THAT much code in the consumer, but there's not only a number of utility classes, but there's also a bunch of Boo language-specific collections and such. Also, as .NET 2.0 doesn't include Diffie-Hellman support (Orcas does, BTW), the OpenID library referenced Mono.Security to get there BigInteger class and Diffie-Hellman support.
ASIDE: Be aware that Mono is GPL'ed Mono Libraries are MIT X11. Mono produces IL, and Mono libraries are CLS compliant, you can reference them in your Windows .NET applications happily, and they'll work fine 99.9% of the time. Adding a Mono library to my Windows .NET CLR program doesn't make it run under Mono, it's just referencing a library. Some people, like myself (yesterday) look down on this like we look down on C# programs referencing Microsoft.VisualBasic.dll, but hey, it's tested code I didn't have to write...you'll no doubt see my own personal epiphany coming later in this stupid Blog post of mine...
I thought I might write my own Diffie-Hellman [D- H]...
Note that I'm getting totally off the main task-at-hand already here...but I've not noticed it...yet...
or find one that was already done. If I could just remove that Mono.Security reference...
4. Guilt
I started to feel bad, who am I to remove this library? Someone's worked hard on it, it shipped, let's leave it be, and get to the real work. Maybe I can find a better way to port this...ah, yes, Reflector!
I'm completely delusional...lack of sleep? Analysis paralysis or just complete lack of thought? Ah, too much club soda, perhaps? High blood sugar?
I'll just reflector the assembly and decompile it into C#. Heh, maybe I'll use Denis Bauer's FileDisassembler. There's probably some Boo specific stuff, but I'll yank that, no problem. It might be sinful, but no one is looking.
Of course, Boo assemblies include dozens of anonymous generated types and adapters to make Boo's closures work (it was designed before Anonymous Delegates could be used for closures) as well as for type inference.
Gosh...this decompiled C# code isn't even close...this may express the intent to the computer, but it doesn't reflect the Programmer's Intent at all. damnnn..
5. Anger
Stupid piece of crap Reflector! Man, Lutz can't even decompile to something I can freaking read!
Remember that IL is the applesauce on its way to becoming apple juice. Note that Stupid Shiv is pissed here because Lutz's Reflector can't turn applesauce back into an apple. Darn Reflector and the Laws of Abstraction.
Shoot...this is going to take longer than I thought. Now I've got to just freaking write thing whole thing from scratch by actually thinking and understanding what the code is intending to do! Man, I wasn't planning to think tonight, I just wanted to get OpenID on my blog.
6. Depression
I'm not a good programmer! I've been coasting on charm for at least the last three years. I remember what closures were in college, but I've been using .NET for the last five years and it dulls the senses...I might as well just give up and become a male nurse.
7. Acceptance and Hope
Wait a second. I've already got a library that works. It's got unit tests. It depends on a tested and released Mono library and a 3 year old non-mainstream language, but it works. It's been used and implemented live before and someone has already wrapped it into an even better and more useful abstraction. Maybe it'll work after all.
The moral of this story is that my time would have been better spent learning Boo, reading the source, and using the Library. The source came with a NAnt Task, but I just created a Boo Project in SharpDevelop - THAT wasn't wasted time.
After I'd learned enough Boo, if I really wanted a C# version, for whatever reason, I should have just written it from scratch using the public interface as a template and the Programmer Intent, written in Boo, as my algorithmic scaffolding. Hindsight is 20/20.
NOW, HOW DO I GET MY EVENING BACK
???????????????????????????????????????!!!!#@%#^%%$%^&;(**&;%$^%$@%!!!!!!