Monday, November 21, 2011

Salesforce and Max Trigger Depth

So, I regularly keep an eye on the apex/VF message boards for salesforce and there are a couple of recurring issues that arise over and over again. I have already written on the issue of test classes here, but another one that pops up at least once a week if not more is the issue of Max Trigger Depth.

What Happens

Simply put when you are writing a trigger and start to insert items you get an error similar to this:

System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, XXX_OBj: maximum trigger depth exceeded XXX_Trigger trigger event BeforeInsert

Why this Happens
Generally, when you receive this error you have updated the same object that your Trigger is working on with a DML statement in your trigger. Here is an example:

Trigger someTrigger on some_obj__c (before insert, before update){
  for (some_Obj__c o: trigger.new){
    o.somefield__c = 'This is my data';
    update o;
  }
}

Now there are several things wrong with that trigger, but for our purposes the one that matters is the I am updating some_Obj__c in a trigger on that same object that activates on update. So what happens is that the trigger is called, the object is updated, the trigger is called again and the object is updated again causing the trigger to be called again and so on. After a certain point there are too many triggers being called and you receive the error message above. Be warned that sometimes finding that DML statement, may not be as easy as it sounds. It could be in some utility class that is being called by a helper class that is called by your trigger and you may not even realize it!

How to solve the problem

Solving this problem my not be as easy as finding this problem. Obviously, the easiest way to resolve this issue would be to remove the offending DML statement, but this may not be possible so we have to investigate other workarounds.
At the most basic level what you have to do is add some sort of check that will stop the trigger loop, preferably before you get deep enough to throw an error. This can be accomplished in many ways. I will quickly outline a couple, but this is by no means an exhaustive list.

1. Check a field on the object. Basically, create a scenario where the object has a field that will somehow indicate that the record has already been updated. Then all you do is check this field, if it indicates that the record has already been updated, then you do not call the DML statement, the chain is broken and everything will terminate normally.

2. Use a static variable. This is similar to number one, but instead of using a field on the object, you use a static data member of a public class to check and see if the DML statement needs to be called. This is effective if there is no field on the object to indicate if the update needs to be performed, or if the update is on a different record than the one that fired the trigger.

There are probably other ways to stop the execution loop, but the general idea remains the same.

Wednesday, November 9, 2011

The Secret Life of Crows


http://www.cracked.com/article_19042_6-terrifying-ways-crows-are-way-smarter-than-you-think.html

Found an interesting article the other day (see above).  It details the intelligence level of crows, which is remarkably high.  As pointed out in the article, crows are capable of doing many things that the average human has trouble with, such as communication, memory and advanced planning.  Although the article in itself is interesting it led me to examine a couple of things.

My first thought on reading this is, why are we just finding out about this now?  I mean, crows have been around for thousands if not millions of years, probably have exhibited this behavior for a significant portion of that time, so why are we just now studying it?  Here are the possible reasons that I came up with:

Reason #1: Just noticed

One reason that this could just now be coming to light is that the behavior in the crows was just observed recently, but I do not buy that one.  For centuries, crows have been painted as evil.  In order to be evil there has to be some sort of intelligence, albeit a malignant one.  In many stories, crows are even able to talk, even when other animals can’t.  This says that on some, possibly subconscious level humans have always realized that crows were smart and just have never really studied it.  But why?

Reason #2: My take

The conclusion that I came to is that humans failed to recognize the intelligence of the crow because of a me-centric attitude.  Humans always want to believe that we are special, that the world revolves around us, that something in the universe, be it our intelligence or even a higher being, provides us with a superiority over other animals.  With this in mind, it is easy to see why we studied intelligence in chimps, apes, and other primates with way more voracity than other animals.  These animals are the closest in their relation to us, thus, even if they are not as smart as us, they must be smarter than other animals.  So we will study them before all else.

Now on the surface this sounds like a reasoned argument, but a deeper look will reveal the flaw in that argument and possibly give all of us something to think about going forward.  Namely, that even when we tried to apply logic to this problem we still apply this logic through the lens of our human bias.  To me this serves as a lesson that we need to look outside the bounds of said lens and face problems or make decisions on a factual basis, not a wistful one.

Anyway, these were my thoughts when reading the article and I just wanted to put them out there. 

What's up with Force.com Test Code

On the force.com discussion boards for Apex coding and general development questions, one of the most often asked questions is how to write a test method for a given apex class. Some users have specific questions and some have no idea where to start writing test code, but I feel that most of these users have one thing in common: they do not understand the purpose of test code. I have seen many blog posts and comments on how to write test code and what structure to use, but very few of these touch upon the why of test coding or explain exactly what you are doing when writing test code.

Why do we write test code?

For the force.com platform test code serves as a check on bad programming. However, the way that it is utilized by force.com is misleading for many. When Force.com checks the coverage of a code, all that is checked is whether or not the code will run. One hundred percent code coverage is great, but really by itself is worthless as a test. As a simple example take the line:

Integer x = 1 + 2;

This is a perfectly valid line of code. If I call the method containing this line of code in my test class, this line will be covered and pose no problems. However, what if I need x to equal four? That 100% test coverage then gave me a false sense of security in code that is logically flawed. So a good test class needs to cover two scenarios, first it needs to ensure that all the code it is testing will run, i.e. the test must provide adequate code coverage. But also just as important, the test should ensure that the code will produce the result that it was meant to produce, i.e. that the code is logically sound.

How do we write test code?

When we go to write the test code then, how do we do it? I think that everyone may have a different method for this, but what I do is picture how the user will use the program that I am writing and write code to accomplish the same thing.

For example, say I write a VF page with a custom controller that takes the data entered on the page and inserts in into two different related custom objects, the first step would then be to programmatically enter data into the system, then I would insert the data into the appropriate objects. These two basic steps would provide me with 100% code coverage for that basic scenario, but my test is not finished. At this point I know that the code ran, but did it really insert the records, and just as importantly did the right data get into the right field? So to finish my testing scenario, I would query the records that I just inserted into the database and then compare the data that I queried with the data that I wanted to place in the database and ensure that they are the same. This would check the logic of my code and ensure that not only is the code running, but that it is running properly.

Is that it?

No, far from it. The controller method probably contains validation and condition checks to ensure that only the correct data is inserted and only inserted in the proper conditions. All of these validations and conditions must be checked as well in order to obtain 100% coverage and to ensure that our code is functioning as intended. We can check this by attempting to insert invalid data and/or conditions into the database. This will allow us to follow the various branches of the code and will give us the complete coverage that we want.

So are we done yet?

Yes, for now. The points that we have covered here should allow you to approach writing test code with a clear and concise plan of attack, allowing you to avoid the frustration of 74% code coverage or 100% code coverage for code that does not work.