Reason #232 That Windows Makes Me Crazy

Here’s a not-too-infrequent scenario:

What’s up with that file on my flash drive? I’d really like to delete it, but Windows keeps telling me “permission denied”. I’m pretty sure I have access to that directory.

Oh, I see. It’s in use by an application. Which one? Oh, it’s not going to tell me that.

Guess I’d better download a copy of Process Explorer.

Ah, there we are. That’s what’s holding that file. Ok. Terminating that program… Yay, now I can delete the file.

Now I’m just going to stop the drive so I can safely remove it…oh, look, the drive is still in use; it won’t let me stop it. Let’s see what Process Explorer says is in use on E:\…

Nothing. The drive isn’t in use after all. Yet I still can’t stop it.

*sigh* *yank*

…and now it’s bitching that I have to stop devices before removing them or risk data loss. Thanks, Windows!

Reason #574 That Windows Drives Me Batty

What is it with virtually every application you install, plus Windows itself, wanting to put crap on the desktop? (Or worse, doing so without even asking you?)

The desktop is my workspace. Mine, mine, mine, mine, mine!! If there’s something that I’m likely to be using soon that I really want sitting there, I will put it there. Further, to all you developers who helpfully include a by-default-selected option to add a shortcut to your crummy app on the desktop: YOU’RE NOT HELPING. There’s no point in putting an application shortcut on the desktop. If I use the application frequently, it’s going to be in the frequently-used section of the Start Menu. If I’m always using it, I’ll set it to start up when I log in. If I don’t use it frequently, there’s no conceivable point to having it on the desktop.

And why on Earth does Windows make it so blasted difficult to remove “My Computer”, “Recycle Bin”, etc. from the desktop? I don’t know of any way to do it short of registry hacking or using TweakUI. Gah.

</rant>

Self-closing Script Tags

A cautionary note: using self-closing <script> tags generally will cause your browser to ignore the tag altogether. E.g., this doesn’t work:

<script type="text/javascript" src="foo.js" />

It took me a bit to figure out what was going on here, because it’s perfectly valid XML. However, since most web servers are going to mark webpages as HTML rather than XHTML+XML, it gets parsed as HTML, which doesn’t allow you to self-close tags that don’t have the EMPTY content model (like <br> or <hr>).

The Evil Empire

After many years of using Mac OS and Linux nearly exclusively, I’m in a job where I’m using a Windows PC and having to write programs targeted at Windows users in Microsoft-created languages. It’s been a long time since I’ve had to deal with the Evil Empire more than cursorily. Some observations, good and bad:

Good

  • ASP.NET is a surprisingly well-thought-out development platform. It’s very good at keeping code and presentation separate, allows for modular design at a number of different levels, and allows you to do a lot of things declaratively instead of programmatically. It’s pretty fab for creating CRUD web applications.
  • C# is a pretty nice language. It’s not Python, but it does have a lot of nice features, including “delegates”, which almost let you believe that functions are first-class.
  • Visual Studio is really an amazing product. Intellisense is brilliant; a lot of times, you can type a couple of words, and then basically autocomplete your code. I hate to say it, but it might be on par with Emacs as a powerful IDE.

Basically, most of their tools for development are extremely well-done. The big problems crop up when they try to use those tools to create anything else:

Bad

Windows.
Oh, God, how I hadn’t missed this. Having to run anti-malware software because the OS is too dumb to prevent itself from getting infected in the first place. No way to conveniently enter characters that aren’t on the keyboard (I can has em-dash?) Third-party apps to do anything useful (you didn’t really want to play DVDs, did you?). Applications that require the use of the context menu to do important tasks. Stupid “Are You Sure?” confirmation dialogs. Rebooting because you changed the color of the desktop.

The thing that really, really agitates me, though, is the lack of control of the computer that Windows provides. Windows frequently decides that what it’s doing is more important than what you’re doing. You’ve got the start menu open, and an application starts up? The start menu’s gone; now you’re working with the application. Fire up an application, and then switch to another one while it’s loading? The new app will steal focus back when it creates its first window. Windows thinks you need to clean up your desktop/install anti-virus software/brush your teeth? Look, a little popup in the taskbar, getting me away from what I’m working on. And the modal dialog boxes!! Sure, you see them occasionally in any environment, but man, I run into a lot of them here. The bottom line in any computing environment is that I am supposed to be in control. At all times. The machine exists to serve me, not the other way around.

Internet Explorer 6
The bane of developers and users everywhere. Insecure. Buggy as crap. No debugging features that compare to other browsers. Unaware of standards that had existed for YEARS before it was released that every other browser has somehow managed to competently support . When you write a web app, you basically have to write your app twice; once for web browsers, and again for IE 6. It warmed my heart to see that IE 6 is not supported by the “new Facebook”, which will soon be the only way to use Facebook. Hopefully if another big player or two gives IE 6 the treatment it so richly deserves, it’ll be relegated to the junk heap before Microsoft officially puts a bullet in its head in July of 2010.
Outlook
Big. Evil. Doesn’t work well with anything other than Exchange. Clumsy, clumsy user interface. I was aghast to find that you can’t do ad-hoc searches of your mail. You want to find that message about TPS reports from a few days ago? Create a new search folder, make a new filter to tell it that you’re searching the whole message, type in “TPS”, save the folder, click on it, and wait. Then delete it when you’re done. On a Mac? Command-option-F TPS. Or Command-Space TPS and look through your entire system. People need to be able to search their mail quickly and conveniently. (Oh, and I hear that the HTML rendering engine in the new version of Outlook is the same one that Office uses, taking the dubious task of writing HTML email that will display reasonably on many clients from the realm of “difficult” to “impossible”.)

Programmatically Selecting a A GridView Row in ASP.NET

I recently ran into a situation where I wanted to be able to select a row in a GridView control when a page is loaded.

The obvious solution is just to (as suggested on many forums) add the “Selected” property to the row you’re interested in, but that’s fairly suboptimal. It doesn’t trigger the OnSelectedIndexChanged or OnSelectedIndexChanging events, and I don’t think it updates other properties like the SelectedIndex on the GridView. What I really wanted to do was trigger an event that would be identical to what would happen if you selected the row using the web interface.

Googling only revealed one place that claimed to have an answer, and of course, it’s the ever-annoying ExpertSexChange. I finally figured out a way to do it on my own, so I figured I’d share. (And, perhaps, deny the aforementioned site a bit of revenue. >:-) )

The trick is to use the containing Page object’s RaisePostBackEvent() method. It sounds obvious in retrospect, but I was looking for a method on the GridView object rather than the page. (There is a RaisePostBackEvent() method on the GridView object as well…but it’s protected.) Instead, you send the event to the Page object, which the control has registered itself with, and the page informs the control. Specifically, to select a row, make the event argument “Select$rowIndex”. Shazam!

A Somewhat More Efficient Gift-Giving Algorithm

After reading the Wikipedia article on derangements and seeing how one goes about finding the number of derangements of a given size, I figured out how to generate a random size-n derangement without generating all size-n derangements and picking one. This made my Secret Santa program rather more efficient (O(n) is just a little better than exponential time!)

Also, in writing this program, I found a point in Python where two of its paradigms don’t mix well. Like most languages with first-order functions, python has map() and reduce() functions. However, method calls are handled more like C++ or Java: you call them as object.methodname(). If you want to get a list of results of a method applied to each element of a list, there doesn’t appear to be a straightforward way to do it. In this case, I wanted to strip whitespace from a list of strings. I ended up using a lambda that takes a string s and returns s.strip(), which isn’t too clumsy.

Edit: One of my friends noted that this could be handled nicely with a list comprehension. D’oh! Fixed, though the original line has been left in, commented.

For those who are interested:

#!/usr/bin/python
#
#     derange-strings.py
#
#     Takes a list of strings on standard input (one per line)
#     and prints it out alongside a random derangement of the list.
#     Can be used for secret-Santa-type gift-giving arrangements.
# 
#     Copyright (C) 2007  Neal Groothuis
# 
#     This program is free software: you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation, either version 3 of the License, or
#     (at your option) any later version.
# 
#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.
# 
#     You should have received a copy of the GNU General Public License
#     along with this program.  If not, see <http ://www.gnu.org/licenses/>.

import sys
import random

def swapElements(i, j, l):
    l[i], l[j] = l[j], l[i]
    return l

def randomDerangement(n):
    if n==2:
        return [1, 0]
    else:
        k=int(random.random()*(n-1))
        return swapElements(k, n-1, randomDerangement(n-1)+[n-1])

#names=map(lambda(s): s.strip(), sys.stdin.readlines())
names=[s.strip() for s in sys.stdin.readlines()]
n=len(names)
assignments=randomDerangement(n)
for i in range(n):
    sys.stdout.write(names[i]+"\\t"+names[assignments[i]]+"\\n")

Two More Reasons to Not Use PHP

In a recent project, I found a couple more reasons to dislike PHP (not that there aren’t plenty already). While, admittedly, PHP 5 is a substantially better language than PHP 4 (for instance, it kinda supports object-oriented programming), it’s nonsense like this that makes it nastier to work with than better-designed programming languages.

  • Quasi-signed Integers

    According to the documentation, PHP “does not support unsigned integers”. Like many things in PHP, it’s true, except when it’s not. Obviously there’s an expectation that integers will be treated as unsigned values, since functions like sprintf() include provisions for handling them. I stumbled across this when using the ip2long() function. It always returns an integer for the IP address, even though it may be negative if your integers are 32 bits long! I ended up having to wrap every use of the function with a clever but nasty hack to avoid storing negative IP addresses in the database.

    The “proper” behavior for dealing with values larger than the integer type can handle, according to the docs, is to promote it to a float. That might be reasonable if it were consistent…but it’s not. For instance, if you’re on a 32-bit platform, you’ll probably find that 0x7fffffff is equal to 0x1000000000, because hex values don’t get promoted consistently. Going the other direction isn’t any better. If you cast 2147483648 on a 32-bit system to an int, it comes back as -2147483648, without so much as a warning. In general, integer math in PHP is risky.

  • Bizarre NULL semantics

    PHP has a NULL type. What it doesn’t appear to have are any rules, conventions, or even vague notions about how to handle it. In general, I’d expect one of two results if I use a NULL value in a computation or pass it to a function that doesn’t have obvious NULL semantics (e.g., is_null()):

    1. A returned NULL value, à la SQL. If I try to do a computation with a missing value, I get no value as a result.
    2. An error. Python, for instance, will throw exceptions if you try to evaluate something like “1 + None”.

    What does PHP do? …who knows?. “1 + NULL” is 1, “ip2long(NULL)” is -1, and “NULL + NULL” is NULL. Nothing In, Garbage Out.

    While this may sound niggling, keep in mind that PHP’s stereotypical use is database-driven web apps, and SQL-speaking databases all support NULL values. You generally don’t want to handle NULL in the same way that you handle a value that’s present, and you certainly don’t want to handle it in an arbitrary and indeterminate fashion. This caused much consternation on my aforementioned project, as NULLs were “helpfully” converted to zeros and saved into a column in the database which had a UNIQUE constraint on it. It worked okay for the first person save the form without filling out that value…

Update:I got flak on Reddit for posting an X sucks article, which is probably fair. I added a comment there finishing my thought, which I hope will turn it into X sucks, here are better alternatives.

These are indicative of fundamental problems with way the language is developed; namely, the apparent lack of any consistency or thought regarding the consequences of the designers’ decisions. I’ve had an app crash during minor-version PHP upgrades because they changed the semantics of one of the LDAP functions and didn’t note it in the changelog. I’ve fought with data-input bugs in existing PHP apps that invariably crop up because somewhere, someone didn’t wrap a request variable with the four lines required to un-magic-quote-it, or un-magic-quoted a variable on a system where it wasn’t turned on. And it took them until version 4.2 to realize that it was maybe a bad idea to, by default, allow web requests to set arbitrary variables in the global namespace.

Why fix PHP when, as I noted in the post, there are already plenty of other languages that don’t suck? Python’s well-thought out and has an enormous set of libraries and development frameworks available for free. The same can be said for Java. (I personally find the repetition it often requires maddening, but at least it’s consistent.) I haven’t played with it myself, but lots of folks back Ruby too, and Perl’s still got a sizable fanbase. The changes required to make PHP enterprise-ready are immense:

  • audit all functions to ensure proper handling of NULLs
  • completely redo how integers are handled
  • modify all functions to throw exceptions when exceptional cases occur, rather than returning 0/FALSE/-1/”ERROR”
  • cull unnecessary nearly duplicate functions
  • standardize function naming
  • introduce namespaces

…and that’s just what I’m coming up with off the top of my head. Why bother fixing something so fundamentally broken when better things are already out there? (To be fair, I know that PHP 6 is going to try to resolve some of these issues, but that’s going to be a hard transition that’s going to break most existing PHP 5 apps, and it’s still a ways down the road.)

Update, 19 June 2017: I got a note from Craig B. Peck at iFlexion with an article they posted on the resilience of PHP. I can’t say that the problems generated by its use are the ones that I’d want to spend my time solving, but I can certainly believe that there will be plenty of them to work on for years to come for those who are so inclined.

Filling in the Gaps (in SQL)

In an application that I developed recently, I needed to be able to choose an unused IP address from a set of available address ranges. I didn’t really want to have to write some stored procedure to iterate over the entire space to until it found a gap. After a while I came up with (roughly) this:

SELECT MIN(addresses.available) FROM (
  SELECT i1.ip_addr + 1 AS available
    FROM interfaces i1
      INNER JOIN assignable_ip_ranges r
        ON i1.ip_addr >= r.start AND
           i1.ip_addr < r.end
      LEFT OUTER JOIN interfaces i2
        ON i1.ip_addr + 1 = i2.ip_addr
    WHERE i2.id IS NULL
  UNION
  SELECT r.start AS available
    FROM assignable_ip_ranges r
      LEFT OUTER JOIN interfaces i
        ON r.start = i.ip_addr
    WHERE i.id IS NULL
) addresses;

A quick explanation of what’s happening here:

If you do a left outer join of a table with itself with the criteria that some field on the left side, plus one, is equal to that same field on the right, the rows in the result that are NULL on the right side will have the maximum values of sequences on the left. For example, say you have table xyzzy containing four records with field foo containing the values 1, 2, 3, and 5. This query:

SELECT * 
  FROM xyzzy a
  LEFT OUTER JOIN xyzzy b
    ON a.foo + 1 = b.foo;

will yield:

a.foo b.foo
1 2
2 3
3 NULL
5 NULL

That explains the LEFT OUTER JOIN and WHERE clause in the first sub-SELECT. The INNER JOIN just restricts the addresses to being chosen from the ranges in assignable_ip_ranges. (Note that the “end” comparison is a strict less-than, though. An address that has a gap following it at the end of an assignable range doesn’t do us any good!)

This technique has one big problem: it has no way of filling in the gap between the beginning of an available range and the first used address! That’s where the second sub-SELECT comes in. It uses roughly the same LEFT OUTER JOIN technique, but instead of doing a self-join, uses the start of the available IP ranges and the used IPs for joining. In essence, we’re pretending that there’s an assigned IP just before the beginning of every range.

At this point, we’ve got a list of the beginnings of all gaps, and we just take the minimum for the next address. Shazam!