14 Feb 2006
•
Miscellaneous
•
Personal
Update: Due to a misconfiguration some of my blog entries from the month of Feburary recently lost. This is merely a repost of the original content.
As
I get older I have been slowly reducing the number of additions I
maintain. These day, about the only addiction I have left is caffeine
and it is officially under siege.
Elliot has become increasingly more interested in what I and
Catherine do. To the point that lately he has been asking for coffee.
He is, of course, not allowed to have coffee but repetition of the
request is beginning to be bothersome. To the point where I will
probably have to curtail my coffee consumption when Elliot is around. I
suppose I will switch to tea rather than be completely decaffeinated.
We have some fruity herbal tea that Elliot likes and he has not noticed
the difference between it and the tea I drink, yet.
By coincidence I am reading Complicity by Iain BanksGreat book, by the way. Though, probably not for everyone. It is quite dark and twisted.
whose protagonist is a drug addicted journalist. Mr. Banks has a
brilliant way with words and managed to remind me how I felt when I
first started smokingIt
has been over 7 months since I stopped smoking. That is long enough
that I had to go look in my blog archives to figure out when I stopped.
I am definitely not going to start smoking again, at least not until I
can order replacement lungs over the Internet, but do miss it
sometimes. and drinking coffee, which happened about the same time.
I sucked that smoke in and made it part of me, joined mystically with
the universe right at that point, said Yes to drugs forever just by the
unique hit I got from that one packet of fags Andy liberated from his
dad. It was a revelation, and epiphany; a sudden realisation that it
was possible for matter — something in front of you, in your hand, in
your lungs, in your pocket — to take your brain apart and reassemble it
in ways you hadn’t thought of previously.
09 Feb 2006
•
Software Development
Stephen O’Grady and Tim Bray have been having an interesting conversation
about how the Java, and the JVM, relates to the LAMP stack, and dynamic
languages in general. Dynamic languages are a subject close to my heart
so I want to toss in my two cents.
On the ubiquity issue I am with Mr. O’Grady here, except, perhaps,
that I will go a little further. I think that the JVM is in a lot fewer
places than most Java advocates do. It is true that you can get JVM for
just about any platform, but it is also true that you can get a Ruby or
Python interpreter for just about any platform. Ubiquity is a function
of how many people use a technology not the other way around and PHP,
Perl and Python are just as ubiquitous as Java, if not more so.I _really_ wish I could say this about Ruby, but I just can’t. Yet.
I have only used Jython a little bit but I recognize the frustration Mr. Sequira describes.
I found it quite disconcerting to be working in an environment that
was, at the same time, both, and neither, Java and Python. Particularly
for the conceptual types that both languages support. For example, if
you call a method that returns a string having to figure out whether it
is a Python strong for Java string is just annoying.
The threading issue is the one that interests me the most. I think
that Mr. Bray is right that hardware threading is quickly becoming an
important issue. In the near future most machines will support
significant levels of true, hardware level, concurrency. But I think
the shared memory native threading model that Java has is completely untenable.
Even vm (green) threads, which are well understood and have nice
uniform semantics are difficult to use correctly. Once you throw in the
vagaries of native threads you have morass of complexity that is
practically unbearable. Worst of all, the usefulness of most of the
techniques we have to help manage software quality, like automated unit
tests and continuous integration, are inversely proportional to the
number of threads in the application.
The most important thing to keep in mind here is that, in the long
run, it is always better (read: cheaper) to use extra computing
resources to make problems more tractable for the humans in the system.
For example, we have garbage collectors because it is cheaper to buy a
slightly more powerful computer than to have you developer waste time
managing their own memory. I am not sure what the best solution to
highly concurrent hardwareThe Cincom Smalltalk guys [think that green threads and multiple processes are the best solution](http://www.cincomsmalltalk.com/blog/blogView?showComments=true&entry=3303013147) and they might be correct. I have my doubts but I do think it works better than Java’s native threads approach. is but I am quite positive it is not Java style threading. My gut tells
me that none of the approaches I know for apparent concurrency are
going to work well for a highly concurrent application on highly
concurrent hardware. If that is the case we will see something new and
differentI am guessing new and different will not from from Java-land because it
Sun is looking very risk averse with regards to the Java spec right
now. For example, they appear to have gutted Java generics with
erasure, just to maintain backwards compatibility as soon as the cool hardware gets into circulation.
It does feel broken that there are so many bits of code written in
different languages that do the same thing. However, the JVM is not the
One True Platform on which to solve that problem, if, indeed, it even
is a real problem. The JVM appears, from a my layman’s point of view,
not to be well suited to dynamic languages. Even if it were technically
well suited the culture around Java and the JVM is far too static to
support the experimentation need to find new and better ways to deal
with the complexities of highly concurrent environments. I think, for
the most part, dynamic languages need to stay off the JVM.
09 Feb 2006
•
Software Development
Update: Due to a misconfiguration some of my blog entries from the month of Feburary recently lost. This is merely a repost of the original content.
Danny Ayers has been going on about grazing the web
lately. I think he is on to something with this meme. Managing a set of
subscriptions is hard work if you don’t want to be overwhelmedI know because I am failing miserably at keeping my subscriptions to a manageable number. and I might be willing to delegate that to someone, or several someones, that I trust. Recently, Mr. Ayers decided to use del.icio.us to create/manage a technical reading listI do not use [del.icio.us](http://del.icio.us/) much but I never cease to be amazed at how other people put that system to good use..
Sounds pretty good so far. Well except that FeedLounge does not support reading lists, but I assume that is only a matter of time before this is rectified. And then I read this:
So I’ll find a few feeds (the feeds, not the blogs) and tag them ‘readinglist’.
My heart falls. I hate this. The fact that the feed and HTML
versions of most blogs have different URIs has got to be one of the vilest kludgesI think this kludge came about because a) most developer have yet to
internalize RESTful architecture and b) most web application frameworks
are exceedingly bad at content negotiation. As a practical matter it is
probably not as bad as I make it sound, but it just so dumb that it can
hardly be borne.
to ever exist. It should not, under any circumstances, be encouraged.
In almost all cases, a feed is just another representation of the blog.
Therefore, the HTML and feed versions of the blog should have the same URI. It is rare, today, to find a blog in which then HTML, RSS and Atom representations share the same URIEven
my blog has a separate URI for each representation. This has bugged me
for a long time but I have yet to find the time to fix it.
but that does not mean that we should give in. New system, like reading
lists, should strive to be better than the systems that came before. We
can start by not muddling our documents with the bad design decisions
of the past, especially when there is an easy alternative.
Reading lists should point at the resource of interest,
namely main human readable page of the blog. Aggregators can, and
should, deal with blog software that does not handle content
negotiation correctly by requesting the resource with an accept header
that looks like application/atom+xml;q=1, application/rss+xml;q=0.9, text/xhtml+xml;q=0.2, text/html;q=0.1.
If an html document is returned the aggregator should use the
“auto-discovery” kludge to work around that particular blogging
software’s damage. Someday the world will be RESTful and we don’t need
a bunch of broken interchange formats, like reading lists that point as
ugly feed URIs, holding us back.
03 Feb 2006
•
Software Development
REXML could not parse this XML/HTML:
<i>Update: Due to a misconfiguration some of my blog entries from the
month of Feburary recently lost. This is merely a repost of the
original content.<i>
At the [Ruby User Groups meeting][] the other day someone asked me
what things I did not like about Ruby and Rails. At the time I did not
have any really good answers, which bothered me because that is an
important question. No technology is perfect and honest critiques are
a vitally important way to improve the state of the art. In that
spirit this is the first in a series to relate some issues I have with
Rails (and fixes when possible).
When everything works Rails is absolutely brilliant. However, it when
things do not go well it often yields ambiguous, vague or misleading
error messages. I have noticed this several time but today it was
driven home once again. Error messages might seem like a little thing
but a single bad error message can send a developer off in the wrong
direction wasting hours (or at least tens of minutes ).
For example, earlier today I was investigating moving our database
schema management onto ActiveRecord::Migration.[^migrations-good] I
found Jamis'; [Getting Started With ActiveRecord Migrations][] article,
which is excellent. I followed all the steps but when I ran the
migrate rake task I got the following instead of the correct schema.
pwilliams@xps:~/projects/ramps$ rake migrate
(in /home/pwilliams/projects/ramps)
rake aborted!
MysqlError: Table ';ramps_development.schema_info'; doesn';t exist: SELECT version FROM schema_info
My first thought was that I needed create the schema_info table that
the SQL above references. However, while looking for the shape that
table I find that the [ActiveRecord:Migration API documentation][]
says it does not need to be create manually.
> To run migrations against the currently configured database, use
> rake migrate. This will update the database by running all of the
> pending migrations, creating the schema_info table if missing.
At that point I was totally confused, the documentation says this
table will be created for you if necessary but the code is *not
actually creating it*. After digging around in the
code[^reading-rails-is-complicated] a little I finally
figured that the problem was the table create code was eating the real
error message. The code that creates the schema_info table looks like
this</p>
# Should not be called normally, but this operation is non-destructive.
# The migrations module handles this automatically.
def initialize_schema_information
begin
execute "CREATE TABLE #{ActiveRecord::Migrator.schema_info_table_name} (version #{type_to_sql(:integer)})"
execute "INSERT INTO #{ActiveRecord::Migrator.schema_info_table_name} (version) VALUES(0)"
rescue ActiveRecord::StatementInvalid
# Schema has been intialized
end
end
That code just tries to create the needed table. It catches any failures while executing the table creation and eats the error under the assumption that a failure to create the table means the table already exists. And therein lies the problem. I had not granted the user specified in my database.yml rights to added tables. The rails user did not need this privilege before because I was loading sql files as myself not as the rails user. It is appropriate that ActiveRecord::Migration failed, it cannot add tables if the RDBMS does not allow it to, but that error message is totally unacceptable. If the actual problem had be reported it would have taken be about 30 seconds to fix it, rather than 30 minutes.
In the spirit of improving this problem here is a patch that make ActiveRecord::ConnectionAdapters::SchemaStatements#initialize_schema_information return a better error message in this case, and possibly others. As it turns out it was actually quite easy to improve this error message. Rather than rescuing the attempt to create the table from all failures. Try to select from the tables first, if that fails then attempt to create the table but let any failure be raise up so that the user sees them. Here is a file that when added to RAILS-PROJECT-DIR/lib/tasks does the trick. Below are the entire contents of that file.
module ActiveRecord
module ConnectionAdapters
module SchemaStatements
# Creates the schema_info table in preparation for using
# ActiveRecord::Migration. Obviously, this should not be
# called normally, but this operation is non-destructive.
# The migrations module handles this automatically.
def initialize_schema_information
begin
execute "SELECT COUNT(*) from #{ActiveRecord::Migrator.schema_info_table_name}"
rescue ActiveRecord::StatementInvalid
execute "CREATE TABLE #{ActiveRecord::Migrator.schema_info_table_name} (version #{type_to_sql(:integer)})"
execute "INSERT INTO #{ActiveRecord::Migrator.schema_info_table_name} (version) VALUES(0)"
end
end
end
end
end
I tried implementing that as a plugin but apparently plugins do not get loaded when executing the migrate rake task. That makes sense since plugins are really a Rails thing and not a Active record thing. Implementing it as a rake file meant that it gets loaded automagically before the migrate task is actually executed so the code changes are in place a the appropriate time.
This is yet another example of the power of open classes. The ability to fix bugs in the framework and libraries without having to physically patch the shipped source code of the framework or library is priceless.