7 Habits of Highly Efficient Visualforce Pages

6,547 views

Published on

0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,547
On SlideShare
0
From Embeds
0
Number of Embeds
12
Actions
Shares
0
Downloads
277
Comments
0
Likes
8
Embeds 0
No embeds

No notes for slide

7 Habits of Highly Efficient Visualforce Pages

  1. 1. 7 Habits of Highly EfficientVisualforce PagesHow to Not Shoot Yourself in the Foot with VisualforceEric Wilson, salesforce.comDirector, Product Management - UI Platforms
  2. 2. Safe Harbor Safe harbor statement under the Private Securities Litigation Reform Act of 1995: This presentation may contain forward-looking statements that involve risks, uncertainties, and assumptions. If any such uncertainties materialize or if any of the assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results expressed or implied by the forward-looking statements we make. All statements other than statements of historical fact could be deemed forward-looking, including any projections of product or service availability, subscriber growth, earnings, revenues, or other financial items and any statements regarding strategies or plans of management for future operations, statements of belief, any statements concerning new, planned, or upgraded services or technology developments and customer contracts or use of our services. The risks and uncertainties referred to above include – but are not limited to – risks associated with developing and delivering new functionality for our service, new products and services, our new business model, our past operating losses, possible fluctuations in our operating results and rate of growth, interruptions or delays in our Web hosting, breach of our security measures, the outcome of intellectual property and other litigation, risks associated with possible mergers and acquisitions, the immature market in which we operate, our relatively limited operating history, our ability to expand, retain, and motivate our employees and manage our growth, new releases of our service and successful customer deployment, our limited history reselling non-salesforce.com products, and utilization and selling to larger enterprise customers. Further information on potential factors that could affect the financial results of salesforce.com, inc. is included in our annual report on Form 10-Q for the most recent fiscal quarter ended July 31, 2012. This documents and others containing important disclosures are available on the SEC Filings section of the Investor Information section of our Web site. Any unreleased services or features referenced in this or other presentations, press releases or public statements are not currently available and may not be delivered on time or at all. Customers who purchase our services should make the purchase decisions based upon features that are currently available. Salesforce.com, inc. assumes no obligation and does not intend to update these forward- looking statements.
  3. 3. Eric WilsonDirector, Product ManagementUI Platforms
  4. 4. About Me Product Manager for All Salesforce UI Development Platforms 10+ Years @ Salesforce Application Instructor UI Developer Interaction Designer Product Manager
  5. 5. Highly Efficient Visualforce Pages......Have Rock-Solid HTML, CSS, & JavaScript
  6. 6. If You Don’t Know Basic Web Technologies...
  7. 7. Pop Quiz!
  8. 8. What’s Wrong With This HTML? <table> <tr> <td class="header" colspan="2">...</td> </tr> <tr> <td class="sidebar">...</td> <td class="content">...</td> </tr> <tr> <td class="footer" colspan="2">...</td> </tr> </table>
  9. 9. What’s Wrong With This CSS? .button { background: #F8F8F8; background: -webkit-linear-gradient(#F8F8F8, #D4DADC); background: -moz-linear-gradient(#F8F8F8, #D4DADC); background: -o-linear-gradient(#F8F8F8, #D4DADC); background: -ms-linear-gradient(#F8F8F8, #D4DADC); background: linear-gradient(#F8F8F8, #D4DADC); filter: progid:DXImageTransform.Microsoft.gradient(...); }
  10. 10. What’s Wrong With This JavaScript? function getTotalSum(itemArray) { var sum = 0; for (var item in itemArray) { sum += item; } return sum; }
  11. 11. Highly Efficient Visualforce Pages... ...Do Not Support aSingle, Pixel-Perfect UI on Every Browser
  12. 12. Theory A: One UI to Rule Them All
  13. 13. Theory A: One UI to Rule Them All .button { background: #F8F8F8 url("...") left top repeat-x; background: -webkit-linear-gradient(#F8F8F8, #D4DADC); background: -moz-linear-gradient(#F8F8F8, #D4DADC); background: -o-linear-gradient(#F8F8F8, #D4DADC); background: -ms-linear-gradient(#F8F8F8, #D4DADC); background: linear-gradient(#F8F8F8, #D4DADC); filter: progid:DXImageTransform.Microsoft.gradient(...); }
  14. 14. Theory A: One UI to Rule Them AllQ: Why Is This Bad?A: Fragmentation (Code Maintenance), Performance  Browser-specific HTML  Browser-specific CSS  Browser-specific JavaScript  Unnecessary HTTP Requests (Makes Mobile Sad)
  15. 15. Theory B: It’s OK To Be Different
  16. 16. Theory B: It’s OK To Be Different .button { background: #F8F8F8 url("...") left top repeat-x; background: -webkit-linear-gradient(#F8F8F8, #D4DADC); background: -moz-linear-gradient(#F8F8F8, #D4DADC); background: -o-linear-gradient(#F8F8F8, #D4DADC); background: -ms-linear-gradient(#F8F8F8, #D4DADC); background: linear-gradient(#F8F8F8, #D4DADC); filter: progid:DXImageTransform.Microsoft.gradient(...); }
  17. 17. Theory B: It’s OK To Be Different .button { background: #F8F8F8 url("...") left top repeat-x; background: -webkit-linear-gradient(#F8F8F8, #D4DADC); background: -moz-linear-gradient(#F8F8F8, #D4DADC); background: -o-linear-gradient(#F8F8F8, #D4DADC); background: -ms-linear-gradient(#F8F8F8, #D4DADC); background: linear-gradient(#F8F8F8, #D4DADC); }
  18. 18. Theory B: It’s OK To Be Different .button { background: #F8F8F8 url("...") left top repeat-x; background: -webkit-linear-gradient(#F8F8F8, #D4DADC); background: -moz-linear-gradient(#F8F8F8, #D4DADC); background: -o-linear-gradient(#F8F8F8, #D4DADC); background: -ms-linear-gradient(#F8F8F8, #D4DADC); background: linear-gradient(#F8F8F8, #D4DADC); }
  19. 19. Theory B: It’s OK To Be Different .button { background: ; #F8F8F8 background: -webkit-linear-gradient(#F8F8F8, #D4DADC); background: -moz-linear-gradient(#F8F8F8, #D4DADC); background: -o-linear-gradient(#F8F8F8, #D4DADC); background: -ms-linear-gradient(#F8F8F8, #D4DADC); background: linear-gradient(#F8F8F8, #D4DADC); }
  20. 20. Highly Efficient Visualforce Pages... ...Are Stateless,Don’t Poll Our Servers,and Defer Difficult Work
  21. 21. Stateless / Non-Polling / Deferring TechniquesUse the transient Keyword (Reduces Viewstate)Implement Visualforce Remoting (Reduces Viewstate)Use the Streaming API (Removes Need for Polling)Use @future Annotation (Executes Apex Asynchronously)
  22. 22. transient Keyword: The Example
  23. 23. transient Keyword: The Apex ClassBEFORE public with sharing class EditClientController { public Contact client { get; set; } public List<Contact> connections { get; set; } public List<Account> previousEmployers { get; set; } public Set<String> hashTags { get; set; } }
  24. 24. transient Keyword: The ViewstateBEFORE
  25. 25. transient Keyword: The Apex ClassAFTER public with sharing class EditClientController { public Contact client { get; set; } transient public List<Contact> connections { get; set; } transient public List<Account> previousEmployers { get; set; } transient public Set<String> hashTags { get; set; } }
  26. 26. transient Keyword: The ViewstateAFTER <input type="hidden" id="com.salesforce.visualforce.ViewState" name="com.salesforce.visualforce.ViewState" value="fMiWLUoSiUjWyBHX9fDk1eLUrkW+FrZ1mLRQEcDZv4ocKNGwrFcWs+v0EzuEiisflTMEci830WiYmlUP9LB7VaxOURd20gbjZdaW+rTM9rhSEgwHsAv5csZFYy0ILY9urD0/9ekk26o5GJJ/7mJB8UVmTU4bAPCj27mq+y9WTO PPeHAF6MXBUt16MTNlzoVlWTUEKuvFwhz/GZoApQoL8KmHqaP9kYWcSbsormJB8hNdWQpLh2ayKNfAcKyNk+xrDQVlQAMcAog12mixM97l2FOfcpKtTQF33zRVloMx2mYKst9tTps4VykwyQK7tXjhT9DKG8RvQ1jLk5vgQRGD/Is9nNw z1v0zwpl9h+dEJOoHzxaIv7fwJKdjxjlJ35qsVhUaAdUSKDlbI8iW+l25aWlWTcWFKU1Sprdq5mix8MGjpDkwdhCEFdhGTUpcFkVTIfBDqbTJXQ1Xkx3cuqLqn52TMNFrTjgH2AASjo1DQONlbajQXW/KbCAKPqzx1lRqFIZrn4cpVGzV Xk+CXzROAQwKwBPIenKeNNmZKy/8pTB79U7FWH5Jlm346EvCDS4M3F1B6Z73gfiWany5DqjAkNPRED6YFcTaGrV3Asguqth73d664RiWn7wldBMnl0CSdqL6PFnXvVq958kNZuVtTbNTCMwcfSzD3QvHsUJWVRuMYKRL3UlXBl0bid9VS ViFGMlwTLIj0g3yjpPLvtbaDME1J6VgkXU/C8MGBPcFCkW9v6XummLawdx4jIiwha8jIzJXqZALXJlTap8M1fJGOmxQuO5e0Na4b5RCWJWET+rLdNI5iizosTAt29aJLWdi5LYCsw1iDnWQB4X4VsF2P0ZDwK50xX/x/PrVj9TiuPXrWW Riolzb8gqbJXEV1a8i+AuU/SHhaK+eEdQH/CDy9hABrTaa2FijLx3GOGUP0LxItdZbQbSsIwAqE/U/mFYgEdqFkuo85Lyv6qAyCZFIN/vuNf3SbvuHDjjBGJni8zCwev8iU6LJM3cSy73mWK23HxydSraCpIYFZSbkrfSnlG1Ie7vNG9t RTE+TKstXAPzVCL8egJfBSTLE2IvKHKvFiQoNpNZKPeQchse027RjxzCGVAN8zmrNx2kxdTY6waDStw2Etj0fJsXbE9Us1wnk+YSAQARdQv/5cdZ/TiCX5mZ4lct2sP2B+8KsfpCi7SOYeXMhfZnvNkgT4xrDL/8PCV7FKRa0mR6sYRQt sFQXgbRQCGG3WGGMRrQNCpG+jM0BZvScsjXnBrlmyoqs4XIVyYRBo7ZAA9pJcIdxX79AzWgzFxL14G4n7uzl2lzjllOHe+qh7xLXNkFOQAiq5UIQhyWyU54VZjkwT2JatJteLfqU1ChtZDZ8jmmbRk7WejKlAW00MLN7ep2AGWJC0fek3 VSdtn+dJoTHDnsH3Lj6OtlS2zUVaQgvrL8S9YYF/m+lCpLTKKRKmt7jbOVjlmJ4gQvp7Uf0LLsh9gROLWpHCnwxy5oYoRhLVVNLUak6niRI8LGqGG0StT0HBnHQsy9nT+01Hnv7P4Bm41NBrV/MaVxxal/Q23Uq+00W8T4k/yox5+hxHX RU7XF6rYx0/nNdIFvPWlU2He4JkPskiglpr3X9Gxdq9YgaANh7kgZRjdZAZW7lFlqT6io1HpscnUNv6hN8tv19HWLVwD+SsB1MKlsxgX0pbPDikQEQPo4CrT8kojE89PPQdbFJ8wbu2rHykJh3o5OhokQlgYc+ICVxp4mfrqFFOP7I6U+ g/z+mcrvDCTnTTzTwsxEIziwhwrWEYhM7P4cyOlqGtiZ1KaBGWe6Lmt4FEOPdmMB3poXg1zThQSbeZBSDYYYb5w/aSUZ+4OYeDPjReYOql3/dhUGB8+awOa+xXGIvCpprefZ9lsDpUYXMJasgUojt++7wCcYFSfRngvRKf/Jgy1uj3VEx SOFtarhoXams6oZNCtkvjkXER6qZStgdG++8ZkVwKRRYur8k06UDRmAUwVrKiwN+s1NynFq/xIhaAWcSoQA+M1F1HA7Kx1oQ112GK1Crr7wI0BT5vmtnrd7PwpJYSg/wM9vzmCI3f3s8Zck45zUYAt+XyvgHr2aOTxVeQ6bwOyT0lTEZ1 zHAH+y5ZAnkFIrb+Lyds7dK0Mwl6SJKu7XZ+jo0M+mGWxY1cVaFahn6vfctSBakb62qrWwAjmBJ08cDVJn0H+n3LuSR1lwkhOhNti5xnpke6iXVs0KHhuU8uBHi6ch3lrJB4CFEPSSX2EXI6tBcGHZAsafvJQxhDaSL5VARk5GLI++ziP rxd5E/UYOm9Vp5N6NX9REbXjwNCoyWvUInU/E8yBJbixXGJ4VqG8CpM8ZPoeCfJXl99a3A02nufVrvn9JarCpRfVNw4anZ3rd3jIOBxr3GCdKMelW/ujtM3v2T+v0WOloGS//lv8ReFZZmE+p6UQaQh+6RrqsJid/9Ovu8ADXhQdSdZJ1 COrP5wFus9GOYsdFBh2nDGIWs7ZirdXZ7+XFzGvWzAnaaoBDH6h59Sg3OUbSmf8Q+0SKPe4PPhnui3fQAAtlOISNhr+EALVSY+NRRFUytaLs716zLRXVFO4WHFh4c1p/45JUwYz1ALUKS4++QCNidbMzfkyhfSbcETmuz1Se4N2SDymzx 4+mwBuk/SqVrVJOqoLSyGWou0sHvfYfdusQA5akx03ka5xISMDM9xequmuF88mn9IGktWrZWbfUCc/xV/hjqrhFZIK1f1F83G86OjmWTTDWmP11OCrkKeLRhj6WDsRlv4MyepIi0tUiVWwUUtXPL/sKVL1FcGPjpEugiIs0wMtm9dhcq8 /EnhmCep/Gxs+gU1bz9rSjW+mCjMkPzPR11XewCisKewWskx6PzHPHSqM614w9l7O1m901kwG94aQ==">
  27. 27. transient Keyword: The Results BEFORE AFTER 58%
  28. 28. Visualforce Remoting: The Example Find Customer: <apex:actionFunction ... /> <apex:actionRegion ... /> Visualforce Remoting <apex:actionSupport ... />
  29. 29. Visualforce Remoting: The Lifecycle JS Function Apex Method Client-side JS Callback Server-side
  30. 30. JS FunctionApex MethodJS Callback
  31. 31. Visualforce Remoting: The Page<apex:page controller="FindCustomerController"> <input id="searchField" type="text" placeholder="Enter Last Name"/> <button onclick="findMeSomeCustomers();">Search</button> <table> <tbody id="results"></tbody> </table></apex:page> JS Function Apex Method JS Callback
  32. 32. Visualforce Remoting: The Page<apex:page controller="FindCustomerController"> <input id="searchField" type="text" placeholder="Enter Last Name"/> <button onclick="findMeSomeCustomers();">Search</button> <table> <tbody id="results"></tbody> </table></apex:page> JS Function Apex Method JS Callback
  33. 33. Visualforce Remoting: The JavaScript Controller function findMeSomeCustomers() { var searchTerm = document.getElementById("searchField").value; FindCustomerController.doSearch(searchTerm, renderResults); } JS Function Apex Method JS Callback
  34. 34. Visualforce Remoting: The JavaScript Controller function findMeSomeCustomers() { var searchTerm = document.getElementById("searchField").value; FindCustomerController.doSearch(searchTerm, renderResults); } Apex Class Apex Method Apex Method Parameter JS Callback Function JS Function Apex Method JS Callback
  35. 35. Visualforce Remoting: The Apex Classpublic with sharing class FindCustomerController { @RemoteAction public static List<Contact> doSearch(String customerLastName) { customerLastName = % + customerLastName + %; return [ SELECT id, FirstName, LastName FROM Contact WHERE LastName LIKE :customerLastName LIMIT 200 ]; } JS Function Apex Method} JS Callback
  36. 36. Visualforce Remoting: The Apex Classpublic with sharing class FindCustomerController { @RemoteAction public static List<Contact> doSearch(String customerLastName) { customerLastName = % + customerLastName + %; return [ SELECT id, FirstName, LastName FROM Contact WHERE LastName LIKE :customerLastName LIMIT 200 ]; } JS Function Apex Method} JS Callback
  37. 37. Visualforce Remoting: The JavaScript Callbackfunction renderResults(results, event) { var container = document.getElementById("results"), html = []; for (var i=0, j=results.length; i<j; i++) { html.push("<tr><td>"); html.push(results[i].LastName + ", " + results[i].FirstName); html.push("</td></tr>"); } container.innerHTML = html.join("");} JS Function Apex Method JS Callback
  38. 38. Visualforce Remoting: The Results JS Function Apex Method JS Callback
  39. 39. Visualforce Remoting: The Results BEFORE AFTER 234ms 152ms 35%
  40. 40. Visualforce Remoting: The Difference <apex:action*/> Visualforce Remoting Uses Viewstate No Viewstate Indirect Parameter Passing Direct Parameter Passing Visualforce Handles Re-rendering You Handle Re-rendering Less Flexibility More Flexibilty
  41. 41. Streaming API: The Example New Accounts Show Up Here...
  42. 42. Streaming API: The Page BEFORE<apex:page controller="NewAccountsController"><apex:form> <apex:actionPoller action="{!find}" rerender="wrapper" interval="15"/> <h1>Streaming API Example</h1> <h2>New Accounts</h2> <apex:outputPanel id="wrapper"></apex:outputPanel></apex:form></apex:page>
  43. 43. Streaming API: The Page AFTER<apex:page controller="NewAccountsController"> <apex:includeScript value="..."/> <!-- 4 js files needed --> <h1>Streaming API Example</h1> <h2>New Accounts</h2> <div id="wrapper"></div> <script>... $.cometd.init(...) $.cometd.subscribe(...) ...</script></apex:page>
  44. 44. Streaming API Demo
  45. 45. Streaming API: Steps to UseDefine SOQL QueryCreate a PushTopic RecordInclude Necessary JavaScript Libraries on Visualforce PageCall cometd’s init(...) and subscribe(...) Functions (Inline JS)Watch Magic Happen
  46. 46. Streaming API: The Difference <apex:actionPoller/> Streaming API Uses Viewstate No Viewstate Uses Polling Method Uses Pub/Sub Method XHR Happens Always XHR Happens Only When It Has To All Apex-Exposed SObjects Available Subset of Apex-Exposed SObjects
  47. 47. Asynchronous @future: Why Does It Matter? Perceived performance is more important than actual performance.
  48. 48. Asynchronous @future: The Apex Class public with sharing class SendInvoiceController{ @RemoteAction public static String requestAllInvoices(String customerId) { sendAllInvoices(customerId); return(All invoices have been requested.); } @future public static void sendAllInvoices(String customerId) { EmailHelper.emailCustomerInvoices(customerId); } }
  49. 49. Asynchronous @future: The Difference Synchronous Asynchronous User Must Wait for Server Response Returns UI Control Immediately Slower Perceived Performance Faster Perceived Performance
  50. 50. Highly Efficient Visualforce Pages......Have Optimized SOQL
  51. 51. Optimized SOQL: The Basics Place SOQL Queries Outside Loops Use WHERE Clauses Use Indexed Fields in WHERE Clauses Use LIMIT Use OFFSET Use COUNT() (...or other aggregation functions, when possible) NEW! Use FOR VIEW (...MRU API Pilot - adds items to MRU list)
  52. 52. Optimized SOQL: Loopspublic List<Invoice__c> getFamilyInvoices() { List<Invoice__c> invoices = new List<Invoice__c>(); for (Contact c : this.contacts) { invoices.addAll( [SELECT id FROM Invoice__c WHERE Client__c = :c.id] ); } return invoices;}
  53. 53. Optimized SOQL: Loopspublic List<Invoice__c> getFamilyInvoices() { List<Invoice__c> invoices = new List<Invoice__c>(); List<Id> contactIds = new List<Id>(); for (Contact c : this.contacts) { contactIds.add(c.id); } invoices.addAll( [SELECT id FROM Invoice__c WHERE Client__c IN :contactIds] ); return invoices;}
  54. 54. Optimized SOQL: WHERE Clauses public List<Contact> getContacts() { return [ SELECT id, lastName FROM Contact ]; }
  55. 55. Optimized SOQL: WHERE Clauses public List<Contact> getContacts() { return [ SELECT id, lastName FROM Contact WHERE CreatedDate > LAST_N_DAYS:365 ]; }
  56. 56. Highly Efficient Visualforce Pages... ...Use Standard Set Controllers
  57. 57. Standard Set Controllers Optimized for Large Data Sets Play Nicely With Salesforce List Views Provide Robust Paging Capabilities Should Be Used Liberally
  58. 58. Highly Efficient Visualforce Pages......Aren’t Kitchen Sinks
  59. 59. Don’t Do This...
  60. 60. ...Because Here Are Your Limits... Viewstate: 135K Total Page Size: 15MB (!!!)
  61. 61. Bottom Line: Less is More
  62. 62. Highly Efficient Visualforce Pages... ...Do Not Use Any Salesforce Resources
  63. 63. Um, OK, But Why?Sheer SizeNo Developer Support
  64. 64. Salesforce Resource Size
  65. 65. How Do I Not Use Salesforce Resources? <apex:page showHeader="false" standardStylesheets="false"> ... </apex:page>
  66. 66. Developer Support Salesforce Resources Are Not Supported APIs
  67. 67. Eric WilsonDirector, Product Management UI Platforms

×