I am in beginning stages of rewriting a rather large app. In looking at the current code, there are a lot of custom 'hacks' within it for individual clients. Basically this system ships crap for people, and we integrate with many different customer systems, some of which are really whacked.
Example: One client sends us orders that only contain two shipment types, indicated by '1' or '2'. Our internal codes are things like UPN, MR, PM, UPS, DHLR, etc. The codes we use are pretty standard. In order for us to work with this client, we had to map '1' to UPS (UPS ground) and '2' to DHL2 (DHL 2nd day air). This was accomplished with a nasty if(clientID = X) { do mapping } statement.
One obvious solution to this would have been to tell the client to fix their system, however that is not an option if the client is worth several million a year, we have to bend to them a lot of the time. Another solution might have been a custom import adapter for the client, but there was no way for us to easily implement this and only allow only the one client access to their specialized adapter.
These customizations also occur at different spots in the system, and could occur anywhere. For instance we had to do a custom SOAP request for a client after their orders were shipped. This is also a nasty if. There are also specializations for customers who are using amazon seller central as their order system. At order fulfillment time we have to check if the client is a amazon seller then write out an XML file for each order. This amazon thing was a customization I had to put in on Friday in the old system and it sucked.
Their are a lot of problems with this in the old system. The code is a disaster that becomes worse each week, and if a client goes away it is impossible to remove all of their customizations without worry of something else exploding.
So as I see it, there are probably four different ways we have to check for custom code
1. ClientID
2. Integration platform (their shopping cart or ERP system type)
3. The client status (deleted, haven't paid their bills, active, etc.)
4. The shipment type. For instance if its USPS international we might have to print a custom form or something, or some weird freight vendor we might have to send the order to them via soap.
One thing we thought of is a trigger system. At arbitrary points in the system I want to be able to mark a trigger or event. This should be extensible so I can easily add in triggers later on without a lot of refactoring. That way if I get a crazy request like "we need to have X happen if an order is on backorder for client Y and it needs to happen right before the order is released but only if it is on a Tuesday and the order consists of products in warehouse 2".
Secondly we need to code encapsulated somehow, so if a client goes away, or an order method goes away, then the code goes away too. I was thinking we would have an override object for each client, platform type, status type, etc. In that object we would create a method with the same name as a trigger, then the trigger would execute those methods if they existed by passing information related to the trigger event, then those arguments would be passed back if they changed, like.
Code: Select all
// 232 is the clientID and I guess this class would be returned by a factory/instance map thingy
class Triggers232 extends Triggers
{
public function OnOrderEvent( $order )
{
// do something custom to the order for NeedyClient
return $order ;
}
}The big problem I can see with this is that we have 300 clients right now, and sometimes process up to 2000 records at once. So this would mean possibly 60,000 method calls to the triggers thing just for that one action. If this is the only way it can be done, thats ok. I can just buy more servers.