Tuesday, July 05, 2005

The Next SQL WTF: Where-Unaware Select

Alex Papadimoulis writes: "There was a time where I used to believe that the worst possible way one could retrieve rows from a table was to SELECT the entire table, iterate through the rows, and test a column to see if it matched some critera; ..."

Another infamous SQL WTF: The Where-Unaware Select - woooha, makes me shiver...

By the way, if you think selecting a whole table into memory and scanning through each row programmatically just must be unreal - that's exactly what one of those framework astronauts recommended in a real-life project I know of, where people were forced to use his blasted O/R-mapper. No need to say the project was canceled months later...

The Best Software Writing

Today I received my copy of Joel Spolsky's "The Best Software Writing", a collection of software essays (mainly blog articles, hand-selected by the readers of Joel On Software, resp. Joel himself).



I even ordered this book in the States, as it had not been available in Europe at that time. Highly recommended reading material!

Saturday, July 02, 2005

Pragmatic Solutions For An Imperfect World

Some time ago, with only one week to go until the scheduled delivery deadline of our .NET client/server product, our customer reported increasing application instability. My developers had not observed that issue so far, but the application seemed to crash sporadically (but unrepeatably) on our customer's test machines. As we were coding in managed C# only, my first guess was a .NET runtime failure, or a native third party library bug. Luckily, we had installed some post-mortem tracer, which turned out the following exception stacktrace:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.

at System.Windows.Forms.UnsafeNativeMethods.PeekMessage(MSG& msg, HandleRef hwnd, Int32 msgMin, Int32 msgMax, Int32 remove)

at System.Windows.Forms.ComponentManager.
System.Windows.Forms.UnsafeNativeMethods+
IMsoComponentManager.FPushMessageLoop
(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)

at System.Windows.Forms.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)

at System.Windows.Forms.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)

at System.Windows.Forms.Application.Run(Form mainForm)


Great. Win32 API's PeekMessage() failing, and the failure being mapped to a .NET NullReferenceException. I was starting to get nervous.

I told our customer that our code was not involved (it's always good to be able to blame someone else). But as expected this answer was less-than-satisfying. The end-user couldn't care less about who was guilty, and so did our customer (and they are right to do so). They wanted a solution, and they wanted it fast.

Now I have some faith in Microsoft's implementation of PeekMessage(). It seems to work quite well in general (let's say in all Windows applications that run a message queue) - so something must have been messed up before, with PeekMessage() failing as a result of that. Something running in native code. Something like our report engine (no, it's not Crystal Reports).

We had not invoked our reports too frequently during our normal test runs, as the report layouts and SQL-statements are being done by our customer. So after some report stress testing, those crashes also occurred on our machines. Rarely, but they did. And they occurred asynchronously, within seconds after the last report invocation. Here was the next hint. This was a timing problem, most likely provoked during garbage collection.

So how to prove or disprove this theory? I simply threw all reporting instances into one large ArrayList, so that those would never be picked up by the garbage collector (SIDENOTE: NEVER DO THIS IN A REAL-LIFE PROJECT), and voila: no more crashes, even after hours of stress testing. Obviously keeping all reporting instances in memory introduces a veritable memory leak (still better than a crashing application someone might argue, but this is something I never ever want to see in any implementation I am responsible for). But I had a point of attack: the reporting instances (or one of the objects being referenced by those instances) failed when their Finalizers were invoked.

First of all I noticed that the reporting class (a thin managed .NET wrapper around the reporting engine's native implementation) implemented IDisposable - so I checked all calling code for correct usage (means invocation of Dispose(), most comfortably by applying C#'s "using" construct). When implemented properly, this should prevent a second call to Dispose() during finalization, which might be the root of evil. But our code seemed to be OK.

Next I hard-coded GC.SuppressFinalize() for all reporting instances that had been disposed already, in order to prevent the call to its Destructor (Finalizer in .NET terms) as well, but still no cure - obviously it was not the reporting instance itself that crashed during finalization, but another object referenced by the reporting instance. I ran Lutz Roeder's Reflector, and had a look at all the reporting .NET classes, resp. their Dispose()- and Finalizer-Methods: they only wrapped away native code.

If I could only postpone those Finalizer-calls until as late as necessary (e.g. until free'ing their memory was an absolute must - native resources would not be the problem, as they would be cleaned up long before during the synchronous call to Dispose()). The moment the application would run out of memory even after conventional garbage collection (which might never happen), it would collect the reporting instances. I needed SoftReferences. The garbage collector delays the collection of objects referenced by SoftReferences as long as possible. Unfortunately, .NET does not provide the concept of SoftReferences (Java does, though). .NET has WeakReferences, which will be picked up much earlier than SoftReferences. So I simply started my own background thread, which would remove reporting instances from a static Collection after some minutes of reporting inactivity, hence make them available for garbage collection.

Sometimes luck just strikes me, and that's what happened here: this approach extinguished all sudden crashes. The reporting instances got picked up by the garbage collector (I debugged that), but just a little bit later. Late enough for their finalization to run smoothly. So up to now I don't know the exact cause (as mentioned before, it must have been a timing problem - if reporting instances survive some seconds, they will not crash during finalization). We are still investigating it, and we will find a more suitable fix. But much more important: we shipped on time, and we made our customer happy. All end-user installations are working fine so far.

Do I like the current solution? No, it's a hack. But still it's 10.000 times better than shipping an unstable product. From a certain level of complexity on, all software products contain hacks. Just have a look at the Windows 2000 source (esp. the code comments) that were spread on P2P-networks some time ago. In an imperfect world, you sometimes have to settle with imperfect (but working) solutions for your problems.

Tuesday, June 14, 2005

WTF Of The Year

This must be the WTF of the year! Please only look at it when you are mentally prepared. And don't say I didn't warn you: Plain SQL-Code in a browser cookie, executed with DB sysadmin privileges once a certain webpage is visited again. An invitation for SQL-Injection to everyone who happens to know how to type "drop database".

Saturday, May 21, 2005

HP: Why Not Just Zip Your Printer Driver?

Damn, three large downloads, one hour of wasted time, and my HP Deskjet 3820 still doesn't print thanks to the geniuses at HP who cannot even provide a working driver installation package. The first setup wizard crashes after 10% of unpacking, the second one won't find a DLL function entry point and terminates, and the third one displays an empty frame on my desktop, and that's about it. Go and throw your files and your driver.ini into a zip, would you? I don't need your flashy installer anyway.

Update: Cool, one of the crashing HP driver setup wizards did exactly that - left the driver files laying around in it's working directory. That's what I call customer service. Thank you, HP!

Reminder: Always keep driver CD.

Friday, May 06, 2005

Don't Surrender To The Technology Pipers

Over and over again non-technical decision makers have screwed up software-projects by blindly following pied pipers propagating their inappropriate technologies. Only in conjunction the clueless suit and the shallow wannabe-techie unfold their destructive powers.

Today, many IT middle and upper management positions are staffed with folks who are technological dinosaurs (the last time they coded was in Basic at highschool, before they stepped out of comp-sci classes when they didn't quite grasp the concept of pointers). Their cluelessness then opens the doors for semi-educated people in the lower ranks, who spent 10 years at college campus playing multiuser dungeon games or others who just went through the federal employment offices' "Becoming a webdesigner in four weeks"-training.

Especially in large corporations this kind of host/parasite-relation happens quite frequently. Some of the species you might encounter:

Framework Astronauts
Here we talk about folks who spend most of their time building application frameworks, that no one on this planet asked for. But that doesn't really matter - the astronaut's goal is to play around with technology, not to produce a valuable product. And without any actual application depending on the framework, there is also no need to maintain backward compatibility, so all the old programming interfaces can be thrown over board each time the astronaut wants to try something new.

Bullshit Pipers
Those people just unload all the latest tech terms on their CEOs, who in change will surrender to the piper's technical superiority. Truth is, the piper has no clue either, most of all he has no practical experience, and he also won't bother to consider the project requirements, as this might make his favorite technology look inappropriate (which it is, of course).

Not-Invented-Here Pilots
They will re-invent the wheel, and write their own database engines, XML-parsers and workflow systems - briefly everything that has been done before by more qualified people, as long as they don't have to work on their real task, namely implementing application logic. My favorite example: proprietary object/relational mappers - right, after all there are no commercial or open source O/R mappers out there, so the only way is to ramp it up on their own.

Some real-life experiences:

  • The consultant who used webservices in every scenario (even for downloading binary data), and designed all of them with the same method signature (input: string, output: string). So much about "service-oriented architecture".

  • The integration specialist who parsed huge XML chunks by applying DOM (which loads the whole XML structure into one big in-memory tree), instead of SAX (which is stream-oriented / event-triggered). Of course he found out too late (after deployment on the production servers), so he recommended to split large input-files into several smaller ones each time.

  • The self-proclaimed Java architect, who wasted his customer's money by implementing his own (erroneous) HTTP-protocol and XML-parser (which of course exist already as part of the JDK), and managed to deliver a Java application which was not able to handle unicode.

  • The programmer who explained that Visual Basic 6 had garbage collection (hint: that's reference counting, not garbage collection, dude).

  • The webdesigner who insisted that the casing of his filenames were not important on a Solaris webserver (yes, he came from the Windows world).

  • The guy who hand-coded his XSD- and WSDL-files, disregarding the actual implementation, or even broke XML schema syntax rules. Design by (service) contract, anybody?

A cobbler should stick to his last. I don't pretend to know about networking, so I will not tell our network folks how to configure our routers. And that's why MCSEs should not design software architecture, webdesigners had better leave their hands off enterprise application integration, why Visual Basic programmers can't just switch over to Embedded C++ in a week, and why college hackers might better not single-handedly build up the corporate system infrastructure.

If you want more proof, have a look at The Daily WTF - Curious Perversions In Information Technology. Those things happen each day (believe me, I have seen it) - at a software company close to you.

Wednesday, April 27, 2005

Retro Computing: Some Things Just Never Change

Me, in front of my Commodore 128D (1986):



Me, in front of my Commodore 128D (2005):

Saturday, April 16, 2005

Retro Computing: The Best Joystick Of All Times

Uhhh, I was extremely lucky. Chances were minimal, but I found Suzo's "The Arcade" joystick for 8/16-bit homecomputers on eBay Netherlands. Even better, this turned out to be a "Buy it now"-offer - there was no hesitation for me.



The Arcade was by far not as common as the Quickshot II or the Competition Pro, but there is no other design that fits as comfortably in the palm of my hand. All microswitches, of course. I just spent half an hour playing Soccer II on my C64 using another ancient joystick model, and I constantly hit a misplaced fire button, plus my hand started hurting within minutes.

I can't wait to plug in the Arcade again.

Friday, April 15, 2005

Weirdoz.Org Visual Chat Up And Running Again

Just a short note that the folks at weirdoz.org got their Visual Chat system up and running again.



I developed Visual Chat about eight years ago - those were the days of JDK1.1, Netscape 4.0 and MSIE 4.0 - so please overlook the client's obvious weaknesses. weirdoz.org is now the longest running Visual Chat installation - since 1999 about 300.000 users have signed up.

Wednesday, April 13, 2005

Arno's Software Development Bookshelf

This part of my bookshelf (see below) is all about software development and the software industry. It is slowly starting to outgrow the shelf-space I originally had reserved. I am particularly interested in object oriented design / development (mainly in C++, Java and C#/.NET), application servers, database systems, graphical user interfaces (thin clients and rich clients) and software project management in general. Another fascinating area is the microcomputer revolution, and the history and the legends of silicon valley.

On the other hand, I also try to build up a basic level of knowledge in areas outside my expertise - e.g. I didn't have a a lot of idea about networking in general (one course at university and my little peer-to-peer home LAN just wasn't not enough, and at work networking has always been outside the scope of my tasks). Severals books later I now have something like a global impression of what it is all about (suffice to say that more practical experience is still missing). Same is true for electronics, image editing, game programming, and so on...

Please click on the image in order to zoom in. Some of those books are also listed here, resp. on my Amazon Listmania Lists.



This reminds me that I have to urge some folks to return the following items:

Sunday, April 10, 2005

Popular Electronics / January 1975 Edition

Please don't tell anybody [;-)]- but I am currently bidding for an original Popular Electronics January 1975 Edition on eBay.



Yes, that's the one where MITS announced the Altair 8800, the one issue that Paul Allen happened to notice at a local newsstand on Harvard Square, Cambridge (Allen was working for Honeywell in nearby Boston at that time). He bought it and showed to Bill Gates at his friend's dorm room. "It [the PC revolution] is going to happen", Gates knew. Here was their opportunity to do something with Basic...

Tuesday, April 05, 2005

My Computer Museum (Update)



From left to right:
(1) Commodore CBM8032
(2) Apple IIc, Apple II Green Composite Monitor
(3) Sinclair ZX81, B+W TV Set
(4) Sun SparcStation 5, NEC 21" VGA Monitor
(5) Commodore 128D, Commodore 1901 Color Monitor
(6) Commodore Amiga 500, Commodore 1085S Color Monitor
(7) Atari 1040ST, Atari SM124 Monochrome Monitor, Atari SC1224 Color Monitor
(8) Apple Macintosh LC, Apple Monochrome Monitor
(9) Commodore 64, Commodore 1541 Floppy Drive, Commodore 1081 Color Monitor

Latest Purchases:
(1) Apple IIc, Apple II Green Composite Monitor
(2) B+W TV Set for Sinclair ZX81

Currently looking for:
(1) Tape Recorder for Sinclair ZX81

Sunday, April 03, 2005

Retro-Computing: International Soccer On The Commodore 64

So I connected my Commodore 1541 floppy drive to my PC's LPT1 port using a XM1541 cable and invoked a transfer program called Star Commander, just to find out that Windows 2000's pre-emptive multitasking and asynchronous I/O just won't allow for the kind of synchronous control required to read from and write to the old 1541 drive. Star Commander even ships with an additional I/O driver for this scenario, but still it just didn't work. I had to switch back to DOS (now, this is one thing DOS is definitely doing a better job in), and voila - no timeouts any more.



Besides getting more or less every ancient program floating around on the internet onto my C64, I can as well transfer data from my old C64 disks to my PC, and run it in any C64 emulator, e.g. VICE. Also, most of my friends did not really keep their Commodores for the last 18+ years, so I can provide them with images of their old C64 disks for usage within their favorite emulator.

After Friday's Speedball session, I simply had to try Commodore International Soccer. Have a look, and don't tell me this doesn't beat EA Sports FIFA 2005 by far!



Friday, April 01, 2005

Retro-Computing: Speedball On The Atari ST

After plugging in my brand-new (or actually nor-so-brand-new) Atari SC1224 Monitor, there was just one and only one adequate game for re-inaugurating my Atari 1040ST: Speedball (by the Bitmap Brothers).



A highschool-friend of mine and me used to play this for endless hours, and - after years of practicing - we achieved something like mastery.



Today, more than 15 years later (OK, admitted, I also played it once or twice on PaCifiST, another Atari ST emulator on the PC - but hey, this wasn't quite the same), I reached knockout round 8 out of 10 in my first Speedball tournament. Gee, I need to train harder! And I want my old Arcade Joystick back!