One of my former co-workers recently sent me Joey deVilla’s article about netbooks and the “zone of suck.” This article makes a good case for why netbooks–those wee computers that are smaller than a breadbox but larger than a McDonald’s apple “pie”–are in a middle zone that is a solution looking for a problem. They’re more portable than a laptop, but less portable than a smart phone; they’re more powerful than a smart phone, but puny compared even to a low-end laptop. In other words, why bother?

And if we’re putting the average netbook (like my Dell mini) up against laptops and smart phones, I think that argument is dead on. But that’s not a game, I would argue, that the netbook should be playing; let the laptop be the portable power platform, and the smart phone be the ubiquitous pocket rocket. For me, the netbook has the potential to be a Kindle-killer.

I’m not a great partisan of the e-book; 16th century technology is fine, thank you, for most of my reading needs, at least when it comes to reading for pleasure. But I can see the value of the e-book in some situations:

  • Out-of-print, public-domain books available through sources like Project Gutenberg
  • “Long tail” books that have a small niche appeal that makes print publication prohibitively expensive
  • “Soft” books with volatile content, like technical manuals or current affairs studies
  • “Disposable” books–”beach reads”–that leave only lingering traces in the reader, and so should leave fewer on the shelves

I could also imagine loading up a thumb drive with vacation reading before a trip. My usual modus operandi is to pack a few books for the road, but inevitably it turns out that one or more of the books I’ve brought along isn’t worth carrying, and I often run out of material at the end of the trip and am at the mercy of the airport newsstand (the horror! If I’ve missed The New Yorker or The Atlantic summer fiction special, I have to choose between The Economist and People).

Most netbooks have pre-installed, or can very easily run, an e-book program capable of reading most standard file formats. FBReader, for example, comes with the Ubuntu Netbook Remix, which in addition to reading things like plucker and orb files, also has the handy feature of letting you turn the display 90 degrees so you can read the screen like a page.

At $359, Amazon’s Kindle is a price-point match for the netbook as an e-book reader. And with its slim profile, “electronic ink” interface, and cool-kid factor, the Kindle tromps the netbook as a dedicated e-reader. But the netbook has a few advantages over the Kindle:

  • You don’t have to pay Amazon to subscribe to blogs or read the news.
  • You can do more than read e-books on it. Though the keyboard is cramped, you can do some light typing (like this blog post), work with web applications, and read your e-mail.
  • You’re not bound by the Amazon monoculture. Let it not be forgotten, the Kindle and the DRM-laden format it supports are proprietary creatures of Amazon; the formats supported by e-reader software are open and accessible to any publishing and distribution service.

There are a couple of things that would greatly improve the netbook’s utility in the e-reader space: improvements in design, and improvements in ecology.

The design of most netbooks, for example, is derived from their laptop progenitors; the result is a screen and keyboard that are very much in the “zone of suck,” simply too small to be all they could be without sacrificing portability. As an e-reader device, the screen should be bigger, and the keyboard somehow less obtrusive (folding against the back of the screen for easier handheld reading? sliding out from the screen? virtually popping up on screen?). Clever people, no doubt, are working this out.

To really play against the Kindle, though, netbooks would need to have an infrastructure to support them as an e-book platform. The Kindle, of course, has Amazon, which relentlessly leverages its search and delivery system to make buying and downloading e-books seamless. For the open platform e-book reader, things are much looser: Gutenberg and other services, a few publishers like O’Reilly, and some public libraries make e-book acquisition easy enough, but highly decentralized. What the e-book environment really needs, if it’s going to be a viable platform outside Amazon’s control, is a clearinghouse (or competing clearinghouses) of titles, covering a broad range of topics and easily searched and browsed. No doubt some nascent clearinghouse or consortium (I can’t help but think of the IndieBound model for bookshops) is out there already, just waiting to rise out of the digital morass.

Tags: , , , , , ,

I’ve received some great feedback from people who have tried BookLinker (big thanks to Jane, Tempest, and Althea!), and I’ve made a few changes and fixes. These are available in the version of the plugin on this site; tomorrow I’ll finalize testing and get them into the WordPress.org plugin repository for wider release.

The fixes and changes are:

  1. Fixed a problem generating the native (rel=’BookLinker’) links; these now work as advertised.
  2. Added a switch to let you turn the book cover in the popup on or off; when installed/activated, the switch is on by default, but if you’re upgrading in place you’ll have to turn the switch on in the BookLinker settings, or deactivate/reactivate the plugin.
  3. Added options for additional styling on the book title and author text in the popup; you can enter your own CSS here, and it will override the CSS in the plugin files. (This would be the preferred approach over changing the CSS in booklinker.css directly, so as to maintain forward compatibility.)

I have another issue I’m trying to work out which affects some themes and not others. It appears to be related to CSS positioning: if a theme uses a lot of position:absolute styles, odd things can happen in spacing and location of elements, particularly sidebar elements. The two elements that make up the BookLinker HTML–the shield and bookLinkerCollection DIVs–are absolutely-positioned to do the nifty modal window thing; I’m looking into alternatives and workarounds for those situations where adding these elements causes other things to break.

As always, thanks very much people who’ve tried it out (75 downloads to date from the Plugin Directory); feedback, especially of the bug-and-feature kind, is greatly appreciated!

I’ve added the BookLinker plugin to the WordPress.org Plugin Repository, and submitted it to a couple of other plugin directories as well. (If any WordPress veterans know any good places to publicize plugins, do let me know!)

The WordPress repository provides a Subversion project for the plugin source, which is a nice feature; it also builds the download file for the user and unpacks the readme.txt into a nice web page, and helps people keep up to date with the latest versions. I’ll be keeping both the WordPress.org site and this one current with the latest plugin releases.

I’ve heard of a couple of theme-related issues, which I’m tracking down; if you gave BookLinker a try before today (May 26, 2009), please download the latest version from WordPress or this site (link here), as there have been some changes. WordPress.org should help keep fixes distributed to users. And I have a couple ideas for new features and spinoff projects; if you’ve got a clever idea for this plugin, or if you’re using it in an interesting way, I’d love to know about it!

Tags: , ,

The Open Library JSON API includes an image URL in the book details. The images are lower resolution than the LibraryThing images, but a low-res image is better than none. So in cases where the book’s image is not available from LibraryThing, the BookLinker plugin will use the Open Library image if one is available.

You’re still required to supply a LibraryThing API key if you want the high-res images; but if you don’t supply the API key, you’ll still get a book cover if one is available from Open Library. The “No Image” placeholder will show only if Open Library can’t supply one.

The latency in the Open Library service is significantly higher than the LibraryThing latency; this could be due to how I’m parsing the JSON, or it could be on the service side. So there may some delay in getting the author, title, and book cover to appear in the popup (no more than a couple seconds).

That, and a little tweak to the CSS for displaying the title and author, and I’m calling it ready for testing. You can get the plugin here if you want to try it out in your own WordPress site; otherwise, it should be available in the main WordPress plugin repositories some time next week.

Let me know what you think of this plugin; leave enhancement requests and bug discoveries in the comments on the BookLinker posts or page, or drop me a line. If you have a bug to report, the more information you can provide the better: WordPress version (I’m using 2.7), browser version (so far, I’ve only tested in the current Firefox), operating system (currently working on Windows XP and Ubuntu Jaunty Jackalope), and original URL of the book link you’re using. Bugs are much more fun to squash if I can make them appear on my screen.

Tags: , , , , , ,

Just a couple more updates on the bookLinker WordPress plugin:

  1. Title and author information is now displayed in the popup. The plugin uses the Open Library API, which returns a nice JSON bundle of data. Note that the information is incomplete: not all books are cataloged, and not all cataloged books have title and author information. But it’s an open project, so if you have an interest in helping to make the data more comprehensive, you can visit the site to learn how.
  2. Open Library and GoodReads links are supported now. They can be turned on and off in the plugin settings, just like the other links (IndieBound, Powell’s, Amazon, LibraryThing, and WorldCat).
  3. You can specify your own colors for the popup background and text, and also for the shield layer that comes up between the popup and the main text.

No doubt there are other little adjustments that can make this plugin more useful without adding bloat; feel free to suggest changes or configurations you’d like to see. I plan on giving it a thorough test over the next couple days, both from the admin side and across major browsers, and then submit it to the main WordPress plugin repositories by early next week. Until then, feel free to download it from the BookLinker page and play around with it.

And now it’s time to go do some non-technical reading before bed.

Tags: , , , , , ,

I’ve made a couple of small adjustments to the BookLinker plugin I announced yesterday.

  1. The popup will now be placed according to the available window width. I found that if the link appears close to the right margin of the browser screen, the popup could drift off-screen. Now, the popup’s left position will be based on the position of the link and the window width; ideally, the popup will be positioned directly above the link, but it will shift left accordingly.
  2. LibraryThing has many book cover images available, but it doesn’t have them all. If a book cover is not available, an appropriately-size “No image available” image will be loaded instead. (I actually like the way I got this to work, by registering an onLoad event on the image; because there’s some latency in the request from LibraryThing, who will send an invisible 1×1 image when no cover is available, I don’t really know until the image loads if I got anything good. Registering an onError didn’t work, since something will always load, but in the onLoad I check the image width and then swap as appropriate.)

I would really like to add an AJAX call, probably to LibraryThing, to retrieve more information about the book and display the author and title. Not as elaborate as the LibraryThing widget (you can build your own here or see mine in the left sidebar here), but a little more than blank space. This is a little beyond my PHP skills this morning, though maybe I’ll have a solution by tonight.

Tags: , , , , , ,

I’ve just written my first major WordPress plugin, BookLinker. It was developed for another of my websites, which features quite a few book reviews; the philosophical reasoning behind it is here. But it was also an interesting little glimpse into the WordPress programming paradigm.

The plugin’s goal was to make it easy for me to switch Amazon affiliate links, or augment those links, with links to other book sources. It was prompted by the “#amazonfail” fiasco of a month ago, but the need for such a tool goes deeper than one incident. I want to encourage people to buy books from other places, like Powell’s or IndieBound, or to get them from their library, but the thought of changing all those Amazon links was daunting.

My original thought was to write something that would go into each blog post with an Amazon link and change it to an IndieBound or Powell’s link. But as I looked into the variety of link formats that Amazon provides, and the number of links on my sites, that seemed a more dangerous way to go: it would be difficult to back out a data change like that.

So my second thought was to make the changes on the client side, in JavaScript. This let me do most of the heavy lifting in a language that I’m at least familiar with, using PHP just for the plugin framework and configuration, and it also makes backing things out or tweaking the functionality a lot simpler than a data change would have been.

Consequently, there’s not a lot of PHP in this plugin. All I really had to learn was how to collect, save, and retrieve user configuration variables, and then emit those variables onto the page for the JavaScript piece to take over. And from what little I saw of PHP to accomplish this, I’m glad there wasn’t much; it reminded me of the bad old days of early JSP coding, when people would plug JDBC code and huge scriptlet blocks into their pages, tiered architecture be damned. I have a new respect for people who can take a scripting language with limited tooling and turn out a robust and powerful tool like WordPress.

I like the WordPress plugin architecture. It’s very easy to use the “hooks” and extend the functionality of the core system, which makes for a rich and varied ecosystem. This is certainly one of the best arguments for open architecture as well as for open source.

The thing I like most about this plugin is the UI. I was able to reuse some concepts from the last professional project I had, and build a nice little modal window to hold the collection of links.

You can see it in action here, with this link to Effective Java (2nd Edition) (Java Series); buy it from Amazon if you must, but you can’t blame me for limiting your choices.

Tags: , , , , ,

I’ve been using a Dell Mini netbook for about five months now, and I’ve been pretty happy with it. It’s lightweight and small, making it easy to tote to the library, park, or coffee shop. The battery life is very good (I get about five hours of typical use off the grid), and though the keyboard is small (and annoyingly laid out for a touch typist), I can easily plug in a cheap USB keyboard for those times when I need to do extended typing. When my desktop computer is commandeered for a round of Club Penguin or some hardcore Lego Digital Designer work, I can retreat to the porch and still get work done.

But lately I’ve been plagued by system stability issues. The wireless connection randomly conks out when I’m using Firefox, and the browser crashes regularly. I get weird JavaScript errors (preventing me from sending Facebook “Mafia Wars” energy packs to my wife, which has begun to affect my marriage…), and whenever I try to use the Ubuntu system updater I get strange failures. My Firefox has been out of date, and system upgrades have been difficult to perform. And I wasn’t really thrilled with the stripped-down Dell desktop view, which makes switching between applications or getting to the file manager more tedious than it needs to be.

So I decided that the time had come for a major upgrade: the Ubuntu Netbook Remix for 9.04 Jaunty Jackalope.

The upgrade process itself wasn’t difficult at all, particularly if you follow the instructions. I was burned in my initial attempt by trying to skip a step; don’t be like me …

I did steps 1 through 3 on a Windows XP desktop; you can accomplish the same results on a Mac or Linux machine (indeed, if you’re brave or have small fingers, you can do it on your netbook).

  1. Download the flash image IMG distribution
  2. Perform MD5 checksum (this is what I skipped, and it cost me an hour of aggravation when my initial download turned out to be corrupted)
  3. Use an image-writer tool to transfer the flash image to a USB device
  4. Boot up the netbook with the USB device installed, and hold down the “0″ key for boot options
  5. You can test drive the netbook remix (highly recommended) to verify that it will work with your hardware, running the OS off the USB device
  6. When you’re ready to install, reboot into the boot options and follow the prompts for basic configuration

Note that this will wipe your netbook clean; back up anything you want to save, including your e-mail client settings. (Evolution Mail, the default client, has a nice backup utility that will make a TAR of your mailboxes for easy re-installation.) I’d also recommend installing the Xmarks Firefox plugin and saving your bookmarks to the network: I’ve been using Xmarks (née Foxmarks) since getting the netbook as a way of sharing bookmarks with my desktop, but it’s also a great utility for backing up your browser bookmarks.

So far (albeit after just a morning’s work), Jaunty Jackalope is more stable than the original Dell version of 8.x, and I like the interface a lot better. The things I work with most are right up front on the desktop, and I can easily see what applications are running and switch between them without a lot of ALT+TAB toggling. Most important, though, I was able to send my wife a Mafia Wars energy pack, which I hope will keep me from being capped.

Tags: , , , , , , ,

Scout SaluteA SCOUT IS A FRIEND TO ALL, AND A BROTHER TO EVERY OTHER SCOUT, NO MATTER TO WHAT SOCIAL CLASS THE OTHER BELONGS. If a scout meets another scout, even though a stranger to him, he must speak to him, and help him in any way that he can, either to carry out the duty he is then doing, or by giving him food, or, as far as possible, anything that he may be in want of. A scout must never be a SNOB. A snob is one who looks down upon another because he is poorer, or who is poor and resents another because he is rich. A scout accepts the other man as he finds him, and makes the best of him — “Kim,” the boy scout, was called by the Indians “Little friend of all the world,” and that is the name which every scout should earn for himself.

I subscribe to the tenets of Java, to the gospel of write-once-run-everywhere (even though, like so many other gospels, this one has never been successfully implemented in the real world). I believe in the strong typing of objects,the early binding of classes, and the clear separation of application tiers, world without end, amen.

I also attend the church of open source software, with its mutable prayer books and receptivity to revelation in the latter days. I believe in web standards, in XML validation, and in the W3C. These are my fervently-held creed, the values that guide my every line of code, and I scoff at the infidels who would disagree.

Except, of course, when I have to work with those infidels, and when those infidels have really great ideas or services I’d like to leverage. In both enterprise and web development, there’s no true church to which everyone subscribes, no matter how hard architecture steering committees try to make it so. Like it or not, your Java code has to co-exist with COBOL and Perl, your PHP needs to be VBScript-aware, and if your .NET can work with LotusScript, so much the better. We live in a diverse technology ecosystem, and we had best be able to extend a hand or accept assistance from programming worlds that are bizarrely alien to our preferred approach.

Write code that can be leveraged across the enterprise, learn the lingua franca of your environment’s technology, and strive to “play nice” in the bigger sandbox.

Once upon a time, I wrote a web portal using Lotus Domino. It was pretty well self-contained, using Domino data sources and APIs with just a smattering of JavaScript. Because everything it did happened on Domino servers, it was fast and self-contained, easy for a Domino expert to maintain in the standard Lotus tool set. And, like so many things that belong to a single programming ecosystem, it was not especially scalable or flexible.

Opening up the portal to other environments was an arduous refactoring effort, but it paid off. With a clear separation of tiers–business logic in web services accessed via SOAP over HTTP, the presentation layer in modular portlets that relied on CSS and JavaScript, and agnostic container-managed data sources–I was able to swap out pieces and make adjustments to the application without breaking a lot of interconnected pieces. There was still some Domino in the mix for a long time–a web service that delivered e-mail information–but it was far less dependent on Domino, so when the decision to switch mail platforms came along the code-level work was minimal to maintain the functionality. Even better, the services that ran the portal could be accessed by other applications, offering reusability, one of programming’s holy grails.

When developing services that are going to be leveraged across platforms, in places you may not even imagine possible in the initial design, simplicity is the key to flexibility:

  • Receive and return primitives: sending objects over the wire in SOAP is both expensive and limiting. You can have a strong object model on the service side and on the client side, but in the communication layer, break things into integers and strings. Converting a .NET object into a Java object is tricky at best; complex types being passed between Java and ColdFusion or PHP is a recipe for disaster.
  • Use lightweight service transports: my original Domino portal used a lot of DIIOP, an IBM flavor of CORBA; it caused me grief to no end because it was so resource-intensive, more than a little buggy, and difficult to use outside the IBM environment. XML-RPC was a good, if clunky, middle step, allowing a LotusScript service to work easily with a Java client. SOAP (originally Axis, later XFire) was better; REST, with its reliance on the standard HTTP protocol model, would have been better yet. If you can expose your API as a set of URLs, you’ll find many more friends than if you require a lot of proprietary components.
  • Use XML (with a DTD) for sharable data: most modern programming languages can use XML easily; and even languages like COBOL and LotusScript can work with XML by brute-force text parsing. It’s the closest thing we have to Esperanto in the programming world, and a great tool for cross-platform communication. Even if you don’t think the data will be shared across platforms, using XML up front will save you a lot of work when the inevitable request for integration comes along.
  • There’s nothing wrong with text files: for simple document management and configuration settings, plain text (or properties/.ini files) are a great cross-platform solution. ASCII is supported on most platforms, and on those where it isn’t (I had to work with EBCDIC a few times on the z/OS platform with Domino), it’s usually possible to convert without too much pain. Even better than its accessibility to programming platforms is text’s accessibility to human eyes: a lot of troubleshooting can be done in vi or Notepad if an application’s data and configuration is in plain text.

I’m still a believer in the Java model, of course, and I like to see Java code used to do great things. But I’ve learned that a dose of ecumenicism is a useful tool for keeping the peace and making friends across the spectrum of technology confessions.

Tags: , , , , ,

Scout SaluteEvery Scout in the United States learns the legend of the “Unknown Scout.” In 1909, an American businessman, William Boyce, was lost in the fog in London (this was before the Clean Airs Act restricted the burning of coal, and London’s fogs were really more a noxious smog than a quaint low-lying cloud). A boy emerged from the fog and helped Boyce get back to his hotel. When Boyce offered a tip, the boy refused, explaining that he was a Scout and simply doing his daily Good Turn before disappearing back into the fog. Boyce was so impressed with the Scout ethic that he brought Baden-Powell’s “Scouting for Boys” back to the United States, thus launching the Scout movement in North America.

Like most good legends, this one has some holes in it. Apparently there wasn’t really a fog that day, and the boy just helped Boyce get across a busy street. A nascent Scouting culture already existed in the United States and Canada, founded by Dan Beard and Ernest Seaton, and in fact the Woodcraft Indians and Sons of Daniel Boone greatly inspired Baden-Powell; B-P’s version of Scouting would probably have made its way over the Atlantic without that helpful Scout. But like most good legends, it’s a useful one, and illustrative of the Scout spirit.

A SCOUT’S DUTY IS TO BE USEFUL AND TO HELP OTHERS. And he is to do his duty before anything else, even though he gives up his own pleasure, or comfort, or safety to do it. When in difficulty to know which of two things to do, he must ask himself, “Which is my duty?” that is, “Which is best for other people?”—and do that one. He must Be Prepared at any time to save life, or to help injured persons. And he must do a good turn to somebody every day.

Scouting for Boys, Robert Baden-Powell, 1908

Helpfulness involves offering up something that we have to someone who lacks it. In information technology, the thing that we have an abundance of is, of course, information. We have access to tons of data, and our daily bread is extracting, manipulating, and distributing that information in useful ways.

Simply providing information, though, isn’t helpful. Helpful information is specific, timely, and relevant. The Scout who helped Boyce (in the fog version of the legend) could have given a lot of information to the befuddled businessman. He could have told him that they were standing in the city of London, and that the fog was especially thick that day; a certain kind of Scout could also have told him the temperature and dew point, explained the effect of prevailing winds on the fog, and suggested that the composition of the fog was largely coal smoke and a North Sea low pressure system. All good, true information, but all horribly useless: the Scout would not have been helpful at all by giving those facts. Boyce needed task-specific information–how do I get to my hotel?–and that’s what the Scout provided.

As programmers, we need to be in the habit of providing the same kind of targeted information: to our managers, our business partners, and each other. A good place to start practicing that habit is in the code we generate:

Comment only what requires a comment, and strive for readability in your code.

We’ve all seen, and been guilty of, unhelpful comments in our code. An unhelpful comment isn’t necessarily a false comment; it’s just one that doesn’t aid in understanding the task the code is trying to accomplish. For example, a lengthy comment on the inner workings of SOAP and the implementation of a Jakarta HTTP client to negotiate an XML-RPC connection might be fascinating, but it has no place in the code itself. Tell me what you’re getting from that SOAP source, not how you’re getting it; if your code is clean, I can figure out how it works.

Commenting the obvious but skipping the difficult is another sign of unhelpful code. When I see source code where simple iterator loops and string parsing functions are heavily commented, but an obscure and obtuse method has no comments at all, I’m nervous; I suspect that the person who wrote (or copied and pasted) the code doesn’t really know how it works, either, and I start to wonder if those other comments hold water, either.

You can cut down your need for comments by writing readable code to begin with. One of the first places to start is with variable names. It’s all well and good to use throwaway names for purely instrumental variables–iterating over an integer called “i”, doing transient string manipulations on “s”. But if it’s going to persist for more than the scope of one method, or if it represents a business object, or especially if it’s going to be exposed in an API function someone else will use, then give it a real name. “Foo,” incidentally, is not a real name; nor is “bar” nor (as one of my Lotus Notes colleagues tended to name things) “chucky.” Since most modern IDEs offer type-ahead, and most modern languages don’t have onerous limits on variable name length, you can be verbose without wearing out your fingers.

I’m a fan of the much-maligned Hungarian notation system, at least in untyped, late-binding languages. It may be overkill in an IDE that lets you inspect an object’s type by hovering the mouse over it, or with tools that aggressively do type checking as you go, but in other cases–I’m thinking in particular of JavaScript, PHP, and LotusScript–encoding the object’s type into its variable name can save you grief down the road. Though one of the benefits of loosely-typed languages is that you can let things be a little slippery, it’s also one of the downfalls when developing in such a language across a team or over time; “strName” is a helpful hint, to your co-workers or to yourself in a week or two, what to expect of an object, so you don’t expect it to behave in a way that it can’t.

As one who has both developed and maintained a lot of code, I’ve learned to see myself like the Tralfamadorians in Slaughterhouse-Five: a four-dimensional being stretching off into the future. When I make my code clear and well-commented, I’m not only helping my teammates now, I’m helping the future me who will forget the nuances of the code almost as fast as it was compiled.

Tags: , , , ,

« Older entries