With the guidance of Subversion developer Daniel Rall, I managed to fix Issue 660: ra_dav should have some support for redirects. I complained about the issue when I moved my Subversion repositories to a new domain.
I know it's not a major work or anything, but I enjoy improving user interfaces where possible. Even command-line interfaces. Contributing to open source projects also makes me happy. :)
Tonight an interesting bug cropped up in the development version of Podbop, where it was basically getting confused and finding the wrong city. I'll spare you the ugly details.
The thing is, I would never have discovered this issue had I:
It took me a while of staring at the generated SQL to understand the bug. When a table has two or more unique constraints which share at least one column, the WHERE clause ends up looking like:
WHERE ( … first unique constraint … ) OR ( … half of the other unique constraint … )
This gives us a pretty good chance of returning the wrong row. Whoops.
I can hear the programmers saying, "Sounds like a lack of test coverage in DBIx::Class…" Well, yeah.
What amazes me is that it hadn't cropped up in at least one application out there. I know people are testing the development releases of DBIx::Class, but I guess no one had more than one unique constraint on their tables.
Well, it's code I contributed, so I better fix it. :-)
I'm going hunting
While debugging some Unicode issues on Podbop:
[Sat Apr 29 14:46:29 2006] [catalyst] [debug] No cities found; searching EVDB for location [☠]
[Sat Apr 29 14:46:40 2006] [catalyst] [debug] Redirecting to "http://fortuna:3000/cities/us/mo/st_louis"
Um, heh? I've never been to St. Louis, so I'm not commenting on the city or anything. Just thought it was an amusing result. Now to figure out why…
So Amy Hoy has some thoughts about surviving a Digging. She's quick to dismiss Apache in favor of lighttpd, which honestly surprises me.
Podbop served 10,502 page views on February 23 according to Google Analytics, when it was near the top of del.icio.us/popular. Amy received 152% more page views (16,010) according to Mint. (I'm going to ignore her Webalizer numbers because Mint and Google Analytics have quite similar profiles: they are both invoked via JavaScript.)
To compare, Podbop runs as three FastCGI listeners under Apache 2.0.55 on a Linode 160, which has 160 MB of RAM and a guaranteed CPU speed of 200 MHz. Amy says that her Typo instance runs under Apache on a dual PIII. Without knowing more about Amy's setup, it's hard to draw any real conclusions here.
Still, I don't think Apache is to blame here. Podbop didn't have any caching on February 23, and while it certainly broke a sweat, it was not in danger of being replaced by static content. :-)
My guess is that Amy's FastCGI setup isn't tuned very well, or she's got a lot of other stuff happening on that server. Don't forget, Mint runs at least one MySQL INSERT per page view in addition to the cost of the PHP.
So Amy, if you see this, please run benchmarks at each step of the tuning process. I'd be really interested to see if switching from Apache to lighttpd (with no other changes) makes a huge difference.
After getting upset about the Gentoo Forums post, I moved on with my work … the whole reason I created the ebuilds in the first place.
But due to recent traffic on the Catalyst mailing list, I've revisited the "make Catalyst easy to install" issue. You can now find all of Task-Catalyst in my perl-catalyst overlay.
My overlay has at least one distinct advantage over the tarballs being passed around in the forums: it's in Subversion. Getting updates is much simpler than downloading a new tarball, unpacking it, etc.
First, checkout the overlay to your Portage overlays directory:
mkdir -p /usr/local/overlays
cd /usr/local/overlays
svn checkout http://svn.danieltwc.com/overlays/perl-catalyst/trunk perl-catalyst
Then add the overlay to PORTDIR_OVERLAY in your /etc/make.conf file.
PORTDIR_OVERLAY="/usr/local/overlays/perl-catalyst [...]"
Some of the ebuilds in Portage are not stable yet, so add the following to /etc/portage/package.keywords:
dev-perl/MIME-Types ~x86
dev-perl/Tree-Simple ~x86
dev-perl/DBD-SQLite ~x86
dev-perl/PAR-Dist ~x86 # Only with USE="par"
Finally, install the package:
emerge -av Task-Catalyst
Periodically you'll want to fetch updated packages:
svn update /usr/local/overlays/perl-catalyst
Gentoo users may note that I've duplicated a couple of ebuilds that exist in the Gentoo tree. One is dev-perl/libwww-perl - the version bump is needed for changes to HTTP::Response that HTTP::Request::AsCGI depends on. The other is a version bump to dev-perl/yaml, which is needed for Catalyst 5.64.
The whole process may become easier in the future - Allen and I are tossing around the idea of a CPANPLUS::Dist::Ebuild. Ideally we'd be able to improve on g-cpan. Stay tuned.
[18:00:55] <omega> I dont really fear ror, its not really competition
[18:01:07] <omega> its like duplo vs technic lego :p
Yesterday I sent a patch to the author of Net::Delicious to escape CGI query arguments. Currently links which contain an ampersand are truncated, which means I have to fix by hand some links from IRC sent by deliciousurl.pl. Haven't heard back from ASCOPE yet, so I dunno.
Today I wrote some documentation and updated one of my WordPress plugins.
WordPress 2.0 seems pretty awesome. They seem to have abstracted away a lot of stuff that was previously annoying to implement in plugins. It's a shame I wrote about 4000 lines of plugin code for our sites before that happened. :-/
Writing PHP is painful, even with the better API in WordPress 2.0. What I wouldn't give to have a production environment with Catalyst, DBIx::Class, and PostgreSQL…
Since when did Tomcat require like 20 other packages?
aurelia root # emerge -av tomcat
These are the packages that I would merge, in order:
Calculating dependencies ...done!
[ebuild N ] dev-java/commons-daemon-1.0 -doc -jikes 214 kB
[ebuild N ] dev-java/commons-pool-1.2 -doc -jikes +junit 263 kB
[ebuild NS ] dev-java/servletapi-2.4-r1 -doc -jikes 3,560 kB
[ebuild N F ] dev-java/jmx-1.2.1 -doc -jikes 2,126 kB
[ebuild N ] dev-java/commons-digester-1.6 -doc -jikes +junit 245 kB
[ebuild N ] dev-java/commons-modeler-1.1 -doc -jikes 90 kB
[ebuild N ] dev-java/commons-httpclient-2.0-r1 -doc -jikes 1,393 kB
[ebuild N ] dev-java/commons-fileupload-1.0 -doc -jikes 29 kB
[ebuild N F ] dev-java/sun-jaf-bin-1.0.2 -doc 348 kB
[ebuild N ] dev-java/commons-launcher-0.9 -doc -jikes 40 kB
[ebuild U ] dev-java/commons-beanutils-1.7.0 [1.6.1-r1] -doc -jikes +junit 252 kB
[ebuild N ] dev-java/commons-dbcp-1.2.1 -doc -jikes 565 kB
[ebuild N ] dev-java/commons-el-1.0 -jikes -source 62 kB
[ebuild N ] dev-java/saxpath-1.0 -doc +junit 2,115 kB
[ebuild N ] dev-java/commons-validator-1.0.2-r4 -doc -examples -jikes -source 52 kB
[ebuild N ] dev-java/commons-lang-2.0-r1 -doc -jikes -source 430 kB
[ebuild N ] dev-java/struts-legacy-1.0-r1 -doc -jikes 12 kB
[ebuild N ] dev-java/struts-1.1-r2 -doc -jikes 9,711 kB
[ebuild N ] dev-java/dom4j-1.4-r1 -doc 11,816 kB
[ebuild N ] dev-java/jdom-1.0_beta9-r1 -doc -jikes 3,337 kB
[ebuild N ] dev-java/jaxen-1.0 -doc +junit 3,120 kB
[ebuild U ] www-servers/tomcat-5.0.28-r2 [5.0.27-r5] -doc -examples -jikes 3,482 kB
Total size of downloads: 43,270 kB
Do you want me to merge these packages? [Yes/No]
Erik Benson has an interesting implementation of something I've had on my mind for a while, but never got around to doing: a morale graph. I really like how caffeine, alcohol, and sleep are tracked.
I've always wanted to associate my listening habits with my mood. Maybe someday.
I'm doing some research at work today. I've started by trying to get a feel for what the Apache Jakarta Project has available in the space.
The Jakarta Project seems to have a hard time describing their products without resorting to marketing language and buzzwords. Take, for example, HiveMind:
HiveMind is a services and configuration microkernel:
- Services: HiveMind services are POJOs (Plain Old Java Objects) that can be easily accessed and combined. Each service defines a Java interface it implements. HiveMind takes care of instantiating and configuring each service just as necessary. HiveMind lets services collaborate with each other via dependency injection.
[...]
Much of the terminology is so generic that the projects blend together in my mind. There are too many frameworks, too many general-purpose engines. If you want developers to use your products, you must provide specific information on them. "A general-purpose blah blah blah XML blah blah blah framework" is NOT helpful.
I apologize for picking on the Jakarta Project and its products (I'm NOT picking on its members; please don't take this personally), but this is VERY frustrating. I'm sure there's a lot of great technology available from the Jakarta Project, but I sure can't find it.
Seven Low-Cost Ways to Improve Legacy Code - I agree with basically everything he says.
I was reading C, Objective-C, C++... D! Future Or failure? this morning, and was surprised to see a comment that completely missed the point of exceptions and their benefits over other forms of error handling. I replied, arguing in favor of exceptions. Some people agreed with me, while others completely missed the point. Again.
(The rest of this discussion is heavily based in Java since it is arguably my primary language, but it applies to any language with (checked) exceptions for error handling.)
My main argument is that exceptions, when used properly, provide a much cleaner and more expressive way to handle problems than other forms of error handling, such as function return values. Proper error handling with checked exceptions isn't really that difficult:
return -1 or return 0 should not appear in languages with exceptions. Consistency is much more difficult to achieve, and there is no telling what a specific return value means.catch blocks. I've seen entirely too much code that looks like:
try {
// ...
}
catch (Exception e) {}
This can lead to some very annoying bugs, as your code has a decent chance of breaking with no explanation. If you don't know what exceptions might be thrown by a call you make, defer your decision on how to handle it until you compile or use an editor that tells you what exceptions are thrown (IntelliJ IDEA comes to mind, though there are many others).
System.exit(1)). This is perhaps the most important rule to follow when using exceptions.finally blocks, if appropriate. For example:
Connection conn = null;
try {
// Open connection, possibly get an exception
}
finally {
if (conn != null) {
try {
conn.close();
}
catch (SQLException ex) {
}
}
}
This is the only case I've come up with that breaks the Obviously, these "rules" are just suggestions. They don't apply in every case, and there are times when you might need to adopt different practices.
One final point: When programming in Java, I sometimes feel exceptions are being forced down my throat, whether I like it or not. Some people feel that checked exceptions are a little too much. Since I haven't worked in a language with exceptions that are not checked, I'm curious as to how well this works out.
Update: Fixed a minor mistake in the fifth rule.
Whenever I work on group projects in computer (science|engineering) classes, I always debate whether to ask my fellow developers to use CVS.
Ever since I started using CVS at work, I've realized that I can't program without it. It's useful for almost any work I do on my computer - including digital design labs, numerical analysis homework, and so on. I haven't put my entire life in CVS, but I'm close. (If I were to consider putting my home directory in CVS, I would first consider moving to Subversion.)
On group projects, I weigh the advantages and disadvantages of asking fellow students to use CVS. If I see a lot of code sharing happening, or it's a large group, I try to push for it - as long as it's understood that no one commits broken code. All of the logistical headaches of group development go away - there's no sending files back and forth over email and no confusion over which version we're all working from. Just a simple cvs up, and I have everyone's latest code.
The problem comes in introducing new users to version control in general and specifically to CVS. It was admittedly difficult at first, but I quickly became comfortable with the common commands. I try to give examples of how CVS will save your ass, and how it makes collaboration easier. Sometimes people welcome the idea, while other times I just get blank stares.
Asking others to use CVS also leads me to consider other students' build "process". Too many of my peers are accustomed to typing javac *.java, followed by java MyClass to compile and run their code. While not strictly necessary, build tools such as Ant and make greatly speed up development.
To prepare students for industry this situation absolutely needs to be improved. Training in standard version control and build utilities should happen at the undergraduate level, before we are on the job. Version control is mentioned in passing in our software engineering course, as are build tools, but I don't recall the instructor mentioning them more than once.
Using these tools does not require students to switch platforms, with the availability of great CVS frontends like TortoiseCVS (and TortoiseSVN for Subversion) and WinCVS. The difficulty comes in establishing a CVS repository for students, since that is not a "common" task when using CVS. It's also not all that easy to set up a repository on Windows, and not everyone has an always-on connection that allows them to host a repository.
Nathan and I discussed the idea of a department-wide (or university-wide) repository at one point. We decided that using CVS would probably be a bad idea due to its reliance on filesystem permissions (managing users and groups would be difficult) and its ignorance of binary files. Ideally, this repository would use GatorLink authentication, and would (automatically?) handle students who are part of a specific class and group. In other words, a specific repository would only allow access to GatorLink IDs of members in my group of CEN 4500C for Spring 2004. Turning in a project would be simple for the professor or TAs: just cvs tag everyone's files at the exact time it's due. Then, checkout based on that tag when grading.
There are obviously some issues with setting up a department- or university-wide repository. The main one is computing resources - mostly disk, but CPU and memory also need to be considered. Another is authentication - GatorLink is backed by LDAP, I believe, so plugging that in hopefully wouldn't be too difficult. Associating GatorLink IDs with courses and teams within a course is probably the one area that hasn't been dealt with at UF, though getting a list of GatorLink IDs registered for a course is apparently pretty standard. A little bit of glue code, and this shouldn't be too difficult.
Using version control, in my opinion, should not be optional at this level. We are supposedly professionals, and all the professionals use version control in one form or another. Many of our professors have been in industry before teaching - surely they collaborated with their peers.
I've been reading Planet Debian recently, which aggregates the blogs of various Debian developers. I'm particularly interested in a thread on scripting languages, which started with Colin Walters' post, "Arch Server and Python". Further posts include: Joey Hess' "If you don't grok it, don't bash it.", Scott James Remnant's "Perl vs. Python -- The Debate Continues", and Walters' "I guess I should have expected a response...".
Success! Using Fink's GLUI package as a starting point, I was able to get GLUI installed and running on Panther. I made a few modifications to the Makefile, and patched up the examples to make them build properly. After a quick fink rebuild glui, I had the library installed.
This was all in hopes of doing my graphics projects on Linux or Mac OS X without worrying too much about platform issues. (Windows also falls somewhere in the mix, since we are essentially required to turn in a Visual Studio solution for each project. Grr.)
After some rethinking of my project's Makefile (based almost entirely on the examples in the GLUI Makefile), I was able to get it to compile, but not to run. I was getting an error about my X11 visual:
GLUT: Fatal Error in project1: visual with necessary capabilities not found.
Comparing the project code to a GLUI example, I tracked it down to the following function:
glutInitDisplayString("rgb double");
Changing this to:
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
made everything work!
I've pretty much forced myself into getting very comfortable with C and C++ this semester by taking two classes that require it (CAP 4730 and CEN 4500C) and another that will probably use it (CIS 4914). That's why I find this fake interview with Bjarne Stroustrup a little worrisome.
The all-important virtual space settings of IntelliJ IDEA have given me the text editing functionality I desire. Most importantly, no more "I'm stuck on column 0" issue. Make sure to unset "Allow to place caret after end of line".
Damn you:
Virtual Host or Web Application Not Found
The web group xyz.xyz.com has not been defined
IBM WebSphere Application Server
Here's an interesting article entitled Language Fermentation about strongly and dynamically typed languages.
From New Language Features for Ease of Development in the Java 2 Platform, Standard Edition 1.5: A Conversation with Joshua Bloch, the current version of iterating over a collection:
void cancelAll(Collection c) {
for (Iterator i = c.iterator(); i.hasNext(); ) {
TimerTask tt = (TimerTask) i.next();
tt.cancel();
}
}
The improved version of iterating over a collection, using generics and "enhanced for":
void cancelAll(Collection<TimerTask> c) {
for (TimerTask task : c) {
task.cancel();
}
}
And Bloch's comment: "I think this is really pretty!"
*bzzt* Wrong! That's ugly. Let's try something else:
void cancelAll(Collection<TimerTask> c) {
foreach (TimerTask task in c) {
task.cancel();
}
}
Sorry, but foreach is something C# got right. Bloch's comment that "[i]t might have been more natural to use two new keywords, foreach and in, but new keywords are destabilizing" is certainly valid, but I would be willing to break some code (there's only ~400 occurrences of in and zero occurrences of foreach in all of the Java 1.4 source from IBM) to have the more natural feel of foreach.
What about Perl's syntax?
void cancelAll(Collection<TimerTask> c) {
foreach TimerTask task (c) {
task.cancel();
}
}
That's not really much different than using the colon, and actually looks a bit worse because of the type. I guess I'm just bitter that I can't use foreach because they think that people really use it as an identifier.
Overall, I'm happy about these changes. I like Java for its consistency, and Sun seems to be adding a lot of features to improve the language while maintaining this. Cool.
I'm sure some will cringe at this, but I find the idea really interesting. I really liked the following quote:
I'm thinking about things like simplicity -- how easy is it going to be for someone to look at it later? How well is it fulfilling the overall design that I have in mind? How well does it fit into the architecture? If I were writing a very long poem with many parts, I would be thinking, "Okay, how does this piece fit in with the other pieces? How is it part of the bigger picture?" When coding, I'm doing similar things, and if you look at the source code of extremely talented programmers, there's beauty in it. There's a lot of attention to compression, using the underlying programming language in a way that's easy to penetrate. Yes, writing code and writing poetry are similar.
I'm trying to learn .NET. I almost wish I didn't have previous experience with Web programming, since .NET seems totally different. I'm also trying to use my knowledge of JSP in .NET, but that's not working too well yet. I'm trying to keep the mantra ".NET is like GUI programming for the Web" in my mind for now; I don't know yet if it's appropriate.
"Perl is Internet Yiddish", by Yoz Grahame, accurately describes why I like Perl.
"I'm not opposed to run-time solutions--I've used them often enough in the past. But I'd really like to avoid creating yet another layer of OO. There's only so much polymorphism that a language can put up with before it turns into Python." -- Larry Wall (Note: I'm not dissing Python; I just think it's an amusing quote.)
Intellectual property issues for programmers: 1 and 2