To my experience I can classify a Product into two types Configurable and Cogs Product.
A Configurable product is a product that is wired to a particular algorithm or logic. What really changes are the actual parameters that feeds the logic. Usually those parameters are written as XML configuration file or in tables whatsoever.
Configurable products are fast to develop and easier to test. The reason is that you collect certain requirements and develop this product as per these requirements. The challenge is to make your product as generic as possible so it can fit as many of your clients.
Say I have a product that can draw a map of customers usage of electricity in a given year. This product is configured to take as an input Customer Table Name, the table should contain Location field which represents the location of the customer and the a Load field to create the legend. So you might have the Location field named as CustomerLocation or Customer_Location or Customer_Position or Customer_Lat_Lon doesn't matter. As long as you configure the product correctly you don't need to change your Customer Table name or its fields.
However, the product won't work if you have for example the Load field in a table while the customer data is in another table, because this violate the infrastructure of the product.
Think of Cogs product as a framework application replaceable Cogs (Classes). So the product is a collection of classes that talk to each other via the Interfaces ONLY. And its important the word interface in this context. Oriented approach plays a major rule in the cogs product. Clients can write their own logic that Implements those interfaces and literally replace the built in logic with their own.
Cogs product require a neat UML design and a decent knowledge of Design Patterns.
Lets have an example.
Lets take again our product in the example above and alter it a bit. The product have a class called DrawMap that Takes in its constructor ICustomer interface. ICustomer interface has method called getLoad and getLocation. The beauty of this design is that I can write my own Customer class lets call it MyWeirdCustomer that implements ICustomer and write the methods getLoad/getLocation which reads from a table or file or whatever and return the load and location respectively. Feed that object to DrawMap class and TADA. It works. The reason is that DrawMap doesn't care what your class is or how it is reading the load or how it is calculating the location. Whether you are asking Google Earth to geocode your location or have your location as native X/Ys; What DrawMap only cares about is that you implements ICustomer and that you have the function getLoad/getLocation.
The best approach is to merge the Cogs Product with Configurable one giving your client the ability to customize their code and have a configurable product. Having a hybird like product