As a developer, I’ve seen quite a few articles or blog posts with a title something similar to “5 Best Practices for Apex.” Occasionally I’ll even see something as stirring as “Visualforce the Right Way.” Well, this isn’t a blog post about the right way to do something. We’re going to have a nice long chat about what NOT to do. These are the things that a developer should, basically, be kneecapped for. If these things make it out of development and into production, someone has got some serious explaining to do. Some of these should probably even elicit kneecapping if they occur IN a development environment.
Just Because We’ve All Done it Doesn’t Make it Right
The first is something that most of us have done. You are working hard on a project and you just want it to work. The specification is in flux and all you know is that it needs to do this one thing but you don’t know how to get it there…yet. You’ll get it there come hell or high water, and when it’s finally done you sit back and bask in the glory of the thing. Until the next day when someone says, “So, how do the unit tests look?” Don’t be the person who has to try to explain why there are no unit tests on entire swaths of code. We’ve all been there, but avoid it like the plague.
Keep the ‘Nutter, Get Rid of the Fluff
Next is something my coworkers like to call “Test Fluff.” I didn’t even believe it existed until we had to look at an organization that had it. Test Fluff is when someone can’t figure out how to raise the test coverage of their code by writing more tests and instead write more code. Eventually, after you’ve written enough pointless code that is easily tested it outweighs the rest of it. This gets you a higher percent coverage and allows you to deploy to production. I can sense several of you out there shivering at the very thought of it. “How bad can it be?” others are asking. Some might even be saying, “Hmmm…tell me more.” Don’t do this. How bad can it get? “Twenty thousand lines of “i += 1;”. That is how bad it can get. Test fluff is not helping anyone. Take the time to write quality tests.
No Cheating on Tests
In the same organization, we found another gem. But let me back up a bit and explain something. Or at least talk through an idea so that everyone is on the same page. Unit tests are written in order to make sure that the code that has been written does what it is supposed to do. In theory, a unit test does this by executing the code and making sure the results are as intended. Part of the way that this is done is through the use of asserts and blowing up if something goes wrong. That way someone can look at the tests or test log and go, “Oh, look. Something has blown up badly. We should fix that.” So, letting tests blow up is usually a good thing. It’s a sign that something is wrong, and someone should fix it. So, when you use a try-catch block to catch those errors, it kind of prevents that whole “catching a problem before the users do” thing. Do not write unit test that use a try-catch block to make sure the unit tests pass.
Functional unit tests make sure that the functionality of your code works. Basically, it ensures that what you are hoping the code does, it actually does. But if you write unit tests that don’t check to make sure return values or database updates are valid, then you aren’t really confirming that the code is working. Make sure your code is actually doing what it is supposed to be doing.
Here we go again…and again…and again
Most of these things are concepts that apply to more than just Salesforce and Apex. Now it’s time to get into a couple worst practices that are a bit more Salesforce specific. Since Salesforce is a multi-tenant cloud solution, you can’t let one person suck up all the resources. It just wouldn’t be nice. But this means that you need to write code so it’s a bit more efficient than you might get away with somewhere else. Outside of Salesforce, you can do a database update each time you pass through a loop and maybe just piss off the database administrator. However, in Salesforce, there are things called limits that mean you can only do a certain number of database calls per transaction. So, if you are looping through 50,000 records and you try to do an update of each record, it isn’t long before you hit the limits that Salesforce has built in. Don’t do DML inside loops. It never works out in your favor.
Five ways to do something. Who goes first?
Salesforce has wonderful things called triggers. They are bits of code that fire off whenever you do certain things to the object the trigger is working with. This is very useful stuff. Suddenly, you leap into action, writing triggers for all the things that need to be triggered. Now you’ve got 5 triggers all waiting for updates to a single thing. Huzzah! The angelic choir sings of your abilities. Wrong. Which trigger is going to be executed first? If one trigger does run, what is the state of the data by the time it gets to another trigger? What happens when you have 2 different triggers that touch the same piece of data but with different triggering conditions. Which update is the one that actually gets committed to the database? Multiple triggers hugely complicate the ideas of an already complex issue. Don’t have more than one trigger per object.
These are a few of the things I’ve come across in Apex that have annoyed me recently and is by no means a complete listing of worst practices. Any worst practices that you’ve come across that I haven’t covered? Go ahead and get it off your chest–sound off in the comments section below for all of us to see and learn from.