Managing your own skepticism is a major part of being a software developer. It’s important to be skeptical sometimes. It’s always tempting to spend all your time playing with new tools, frameworks, and technologies. But that’s not what you’re getting paid for, and you can only spend some much of your own time learning. On the other hand, being too skeptical can lead you to be inefficient and behind the times.
I’ve had a history of being very skeptical about technologies that I’ve later come to embrace. While this has inevitably lead to being made fun of by a coworker who’s been there to observe this trend, I’m confident that thinking critically about each new thing before accepting has been a good thing, and I’m sure that I’ve avoided countless wrong paths that I can’t even remember. To catalog my mistakes: I scoffed at XML, I constantly questioned unit testing, and I dismissed Ruby. I’m still skeptical about Ruby on Rails though.
I’ve also had a few successes. Though I’m certainly no visionary, I picked up on Hibernate, Spring, Maven 2, and EasyMock without going through a long period of doubt.
So, how do you know when to give a technology a try? Don’t say ‘experience’: experience is just a proxy term because you haven’t consciously figured out what your techniques are. Do you follow certain people you consider experts? I was certainly more willing to try Ruby after reading essays by Steve Yegge, but I’m still not looking to use Emacs. Do you prefer to take it slow, and wait for the bandwagon to get big enough before even looking at it? Are there times when you can’t skip ahead, because you first need to do things the hard way, to feel the pain that some new tool fixes?
Instead of working on the conversion of the blog to Webby, I spent much of the day playing with jQuery and JavaScript. A good portion was mostly wasted time attempting to make the loading of the syntax-highlighting scripts more dynamic. While this ultimately failed, it did get me to re-learn a lot of JavaScript and jQuery.
Rather than put that time completely to waste, I decided to prettify the archives section. Without JavaScript enabled, you get a linked list of links for each month of each year that I’ve published something. Now, with JavaScript, I transform that list of links into drop-downs for each year, where you can select the month within the year, and it will take you to the archive page for that month.
Now, for the code. First, on each blog page (via the template), I load my JavaScript file, and I load jQuery via Google AJAX Libraries API:
1
2
3
4
5
6
7
8
9
<script type="text/javascript" src="/js/main.js"></script>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('jquery', '1.3.2');
google.setOnLoadCallback(function() {
prettify_archives();
});
</script>
This runs prettify_archives
function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function prettify_archives() {
var years = [];
$("#archives > ul > li").each(function() {
var year = new RegExp(/\s(\d{4})/).exec($(this).text())[1];
if ($.inArray(year, years) == -1) {
years.push(year);
}
});
years.reverse();
var html = ['<h4 style="margin:0;">Archives</h4>'];
$(years).each(function() {
html.push('<select style="width: 11em;" ' +
'onchange="document.location.href=this.options[this.selectedIndex].value;">');
html.push('<option selected="selected">' + this + '</option>');
$("#archives > ul > li:contains('" + this + "') > a").each(function() {
html.push('<option value="' +
$(this).attr('href')
+ '">'
+ $(this).text()
+ '</option>');
});
html.push('</select><br />');
});
$('#archives > ul').replaceWith(html.join("\n"));
}
So, I stayed up way too late last night uploading version after version of this website. I updated the version of the syntax-highlighter I used on the one code sample I’ve posted. Nothing special there, but the fall-back when Javascript isn’t enabled is nicer, as it’s a pre-tag, instead of a text-area like before.
I fixed all the pages to have the extension .html instead of .shtml. The .shtml was leftover from when I used to use server-side-includes instead of a combination of Blogger templates & Webby layouts to handle common layout issues. Here’s the content of the .htaccess file I used to make sure old links are given a permanent (301) redirect to the new extension:
1
2
3
RewriteEngine On
RewriteBase /
RewriteRule ^(.*)\.shtml$ /$1.html [R=301,L]
During the process, I noticed that Blogger wasn’t producing an archive index page anymore. So I added archives to the sidebar for each blog. I made my css rules a bit more generic by making sidebar sections a class, instead of duplicating rules for different ids.
All of this took a bit longer than it should because any changes on the Blogger side required republishing the whole site (actually twice, once for the main blog, once for the politics blog). Whereas, for the non-blog content, I could run Webby locally, rsync it to my VirtualBox Ubuntu Server VM, and test it locally. So my next task is to figure out how to turn an export of this blog into Webby source files so that I can manage the whole process locally (and get my blog posts into version control as a bonus).
I have released EasyMock-PropertyUtils 1.1, and it’s available in the Maven repository or for download directly. If you have issues, post them at the Google Code site, or ask at the Google Group/Mailing List.
The main changes from 1.0 are:
propEq
I’ve released EasyMock-PropertyUtils 1.0, and it’s available in the Maven repository. If you have issues, post them at the Google Code site. If you use it, just post a comment here to let me know.
I’ve recently finished reading all of Steve Yegge’s blog-rants. The overarching theme is Steve searching for ways to do better at software development. For instance, Being the Averagest on why many programmers aren’t trying to get better, and Practicing Programming on how to get better for those who listened and decided they want to try. He also chronicles his search for a better programming language. I suggest reading all of the essays; hopefully they’ll inspire you to be a better programmer, and you can take advantage of the work “Stevey” has done to guide you down the path of improvement. Stevey wrote all these articles while working at Amazon; make sure to also check out his current blog now that he works at Google.
I’m looking for feedback on my XPath Replacement Maven Plugin. It’s barebones right now; please send me any ideas you have on how to make it better, or just let me know if you’re even interested in it. The goal of the plugin is to allow you to do configuration (similar to normal Ant/Maven filtering), but without requiring placeholders so that your source version has a valid value that let’s a developer get going straight from source.
I also updated the EasyMock Property Utilities site to include the example posted here on the blog.
Here’s the promised example of how to use my EasyMock-PropertyUtils library.
It’s a TestNG test class with two test methods. The first, testSayHelloTo()
uses the single-property matcher test. The second,
testSay()
uses the multiple-property matcher test by supplying a Map
of property names to property values. If you haven’t used EasyMock
before, this should also serve as an example of how EasyMock can allow you to unit test in isolation a method that interacts with another
class. Check out the EasyMock Documentation for more information.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package test;
import static com.stephenduncanjr.easymock.EasyMockPropertyUtils.propertiesEq;
import static com.stephenduncanjr.easymock.EasyMockPropertyUtils.propertyEq;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import java.util.HashMap;
import java.util.Map;
import org.testng.annotations.Test;
/**
* Test the Service class.
*/
public class ServiceTest
{
/**
* Test the sayHelloTo method.
*/
@Test
public void testSayHelloTo()
{
String address = "someone@example.com";
MessagingService messagingService = createMock(MessagingService.class);
messagingService.sendMessage(propertyEq(Message.class, "address", address));
replay(messagingService);
Service service = new Service();
service.setMessagingService(messagingService);
service.sayHelloTo(address);
verify(messagingService);
}
/**
* Test the say method.
*/
@Test
public void testSay()
{
String address = "someone@example.com";
String text = "some text";
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("address", address);
properties.put("message", text);
MessagingService messagingService = createMock(MessagingService.class);
messagingService.sendMessage(propertiesEq(Message.class, properties));
replay(messagingService);
Service service = new Service();
service.setMessagingService(messagingService);
service.say(address, text);
verify(messagingService);
}
}
I’ve created a new open-source project: EasyMock-PropertyUtils. Basically, this library allows you to use JavaBeans-style property matching for arguments when using EasyMock. I plan to add some end-user documentation and blog some more about both EasyMock and this project soon. This is being done separately from EasyMock because it’s use of non-refactoring safe strings doesn’t fit the philosophy of EasyMock. The project is quite small, and I have no idea what the interest-level will be, so I’m just hosting it alongside the rest of my personal projects on my Google Code Hosting site. Hopefully there isn’t something like this already out there that I missed.
I’ve created a project on Google Code Hosting. It’s really just a place for me to put code I’m playing with so that it’s version-controlled and accessible anywhere. Right now it has a simple command-line draw-the-high-card game that I’m using to try to learn Ruby.
While there may be valid reasons that Google Code Hosting isn’t good enough to really compete for hosting real open-source projects, for my needs nothing beats the no-barrier-to-entry factor here. If nothing else, it’s nice to have a proper SVN repository available to me for free.
The Abdera Apache Incubator project is now up and running. The project is to provide tools for The Atom Syndication Format and The Atom Publishing Protocol. Right now I’m mostly contributing by maintaining the Maven build configuration for the Java implementation. I hope to be able to do a little more later (especially once the World Cup is over…)
I’m convinced that there’s a lot of potential for uses of these two standards (well, soon-to-be-standard in the case of the publishing protocol), beyond blogs & aggregators. Having a good Java library for working with this stuff is going to enable a lot of applications, and save a lot of time and money for tools and products built on Atom. Open source projects succeed based on participation, so if you might need to use Atom, then please, come join in. It’s just getting started, so it’s a good time to get yourself familiar with the code and get your ideas into the mix.
I attempted to make a Maven 2 build for the proposed Abdera project. I’ve never made a patch before, so I attempted it by checking in the contents of the original tar into my local-file-system SVN repository, and then made my changes against that, and finally generated a patch using the Subclipse tools. In case that isn’t good enough, I’m also providing the resulting tar.
The most important thing to note is that when I switched it from Ant to Maven, one unit test now fails that passed before. The resulting XML that is supposed to be checked contains some unexpected spaces. This is probably due to some dependency version difference. The dependencies will need to be looked at and worked on; I just specified enough to get the projects to compile for the most part.
I did update the Ant build file, so that still works. The security and examples modules also build now in Maven (but I did not add them to
the Ant build). There’s plenty of stuff to be improved/changed. The test module should probably go away, and the tests should be moved into
the module that is being tested. The “bin” folders should go away. The .project
files should go away in my opinion (they are assumably
broken right now, as I didn’t update them).
I just found this bug today in EXO's portlet taglib implementation. I also hit the same problem when developing custom tags for the first time. So, I thought I'd discuss, and hope that people having problems might stumble across this post.
The hardest part is recognizing the problem. As a consumer of the taglib, I spent several hours trying to figure out the source of the problem by analyzing what my code was doing, and by trying to create a simple test case, and was nowhere close to solving the problem. Only when I looked at the source code (thank goodness for open-source software!) did I realize the source of the problem.
The symptoms of the problem are that the results of using the taglib appear to include attributes and nested parameters that you didn't specify. These mystery attributes are actually coming from another usage of the tag somewhere else (another page, another portlet, etc.).
The problem is the taglib specification allows for implementers, such as Tomcat, to pool instances of the tag. This means that if you use the same tag twice, with the same attributes, the same instance of the tag object will be used. The problem tends to come in when you have nested tags. Such as <portlet:param>
tags inside a <portlet:actionURL>
tag. The <portlet:actionURL>
tag object is reused. If the portlet:param
values are stored in a Map instance variable, then parameters from the first usage of the tag will still be around in the second instance of the tag, even if you're specifying different parameters.
The fix is easy. You need to reset any instance variables whose values may vary even when the outer tag's attributes are the same. In this case, the parameters Map needs to be emptied, or simple reset to be a new HashMap. Because you cannot guarantee that the doEndTag
method will be called (in the case of an exception occurring), you should play it safe, and reset your instance variables in the doStartTag
method.
I've decided to go with the Atom format for syndication of data in the web application I develop at work. Inside the content tags, I'm placing inline XHTML (not escaped). I then wanted to use an XSLT to show the feed more nicely in the browser. Simply using <xsl:copy-of select="atom:content">
worked for Internet Explorer, but not for Mozilla Firefox. It turns out it wasn't treating the content as XHTML, so I wrapped the content inside a div: <div xmlns="http://www.w3.org/1999/xhtml">
I was having a major problem with this, and was going to post here and ask for help. But in my attempts to document what I'd been searching for already, I found what I hope will prove to be the answer. I'll find out tomorrow if it helps. Feel free to take a shortcut to the technical details.
Background information found during my hunting that you may also find interesting:
I hate spending a whole day trouble-shooting something, only to find that the problem was something little and dumb.
In this case, I was trying to set up an Oracle connection in Tomcat 5.0 (using the ojdbc14.jar thin Oracle JDBC driver) as a DataSource for access via JNDI. As you can guess from all that, there's plenty of places for things to go wrong. The configuration for all this is stored in an XML file. I tried all sorts of things to fix this. Capitalization of the named parameters, the driver name, the factory name, everything.
What did the problem turn out to be? A $. The password for the account I was using to connect to the database conatined a dollar sign. I got the password changed to something not using a $ sign, and everything suddenly worked.
Now, for any smart people out there: is this an XML issue? Is $ a special character? Does it need escaping? (Already faced that issue with an ampersand that needed escaping). Or is it a Tomcat specific issue? I'm pretty sure it's not an Oracle specific issue, at it seems to break the MySQL driver too, plus the connection worked fine if made straight from Java code.
How important is it for an application to be consistent with the native Operating System? And exactly what does that mean?
This is brought on by work on a new default theme for Firefox, in a peripheral fashion. In a lot of the talk I read about User Interface design focuses on having the app be consistent with the OS's look and feel.
I think a lot of this started with Macs. Mac users are near-fanatical about how great the interface is on their OS. While a lot of it is eye candy, that doesn't make a very convincing argument. So the other facet they can trumpet is the consistency and intuitiveness of the interface. So, as great cross-platform applications come out that Mac users wished to use, they had to complain about the inconsistent look. How these apps just didn't fit in.
The phrase, however, is look and feel. It seems to me that only the "feel" needs to be consistent. The purpose is for user's to be able to use your application without any difficulty. But this isn't enough to make those Mac user's happy. But at least for those of us on Windows or Linux, we have a variety of apps that look quite different. Not even all Microsoft apps look like each other: how similar is Windows Media Player 9 to Internet Explorer 6?
In fact, of course, a unique look for an application is a major branding advantage. You want your application to be memorable and identifiable. Additionally, you want it to by stylish. It's not easy to accomplish that while trying to make your application "fit in" with the OS. Not to mention, what exactly does that mean? It seems in the case of the old Firefox theme, it meant copy the look of the default browser of that OS. Does it make sense to let your competitor define how your application should look?
So far, my conclusion is that most OS's (or desktop environments), such as Windows (which one? 95, 98, 2000, XP, Longhorn?), KDE, or Gnome, haven't yet achieved real consistency anyway, so over-worrying about "fitting-in" should not be the primary concern in UI design at the moment. What do you think?