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" )
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.
That is a *great* idea! I sure appreciate the feedback. This one is going on the todo list.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.
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.
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.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.
Roger that. :-) -Dan
I hope that better explains why I'm wary of your current <carrier>::Package" objects.