Lightning Component Best Practices at Florida Dreamin 2018

Thank you for everyone that attended my talk about Lightning Component Best Practices at Florida Dreamin. As promised, here is a link to the slide deck: Florida Dreamin 2018 – Lightning Tips. Hope it is super helpful to you.

Don’t forget to also check out the other articles on this blog such as:

Debugging Lightning Components with the Salesforce Lightning Inspector

Top 5 Lightning Debugging Tips

Why you should be using the Lightning Data Service whenever possible

5 Ways to Build Lightning Fast Components

FLD18.jpg

Check Out Lightning Component Development Best Practices on Pluralsight

DevBestPractices

I am so happy to announce that my third course about Lightning Component Development Best Practices was published on Pluralsight last night.

I worked extra hard on this course and have spent every weekend for the past 6 months toiling over every little thing I included. I am really hoping that effort shows through and I would love to hear your feedback (good or bad). All feedback is welcome. The good stuff makes me feel good and the bad stuff makes me better, so it’s all good.

Here is the description for the course and a listing of the specific things it covers:

Are your Lightning Components performing at the best level they can? Are they secure? Will they scale well as you start to build more complex Lightning Applications? In this course, Lightning Component Development Best Practices, you’ll learn the answers to these questions and more. First, you’ll find out what simple best practices you can incorporate to improve client-side rendering. Next, you’ll learn how to enhance server-side efficiency. Finally, you’ll discover what you can do to ensure your components are secure. When you are finished with this course, you’ll have the confidence to build Lightning Components that run “Lightning Fast”.

Modules:

  • Improving Client-Side Performance
  • Enhancing Efficiency on the Server
  • Reusing Code in Complex Applications
  • Avoiding the Pitfalls of Inter-Component Communication
  • Enforcing Security and Mistakes to Next Make

 

 

 

 

Lightning Best Practice: Handling FLS Exceptions Gracefully

If you found this article useful, you might want to checkout my latest course on Pluralsight titled, Lightning Component Development Best Practices, where I talk about base lightning components and a lot more.

If you are a Visualforce developer, then you may be surprised to learn that FLS (Field Level Security) and CRUD (Create Access Delete and Update) permissions are NOT handled automatically in your Aura-enabled code.

And in case you do not know, Aura-enabled code is the code used for Lightning components and most of this code is used to access the data in your Salesforce org. The gotcha here is that unless you are specifically checking permissions in this code, then it is possible your Lightning components could be unintentionally exposing sensitive data from your Salesforce org. 

Ouch!!!

The Problem

While there are code examples out there (such as this one on in the Lightning Developer Guide), I think there is a fundamental flaw in most of these examples. And that flaw is that they do not handle exceptions gracefully.

To demonstrate, let’s see take a look at some code that is very similar to the code used in the official Lightning docs. This code is used in the Controller of a Lightning component which lists data from a custom object called Race.

String [] raceFields = new String [] {'Id','Name','DateTime__c',
'Location__c','Attended__c','Type__c','Results__c' };

Map raceMap =
        Schema.SObjectType.Race__c.fields.getMap();

for (String field : raceFields) {
   if (!raceMap.get(field).getDescribe().isAccessible()) {
      throw new System.NoAccessException();
         return null;
   }
}

res.races = [SELECT Id, Name, DateTime__c, Location__c,
               Attended__c, Type__c, Results__c FROM Race__c
            ORDER BY DateTime__c desc
            LIMIT :pSize OFFSET :offset]; 
return res;

This code will first check to see if all the fields that need to be queried are accessible and if any one of the fields is not accessible, it will throw a NoAccessException.

Seems ok, right?

Well to begin, let’s take a look at what you would see in the browser if this code is run and the user does NOT have access to one of the fields:

NoAccessException.png

YUK!!!!

Not only is this message ugly, it is extremely unhelpful.  Surely, there must be something better?

Option 1 – a Better Error Message

Well, the first option you have is to simply replace the code that throws a System.NoAccessException, with code that throws an AuraHandledException, such as this:


 for (String field : raceFields) {
    if (!raceMap.get(field).getDescribe().isAccessible()) {
        throw new AuraHandledException(
            'Were sorry, but you do not have access to this field: ' 
            + raceMap.get(field).getDescribe().getName());
        return null;
    }
 } 

The message you will see now when one of the fields is not accessible is this:

BetterException

Much better, don’t you think?

Option 2 – Handling the Exception Gracefully

But wait, it can get EVEN better…

Instead of returning null when a field is not accessible, we can instead make a few more changes to the code, such as this:


String [] raceFields = new String [] {'Id','Name','DateTime__c',
            'Location__c','Attended__c','Type__c','Results__c' };
  
Map raceMap = 
      Schema.SObjectType.Race__c.fields.getMap();

List fields = new List();
String query = '';
for (String field : raceFields) {
    if (raceMap.get(field).getDescribe().isAccessible()) {
        fields.add(field.trim());
    }
}
if(fields.Size() > 0) {
    query = 'SELECT ' + String.join(fields, ',') + ' FROM Race__c';
    query+= ' ORDER BY DateTime__c desc LIMIT ' + pSize;
    query+= ' OFFSET ' + offset;
}
res.races = Database.query(query);
      
return res;

In this version, I am still looping through all the fields to see if they are accessible, but rather than throwing an exception when even one field is not accessible, I am instead adding the accessible field to a list I created called fields. I am then building a dynamic query string using only the fields that are accessible and finally just executing the query using the database.query method instead.

The result is that when the component renders, rather than seeing any error message at all, the user sees the list of races. But, any fields that are not accessible are just left blank.

Now, I happen to think this is the best solution. What do you think?

If you found this article useful, you might want to checkout my latest course on Pluralsight titled, Lightning Component Development Best Practices, where I talk about handling FLS exceptions and a lot more.

Lightning Best Practice: Adding Pagination to Lists

Pagination

What happens to a Lightning Component that displays a list of data without pagination?

It is probably doomed to suffer from performance problems and who wants to build a component that is doomed? Certainly not you, right?

It’s possible that Salesforce might release a pagination component at some point in the future, but until they do, you will need to roll out your own. Fortunately, it is not too terribly complicated and in this post I will walk you through how to do it.

To begin, I must give credit where credit is due and acknowledge that the paginator component I am using in this post is almost identical to the one used in the Dreamhouse application (which if you have not checked out, you really need to do so).

The markup code for the Paginator component is as follows:

Paginator

And the Controller code looks like this:

({
	previousPage : function(component) {
        var pageChangeEvent = component.getEvent("pagePrevious");
        pageChangeEvent.fire();
	},
    
	nextPage : function(component) {
        var pageChangeEvent = component.getEvent("pageNext");
        pageChangeEvent.fire();
	}
})

Additionally, I use a component event called PageChange which looks like this:

PageChange
Ok, so I have a component that currently renders a list of race data. To make it work with the paginator component through, I will have to make a few changes to both the markup,  controller and helper, along with the Apex Controller it references.

The new version of the markup looks like this:

NewListRacesMarkup

The Modified controller (seen below) now includes two new actions named onPagePrevious and onPageNext and these are referenced in the Paginator component.

({
    doInit : function(component, event, helper) {
	helper.getRaces(component);
    },
    handleAddToRaces : function(component, event, helper) {
        helper.addToRaces(component, event);
    },
    onPagePrevious: function(component, event, helper) {
	var page = component.get("v.page") || 1;
        page = page - 1;
        helper.getRaces(component, page);
    },
    onPageNext: function(component, event, helper) {
	var page = component.get("v.page") || 1;
        page = page + 1;
        helper.getRaces(component, page);
    }
})

And the getRaces function in the Helper file has been modified to look like this:

// Added new parameter called page to pass in the page number
// If no page parameter is passed in, it will just default to 
// a value of 1 and this is the case on the initial call for 
// the doInit action
getRaces : function(component, page) {
    var action = component.get('c.getRacesDB');
    // Added the pageSize variable which is passed in as an attribute
    var pageSize = component.get("v.pageSize");
    // Added code to set the new parameters that are now passed on 
    // to the Apex Controller Code
    action.setParams({"pageSize": pageSize,
          	      "pageNumber": page || 1
    });
    action.setCallback(this, function(response) {
        var state = response.getState();
        if (component.isValid() && state === "SUCCESS") {
            // Instead of just returning all the data
            // as a list, I will get back a result
            // object which is defined in the Apex Controller
            var result = response.getReturnValue();
            component.set("v.races", result.races);
            // Added code to set the values for the page, 
            // total and pages attributes
            component.set("v.page", result.page);
            component.set("v.total", result.total);
            component.set("v.pages", Math.ceil(result.total/pageSize));
         } else {
            //Handle errors
            var errors = response.getError();
            if (errors) {
               if (errors[0] && errors[0].message) {
                   component.set("v.errorMsg", errors[0].message);
                   component.set("v.isError", true);
               }
            } else {
                component.set("v.errorMsg", "unknown error, response state: " + 
                             response.getState());
                component.set("v.isError", true);
            }
          }
        });
        $A.enqueueAction(action);

	},

The last thing to do is to modify the code in the Apex Server Controller, which will now look like this:

public with sharing class ListRacesController {

    @AuraEnabled
    // Changed the return value from List to PageResult
    // which is defined in the inner class below Also added two
    // new parameters for the pageSize and pageNumber
    public static PageResult getRacesDB(Decimal pageSize, Decimal pageNumber) {
    	// Added new variables
        Integer pSize = (Integer)pageSize;
        Integer offset = ((Integer)pageNumber - 1) * pSize;
        Integer totalRows = 0;
        
        // Instead of just returning a List of races from a single
        // query, we are now returning a PageResult
        PageResult res = new PageResult();
        res.pageSize = pSize;
        res.page = (Integer) pageNumber;
        
        // The first query is used to fetch the data that will
        // be displayed and it will be limited to return just 
        // the data for the particular page it needs to render
        res.races = [SELECT Id, Name, DateTime__c, Location__c,
		     Attended__c, Type__c, Results__c FROM Race__c
		     ORDER BY DateTime__c desc
		    LIMIT :pSize OFFSET :offset]; 
	// We have to do a separate aggregate query to get 
        // the total number of records since this will be
        // used to compute the offset
        res.total = [SELECT Count() FROM Race__c];
        
        return res;
       
    }
   
   // Added PageResult class which defines the 
   // results returned from the getRaces method
   public class PageResult {
        @AuraEnabled
        public Integer pageSize { get;set; }
        
        @AuraEnabled
        public Integer page { get;set; }
        
        @AuraEnabled
        public Integer total { get;set; }
        
        @AuraEnabled
        public List races { get;set; }
    }
}

And that’s it. I now have a component that will by default only display 5 races at a time and allow the user to move between the pages using the arrow buttons.

And now I can rest – assured that my component (which honestly could use some other improvements), will not perform miserably when the number of races eventually climbs to a very high number.

Pretty neat, right?

Want to learn about other improvements? Well, the next one is to add caching to this same component and believe it or not, I can do it with a single line of code. Check out this post for more info. And stay tuned because this blog will continue to feature lightning best practices such as these.

EDIT: Below is the requested markup and code for the inner RaceV2 component, which actually includes the individual race data.

First, the Markup:

RaceV2Markup.png

And now the Helper Resource:

({
	updateRace :function(component) {
        var race = component.get("v.race");
        console.log("Calling updateRace");
        var action = component.get("c.updateRaceDB");
        action.setParams({ "race" : race });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (component.isValid() && state === "SUCCESS") {
                console.log("Race successfully updated");
            } else if (state === "ERROR") {
                var errors = response.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        console.log("Error message: " + errors[0].message);
                    }
                } else {
                    console.log("Unknown error");
                }
            } else {
                console.log("Action State returned was: " + state);
            }

        });
        $A.enqueueAction(action);

        
        
    }
})

If you found this article useful, you might want to checkout my latest course on Pluralsight titled, Lightning Component Development Best Practices, where I talk about pagination and a lot more.

Do this Salesforce Security Scan NOW!!!

Screen Shot 2016-08-20 at 11.39.10 AMPrior to about a week ago, if you went to this page and requested a Force.com Security Source Code Scan, you would have most likely gotten an error telling you that it could not be done and that you would need to submit a case.

Luckily, Salesforce has resolved this issue and you can now simply go to the link above, enter your credentials and you will be able to scan your org for security and quality rules. The scan will take a while to run (as in several hours or even days perhaps), but I promise it is worth the wait.

What you will get back is a very thorough report that scans your entire codebase for not only security issues (of which I am sure you will be amazed by how many critical violations it will find) but it will also evaluate whether you are utilizing best practices in your code to ensure good quality.

For example, it will scan your code to tell you where you have code that does the following:

  • Queries With No Where Or Limit Clause
  • Multiple Trigger On same sObject
  • Hardcoded Ids
  • DML Statements Inside Loops
  • SOSL SOQL Statements Inside Loops
  • Async Future Method Inside Loops
  • Test Methods With No Assert
  • Need to Bulkify Apex Methods Using Collections In Methods

I think everyone should take the time to have their orgs scanned and review the results. I suspect that even the most diligent of development shops will find some issue that needs to be addressed.

Happy Scanning.

Top 5 Lightning Component Framework Tips

top5This is a list similar to the one I did for Visualforce, which continues to be one of the most popular posts on this blog. So, I thought since I just published a course about Lightning development, I should do a Top 5 Tip list for it as well.

#1 – Refactoring is a Key Principle

Building Lightning Components is very different than traditional web development. When you are first getting started with this type of development, you are better off if you accept right from the beginning that refactoring is inevitable.

When you are first evaluating a solution, the right combination of components may not be intuitively obvious. This is especially true if you are coming from an object-oriented background and tend to look at breaking everything up into nouns and verbs. That approach does not really work with component-based design.

More than likely, you will start off with a design and then find that it makes more sense to refactor your code and break it up into additional or even nested components. There is nothing wrong with this and when developing with the Lightning Component Framework, refactoring is typically quite painless.

#2 – Apps and Components Run in System Mode

All Lightning apps and components run in system mode, which means that it is possible for your components to expose sensitive data without the correct permissions checks. The first thing you want to do is always include the with sharing keyword in all Apex code. This will enforce record access. But, to make your components truly secure, you must also include CRUD (Create Update and Delete) and FLS (Field Level Security) permission checks.

All Lightning apps and components run in system mode, which means that it is possible for your components to expose sensitive data without the correct permissions checks.

Unfortunately, most of the sample Lightning code that is out there right now (including what is on Trailhead and even what is in my first Pluralsight course on Lightning development), does NOT include code to check for proper CRUD or FLS access on the server-side.

In all fairness, Trailhead does include comment markers telling you where it should be inserted, but does not include the code. And in my course, I include a discussion about this topic in the last module and suggest that the viewer add this code themselves as a learning experience. It is not ignored. It is just that when you are learning how to develop Lightning components, there is a bit of a steep learning curve that goes with it. Educational providers such as Tailhead and my first Getting Started Pluralsight course are introducing you to all this in baby steps.

That does not mean that the concept of checking for CRUD and FLS permissions in your Apex server-side code is not important and why I wanted to include this as one of my tips. So, what is all this about?

Since Lightning components do not automatically enforce CRUS or FLS, your components must do this manually. You should check isAccessible(), isDeleteable(), isCreateable() and isUpdateable before running any queries or DML statements.

My friend at Salesforce University, Andres Perez has posted to his GitHub repo a secured data access helper that you can download and install into your org very easily. It includes methods to both query the database and perform DML securely and will throw back an exception if not valid. I strongly suggest that you check it out and consider using it with your projects.

#3 – Mark Most Resources as Global

You should mark your component resources as global for any that need to be accessed outside of your own org. Otherwise your components, attributes and events will not be seen in Lightning App Builder, Community App Builder or an installed package.

For the moment, the access check restrictions are limited and not being checked for all resources. This means that it is possible for you to create a Lightning component now, not mark it as global and have it show up fine in an outside tool. But then, in a later release, the access checks will be tightened and all of a sudden your component is no longer visible or usable.

Therefore, I suggest automatically marking all the following resources with access=”global”, unless there is a security reason not to expose them to outside tools:

  • aura:application
  • aura:interface
  • aura:components
  • aura:attribute
  • aura:event

#4 – Use Lightning Inspector to Debug and Learn about Lightning

The Salesforce Lightning Inspector is a Google Chrome DevTools extension that offers a lot of really neat features that can help you not only debug your Lightning app, but also learn more about Lightning in general. For example, the Components Tree, which you can see an image of below, shows you attribute names and values for all your Lightning components. Not just the rendered HTML elements, but the actual components as they are defined in your source code. This can be really valuable when you are trying to identify default values for component attributes.

LightningInspector2.png

 

 

 

Other useful tabs include the Event Log and Actions. My favorite is the actions, because you can see exactly what data in being passed into the action and then what is being passed back (see image below), which can be incredibly useful when debugging an issue.

ActionsTab.png

Just keep in mind that when using these tabs, you do need to turn on the recording before you will see results. You do that by clicking the circle icon in the top left corner, which in the screenshot above is red since recording was turned on. If it wasn’t that circle would be grey.

#5 – Take Advantage of Built-in Docs Feature

The last tip involves documentation, which I know is not typically a developers favorite subject, but Lightning makes it so easy to document your components, that it would be silly not to take advantage of this.

You can add a document resource to your component bundle, such as you see in the image below:

DocumentResource.png

Once created, this documentation resource will be rendered in the AuraDocs app, which every Lightning enabled org has and can be accessed through a URL, such as the following:

https://saralightning1-dev-ed.lightning.force.com/auradocs/reference.app

Where you replace the end of your unique org URL with /auradocs/reference.app

So, my rendered doc resource file defined above, will look like the following:

RenderedDocResource.png

Cool, eh?

Even if you do not want to create a document resource for your component, then you can at least add a description attribute for each of the following elements:

  • Components
  • Attributes
  • Events
  • Interfaces

These descriptions will automatically appear in the AuraDocs for your org (even if you never create a document resource).

 

Top 5 Tips for Improving Visualforce Pages

#1 – Reduce or eliminate view state   top5

View State is not your friend when it comes to page performance, so if you do not need it (as in your page does need to persist data between page requests), then do not use it at all. This is especially true for pages that will run on the Salesforce1 mobile platform!!!

How do you not use it all?

Do not include the <apex:form> tag unless you absolutely have to. This tag should only be used when you are accepting input from the user, so if you are only displaying data to the user, you should not have a form tag.

Like this Post? Then you will really like the “Improving Visualforce Performance” course that I designed for lynda.com. It was based on this post specifically and goes into great detail about each one of the tips in this post. Check it out!

And, even if you are accepting input, it is likely that not all the data on your page needs to be submitted through a POST request. For example, you could have a page that lists some account data, but only allows the user to change one particular field. In cases such as these, you could use the Transient keyword in the Controller class to make all the data fields (and especially collections) that are not being changed read-only. This means they will not be stored in the view state and your page will load faster.

You should also consider using JavaScript Remoting to avoid View State state by invoking the Apex Controller or Extension from JavaScript instead. This puts more load on the front-end and typically results in more code, but for certain pages that demand fast performance (especially those on the Salesforce1 mobile platform), this may be a necessary tradeoff to consider. But, if you do decide to go this route, make sure you use very efficient JavaScript code, so you do not violate Tip #5.

#2 – Evaluate SOQL for Efficiency

There are several ways you can write better SOQL code. For starters, ALWAYS make sure you place SOQL queries outside of loops. This should be done no matter what. It will not only make your page perform better, but will help avoid limit errors and should be standard practice. This also applies to DML.

Beyond that essential tip, you should also consider:

  • Only return fields that you are using on the page
  • Use WHERE clauses as much as possible to restrict the number of records returned
  • Use indexed fields in your WHERE clause as it will make the query optimizer work better. Default indexed fields are Id, Name, Owner, LastModifiedDate, and any foreign key or ExternalID fields.
  • Use the LIMIT keyword when possible
  • Use aggregation functions such as COUNT()
  • Use the WITH SHARING keyword in your controllers since the sharing architecture is used by the Query Optimizer and you will only retrieve the records that the users has access to
  • Additional suggestions (per reader JSON Hammerle) are to:
    • Use native (more selective indices) when possible
    • Hash your composite key (if you have one) into the native name field and use this hash in your WHERE clause This is comparable to a skinny table but you don’t have to work with support – and it can be delivered in a managed package.
    • Order your WHERE clause from most selective to least

#3 – Reduce use of Action tags

This kind of goes with tip #1, but since it is so important, I wanted to make it a separate point. Action tags such as <apex:ActionPoller> and <apex:ActionFunction> seem great on the surface since they are VERY easy to use, but they are memory hogs, so limit your use of them and consider alternatives.

Rather than using the ActionPoller tag, you should consider using the Streaming API. It means more code for you, but it results in no view state (remember tip #1). If you do not like the Streaming API, then consider using traditional polling using a Meta tag with a refresh and a window.location.reload.

Rather than using the ActionFunction, ActionSupport, ActionRegion tags, use Visualforce Remoting which uses no view state. Like I said earlier, it results in more code and complexity for you, but for certain pages this may be necessary. Again though, make sure you incorporate efficient JavaScript. Do NOT just copy and paste the first JavaScript snippet you find by doing a Google search.

#4 – Take Advantage of StandardSetControllers when dealing with lists of data

StandardSetControllers, which are used to create list controllers are your friends and you should use them whenever possible. The StandardSetControllers are optimized to work with large data sets of up to 10,000 records and include pagination features (which you should be using) automatically. There is no need for you to do this yourself.

When you do use them, instantiate them using a list of sObjects instead of from a query locator, as this is a more efficient way.

#5 – Incorporate Best Practices with all JavaScript, CSS and Images

No Visualforce page will perform well if it includes poorly used or inefficient HTML technologies. Make sure you incorporate best practices when including things such as Javascript, CSS and images. Things such as this:

  • Remember less is more and smaller is better.
  • Files should be minified and use Static Resources
  • Avoid using global variables
  • Place Javascript at the bottom of the page when possible and use the <script> tag and not <apex:includeScript>
  • Use browser caching when you can
  • Avoid use of iframes

There are tons of documents out there about best practices. Two of my favorites are:

https://developers.google.com/speed/docs/best-practices/rules_intro

http://developer.nokia.com/community/wiki/JavaScript_Performance_Best_Practices

 

 

 

Lessons Learned While Writing Apex Code

I have been writing object-oriented code for several years and specifically writing Apex code for over a year now, yet every time I go to create a new class or a trigger, I feel like I learn something brand new. This post is a summary of some of the most important lessons I have learned. I hope it helps you to avoid some of the same speed bumps that I have encountered.

Tip #1 – Make sure you “Bulkify” every Trigger

This is “THE BIGGEST TIP”. It is probably the one you will see the most written about, but it is so critical to writing good code, that I think it is ok to re-stress the point. In case you do not know, bulkifying a trigger means that the trigger can effectively handle being executed numerous times (200 times typically). trigger

Why 200?

Well that is usually the maximum number of times it can be executed (depending on the context). You see, your trigger can be executed multiple ways. It can be executed by users performing actions in Salesforce, or it can be executed by someone bulk loading data through the Apex Data Loader or the API. If your code is not written efficiently, it could very well throw the dreaded “Too Many SOQL Queries”. Trust me, you do not want to see this message.

So how do you avoid it?

Glad you asked. I am not going to bore you with a long detailed explanation of what you can do to bulkify your triggers, because honestly that has been done to death. I will however, tell you the golden rule to remember when writing triggers:

“If any of the following statements (SELECT,UPDATE, INSERT,DELETE) appear within a for loop, your code needs work.”

Basically, if any of those statements (which represent either a SOQL Query or a DML statement) appears in a for loop, this means you are executing a very expensive operation numerous times (or at least as many times as the loop iterates, perhaps even more). Avoiding expensive database calls is a common thing to avoid in any programming language, but is especially important for Apex development because of Salesforce’s Governor Limits (which imho are GREAT for ensuring that we all create the best code possible).

If you want to learn more about all the things you can do to bulkify your triggers, check out this very informative post by Salesforce Guru, Jeff Douglas. Everyone should also checkout the post on the DeveloperForce Wiki titled, “Apex Code Best Practices“.

Tip #2 – Create at least two testMethods in your Unit Test Code

Most posts or instructions I read did not really stress the importance of creating both a single instance and bulk instance testMethod in your test class.

Why two methods and not just one?

The first method should be for testing what happens when a single record is handled. It is here that you should include System.AssertEquals to test whether a condition is true. This will tell you whether the trigger actually did what it was supposed to do.

It is possible to write Unit Test code that does not do this kind of check and still get 100% coverage. However, I would not consider the test to be a good one and neither should you.

The second test method should cover what happens when the trigger must handle multiple records. The following code is an example of using two such methods to test the validity of a trigger.

TestBulkCode

Tip #3 – Bulkifying your code is not just important for triggers

So what else is it important for?

How about Unit test code contained in class files – especially the ones that were built while keeping tip #2 in mind. That’s right, even your unit test code needs to be written efficiently – especially when it is set to execute a bulk testMethod.

If your Unit Test code uses a For loop to create a set of records and performs a SOQL query or a DML statement within that loop, guess what? Not only might you get an error, but your code is going to take way longer than it should to run tests and ultimately deploy.

This tip also applies to methods contained within a Helper class. The more efficient your code, the better, so always assume the worst and expect all of your code to be called multiple times.

Tip #4 – Use Both the Developer Console AND the Force.com IDE

I have been very impressed with the newly available Developers Console. For a long time, the Force.com IDE was hands down the best tool for developing Apex code, but I feel like that is starting to shift – a bit, at least.

For some tasks, I prefer using the Force.com IDE – like for just browsing and editing code. I also love the schema editor for examining metadata. However, I am discovering that there are certain tasks that I prefer the Developer Console for.

The biggest thing is for running Unit Tests. In my experience, the Developer Console is many times faster at executing unit tests – especially the ones that test bulk methods.

I also like the way the execute anonymous code area is right at the top of the Console. It just makes more sense to me in this spot. I also like the layout of the Query Editor tab and especially that it returns the value of an AggregateResult (see image below). This is something you cannot do with a query in the Schema Editor of the Force.com IDE

DeveloperConsole

If you have not checked out the Developer Console or only glanced at it, I encourage you to give it a look. Try doing some tasks in one tool and then switch to doing the same task in the other tool. You may be surprised by which you prefer.

Tip #5 – Periodically go back and evaluate old code

Just like no two people will likely write the same identical answer to an essay test, no two developers will write the same development code (unless of course, you copy someone else’s code). There are dozens, maybe hundreds of ways to code some things and most ways involve inefficient code. Chances are high that you have written at least one piece of code that can be improved.

Learning how to be an efficient developer is a process. You do not learn it by reading one article, one book, or one post. It takes time to develop the skills to write efficient code in every situation – especially when you are new to a platform or language. Set aside time (say once a year) to periodically go back and evaluate old code you have written. You will probably be surprised at how much you can learn in a year.