关于Stub API

Spring’17,Salesforce为开发者提供了一个强大的工具,Apex STUB API

看完官方文档提供的例子之后,感觉确实很美好,但又觉得没什么机会用。
不同于Java项目对框架和设计模式的极致追求。
我接手的Apex代码均为意识流散文诗式写法。根本没有抽象化,解耦等操作。

Stub Api是基于Java的Mocking Framework
mockito开发的。
使用Mocking Framework的前提是代码必须进行解耦,就是所谓的依赖注入(Dependency Injection)。
要求代码不能按业务直接写成流水账,而是将模块之间的强依赖解开。

比如,A类的构造强依赖与B类,如果没有B则没有A。

A a = new A();
//-----------------------------------
Class A {
    private B b;
    public A() {
        b = new B();
    }
    public String getName() {
        return b.getName();
    }
}

Class B {
   public String getName() {
       return "I'm the B";
   }
}

那么,问题来了,如果我有一个C类,返回“I’m the C”,我就要为C类新建一个A1类,在A1类中将A1与C进行强依赖。
如果需求越来越多,代码也随时越来越膨胀。
那么怎么改变这个局面呢?

B b = new B();
A a = new A(b);
-----------------------------------------------
Class A {
    private CustomObject co;
    public A(CustomObject cObj) {
        this.co = cObj;
    }
    public String getName() {
        reutrn co.Name;
    }
}

Class B extends CustomObject {
    public String getName() {
        return "I'm the B";
    }
}
abstract Class CustomObject {
    abstract public String getName();
}

这样一来,A和B的强依赖就解耦了,不再是每次new一个A,就必然得到B的内容,而是根据我传进去的B来决定A返回的内容。
如果想返回“I’m the C”,就不用再去新建一个A1类,想返回“I’m the D”,不用再去新建一个A2类。

只有依赖注入的写法才能进行方便的Mocking。

Stub Api可以做到的是,在解耦之后,为A类mock一个B类,C类。做到完美的单元测试(模块隔离)。
Whatever,用不上。至今还没见到过有控制反转思想的的Apex。
说句题外话,apex-enterprise-patterns(官方介绍文章)到现在还没推广开呢。

// 未完待续

Salesforce的StandardSetController使用Demo

先放Github地址
https://github.com/Kealthals/Salesforce-StandardSetControllerDemo.git

事情起因,是有人问我为什么StandardSetController无法保存Selected状态。
我觉得既然标准List View可以,那么使用StandardSetController应该也可以。
虽然这个Class我用的也不多,但还是动手写个一个小Demo验证了一下我的想法,虽然花了些小心思,但证明确实可行。
验证完毕,转念一想,既然已经动手了,就干脆把所有的methods都演示一遍吧。权当给自己留一个财富。

StandardController大家都比较熟悉,用来处理单条数据。模拟的是Create/Edit页面和Detail页面。
StandardSetController用的不多,因为模拟的是List View页面。标准List View页面已经很强大了,很少会遇到这种需求。
这个Demo也就是尽量做一个和标准List View类似的页面,时间有限,肯定做不到标准页面一般的好看和完美。
最低目标是将这个Class提供的method都使用一遍,除了一个不明所以的method之外,最低目标我觉得是完成了。
功能上,也提供了基本的
1. 罗列数据
2. 翻页
3. 选择数据(Selected)
4. 选择List View
5. 改变Page Size
6. 跳转指定页
7. Inline Edit(还不完美)
作为一个独立功能来讲,勉强达到了凑合着用的程度。
在功能实现的时候,又不断遇到了一些或新或旧的小问题,在大家的帮助下都找了比较好的小方案解决掉了这些小问题。
比如SFDC的autofocus,inputtext的输入类型限制等等。

继续阅读“Salesforce的StandardSetController使用Demo”

如何优雅的干掉VF的autofocus

How to remove VF input field’s autofocus?
最近在写StandardSetController Demo的时候遇到了一个逼死完美主义者的问题。
在VF加载之后,SFDC会非常Nice的,热心的,把第一个文本输入框设为焦点。
我推测sfdc的产品设计逻辑是下面这样的。
嗯。。。你设置一个输入框,代表着用户一定得输入点什么才能继续。
既然用户必须输入点什么的话,那么就必须用鼠标点一下这个输入框。
那么让我们来做点什么吧,帮用户先把输入框点上怎么样,节省用户的操作。
看呐,如果用户双手都在键盘上,他们连右手离开键盘的工夫都省下来了,用户一定会非常满意的。

对于大部分业务场景,这个贴心的小设计确实很有用。但有的时候会起反作用。
比如我的StandardSetController的Demo。
在List View画面,一般只有在数据列表最下方才有输入框,为了输入Page Size或者Page No。
但是不碰这几个输入框并不影响我使用List View。
不过,当默认Page Size非常大,画面超出一屏的时候,由于sfdc自动把第一个输入框设成焦点,导致画面滚动条直接被拖到了滚动条最下面。
还有当VF的第一个input项目是Date型的时候,sfdc的自动设置焦点机制,会触发datepicker,就像大晴天自动弹开的雨伞一样,造成另一场灾难。

研究了半天,虽然标准List View并没有这个问题,但还是没有找到比较官方的解决方法。
只好Hack一下了。

在VF中插入

   <script>
        function setFocusOnLoad() {}
    </script>

问题完美解决。