http://qs1969.pair.com?node_id=262192


in reply to CPAN Module Proposal: Business::Ship

* Namespace: is Business::Ship a good spot for this? Alternatives?

I guess it depends somewhat on your long term plans for this. If it were just this, I'd be inclined to use something a bit more descriptive. Like, Business::Shipping::Calculator or Business::Shipping::Cost or something.

* Technology/other: How is the design? Good, bad, ugly? (Hubris question)

Well, honestly I didn't get far past the fact that even the POD didn't display cleanly in an 80 char wide terminal... In fact, the POD seems to be pretty well broken, at least for the Ship.pm file. So, I took a look, but not a very deep one.

I noticed there was sometimes a mix of data of code... your %country_translator hash buried in a subroutine in Business::Ship::Package, for instance.

I see you are trying to abstract out common things about packages in Business::Ship::Package and trying to include information about packages required by a specific shipper Business::Ship::<carrier>::Package. I wonder if it might not make more sense to just have a single package class which can hold all the information that might be required by a specific carrier. I certainly don't have a good overall picture of your design yet, but separating that stuff seems to be more complicated than necessary. Afterall, a package is a package is a package no matter who ships it.

Ideally, this would be written so that if you wanted to add Airborne Express next week, you could just write a Business::Ship::Airborne::Rates module and drop it in. I'm not familiar enough with the problem space (it's probably pretty messy) to decide how easy or hard that would be. Just the same, that's what I'd strive for.

Some thoughts on the overall design: I'm picturing a package class and various shipper classes. The Shipping module itself should be able to be queried for what shippers it handles. Each shipper should be able to be queried for what services it provides... maybe code would look like this:

use Business::Shipping; # Query the module for installed shipper specific modules. my @shippers = Business::Shipping::available_shippers(); my %shipping_option; for my $shipper (@shippers) { # Services would be Ground, 2nd day air, things like that. my @services = $shipper->services(); for my $service (@services) { # The $package would have been previously generated. $shipping_option{$shipper->name}->{$service} = $shipper->rate($service, $package); } }
Of course, that's just an illustration. It might be better to compress the rate sub to return a service/rate matrix for the package directly rather than having to build one. Maybe it would work better to return a base cost and modifiers for some service specific options (e.g. insurance.) After the package is actually scheduled for shipping, you can attach shipper specific information to the package itself, so it can be tracked, for instance. Maybe the available_shipper() sub could take an argument like "Saturday_delivery" and, in that case, would only return shippers that delivered on Saturday...

If you want to make it a good CPAN module, consider how people will want to use it. It's relatively easy to consider only how you want to use it but other people will likely want to use it differently.

Good luck with it.

-sauoq
"My two cents aren't worth a dime.";