A Well Oiled Abstraction


A Well Oiled Abstraction

Trading Copy/Paste for Configurable Apex Execution

 

As we continue to build our library of common customizations, we must also be looking at the overhead involved in creating and modifying classes that override B2B Commerce functionality.  As a proof of concept, I recently abstracted logic that we had previously implemented for a customer that rounded the quantities of cart items up to the nearest multiple of the standard pack quantity for that product.


Prior to this exercise, the logic involved was written directly in the child class of the ccrz.cc_api_CartExtension class.


The first step I took in abstracting the logic was to create a custom object that would be used to handle the configuration of the overrides.  My object (named XC_Relection__c) contains two custom fields: XC_Apex_Class__c, and XC_Virtual_Class__c. The first is used to detail the name of the class that contains the logic to be implemented, and the second is used to define where that logic should be injected.



Next, I needed to write a simple abstract class that would be used to call the logic execution from the dynamically instantiated class objects.


public abstract class XC_Process {


 public Map inputData;


 public abstract Map execute ();


 public abstract void setInputData (Map inputData);


 public abstract Map getInputData ();

}


Then each of the subsequent classes that perform the logic (or the execution of those classes) override the abstract methods in XC_Process.


In my POC, I created a XC_CartPreprocess class that handled the execution of the logic class.


public class XC_CartPreprocess extends XC_Process {


 public Map inputData;


 public override Map execute () {

    for (XC_Reflection__c reflection : [

          SELECT Id, XC_Apex_Class__c

          FROM XC_Reflection__c

          WHERE XC_Virtual_Class__c = 'preprocess'

    ]) {

       XC_Process instance =

(XC_Process) Type.forName(reflection.XC_Apex_Class__c).newInstance();


       instance.setInputData(inputData);


       inputData = instance.execute();

    }


    return inputData;

 }


 public override void setInputData (Map inputData) {

    this.inputData = inputData;

 }


 public override Map getInputData () {

    return inputData;

 }

}


Note that I had to explicitly create the getter and setter methods for the inputData variable, and that is likely due to a difference in how Apex and Java interpret the get/set on the class variable definition.


Categories:
Tags: ;

SEARCH ARTICLES