Thursday, August 13, 2009

Designing a Wishlist Service: Feature Set

I've been referring to this project as a “wishlist,” but it's really a “product” list. Product lists appear everywhere in eCommerce, with different names and purposes: wishlists and registries keep track of products that we'd like others to buy for us; favorites and re-order lists keep track of products that we like to buy for ourselves, and the cart holds products that we're buying right now. Sometimes these lists will be shared with others, sometimes they won't. Some of these applications have different data needs: quantity on the registry and cart, versus ranking on the wishlist and favorites. From a design perspective, which features are important and which aren't? Particularly if I'm planning to sell this product to multiple sites?

Before we can think about what data gets stored, however, we need to think about how the list itself will be identified. One approach is to give each list a unique identifier, and have all requests use that identifier. I rejected this approach, because it requires any potential clients to modify their database schema, adding in a lookup table to associate this unique ID to a customer or whatever data they use to identify the list.

Instead, I decided to use a two-part key of customer ID and wishlist name. Every eCommerce site has some notion of a customer ID, so I'm reusing existing data. By giving wishlists names, access to a particular wishlist can be controlled by page-level code — no need to modify the database. These two key components are managed as character strings, with no interpretation by the service: as long as the site uses reasonable-length identifiers, they will work.

The next question is how to identify each product entry. Here I went with another composite key: product ID and sub-product ID. This is a nod to my past experience at GSI, which used a second-level ID to identify the particular size/color of a base product. Looking at other clothing sites, this appears to be a common practice, and sites that don't use such an ID can simply leave the field empty. Again, the values are defined as strings, without any interpretation by the service.

Finally, we get to the information associated with each product. And here I decided that the least information stored, the better: each entry has fields for rank and quantity, nothing else. This is an application of the Agile YAGNI principle (you ain't gonna need it): I've identified cases where these two fields will be used, but don't know what others might be needed. I do, however, recognize that other data might be needed, so attached a free-form string (CLOB) to each entry: should a particular site want to store data there, they can. It won't be interpreted by the service, but will be persisted with the rest of the entry.

Entries will also have a list of comments attached to them. This feature was driven by a specific collaborative shopping application, although I think it will be useful in multiple places (for example, a shared favorites list in which the customer describes why the product is a favorite). These comments are not associated with the product per-se, they are managed via separate service calls.

This brings me to the most interesting (to me) feature of all: how the client will access the service. That deserves a posting of its own.

No comments: