Credit Card Ads

When a fresh face joined my team in Japan from Canada, I recall sitting to him in a train and saying, “Every advertisement in this train is an invitation to self-harm.” The first thing my eyes fell upon when trying to clarify my statement was an advertisement for a Credit Card. It could hardly have been a better example.

I have a credit card. I acknowledge the value. I don’t have to mention that the desired usage pattern is incongruous with your fiscal health. Yet, as all ads do, it simplifies and hides that complexity. Just sign, swipe the card. There is no embarrassment involved; if buy the product online, and there isn’t even another human involved. You can’t afford it really, but who cares right?

Well – it’s debt, and debt always has its day. It is dishonesty based on implication rather than blurted outright.

Computer languages can be much the same. There is the obvious performance penalties involved in using a language like Python versus a language like C. However, this is an honest debt, a healthy debt, a way to build things or avoid an entire classes of bugs.  Python is not lying to you.

Yet, there is an insidious form of technical debt, a dishonest form of debt that is inbuilt in some languages. You can find that in Apex.

When my intern started to learn how to use Apex and Salesforce, I didn’t bother teaching him about the generator limits. It didn’t take him long to check in some code that he had made, and I imagine it looked something like this.

    trigger Basic_Trigger_v1 on Custom_Object__c (before update){
        if (Trigger.isBefore()){
            CommonObjectTriggerHelper.IncrementCustomObjectLineItemCounter(trigger.new);
        }
    }

    public class CommonObjectTriggerHelper{
        public static void IncrementCustomObjectLineItemCounter(List all_custom_objects){
            for (Custom_Object__c obj: all_custom_objects){
                List all_lineitems = [select id, name from Custom_Object_LineItem__c where parent_id=: obj];
                obj.lineitem_count__c = all_lineitems.size();
            }           
        }
    }

From a purely aesthetic point of view, this look like attractive code. It’s short, to the point, and seems to deal with only one task. Yet, what is simple, clean and beautiful is actually useless.

First, the number of SOQL (not a typo) queries in Salesforce are quite limited. Doing a query in a loop is the root of many bugs.

Two, there are multiple things being done in the IncrementCustomObjectLineItemCounter function, and some important work is being wasted / thrown away for no reason.

(Three, there probably is no need to use code as Salesforce has rollup fields that can handle this under some circumstances, but this story is needlessly complicated, so let’s skip it.)

Fixing this is not a particularly difficult issue. However, the code becomes ugly and difficult to read. This mismatch, between code aesthetics and code value, is a major problem with Apex, and a major reason why it is a dreaded language.

In that sense, Apex is a bad credit card ad. The debt you accrue is technical and may only manifest itself at the worst possible time (post go-live, during some sudden need for a mass data update, for example). It’s even worse if you have a vendor who is willing to bend the rules to get the hell out of dodge.

The only difference with credit card debt is Salesforce doesn’t make more money when you do things the wrong way. My feel is that they do, sincerely, want you to do things the right way.

Next time, I will discuss the downsides of trying to fix this through library functions alone, and the Apex Framework I have been working on to try to overcome this issue; Underscore.sfdc