Monday, July 19, 2010

View State and Associated best practices


Few days back i gone through a very interesting article on view state. I putting some its contents as part of this post. This post will be really very help full for the developers who are new to salesforce and looking for good development practices.

The salesforce Summer '10 release introduced a very good feature which will really make the life of a visualforce developer easier. Especially for those who are working on creating some big pages having lots of fields, components and action buttons and facing the challenge of improving the performance of the page. Each visualforce page that contains a form component also contain a encrypted form field that encapsulates the state of the page know as view state. This view is automatically created and holds the state of the page.

This post is to give a brief overview to view state and the best practices for optimizing the view state in order to improve the page performance.

View state Overview:
While working on a page we are either submitting or retrieving the data to or from the server. The page is initially retrieved with a GET request and form submissions happen via POST requests. From users perspective all this is a state full interaction since the page state is changing based on its previous state. But as we know HTTP is a stateless protocol, which means that the initial GET and the subsequent POSTs requests are treated as independent requests for the page. As a result, some other mechanism is needed to persist state information across HTTP requests.

Here come the role of view state mechanism. In view state mechanism page state is persist as a hidden form field that is automatically created in the form when the page gets generated. View state capture the complete state page. The view state is summited back with other form data, which gives the server enough information to recreate the page state to which new changes can be applied.

Note: View state data is encrypted and cannot be viewed with tools like Firebug.

Getting the View State Inspector:
The Summer '10 release includes a pilot of a tool called the View State Inspector, which lets you view the contents of the view state.This information can help you in optimizing the view state size. This feature needs to be enabled by support - please file a support ticket to get it enabled for your organization. Once enabled, it shows up as a tab in development mode.
 
Image showing view state tab:
ViewState

Best practice for optimizing the view state:
As view state is associated with each page page and it has to be transferred back and forth between the browser and Force.com, there could be a potential performance impact in terms of increased page load times when the view state becomes large. So here are some best practices with can help one optimize the view state size.
  • Minimize number of form on a page: Assume a page contains two forms - form 1 and form 2. Irrespective of which form the user submits and causes a post back, the view state for the page needs to get transferred. To support this, each form on your page will have its own copy of view state. If the associated view state is large, instead of having multiple forms on a page, have a single form and use <apex:actionRegion> to submit portions of the form. This will ensure that only a single copy of the view state is associated with that page. You can find additional details on component here.

// Using two forms
<apex:page controller="MyController">

<apex:form>
<apex:commandButton action="{!saveAccount}"
value="Update Account"/>
<!--Account attributes available for editing -->

</apex:form>

<apex:form>
<apex:commandButton action="{!saveContacts}"
value="Update Contacts"/>
<!--Contact attributes available for editing -->
</apex:form>

</apex:page>
This can be combined into a single form by leveraging the <apex:actionRegion> component.
// Combining into single form and leveraging <apex:actionRegion>
<apex:page controller="MyController">
<apex:form>
<apex:commandButton action="{!saveAccount}"
value="Update Account"/>
<!--Account attributes available for editing -->

<apex:actionRegion>
<apex:commandButton action="{!saveContacts}"
value="Update Contacts"/>
<!--Contact attributes available for editing -->
</apex:actionRegion>

</apex:form>
</apex:page>


  • Declare variable as transient: An instance variable declared as transient is not saved and is not transmitted as part of the view state. If a certain field is needed only for the duration of the page request and does not need to be part of the view state, declare it as transient.

<apex:page controller="ExampleController">
The Current Time is : {!currentDateTime} <br/>
<apex:form>
<apex:commandLink value="refresh"/>
</apex:form>
</apex:page>

public class ExampleController {
transient DateTime currentDateTime;
public String getCurrentDateTime() {
if (currentDateTime == null) currentDateTime = System.now();
return '' + currentDateTime;
}
}


  • Recreate state versus storing it in view state: View state should ideally contain only work in progress data e.g. current object being edited, multi-page wizard data etc. If you can reconstruct the data during postback, via a SOQL query or a web services call, do that instead of storing it in controller data members.
  • Use custom objects or custom settings to store large quantities of read only data: Let us say that your controller needs to call a web service and parse a large response object. Storing it in view state may increase the page size. Marking it as transient would incur the cost of an additional web service call and parsing it again. In such cases, you could store the parsed response in a custom object and just use the stored record id to get to the parsed response. Custom settings provide another mechanism to cache data needed by your controller. Accessing custom settings is faster than access to custom objects since custom settings are part of your application's cache and does not require a database query to retrieve the data.
  • Refine your SOQL to only retrieve the data needed by the page: Only retrieve (and store) the fields you need and also filter the data to only retrieve data needed by the page.
  • Refactor your pages to make its view stateless: Instead of using apex:commandLink or apex:commandButton components (which needs to be inside a apex:form component) to invoke an action, use an apex:outputLink or other non action method instead and implement the action through an apex:page action attribute - where it makes sense.
  • Consider doing your own state management in certain case: In certain cases you may want to bypass the view state mechanism offered by Visualforce and do your own state management. In such cases, use a HTML FORM instead of apex:form. This technique is useful for dealing with Visualforce pages that may have to be served to mobile devices where the view state may be too large for the embedded browsers.

Summery:
Proper management of view state will really make the job of developer easier. One can control the view state and optimize its size by paying attention to transient variables, the number of forms on a page, using custom settings to store data and so on.

No comments: