Wednesday, September 24, 2014

Commas and semicolons

Typical in HTTP/MIME standards is that items in a list are separated by a comma. That makes sense. But then when we want to add some attributes to those list items,  SOMEONE decided that it would be a good idea to use a semicolon, like this:

application/json;q=0.9, application/javascript;q=0.5, text/javascript;q=0.5, text/plain;q=0.2, */*;q=0.1


Which is very unnatural, because according to regular written syntax, the semicolons separate parts that have commas in them, not the other way around.

Since the previous syntax already used comma to separate items, it wouldn't make sense to change it because that would break existing software (not that existing software would have been able to match text/javascript;q=0.5 to a file type if it was using an exact match anyway).

It would have been better to use a different attribute separator though. Maybe pipe | or question mark ? would have been fine, or maybe a colon : which of course is completely different than a semicolon.

A colon would be very natural because colons are used to separate a sentence or list which clarifies the first sentence. For example "I like natural colors: blue, green, and brown".  Similarly, the item attributes clarify the item itself.  So this could have been:

application/json:q=0.9, application/javascript:q=0.5, text/javascript:q=0.5, text/plain:q=0.2, */*:q=0.1


Saturday, February 22, 2014

To be Mutable first or to be Immutable first?

Apple's Objective-C library has many pairs of classes like NSDictionary and NSMutableDictionary.  Typically the mutable class inherits from the immutable one to add the write functionality, so that the "normal" class is the immutable one and only in cases where you need to write back to it you declare variables as being mutable.

Apache Commons Configuration has a pair of interfaces Configuration and ImmutableConfiguration. The "normal" Configuration object is the mutable one, and it inherits from ImmutableConfiguration. This is the opposite of Apple's style.

I don't know how many libraries out there even have pairs of classes like this, or whether more of them make mutable normal or immutable normal.  But here's my opinion:

It makes sense for a class or interface X to be immutable, and to have a subclass or subinterface called MutableX which adds the mutable methods.  Given an instance of X, you can check if it is an instance of the mutable subclass or implements the mutable interface.

It makes less sense for a class or interface X to be mutable, and to inherit from a superclass or superinterface called ImmutableX.  This isn't just the opposite of the above because in this case, all instances are either ImmutableX or subclasses or subinterfaces of ImmutableX. So checking to see if an instance is mutable is somewhat strange with this style.

It makes no sense at all  for a class or interface X to be mutable, and to have a subclass or subinterface called ImmutableX which overrides the mutable methods and throws exceptions or does nothing.

In conclusion, make the normal class or interface immutable X first, and subclass or subinterfaces MutableX second. That makes it easy to check whether an instance is mutable or not.

Tuesday, June 05, 2012

iCal imports events with blind dialogue

Apple's iCal program with iCloud synchronization has this annoying habit of obtrusively adding events to my computer's calendar by showing me a dialog that asks in which calendar I want to save the event -- without showing me the event!!

How useless is that? So I've standardized on always accepting the first calendar in the list because at least that way I'll always know that any events I created on my iPhone are in that one.

Even worse, after I click OK it shows a quick animation of adding the event but then immediately another similar dialog for the next event before I have a chance to see where the first event went.

Finally after all events are imported in this one-by-one fashion with the useless "which calendar" question, I get an alert box saying all events were imported successfully.

A principle of user interfaces is don't ask the user a question if you're not going to provide any information for them to make a decision. If you can't provide the facts that you want the user to consider when making a decision then just go ahead and make a sensible guess yourself because the user won't know what to do.

But in this case, iCal does have plenty of useful facts - the event information - and isn't showing them. And more than that, iCal knows what calendar that event came from on my iPhone (or it should, unless they really botched up their internals). So if there is an identically-named event on my iMac, that would be a good first guess, and I'd prefer if iCal just did that and didn't bother me.

Wednesday, July 14, 2010

Priority of Work in Apple Mail

It would be nice if Apple Mail would give priority to downloading the contents of folders I've clicked on, instead of downloading EVERYTHING ELSE first.

The IMAP protocol was built for just this sort of behavior... intelligently choosing what to download.

This misbehavior isn't something I notice on a daily basis. It's something I notice when it hurts the most -- I'm on the road, I've been offline for 2 or 3 days, and when I reconnect there are literally thousands of messages to download, I don't have a lot of time, I just want to see messages in certain folders (my server has mail sorting rules for my account), and I can't because instead of downloading messages in the folder I clicked, Apple Mail is downloading everything else first, and taking forever to do it because I'm in a hotel where the connection is slower than it is at home.

Wednesday, May 26, 2010

1and1 MultiViews

Apache's MultiViews feature is an easy way to let visitors access foo.php with a URL like /foo.

Here's the secret to turning on MultiViews in your 1and1 web hosting account. Put the following lines into an .htaccess file:


AddHandler php5-script .php
AddType text/html php
Options +MultiViews

And it works!

Friday, October 16, 2009

Apache Tomcat Shutdown Command

So at work I have a machine that runs multiple instances & versions of Apache Tomcat, some of them using different versions of Java.

I have everything configured pretty cleanly (I think) but I noticed that when I use the catalina.sh stop command from any instance, it stops ALL the instances of Tomcat.

Here is the part in catalina.sh that seems to stop all the instances even though the both Java and Tomcat configurations should be specific to just one instance:

"$_RUNJAVA" $JAVA_OPTS \
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" -classpath "$CLASSPATH" \
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.io.tmpdir="$CATALINA_TMPDIR" \
org.apache.catalina.startup.Bootstrap "$@" stop

I haven't looked at the source of org.apache.catalina.startup.Bootstrap to see exactly what it does with the stop command.

Enter Tomcat's network shutdown command to the rescue: In each server.xml, the <Server>  element allows two attributes: port and shutdown. It might look like this:

<Server port="8005" shutdown="SHUTDOWN">...</Server>

I modified my Tomcat shutdown script to use this network command first to make sure it kills the correct instance. Then, if the instance is still running (which hasn't happened to me yet), I use ps and grep to find the pids of all instances that were started from a particular base directory (each instance, even if it's the same version of Tomcat, has a separate base directory that it uses for its web apps and temp files).

Here is the ingredient list:
1. server.xml, containing the element
2. XSLT stylesheet to convert server.xml to a reduced XML file that contains only the port and shutdown command I need
3. xsltproc command-line tool
4. Netcat (nc) to send the shutdown command to the Tomcat shutdown port
5. Perl script to convert the reduced XML file to a shell command

Here is my XSLT file, shutdown.xslt:

<?xml version="1.0"?>
<service xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xsl:version="1.0">
<text><xsl:value-of select="Server/@shutdown"/></text>
<port><xsl:value-of select="Server/@port"/></port>
</service>

When used with xsltproc, the shutdown.xslt file generates a small XML file that looks like this:

<?xml version="1.0"?>
<service><text>SHUTDOWN</text><port>8005</port></service>

Here is my Perl script, generate.pl:

#!/usr/bin/perl
local $/ = undef;
my $xml = <STDIN>;
my ($text) = ($xml =~ m{<text>(.*?)</text>});
my ($port) = ($xml =~ m{<port>(.*?)</port>});
print "echo \"$text\" | nc localhost $port";

When given the reduced XML file, generate.pl produced output like this:

echo SHUTDOWN | nc localhost 8005

So putting it all together, the part of my shutdown script that reads server.xml to find the configured shutdown port and the command looks like this:

SHUTDOWN_COMMAND=`xsltproc shutdown.xslt server.xml | perl generate.pl`
$SHUTDOWN_COMMAND

And I can use the same shutdown script with any Tomcat instance without having to duplicate the shutdown port and command information.

Tuesday, June 16, 2009

Simpler instructions

Here's an email I got from Salesforce.com. Notice how they provide one link and then a whole paragraph about how to change the link. They could just provide two links and label them, "this one is to install in production instance", "that one is to install in sandbox instance", and leave out the long paragraph.


To share the app contained in the package with your colleagues, forward the following URL to them:


https://login.salesforce.com/?startURL=%2Fpackaging%2FinstallPackage.apexp%3Fp0%3Dxxxxxxxxxxxxxxx


Note: If you are installing this in a sandbox instance and it was created in production (has a url that starts with https://login.salesforce.com/) you must replace the initial portion of the URL with http://test.salesforce.com/. Likewise, if you are installing a package that was created in a sandbox (has a url that starts with http://test.salesforce.com/) into production you must change the initial portion of the url to https://login.salesforce.com/.

Duplicate entries in Eclipse content assist

I've been asked about this several times already by some Java Programmers so here's the answer:

Go to Eclipse Preferences -> Java -> Editor -> Content Assist -> Advanced, and turn off whichever content assist sources you don't want.