Showing posts with label apex. Show all posts
Showing posts with label apex. Show all posts

Friday, 26 August 2011

Protecting code from configuration

A few posts back, I talked about how you can use SObject in Apex to treat objects generically. For example rather than getting a field from Opportunity like this:

String name = myOpp.Some_Custom_Field__c;

You can use:

SObject mySObject = Opportunity.getSObjectType().newSObject();
String name = mySObject .get('Some_Custom_Field__c');

Whilst this opens interesting opportunities for code re-use, it can leave you exposed - what if someone changes the field's API name? In the first example, a user wouldn't be allowed to rename the API name field - salesforce.com would pick up that the field was referenced and prevent the change. In the SObject example however, this isn't the case - the field name is actually a string, so the change could be allowed and the first you'll hear of it is when your app starts breaking...

One way around this is to create a class that refers to the field directly, as in the first example. Seems a bit wasteful, to create a class just for this. We'll also need to write unit tests even though we're not really going to use the code.

Unless we skip the first part and just create a test class that refers to the field. Something like:

@istest
private class ConfigCheck {
static testmethod void testField {
Opportunity o = new Opportunity();
o.Some_Custom_Field__c = 'Test value';
}
}

This idea can be extended for all sorts of uses. My last post covered Record Types and raised the question: "What happens if someone renames a record type?". Write another test that checks for the presence of record types your code is expecting to be there. This won't prevent the record type name being changed, but if something goes wrong and you suspect config changes are to blame, you could run the tests in ConfigCheck to check your code's assumptions against the current configuration to see if anything has changed that will cause your code problems.

Record Types

The Force.com 201 blog posted a great example of how to query the record type table in salesforce in a way that's considerate toward governor limits - think memoization pattern.

It's a useful technique and I've used it on every major project I've worked on over the last few years. However, there is another way to get record type information. Take the following example:

List oppRecTypes = Opportunity.SObjectType.getDescribe().getRecordTypeInfos();

There are also the following methods:

Map oppRecTypesByID = Opportunity.SObjectType.getDescribe().getRecordTypeInfosByID();

Map oppRecTypesByName = Opportunity.SObjectType.getDescribe().getRecordTypeInfosByName();

These all return RecordTypeInfo objects in some way, shape or form, but without using up one of you SOQL queries! These calls are not without penalty however - instead of a SOQL query, you use up a "record type describe", which you have a hundred of in a transaction on EE. So you'll still want to apply the memoization (cache) pattern explained in the Force.com 201 blog.

There is one other drawback - RecordTypeInfos do not appear to have any reference to the developer name of a record type. Really, both record type names and developer names can be changed pretty easily which could introduce breakage to your code, however developer names are less likely to change in my opinion, so querying the record type table can be a safer option.

Wednesday, 8 September 2010

Static boolean variables as "Locks"

Over 6 months and no new posts, tsk tsk! I'm trying to get back into the habit (though did I ever really have it?) with some - hopefully! - short, sharp posts.

So - do you use static boolean variables to control trigger flow and behaviour? I do - a lot. A common use is when Object A has a trigger that does something to Object B, and Object B has a trigger that does something to Object A. To avoid recursion when you update one, you can use a static boolean to cause the second trigger to return immediately rather than execute it, which causes the first trigger to fire again yadda yadda yadda. Similarly, if you have workflow that will cause an update to a record and you don't want triggers firing a second time, a static boolean does the job.

The advice in this post is simple: I think it's a good idea to keep these variables in a separate class. This is due to recent experiences, when I needed such a static variable in a class. I took the easy route and put it in the same class, and this was OK initially. Later, I needed to access that variable from somewhere else, which was possible, however, in that same class I also had a static code block in the same class that queried the database and set some variables.

Now, just by looking at this variable from outside the class, I was causing queries against the database to happen. I had enough headroom for this at the time but in the long term, it's a potential headache waiting to happen.

The solution is to have a separate class that holds such variables and refer to them from other points of code that need to look at them, rather than have the booleans amongst classes scattered here, there and every where. It'll be easier to manage and is better in the long run.

Friday, 5 February 2010

Too many script statements?

With any luck, this weekend should be the go-live for the project I mentioned in my last post. It's been an interesting project, and, at the risk of sounding schmaltzy, there have been a lot of lessons learnt (and most of them painfully).

I'll be posting about some of the lessons learned in upcoming posts, but I just wanted to take a moment to an idea I have up on Ideas. The governor limit on script statements has been my main obstacle this time around; I know that it's part of multi-tenancy and working with Salesforce. I don't actually mind operating within those limits, but I do like being able to handle meeting those limits in a sensible way.

The reason that "Too many script statements" is special is that, when hitting other governor limits, you can catch them as exceptions and handle them appropriately - usually displaying an error to the user. However, once you've used too many script statements, you don't have any script statements left to tidy up or present something meaningful to the user.

There are ways around this - not hitting the limit in the first place (not a practical solution this time round), periodically checking how many statements have been used and throwing an exception at a threshold (fiddly, unpredictable and uses script statements!). But a neater solution would be nice.

Feel my pain? Don't mope, promote!