I just want to share some loose ends with you, as the train that is 2008 pulls into the station, and the 2009 train prepares for departure. Don't forget to properly de-train and en-train!
I have been trying to keep myself from writing 2009 down when I put dates in my notebook. Usually it's just the opposite; I am still writing last year down in my notebook.
Anyway, in the fine Code Nazi tradition, here is a little something I whipped up months ago, and didn't link you into:
My personal holiday season, which usually coincides with Christmas, starts next week. What this really means: I have to use up accrued vacation days before I lose them!
Also, let me say that if you have an internal implementation of a Wiki at your company, make sure you point your RSS aggregator to the change log of it; you won't be disappointed! I already found out about two rounds of dismissals thanks to someone editing the Previous Employees page!
And finally, I would like to wish a Merry XXX-mas to a female friend of mine whose tastefully posed nude image I found on my laptop, circa 2004. I never thought I would run across anyone I personally knew on the newsgroups, but Oh Well....
I love it when people come in (e.g. via email) and describe a "problem" that actually boils down to a description of how the system works.
For us, going over the project's Open Items List, this was a routine part of the triage of incoming items we saw for the first time.
So is that a defect? A feature request?
Nope, it's a True. They have made a correct statement about the operation of the system.
There's a mismatch somewhere though, usually in the user's understanding of the system, their expectations of the system in the particular scenario they encountered, etc.
Sometimes the answer would be "Thanks for describing how the system works; Next!" Typically, we would collect up all the "trues" at the end, and for some, determine some follow-up questions, which would hopefully lead us in a direction that would help understand how the system failed the user.
Listen closely: NullPointerException doesn't tell me dick about where to look in your code!
If you recall the Optimistic Programming Model post, I'm talking specifically to you people! It is precisely your laissez-faire attitude towards checking for null that screws everyone over, by adding wasted time to the diagnosis of your crap.
"Oh, it will always be configured correctly" is a fucking pipedream, my friend. The first other person to come along and use it will certainly forget to set something, and now they are left with tracing through your crap in the IDE; not really being productive on their task anymore. Or worse yet, giving up (no access to source code) and looking elsewhere or building it. That's not really how I want to discover I needed to set something. Documentation? Yea, like you made any!
Please reconsider your foul ways! Switch over to the attitude that says: Make The System Tell Me What's Wrong! I know, this requires you to be pro-active about helping others, but it pays everyone back in a hurry! I want the You Forgot To Set The 'Important' Property exception!
Look! See how easy it is!
if(this.Important == null)
throw new ArgumentException("The 'Important' property was not set");
this.SomeThingImportant(this.Important, otherStuffThatCanBeNull);
It only took you two lines of code to enhance your system, so now instead of the vague NullPointerException, you now know exactly what it was looking for as well!
In the general case, this technique consists of a series of guard clauses, before any real work is done. This is nice from an organizational standpoint; it puts all the validation in one place, and the "rest" of the method is clean-looking, because you did all the messy validation already.
In the most-general case, we are talking about input validation. If you have ever used FxCop on your code (go do it now if you haven't) you know those messages. I went back and appeased every "public parameter blah not validated" message, and I have never looked back; I do it every time now.
The time to switch is now! You are screwing yourself over along with the rest of us....
Here's an A-number-one reason for you, Joe: your application's perceived start-up time will kick the Major Ass!
Chances are even good that it will be real start-up time.
This is especially true when you have partitioned your UI "correctly" say, as plugins, and in your main form's start-up, you need to iterate all the loaded plugins and invoke the lifecycle start method, say ILifecycle.Start().
If we have a reasonable number of plugins, i.e. UI elements, the whole startup process bogs down in serial processing of everyone's startup. This typically invokes User Gak Syndrome, as your form appears, if at all, as a big, unrefreshed rectanglular glob on the screen.
Using the Windows Forms environment, this means that the ThreadPool, anonymous delegates, and Control.Invoke() are your newest, bestest buddies! No amount of work is too small to do anywhere but the UI thread!
I speak from experience, because I transformed my very own application to use increased background processing, and that biach snaps right up on the screen!
Before the transformation, start-up was becoming noticably slower, to the point of you could see each section refresh. Some other refresh cycles were also causing some noticable flashing, because some "inocuous" processing was trapped on the UI thread between BeginUpdate() and EndUpdate().
Since perception is everything, this approach gives your main form the opportunity it needs to get up on the screen and refreshed as fast as possible, without all of the initialization bogging it down.
So, to recap: in all of your startup and UI event handler responses:
Take advantage of anonymous closures to capture all the context you need to do your processing and UI binding.
Make a closure that will handle the UI binding. This gets used in Control.Invoke().
Make a closure that does the work, then calls Control.Invoke() with the first closure. Use the UI element you are targeting in the call.
Run the second closure on the ThreadPool or dedicated Thread.
Get off the UI thread! There's more work to do....
Since my local Public Radio Station is having their periodic Pledge Drive, I figure "Why the Hell Not?" I will try my best to emulate the mood, and if you stop reading before the end of this post, My Job Here Is Done. On the upside, my Pledge Drive will only last for One Post, and not an entire week, so you can tune back in tomorrow without fear!
This is a shameless plea for membership, in the form of Followers! If you are on this blog already, chances are you didn't get here by accident. But hey, maybe you did!
If you are here visiting for The First Time, please take a moment and register as a Follower. Consider this the blogging equivalent of a donation to TEEG, to keep us operating for another year!
In return for your patronage, I promise to continue to provide the quality ranting you've come to expect from TEEG. Not to mention those comics imported all the way from ToonDoo at great embedding expense to us.
As you can see from The Gutter, we have surprassed our blogging target of 30 posts for the year, with more quality mumblings in-the-pipe. You can guarantee the continued flow of vitriol by simply registering as a Follower. So just go ahead and click on that link!
Because as you know, without the support of Followers Like You, blogs like TEEG will just cease to exist, and you will be left with mindless crap like CNET News to fill your RSS Aggregator with!
It is your Followership that keeps this blog from being overrun with blocks of Google AdWords so thick you can't even find the delicately-crafted prose we are so proud of here at TEEG.
I think I'm gonna yak now....
Okay, but register first! It's way less painful than hitting a click-through ad, which generates fractional-pennies for us, but no prestige....
Stay tuned for an Important Message from The Code Nazi....
I think it's time we increased awareness of our use of control structures! Here is my cartoonish attempt to make everyone more aware of how they use if statements:
As you know, p and q are our old friends from Probability Theory. In the realm of if, our friend p is the probability we will reach the if branch, and our other friend (portrayed as El Diablo in the comic) q is the probability we will reach the else branch.
Now, some programmers, who really suck by-the-by, practice what I call the Optimistic Programming Model. This is a delusional dream-world where no remote resource is ever unavailable, there is no network latency, disk space and memory are unbounded, and nothing else runs on the user's platform but your stuff.
You can easily identify this style by a distinct lack of tests for API failure coupled with a typical lack of exception handling to scope errors, when problems arise (and they do).
The user's experience with this style of system is rarely satisfying, as the system is extremely brittle, sensitive to the smallest perturbation in its environment.
My ultimate anecdote of this goes way back to a previous job in a different century, where everything was in PDP-11 assembly, and we also wrote the OS as well. Somewhere in the system, someone decided that execution would never get here (there was even a comment to that effect), and programmed a HALT instruction.
In our system, a HALT would dump the CPU right to the debug console ODT and its delightful @ prompt.
This wouldn't hurt so bad, except we were running a factory automation supervisory control platform. You know execution found its way to that location eventually.
For extra credit, calculate the number of pissed-off plant management personnel the execution of that instruction generated.
Hey, didn't you say "Else-less If Kills You Stiff"?
I did. Good thing we have TDD and coverage analysis tools, for those smart enough to use them.
The really bad part is we rarely know even estimates of our friends p and q! By ignoring one branch of the decision, you are ignoring an untold percentage of problems that are the responsibility of that branch, whether you did it wrong or ignored it completely!
This leads to the polar opposite programming model, the Pessimistic Programming Model, where everything that can fail is treated like it will fail, return values are accounted for, and every if has its else. This alone can relieve some level of exception handling, because you covered your probabilities completely.
Just remember, if you think "it will never get here" you are wrong. It will find its way there, just when you are ready to leave on vacation....
Danger Will Robinson! Eco-Political tirade ahead...
I am totally convinced that if we go after everyone who escaped the total tanking of our financial complex with big fat paychecks in the 10s-of-millions of US Dollars, we can recoup several hundred millions, which can be put to good use on the Big Bailout itself.
And as for that Big Fat Party AIG threw, all I can say is "Good thing I wasn't there with a CCW!"
Thanks to our de-regulation-oriented political party, the abject greed of these useless fucks is laid bare for all to see, and boy are we pissed!
Not that any of you CEO-fucks would care, but here is a chance for you to actually do the right thing for everyone for once in your greed-infested lives, and give that fucking money back to us, it's ours!
And if that doesn't work, here is a plea to anyone willing to subvert the system for you to declare it Open Season on overpaid executives, wink-wink-nudge-nudge.
I have to relate this one, it was just too ironically funny.
I'm a big RSS nut, and I have our internal Wiki site's change log RSS as one of my feeds. This way, I get to view all recent edits to the Wiki, but otherwise rarely-if-ever access it, and even more-rarely-if-ever create or edit content in it.
Typical fare is product release updates, and people editing their personal pages to claim new skills or skill-levels (What!? Jimmy's a Java Expert? Not hardly!) I have not touched my page; I know too much, rofl.
As we all know, things here in the US economy are tightening, and our organization is no exception. In fact, one of my officemates just got the sack.
Was that the funny part?
Obviously not. The funny part was when I viewed the change log of the Employee List page, I noticed that not only he had been dismissed, but that someone else had been too, and the same day to boot!
Now I obviously feel bad for these new ex-employees, but I feel even worse for the organization that didn't make any mention of it, via email, verbally, etc. but only in the fine-print of some web page.
Fucking-ay right-on! That's about how fed-up I am with this crap.
Why do people think it's easier to just slog it all together, and remember to quote everything, and always messing with date-to-string conversion, and get-a-fucking-clue!
You lamers know I'm talking about you! You wouldn't know a PreparedStatement or a parameter marker, if it came up and bit you on the ass!
How do you expect anyone to externalize and be able to configure your mess of bullshit string-appendage?
Why aren't you smart enough to realize that the parameter markers help your lame ass by letting you pass your values in as their native data type, without all your lame string-conversion bullshit!?
Why don't you want to make your work easier? Don't you think editing a configuration file (you can use Notepad in a pinch) is easier than rebuilding and redeploying everything in Eclipse?
Of course, chances are good you are the same lamers that hard-code all your constants, and never heard of a properties file....
Let it out, bruvva. Don't you want to back that up with some code samples or awt?
Fuck that. Everyone chooses their own path. Just stay off my project.
The whole thing was an exercise in futility. The application was the "Installer" itself, which was a purposefully-designed maze that led to nowhere. Under no circumstances would the user ever be able to install any application (remember there was none anyway) and they would eventually have to give up.
Now in order to keep the user hoping for success, the whole thing had to be plausible, i.e. it had to look like the "installation" was making progress, and if you just confirm this one more scan, I will install, I promise.
What pure evil.
As I watched my infection unfold, the fake anti-spyware it installed reminded me exactly of this, as it pretended to find infections, and flashed across items from my filesystem (or maybe not even). It even prompted me to allow it to "clean" my system, or continue to work "unprotected".
Fortunately, I have a friend in the computer de-fecking business, and he has helped considerably. He instructed me as to what tools to download, etc. Which leads me to another supporting anecdote.
I had been infected at such a deep level, I was redirected to a bogus download page for one of the AV tools I wanted to install. In fact, this is how it got bad! I had never seen the real download page, so I blindly downloaded and installed Rube Goldberg 3.0! The journey was afoot.
Just making a point about i18n and our friend, the date format.
You may not be able to tell, but I live in the US, and we format dates month-day-year, unless you are in the military. I actually prefer the day-month-year format, and use it in my notebooks, etc. I also prefer to use the 24-hour clock, and my car actually allows me to set the display that way (it's a European Luxury Sedan btw). As many devices that allow for it (a delightfully-increasing number), are configured for 24-hour display. Free trade is finally good for something!
People always ask me, "Why do you use Military Time?" and I say "No, that's the World Time". My daughter is almost getting it now, when I answer her "What time is it?" with "It's 19.37 sweetheart".
What kind of high-falootin' title is that!? Don't try to come off all educated now...
Any-road, I have been leading the dual Java/.NET existence for the last few months, and I realized that Java 5 has Annotations, which they obviously stole from you-know-where.
Since I am a great fan of Inversion-of-Control, I took the 10 minutes to read about how to define and use Java Annotations.
The beauty of marking stuff with meta-data is just that: beauty. I can now apply whatever algorithms (i.e. "protocol") I want, and I can control participation simply by checking for the meta-data.
This is important, because otherwise the "burden" of the protocol gets uninverted back into the instance itself, whereby I have to remember to deposit all these bits and baubles of code in a bunch of overriden methods, and heaven forbid if I want to alter the protocol, because now I have all these instances I have to tweak, and hope I get it right 100%.
Another advantage is similar to using interfaces, in that any instance participating in the annotation protocol is not obligated to derive from anything in particular.
I am currently using annotations to produce a UI binding framework for a certain mobile platform, whereby the "gluing" of code to screen elements is a subtle blend of annotations (to identify the participants and their mappings) which "mark" fields that contain (subclasses) of a specific abstract class (it could be an interface).
Without this handy-dandy mechanism, I would be left with (an interface with) bookkeeping methods, at the very least, to build the list of participants the annotations indicate. Not only that, I would have to provide the "extra" data (in the annotation properties) in that code as well.
It's basically the difference between this
public @interface TagMe {
String value();
}
...
public class SomeClass {
@TagMe("LastName") MyInterface field1 = new MyImpl1();
@TagMe("FirstName") MyInterface field2 = new MyImpl2();
@TagMe("FavoriteColor") MyInterface field3 = new MyImpl3();
}
and this
public interface ITagMe {
void add(Map list);
}
...
public class SomeClass implements ITagMe {
MyInterface field1 = new MyImpl1();
MyInterface field2 = new MyImpl2();
MyInterface field3 = new MyImpl3();
public void add(Map list) {
list.put("LastName", field1);
list.put("FirstName", field2);
list.put("FavoriteColor", field3);
}
}
Only with less freedom. The reason being that it is possible to use multiple annotations, in order to specify additional or optional meta-data to the protocol, or to a (possibly unrelated) protocol that is using the same set of participants.
That means "electricty" if you are not hip on Northern English slang...
Yes, what a bummer! Our Internet connection was down for most of the day, as IT staff struggled heroically to bring routers and other networking-whatnot back into packet-shuffling mode.
At first it wasn't too bad, but then it became apparent we were in the equivalent of a "power" outage, because less-and-less work was getting done, and more-and-more slackery took hold of everyone.
And that was just the first 20 minutes....
After a couple hours, people were actually bailing for home, because the connectivity was so crucial to their very work-existence.
It really did feel like a major power outage. My computer felt totally useless without Google to exchange packets with. Sure, I could run all my local applications, but they had no one to "talk" to. What good is email or an RSS reader without remote hosts? Being "offline" with these applications, and The Browser Itself, is like not even having a computer!
I just read a good one about comments, feel free to weigh in. Here is what I had to say about it in the comments section of that blog (with extra formatting here):
Some sniglets for you:
Obso-doc: Comment detailing what the code did last year.
Histo-doc: Ever-increasing comment section detailing revision history, typically duplicating information in Revision Control.
Igno-doc: Comment revealing author's lack-of-understanding of necessary algorithms, alternate syntax, etc.
Personally, I believe in minimal commenting in-code (doesn't count "Javadoc" documentation, which I don't consider comments) only to warn subsequent visitors (like me during maintenance) about certain code sections that are arranged a certain "atypical" way on purpose, i.e. to workaround something somewhere else. I prefix these with "IST" for Important Safety Tip! This heads off the "What the F*** was he doing here?" impulse to just rip it out and re-do it the "right" way.
Continuing on, I also hate:
Identi-doc: Author "marks" every modification with their initials and the date, especially if files are in Revision Control.
I can't tell you how much all of the above comment "styles" are just noise for everyone to slog through! You are not helping anyone by inflating the size of every file with your initials/date or whatever other meaningless information you think you are providing.
Code is more information than comments, if you treat it like a writing assignment, and not like some secret only you can understand. Start by using meaningful names. I don't want to hear about how you can't type; this is your fucking job, you better be good at typing, since using a computer to write software is typing. Meaningful doesn't necessarily mean verbose. Meaningful names are hard to come up with on the first (or second or third) try; that is not an excuse to give it a pass, it is an excuse to use the Rename Refactoring when you come up with a better name!
And one more pet peeve: absolutely never use single-character variable names! Do you know how many times i appears in a file? If you are using if statements and while loops, then there's a big fat fuckload! These are used mostly as looping indices, and we have a simple fix: append an x onto it, so now i becomes ix.
Look!!! Now I can find the fucking thing pretty simply, without visiting every last control structure in my algorithm. Plus, it has x in it, to remind you that it is an index! That's a big payback from one character!
Also don't confuse comments with documentation, which these days is usually maintained within the source code files in some special comment format. If you want to tell nice stories, this is the place to do it, because people using your code will be reading this, and not your Add 1 to I bullshit.
Another in the now-continuing X is a piece-of-shit series...
I have been tinkering with Android SDK lately, and boy is this a way better experience compared to the JavaME slagheap!
Here is the short list that you should care about:
There are actual graphically-appealing widgets to use, and actual layouts to place them in.
Java is treated as a first-class citizen within the device, and not like an afterthought.
Security decisions are controlled by...drumroll please...You, The User, and not by forking over your dosh to VeriSign for a certificate just so I can access GPS, contacts, pretty much everything, without pestering the shit out of you with prompts!
Real multi-process service-based architecture under the hood!
Intent-based invocation allows you to trigger pretty much any other entity in the system, in a generic way!
Did I mention you get lots of slick-looking UI widgets to play with, and you can build UIs declaratively?
I for one am going to shove the Wireless Tookitright up Sun's ass.....
I have a real problem with people coming to me for help, but haven't done the least little bit of reasearch. One of my fellow bloggers (I am unknown to him I'm sure) has the same problem, but he's way nicer about it.
I just encountered this in-person last week. A co-worker was terribly struggling with ASP.NET, and was asking me to basically build this whole page for him, because he did not understand how to use View State.
The very sad part was, he had a perfectly-good book on ASP.NET sitting on his fucking desk, apparently unread!
Rather than do the work for him, I spent some time acquainting him with his book, directing him to the relevant chapter. I also recommended additional reading, since he was going to be doing this quite a bit here at this job.
Needless to say, I asked to borrow the book over the weekend; I am still picking up good bits from it, as I am not an expert, but I know how to become one; do your fucking research...
...is an extension of where you live! I used to have a saying:
"Treat your work as well as you treat your home."
For the people that drink the coffee but never make it, you are a bunch of fucking Free-Riders, and your mommy is not here to keep you serviced with coffee, so take the fucking 30 seconds to make some and keep us from mother-fucking you behind your back, because we are!
For the people that leave their dirty shit in the sink even though there's a dishwasher 2 feet away, and generally fail to keep common areas clean, I am revising my saying:
Treat this place way fucking better than you treat your own home
because your spouse is not here to clean up after your lazy ass! And you better believe the people who are bitching about you behind your back about the coffee situation are getting you on this one too!
If you're down with this, you will probably like my "Walk Like You Drive" theory...
Yes we all know that one. Don't start spamming me with links about how to make it faster, I'm a dumb-fuck, Switch to Linux, Switch to Mac, etc. That was just to get your attention, and I'm not looking for suggestions. This is a Rant.
Ok, We Are Listening...
It's time for a change in philosophy for Operating Systems. The Hardware is not the most important thing for the OS, it's me the fucking user you stupid fucks!!!
To enable this Nirvana, we must take a radically different approach to how the OS decides what is important to load first. Forget about all these background services and crap; no offense, I don't need those until I do something. And I mean systematically apply this; not just the services you think are necessary.
With this in mind, the OS should be booting up in this order:
Kernel,
Graphics Subsystem,
User Agent (Shell),
Nothing Else You Stupid Fucks!!!!
Profanity aside, the point is Appearance Is Everything, and the sooner I can see my customized desktop, the happier I am; I feel like I can interact, and I can, because the OS won't be frantically loading and starting services and thrashing my hard drive while I try to open the Start Menu.
Once I am logged in, all disk thrashing should cease. This would be because there are no frantically loading services.
I've read lots of the Optimize Windows links, so we know it is certainly possible. I should be able to get logged in with only the absolute minimum number of services and drivers running.
Let's spin it another way. We should be trying to limit the attack surface at all times, and that means not even loading shit that the user isn't calling for.
We've all looked at the Windows Services list and we've looked at Task Manager. Why is there all that shit in there? I just logged in and started my browser, and i already have 60 processes running! What the fuck? I am not naive here; I am an experienced software developer, so believe me when I say that seems excessive. I have not started any other applications. I have 7 items in my task tray, and Virus Scanning.
I'm sure someone from Microsoft would argue the other way and say that is totally reasonable, and more and more "system" tasks get more and more cores to dump useless processing on and rob your applications of cycles.
Trying to keep up the pace of posts even with last year; I am really hoping to equal-or-better last year's production of 30 posts. Friday The 13th seems like as good an excuse as any.
Well your luck with traffic can't get any worse...
Some minor configuration tweaks here at the blog, courtesy of Blogger.com, in the gutter so-to-speak.
Not sure how it is any different from any other long-term stressful situation? I'm pretty sure not any different! If you put pressure on yourself, or allow others to, you will feel it, mentally and physically.
Ok, I'm feeling some chest pain, so I better lay off....
It's a depressing feeling. You are full of hope as you configure the XML Documentation setting in the project properties (oh yes, this is VS2005).
You were confident about your diligence at filling out the XML Documentation comments, it seemed like everywhere....
Then the horror. Trigger the build, and 582 XML Documentation warnings. Wtf!!!?!
Ok, so 582 edits later, then what?
Oh yes, download the latest CTP of Sandcastle, and start generating documentation. It even makes it look like VS-style yumminess.
Mmmmm.... Forbidden donut....
Yes, but still a few issues to note:
The DXROOT environment variable has a path-separator appended to it, which is not usually the custom. The "examples" script assumes there's no path-separator, and as a result, it generates double-path-separator in there.
The assembly scanner (which generates the topic list by reflection) wants all dependent assemblies not in the GAC available in the current folder. The build_sandcastle.bat doesn't display this; I only figured it out running it from the command line.
There is msbuild support also; I didn't try it. I am leaning toward making a NAnt version, to increase understanding.
Once that all got sorted, I was generating nice CHM files of my hard-typed-in XML Documentation!!
I was doing some background animation recently, which led me into the realm of real numbers, well-known as the bane of programming everywhere.
For the uninitiated (sad to say there are "programmers" that probably know nothing about IEEE number formats), it sucks because only very few numbers can be represented exactly, and this leads us directly into the world of accumulated error and uncertainty.
Big fucking deal! Spare me your gobbledygook! Just let me treat them like integers, and leave me alone...
Take this innocent loop for a quick example. Really. Take it, and paste into your IDE, and run it.
float total = 0.0f;
float incr = 0.005f;
while(true) {
Console.WriteLine(total);
total += incr;
}
Now, you desparately want the output of this loop to be [.005,.010,.015,.020,...] but you are going to be disappointed when you run it.
Dude, you are scaring me now....
How can this be? Pretty simple actually. Powers of ten and powers of two don't like each other very much; go back and read the first two paragraphs up there.
In the meantime, all is not lost. A more precise way to do the same thing is the following:
int ix = 0;
float total = 0.0f;
float incr = 0.005f;
while(true) {
Console.WriteLine(total);
total = (float)ix*incr;
ix++;
}
What makes this code more accurate (i.e. better) is the distinct lack of accumulated error. The (floating-point) number for the current iteration is the result of O(1) calculations, where as the other loop's is O(n) calculations.
Of course, this also means that directly testing for equality of two floating-point numbers is also a sticky wicket. Let's just save that for another time....
Everything, pretty much. You are basically no one without one.
So why do we suck so badly at gathering them? I'll give you a hint; it has 20 letters in it, 18 of which are usually glossed over, much like the concept itself: Internationalization, or i18n.
Now go ye, and rip out all of those Euro-centric First Name/Last Name fields and fix them. What to do with the database columns you are storing them in, is another problem/post.
I am a guitar-player; I recently started a social network on Ning, so I can infest the Internet with digital artifacts of my practices.
First of all, not only is Tuesday Groovy, so is creating your own network for whatever you want. It doesn't have to be about "me", even though mine is; it's more about the music.
I didn't want to use one of the "big guys" because everyone has one of those; I will not conform (in that way). We all know I'm more of a PA-kind-of-a-guy.
I even have this blog cross-configured into my socnet; I will be flipping browser tabs shortly to see The Internet At Work.
I love consuming podcasts. I won't cite links, I don't have that much time. Being the consumate geek, I built my own plugin-based RSS reader years ago. I won't bother citing that either; it only has about 700 downloads on download.com. Needless to say, it has a podcasting module called "Snarfer", not to be confused with an actual RSS reader of that name; they stole it from me I'm sure of it.
I still have a backlog of over five hours of podcasts from 2007.
No problem; I wasn't ready to let go of last year just yet....