Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re: Re: CPAN Module Proposal: Business::Ship

by danb (Friar)
on Jun 01, 2003 at 16:48 UTC ( #262231=note: print w/replies, xml ) Need Help??


in reply to Re: CPAN Module Proposal: Business::Ship
in thread CPAN Module Proposal: Business::Ship

Thanks a lot for the input, sauoq.
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.

What if the same module were going to be doing a lot of other features as well? (Like the ones I mentioned here).

The various features don't seem to lend themselves to a common designation, so even the vendors come up with vauge references to them: "UPS Online Web Tools" ("Online Web Tools!?", now *that* is vague). The problem is that they *do* easily lend themselves to common technical details (they all generate similar XML, etc.).
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.
Heh heh heh... I went to all the trouble to write the POD, then I forgot to even test it. :-)
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.
Perhaps, I'll have mull over that for a little while. "Package" doesn't represent a physical package, really, but more of a "what does the carrier think of a package as?"

Some carriers think that each package in a "shipment" should know the destination, origination, etc. (i.e. Packages are all treated as individual shipments). Other vendors think of a package as only one part of a larger shipment.
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.
Yes, that's exactly what I'm striving for -- so I really appreciate your advice :-). I guess having the Package object is an additional piece of complexity.

However, I think it's likely that each carrier will have a different expectation for "package" anyway (that has been my experience so far), so to add a new module, one would have to modify the Package handling anyway, and I think having their own derivitive of Business::Ship::Package would be better than having the same code be everything to everyone.
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); } }
Great idea! Part of that feature (like "what services are available for xyz vendor?") are specifically supported by some vendors' XML API.
Again, I really appreciate the feedback.

-Dan

Replies are listed 'Best First'.
Re: Re: Re: CPAN Module Proposal: Business::Ship
by sauoq (Abbot) on Jun 01, 2003 at 21:46 UTC
    What if the same module were going to be doing a lot of other features as well?

    I agree with Aristotle on this. Something like Business::Shipping is more obvious than Business::Ship is. I too had a moment of uncertainty when I first saw the node title. Your intent is to implement a generic "shipping" API right? :-)

    "Package" doesn't represent a physical package, really, but more of a "what does the carrier think of a package as?"

    I guess I'm suggesting that maybe the package really should represent the physical package. All packages have things that, at least from your perspective (or that of any client using your module), are the same no matter what shipper is chosen. Packages have an origin, a destination, a weight, dimensions, contents, a value, etc. None of those is determined by the shipper. Collectively, these variables represent everything you know about the package; if the shipper were to ask you questions about the package, this is the information you'd generate your answers from.

    Other vendors think of a package as only one part of a larger shipment.

    So, it sounds like a "shipment" is another useful abstraction. It would be shipper-specific and so you probably would have a Business::Shipping::<carrier>::Shipment package defined for each carrier. A shipment would contain one or more packages. It would have an origin or destination just as the packages it contains. In fact, you'd probably want to assert that the packages in a shipment all had the same origins and destinations. The shipment would have a schedule attached to it. You'd likely track the shipment (rather than tracking a package.) I suspect you would want to avoid instantiating a Shipment until after one is actually scheduled; you shouldn't need these classes to determine the shipping rates.

    One of the keys to building a successful API is to base it around the perspective of the API's consumers. FedEx isn't going to be using your API, www.yetanotherlittlewebstore.com is... and they don't care how the individual shippers think of packages (or shipments.) They just want to be able to write code that naturally follows from the way they handle packages. Your API should hide the differences between shippers.

    When you walk into the Post Office or a FedEx office, you say "here's my package and this is where I want it to go; how much will that cost?" Your API should be true to that. If a shipper requires more specific information, your clients (those using your module) should be able to query the shipper to determine what information is needed. That way YALWS.com can ask those questions directly of their customers via some inputs on a form.

    I hope that better explains why I'm wary of your current <carrier>::Package" objects.

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

      I agree with Aristotle on this. Something like Business::Shipping is more obvious than Business::Ship is. I too had a moment of uncertainty when I first saw the node title. Your intent is to implement a generic "shipping" API right? :-)

      Well, it's decided then. Business::Shipping it is.

      "Package" doesn't represent a physical package, really, but more of a "what does the carrier think of a package as?"

      I guess I'm suggesting that maybe the package really should represent the physical package. All packages have things that, at least from your perspective (or that of any client using your module), are the same no matter what shipper is chosen. Packages have an origin, a destination, a weight, dimensions, contents, a value, etc. None of those is determined by the shipper. Collectively, these variables represent everything you know about the package; if the shipper were to ask you questions about the package, this is the information you'd generate your answers from.

      Very good ideas... thanks. I might try to go with a simpler 'Package' idea like you are suggesting. Unfortunately, the vendors really do have different ideas of what you need to know about a package. I mean, we could have one "perfect" package that can be everything to everyone, but UPS doesn't need:

      * Is it machineable?

      * Container? (not to be confused with "Package type" )

      * Breadth?

      Whereas USPS does. Then, probably, FedEx has some additional questions about packages that the other two don't.

      But anyway, I was hoping to design it so that the user never had to instantiate a ::Package object anyway -- they are just created behind the scenes.

      Other vendors think of a package as only one part of a larger shipment.

      So, it sounds like a "shipment" is another useful abstraction. It would be shipper-specific and so you probably would have a Business::Shipping::<carrier>::Shipment package defined for each carrier. A shipment would contain one or more packages. It would have an origin or destination just as the packages it contains. In fact, you'd probably want to assert that the packages in a shipment all had the same origins and destinations. The shipment would have a schedule attached to it. You'd likely track the shipment (rather than tracking a package.) I suspect you would want to avoid instantiating a Shipment until after one is actually scheduled; you shouldn't need these classes to determine the shipping rates.

      That is a *great* idea! I sure appreciate the feedback. This one is going on the todo list.

      One of the keys to building a successful API is to base it around the perspective of the API's consumers. FedEx isn't going to be using your API, www.yetanotherlittlewebstore.com is... and they don't care how the individual shippers think of packages (or shipments.) They just want to be able to write code that naturally follows from the way they handle packages. Your API should hide the differences between shippers.

      When you walk into the Post Office or a FedEx office, you say "here's my package and this is where I want it to go; how much will that cost?" Your API should be true to that.

      I guess I could have a "use_defaults=1" option that will just guess various things, like "is it residential", or "is it machineable", etc., that the API user might not care about (and doesn't have much influence on the final price). My first instict was to require every detail that the carrier requires, though.
      If a shipper requires more specific information, your clients (those using your module) should be able to query the shipper to determine what information is needed. That way YALWS.com can ask those questions directly of their customers via some inputs on a form.
      That's a nice idea, but I don't think it would work out for everything, in practice. The consumer would likely put in whatever values that caused it to come out cheaper; in which case the vendor would end up manually correcting it anyway (or eating the cost).

      Now that I think about it, you were probably thinking of things like "which service do you want" and "do you want insurance?", etc. Yes... that makes a lot of sense.

      I hope that better explains why I'm wary of your current <carrier>::Package" objects.

      Roger that. :-) -Dan

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://262231]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2022-11-30 23:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?