Life without generics and list comprehensions

I make utilities for Apex because I miss list comprehensions, and I wind up missing generics instead..

 
    public static List filter(List Objs, String field, String comparator, Object value){
    	 Set VALID_COMPARITORS = new Set{'< ', '>', '< =', '>=', '=='};
    	if (!VALID_COMPARITORS.contains(comparator)){
    		throw new InvalidComparatorException();
    	}
        
    	List ret = new List();

    	Boolean gt = comparator == '>' || comparator == '>=';
    	Boolean lt = comparator == '< ' || comparator == '<=';
    	Boolean eq = comparator == '==' || comparator == '<='  || comparator == '>=';
    	for(SObject o: Objs){
    		Boolean valid_object;

    		valid_object = value instanceof Integer && (
	    			(gt && (Integer) o.get(field) > (Integer) value) || (lt && (Integer) o.get(field) < (Integer) value) || (eq && (Integer) o.get(field) == (Integer) value)
    			) || value instanceof Decimal && (
	    			(gt && (Decimal) o.get(field) >  (Decimal) value) || (lt && (Decimal) o.get(field) < (Decimal) value) || (eq && (Decimal) o.get(field) == (Decimal) value)
    			) || value instanceof Date && (
	    			(gt && (Date) o.get(field) > (Date) value) || (lt && (Date) o.get(field) < (Date) value) || (eq && (Date) o.get(field) == (Date) value)
    			) || value instanceof Datetime && (
	    			(gt && (Datetime) o.get(field) > (Datetime) value) || (lt && (Datetime) o.get(field) < (Datetime) value) || (eq && (Datetime) o.get(field) == (Datetime) value)
    			) || value instanceof Time && (
	    			(gt && (Time) o.get(field) > (Time) value) || (lt && (Time) o.get(field) < (Time) value) || (eq && (Time) o.get(field) == (Time) value)
    			) || value instanceof Long && (
	    			(gt && (Long) o.get(field) > (Long) value) || (lt && (Long) o.get(field) < (Long) value) || (eq && (Long) o.get(field) == (Long) value)
    			);
			if (valid_object) ret.add(o);
    	}
    	return ret;
    }

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

The iPad as a High-Latency Second Monitor with Air Display

At work, I’ve been experimenting with standing while coding. ?I do find it far more effective than the alternative, and as an added side-bonus, I don’t feel crippling exhaustion when I get home. ?Unfortunately, the effect of the loss of a second monitor is quite pronounced. ?Whereas I could previously keep information split between two monitors with ease, I am forced to resort to Expose or the Gnome equivalent. ?Not good.

My use of two displays is generally as follows.

Display #1 – Actual work being done.

Display #2 – Information about models / classes / etc… that I don’t get automatically from my text editor (Sublime Text 2)

The iPad through Air Display sucks for #1; the lag is real and irritating. ?For #2, however, it shines. ?I have it open to the appropriate page right now, and it probably helped me shave about 15-30 minutes of research off my daily routine.

Considering how rarely I want to change the content on screen #2, I wonder if using an e-ink screen could be plausible in the near future…

Django Views As Classes with Python’s __call__ Magic Method

I have been using Django off-and-on for about 2 years now. I am really liking the direction, but what bugged me (for the longest time) is the re-usability of the view section.

For those unfamiliar with Django views, they are not strictly “MVC” views. If anything, they act more like controllers, and I treat them as such. It should be a piece of cake to reuse code between these, but usually what happened was that I would define a bunch of private view functions and have them referenced by various view functions. It wasn’t exactly the shining pinnacle of my development career.

While reading the code for django-jqchat while working on a project for my client, I rediscovered the python __call__ magic method. This basically permits you to call an instance of an object like a function. With a little effort, I managed to re-organize the code to make it a little more easy to parse. This is not complete and not debugged, but maybe you will find it useful.

Github Gist Link

Force Multipliers and Japanese Programmers

日本語で説明ポスト

Yesterday, over coffee, “R” and I traded stories about Akiba, board games and business. However, the main thing that we wound up talking about was programming, or more exactly, why Japanese companies produce lots of code and little progress. To make a long story short, I’ve come to believe it is a failure of management. A failure to facilitate coding through the use of frameworks that amplify work output.

I mentioned the usual generalizations (Japanese aren’t good coders, the Japanese work environment involves a lot of talking and little doing), but “R” mentioned how he worked in a company where they produced a lot of good code and the project managers took care of the insufferable 3 hour meetings – and to be fair, I have too. So why the problem?

The first clue to us both started with frameworks. “R” spent weeks at one company trying to add table joins to a system which simply had nothing of the kind built-in. This reminded me of similar headaches while spending an year of my own time developing Pinki and only having a small search/listing website by the end.

The big clue to me was Fujitsu – and how they constantly had dozens of systems programmers working on Symbian and other tinpot mobile OSes for each of their feature phones. Particularly with feature phones, there was very little difference between handsets, but programmers had to spend obscene amounts of time doing low-level programming to enable old software to run on new hardware. It was rare for me to see anyone going home before the last train. (These were some of the best programmers in Japan, and they had families – even the “overtime bonus” was not reason enough to stay. )

What all these examples have in common is how companies and people brazenly avoid using programming force multipliers. Fujitsu still uses the old/creaky Symbian OS to this day, even though it is a pain to develop for and has little support / community left (particularly in comparison to Android and Win7). I was stupid enough to try to build a website without a framework, and had to re-solve a half dozen problems. R’s former company had settled on some Japanese-language only ghetto framework even though it had no proper DB layer.

My hypothesis is that a lot of Japanese companies produce little new because they have people solving solved problems over and over again. This is probably because of their inability to assimilate newer frameworks with better communities that automatically solve many of these problems for them.

Maybe this is because the English language barrier. You have billions of English speakers and X% are good programmers. Even if 2X% of Japanese speakers were good programmers, you will never have the depth of talent needed to develop native Japanese language versions of computer languages & the community that goes with them. You are restricted to a subset of frameworks, good or bad, that you can explain to your Japanese unilingual boss. He probably is severely risk-averse and is too old to be familiar with current programming technologies and shortcuts. How do you get him to let you program in Python/Django when he is still using Excel as a datastore (a shockingly common issue in Japan!)

I hear the weeaboos across the world now screaming “what about Ruby!”, but Ruby just proves the point. A Mormon Japanese dude (read: English literate, world-focused, non-Otaku, non-loner mindset) coupled with an excellent framework that gained fame world-wide (Rails). It’s nice that there are great Japanese Rubyists but they are not responsible for the popularity of the language.

There are alternative explanations – no money for advanced training, corporate mandates from backroom deals, fear of open source software, incorrect initial assumptions (IE: Japan is the source of all sorts of world class code), but none of them resonate with me.

If I’m right, the solution isn’t that hard. Give the Japanese programmers proper force multipliers in the form of good frameworks and libraries. Give them good training so they aren’t dependent on Google translator-fu. You will see an improvement.

-edit-

This one post got about 10,000 hits through a kind link on Hacker News. You can follow the discussion there. I do not necessarily agree with everything, but it is all generally thought provoking.

-edit #2-

I’m… honoured to see that somehow this made its way to Slashdot Japan, and was translated into Japanese. どうぞよろしくおねがいします。

-edit #3-
みんなさん、ようこそ。 もし不明なところがあれば、是非日本語でコメントをしてください。