I have class MasterData whose instances contain some general information about all possible gadgets.
I have another class CustomerData whose instances contain:
- some specific information about a subset of those gadgets, as provided to us by a customer
- the link from each gadget to the same gadget in
MasterData
CustomerData constructor takes as parameters:
- a file provided by the customer
- a Python module that I wrote for each customer that contains various details about the customer file, in the form of module-level variables; e.g., it says which customer field contains the product identifier; etc.
The linking was as simple as getting the appropriate ID from the customer file and looking it up in the appropriate field of the master data. The names of the fields that contained the relevant IDs (customer and master) were provided, among other things, in the customer module. The actual linking was performed in the CustomerData constructor.
Everything worked fine until we came up with new, much more complicated, matching rules. Each matching rule is only applicable to a specific customer, so I thought to put all the possible matching rules in the per-customer module, and then let the application select which rule it wanted to use. But unfortunately, the new matching rules require operating on the master data, and a module is naturally a “passive” object which does not even have a link to the master data.
Should I create global functions in the modules that take the master data instance and the customer record as a parameter, and return the master data record?
Or should I place matching rules elsewhere?
Generally.
This shouldn’t really be a module. That’s not wrong. But it can be confusing.
Consider changing things so that you have something like this.
Then. Each customer has a module which has
In this way, you can use your
ThisCustomerDatainstances in the customer module. The module’s not an argument to anything; the module contains the customer’s code.The customer’s installation of your application then looks like this
Now you can build the customer’s specific instance of the application from the generic_stuff plus the customer’s specific overrides imported from the customer’s extension module.
This has the advantage of allowing much, much more freedom, since you’re not limited to plugging a module into a class. You’re using module to contain a class definition which can now do anything.