Salesforce 开发整理(五)代码开发最佳实践
在Salesforce项目实施过程中,对项目代码的维护可以说占据极大的精力,无论是因为项目的迭代,还是需求的变更,甚至是项目组成员的变动,都不可避免的需要维护之前的老代码,而事实上,几乎没有任何一个项目的整个周期中,维护人员都是最初的开发人员,所以,合适的编码规范能极大的改善代码的可读性,方便其他开发者,甚至你自己在一段时间之后来阅读,维护你的代码
首先最重要的是包括对象,字段,进程生成器,工作流,class类,触发器,函数,变量在内的所有API的命名应该是“望文生义”的,也即是说,通过你的API就能推测你的函数功能
|
类型 |
规范 |
示例 |
|
对象API |
对象名称单词用下划线连接 |
WeChat_Account__c |
|
字段API |
字段名称单词用下划线连接 |
WeChat_Account_ID__c |
|
Class |
单词连写,首字母大写 |
OrderItem |
|
Trigger |
Trigger名称=对象名+Trigger |
AccountTrigger |
|
Handler |
Trigger的实现类 = Trigger名+Handler |
AccountTriggerHandler |
|
Visualforce页面 |
页面功能描述 |
OrderTracking |
|
Vf页面控制类 |
VF页面的名+Controller |
OrderTrackingController |
|
WebService Class |
类功能描述+WS |
CalculationPriceWS |
|
Batch Class |
功能描述+Batch |
AutoUpdateAccountStatusBatch |
|
Schedule Class |
功能描述+Sch |
AutoUpdateAccountStatusSch |
|
测试类 |
Test_+Class名或Trigger名 |
Test_OrderItem |
|
常量 |
全大写,单词与单词之间下划线隔开 |
PAGE_SIZE |
|
变量 |
驼峰命名法,尽可能避免单字符 |
userName |
|
方法名 |
每个方法前必须加说明包括:参数说明、返回值说明、异常说明。如果方法名实在是太长可以对变量名缩写,但是必须添加相应的说明 |
checkStatus |
上表是一些推荐的命名规范,仅供参考.
在开发的过称中,需要尽可能的减少if,for循环的嵌套,下面是一段嵌套很深的代码节选
public void updateOppInsAccShare(List<Opportunity> list_opp,Map<Id,Opportunity> map_oldOpp){
Set<Id> set_opp = new Set<Id>();
for(Opportunity op : list_opp){
Opportunity old = map_oldOpp.get(op.Id);
if(op.OwnerId != null && op.OwnerId != old.OwnerId){
set_opp.add(op.Id);
}
}
if(!set_opp.isEmpty()){
List<Opportunity> list_op = [select Id,OwnerId,AccountId,Account.OwnerId from Opportunity where Id in: set_opp];
List<AccountShare> list_share = new List<AccountShare>();
for(Opportunity op : list_op){
if(op.AccountId != null && op.Account.OwnerId != null){
for(Opportunity p : list_opp){
if(p.Id == op.Id){
//新的所有人不等于客户所有人,则创建共享
if(p.OwnerId != op.Account.OwnerId){
System.debug('============op.AccountId===' + op.AccountId + '---p.OwnerId--' + p.OwnerId + '----op.Account.OwnerId-----' + op.Account.OwnerId);
AccountShare share = new AccountShare();
share.AccountId = op.AccountId;
share.UserOrGroupId = p.OwnerId;
share.AccountAccessLevel='Edit';
share.OpportunityAccessLevel='Edit';
share.RowCause='Manual';
list_share.add(share);
break;
}
}
}
}
}
if(!list_share.isEmpty()){
insert list_share;
}
}
}
上面的代码可以看到多层逻辑嵌套,读起来不是那么的容易理解其核心逻辑,我们可以这样改写
//业务机会所有人变更,共享该业务机会对应客户的读写权限给新所有人
public void updateOppInsAccShare(List<Opportunity> list_opp,Map<Id,Opportunity> map_oldOpp){
Set<Id> set_opp = new Set<Id>();
for(Opportunity op : list_opp){
if(op.OwnerId == map_oldOpp.get(op.Id).OwnerId){
continue;
}
set_opp.add(op.Id);
}
if(set_opp.isEmpty()){
continue;
} List<Opportunity> list_op = [select Id,OwnerId,AccountId,Account.OwnerId from Opportunity where Id in: set_opp];
List<AccountShare> list_share = new List<AccountShare>(); for(Opportunity op : list_op){
if(op.AccountId == null){
continue;
}
for(Opportunity p : list_opp){
if(p.Id != op.Id && p.OwnerId == op.Account.OwnerId){
continue;
}
System.debug('============所有人变更的业务机会对应客户id===' + op.AccountId
+ '---业务机会所有人id--' + p.OwnerId
+ '----所有人变更的业务机会对应的客户所有人-----' + op.Account.OwnerId);
AccountShare share = new AccountShare();
share.AccountId = op.AccountId;
share.UserOrGroupId = p.OwnerId;
share.AccountAccessLevel='Edit';
share.OpportunityAccessLevel='Edit';
share.RowCause='Manual';
list_share.add(share);
break;
}
}
if(!list_share.isEmpty()){
insert list_share;
}
}
在原有基础上的修改如上,实质上对于权限共享的应该还包括删除原所有人的权限以及处理因所有人变更引起的业务机会读写权限缺失问题,可以参考我的博客:Salesforce 开发整理(三)权限共享
同样需要注意的一点是,避免在循环中使用SOQL查询语句以及DML操作。
Salesforce系统限制一次请求不允许超过100个SOQL查询语句,150个DML操作。下面是一个将查询和更新语句放在for循环中的操作
trigger ContactTrigger on Contact(after insert){
for(Contact c:trigger.new){
Account acc = [select id,Name from Account where id=:c.AccountId];
acc.Name = c.FirstName;
update acc;
}
}
如果一次执行的数据超过200条,那么就超出了Salesforce的限制,所以我们修改为批量的方法
trigger ContactTrigger on Contact(after insert){
//联系人关联客户id
Set<Id> accIds = new Set<Id>();
for(Contact c : trigger.new){
if(c.AccountId != null){
accIds.add(c.AccountId);
}
}
if(accids.size() > 0){
map<Id,Account> accountMap = new map<Id,Account>([select name from Account where id IN:accids]);
for(Contact c : trigger.new){
if(!accountMap.containskey(c.AccountId)){
continue;
}
accountMap.get(c.AccountId).Name = c.LastName;
}
}
if(accountMap.size() > 0) update accountMap.values();
}
同样的,在使用SOQL语句查询时,需要那些字段就查询那些字段,以提高性能。
最后是代码的注释部分
在类和Trigger的头部添加作者、创建时间、功能描述,如果此类需要修改,那么要记录修改时间,修改人,修改内容简介
/********
*
* 作者:Ricardo
* 创建时间:2018-05-31
* 功能描述:
* function1() ...
* function2() ...
* 修改人:updatePerson
* 修改时间:updateTime
* 修改内容:description
*
*****
public class PrintQuote{
////// code....
}
方法注释应该有适当的说明,位于方法声明之前,包括:说明,参数说明、异常说明、返回值说明和特别说明等
/*******
*
* 描述:单个发送邮件
* 参数:address:邮件地址
* 参数:text:邮件正文
* 返回值:发送结果
*
****/
public String SendChatter(String address,String text){
// code....
}
针对一些关键的代码逻辑,特殊的变量都应该标记上代码注释,但是需要避免的是写太多无用的代码注释,否则跟不写注释的效果不没有太大的差异
最后是关于在开发中使用RecordTypeId,UserId,记录ID以及角色名称,用户名称等硬码,如果确定有特殊需要,可以使用自定义设置进行配置
开发时适当的遵循编码规范,可以写出简洁,易读,扩展性强,结构好的代码,既有助于自己编码习惯的养成,也能有效降低开发维护的难度,可以说是很有必要的。
以上如有错漏,欢迎指正,如有疑问,欢迎评论区留言探讨
推荐一些Salesforce编码最佳实践的网站
Force.com Apex Code Best Practices
SOQL(Salesforce Object Query Language)查询
SOOSL(Salesforce Object Search Language)查询
Salesforce 开发整理(五)代码开发最佳实践的更多相关文章
- (转载)PyTorch代码规范最佳实践和样式指南
A PyTorch Tools, best practices & Styleguide 中文版:PyTorch代码规范最佳实践和样式指南 This is not an official st ...
- Java Servlet开发的轻量级MVC框架最佳实践
在Servlet开发的工程实践中,为了减少过多的业务Servlet编写,会采用构建公共Servlet的方式,通过反射来搭建轻量级的MVC框架,从而加快应用开发. 关于Servlet开发的基础知识,请看 ...
- 前端代码标准最佳实践:CSS
前端工程师对写标准的前端代码的重视程度很高.这些最佳标准实践并不是那个权威组织发布的,而是由大量的前端工程师们在实践过程中的经验总结,目的在于提高代码的可读性,可维护性和性能.那么接着上一篇,我们再来 ...
- [libgdx游戏开发教程]使用Libgdx进行游戏开发(7)-屏幕布局的最佳实践
管理多个屏幕 我们的菜单屏有2个按钮,一个play一个option.option里就是一些开关的设置,比如音乐音效等.这些设置将会保存到Preferences中. 多屏幕切换是游戏的基本机制,Libg ...
- React 代码共享最佳实践方式
任何一个项目发展到一定复杂性的时候,必然会面临逻辑复用的问题.在React中实现逻辑复用通常有以下几种方式:Mixin.高阶组件(HOC).修饰器(decorator).Render Props.Ho ...
- 【转】Git代码提交最佳实践
GIT Commit Good Practice The following document is based on experience doing code development, bug ...
- nodejs 后台开发 和C++代码开发
https://www.npmjs.com/package/node-gyp node-gyp Node.js native addon build tool Node.js native addon ...
- 编写高性能Java代码的最佳实践
博客地址: http://blog.csdn.net/dev_csdn/article/details/79033972
- Web前端开发最佳实践(1):前端开发概述
引言 我从07年开始进入博客园,从最开始阅读别人的文章到自己开始尝试表达一些自己对技术的看法.可以说,博客园是我参与技术讨论的一个主要的平台.在这其间,随着接触技术的广度和深度的增加,也写了一些得到了 ...
- YonBuilder低代码开发实践:4行代码实现跨实体列表数据同步
提到增.删.改.查等数据维护,后端开发者们再熟悉不过了.传统的数据维护通过操作数据库的方式实现,步骤比较繁琐,需要通过Java代码实现数据库链接,然后编写SQL语句.编写实体,将想要的数据存到相应的数 ...
随机推荐
- java8 List集合的排序,求和,取最大值,按照条件过滤
public class Java8Test { public static void main(String[] args) { Person p1 = new Pe ...
- Redis(六)Lua脚本的支持
Redis为什么需要Lua脚本的支持 当应用需要Redis完成一些Redis命令不支持的特性时,要么扩展Redis client或者更甚至编写c扩展Redis server.这都大大造成了应用的实现的 ...
- python输入一个字符串,输出翻转后的字符串(翻转字符串)
题目:输出一个字符串,输出翻转后的字符串.例如:输入字符串a123,输出321a. 方法一:使用列表的reverse方法 string=input('请输入一个字符串:') lst=list(stri ...
- 阿里OSS前端直传
第一次写博客,如有错误请多多指教. 先上代码吧: ossUpload = function (file, fun, funParameter) { //第一此请求后台服务器获取认证请求 $.ajax( ...
- 架构师小跟班:教你从零开始申请和配置七牛云免费OSS对象存储(不能再详细了)
背景 之前为了练习Linux系统使用,在阿里云上低价买了一台服务器(网站首页有活动链接,传送门),心里想反正闲着也是闲着,就放了一个网站上去.现在随着数据越来越多,服务器空间越来越吃紧,我就考虑使用七 ...
- electron项目中使用js web worker时,new worker(path)路径问题
如题,在new worker时需要传入js文件路径,可是在electron环境中使用出现问.同目录下,recorder.jsworker.js recorder.js中调用 var path = '. ...
- i春秋——“百度杯”CTF比赛 十月场——Login
根据页面源码提示的 test1 test1 登录 刷新此页面并抓包,有个show=0值得关注 在发送的包的header中加一句show:1,即可得到member.php的源码 <?php inc ...
- Vue+element 修改样式的scoped穿透方法
我们在修改element的一些样式的时候,在加了scoped的时候会不起作用,下面是解决方案: 解决方法:起一个类名将页面包裹起来,后面加 /deep/ <style scoped> 1 ...
- 探秘JVM的底层奥秘
JVM的简单运行流程:主要将字节码文件加载到JVM的内存中,负责跨平台解释字节码文件到不同的操作系统. JVM的基本结构: 类加载器.执行引擎.运行时数据区域.本地接口 类的装载 加载.连接(验证.准 ...
- OAuth 2.0 的四种授权模式
RFC 6749 OAuth 2.0 的标准是 RFC 6749 文件.该文件先解释了 OAuth 是什么. OAuth 引入了一个授权层,用来分离两种不同的角色:客户端和资源所有者.......资源 ...