I've just uploaded the second "real" release of WebService-ISBNDB, version 0.20, to CPAN. I don't have the auto-post-to-use.perl.org thing working that I used to, because I don't use fetchmail anymore (I leave stuff on my IMAP store or save it to a Thunderbird folder). That means I never announced the first release, or the two previous releases that were named Net-ISBNDB. I changed the name after Adam Kennedy made a good argument for the WebService:: prefix.
This package is an object-oriented layer over the actual published API of isbndb.com. It presents all five elements (authors, books, categories, publishers and subjects) as classes. Elements that reference other elements (such as the authors, subjects and publisher of a book) are lazy-loaded when first requested through the accessor methods. You'll have to have an API key from them, which is free once you've registered. The catch is that the key is generally good for 500 requests per day, which most of you probably won't find to be an issue. It did become an issue for me, though, when writing the test suite that this release introduces (the first release had some basic tests, but no actual data tests). I quickly ran up 500 requests in less than two hours the other day. As part of addressing this problem, I checked and found that my suite of tests was making 58 requests per complete run. I had created a key that I was going to use for CPAN build/install runs, but it was clear that the key wouldn't work very well; more than eight people installing in a given 24-hour period would tap it out.
Solving the problem actually proved the robustness of the base communication class, WebService::ISBNDB::Agent (points to the version from the previous release). I was able to create a dummy adapter, overload just one method, and BAM! it would read the XML from local files in the test-suite directory. Even better, I was able to make a run of the suites that actually read from the service, and save all the requests to files, by having the dummy adapter go ahead and call the super-class method and write the data to the filename it would have otherwise read. I then restored the method to the read-data approach, and my hits on the service dropped from 58 to 0.
This was also my first foray into using Class::Std. As someone who worries (too much) about people sub-classing my classes and stepping on my keys, this is an interesting approach. I had some weird issues to work around, though. The framework is meant for you to not have to (ever) write your own new(). So if you do, you have the issues. I had assumed that I could just use Class::Std as my class' base, and it works, but it doesn't seem to be intended for that purpose, at least not on the surface. And in my case, I wanted to provide some syntactic sugar for object creation (i.e., if you are instantiating an object from a known-to-be unique value, you should be able to do so with minimal typing; something like "$book = WebService::ISBNDB::API::Books->new($isbn)"). To make the sugar work, I had to allow new() to take something other than a single hash-ref. And to do that, I had to provide my own. When I did, I got warnings about redefining it, since Class::Std generates one when you use it. I'm not sure how I'd recommend getting around this... I suppose Class::Std could check that you both have an existing new() and have Class::Std in your inheritance hierarchy.
The other issue I had to struggle with is that I'm currently very busy with paying work right now. And every hour I squirreled away for this felt like I was stealing it from "more important" work. The amount of change this release delivers kind of defies the ten days or so since the last release. I could have done all of this in a day (maybe two if it was the weekend and I had other distractions). But I've been sick all of this past week, and I've felt kind of bad each time I worked on this instead of the other. Obviously not too bad, I guess, or I wouldn't be releasing a new version.
This is also the first NEW module I've come up with in what feels like ages, so I'm pretty happy with myself to have broken out of my rut. Now if you don't mind, I have some more hacking (of the phlegmy-lung-variety) and wheezing to attend to.