I haven't seen an Apex linter and was wondering if anyone knew of one or had repurposed a Java linter? I'm so used to having this available when writing JavaScript or Ruby, it would be awesome to see the same reminders while coding Apex.
[SalesForce] n Apex Linter out there
Related Solutions
Have a look into Andrew Fawcett's Enterprise Design Patterns Dreamforce Session, especially the Data Mapper (Selector) part
Source and links to the Video: https://github.com/financialforcedev/df12-apex-enterprise-patterns
In addition check out https://github.com/apex-commons/SoqlBuilder (former apex-lang) on Github.
Regarding your concerns
governor limits (I sometimes need only a couple of fields)
shouldnt be a problem, as long as you dont 'lazy load' in for loops (e.g. retrieve 200 accounts and query contacts for each account)
flexibility (it is not clear in advance which fields and conditions will be needed. It would be great to have a generic DAO from which other classes would inherit)
Andrew's sObjectSelector in combination with apex-commons SoqlBuilder should do the trick
security (I imagine a lot of dynamic SOQL would have to be used)
use
public class MysObjectSelector {}
for your DAO/Selector, so you can enforce sharing rules or not depending on the context. For example your triggers run in system mode, so should your selector, but when using a visualforce controller you might want to enforce sharing by using
public with sharing class MyVisualforceController{}
Although finding elements by ID is the first approach to consider, it is also possible to find elements by other attributes including their CSS class. You can add a class (that has no associated styling), and use the class names to find the elements.
For your situation where the field names are coming from a custom setting, using the class names to do the matching works well because you can just use the field name as the class name. (Visualforce does not allow ID values to be expressions.) Adding jQuery into the mix ensures that the code works well across multiple browsers.
Controller:
public with sharing class MyController {
public String[] fromFields {
get {
return new String[] {'BillingStreet', 'BillingState'};
}
}
public String[] toFields {
get {
return new String[] {'ShippingStreet', 'ShippingState'};
}
}
public MyController(ApexPages.StandardController sc) {
String[] fields = new String[] {};
fields.addAll(fromFields);
fields.addAll(toFields);
sc.addFields(fields);
}
}
Page:
<apex:page standardController="Account" extensions="MyController">
<apex:form>
<apex:pageBlock>
<apex:pageBlockButtons>
<apex:outputLink styleClass="copyLink">Copy</apex:outputLink>
</apex:pageBlockButtons>
<apex:pageBlockSection>
<apex:repeat value="{!fromFields}" var ="f">
<apex:inputField value="{!Account[f]}" styleClass="{!f}"/>
</apex:repeat>
<apex:repeat value="{!toFields}" var ="f">
<apex:inputField value="{!Account[f]}" styleClass="{!f}"/>
</apex:repeat>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
<apex:includeScript value="//code.jquery.com/jquery-1.11.0.min.js"/>
<script>
var j$ = jQuery.noConflict();
j$(document).ready(function() {
j$('.copyLink').click(function(e) {
var fromFields = [<apex:repeat value="{!fromFields}" var ="f">'{!f}',</apex:repeat>];
var toFields = [<apex:repeat value="{!toFields}" var ="f">'{!f}',</apex:repeat>];
for (var i = 0; i < fromFields.length; i++) {
j$('.' + toFields[i]).val(j$('.' + fromFields[i]).val());
}
e.preventDefault();
});
});
</script>
</apex:page>
PS
This is one way of having a named function that you can also invoke in oncomplete
:
<apex:actionSupport ... oncomplete="addClick()"/>
...
<script>
var j$ = jQuery.noConflict();
var addClick = function() {
j$('.copyLink').click(function(e) {
var fromFields = [<apex:repeat value="{!fromFields}" var ="f">'{!f}',</apex:repeat>];
var toFields = [<apex:repeat value="{!toFields}" var ="f">'{!f}',</apex:repeat>];
for (var i = 0; i < fromFields.length; i++) {
j$('.' + toFields[i]).val(j$('.' + fromFields[i]).val());
}
e.preventDefault();
});
};
j$(document).ready(addClick);
</script>
Related Topic
- [SalesForce] Rest HttpRequest to outside system
- [SalesForce] Critical update: “Predictable Iteration Order for Apex Unordered Collections” documentation
- [SalesForce] specific reason why we can’t upcast Sets
- [SalesForce] How to properly deserialize json into Apex classes and inner classes
- SOQL SubQuery Parent-to-child-Junction Returns Child Records in Query Editor but not Apex. Any Idea why
Best Answer
There's PMD Apex, which has a bunch of linting, plus various rules for SOQL inside loops, etc. That's the only one I'm aware of today.