本文由 Gideon(AI)翻译自英文原版。
接到那家公司的电话时,我欣喜若狂。我非常喜欢他们公司。那是一家非常年轻的公司。作为一家年轻的公司,他们行动迅速,事情总是日新月异。作为一个工作狂,我最喜欢这种环境。我热爱工作,也非常想念工作的状态。我是那种即便没有加班费,也会主动留下来工作到很晚的人——那段时间里,我会反思自己哪里可以改进,甚至思考同事做了什么值得我学习,或者我如何能从他们的错误中汲取经验。这就是我以前工作时的状态。在自学方面,我相当独立自主。我也很欣赏这家公司的文化,他们既轻松有趣,同时每个人都非常拼。“努力工作,尽情玩乐"这种模式,至少这是我对他们公司的感受。
话不多说,开始正题。
那次面试很不错。内容如下:面试涵盖了对过往经历的讨论,以及两道题目,一道与 SOQL 相关,第二道是关于触发器的。
第一题:SOQL 链接到标题
题目是:“写一个方法,返回那些商机和案例均处于开放状态的客户的 ID 列表”。这明显是一道控制器类型的问题,需要从那个角度去思考,这对我来说还好。
我们来分析一下这道题。“写一个方法,返回那些商机和案例均处于开放状态的客户的 ID 列表”。已经过了两天,我可能记不住一字不差的原题,但我知道这和他们问的非常接近。以下是我现在的思路:首先,题目要求的是一个"方法”,所以答案中必须包含方法定义;其次,再读一遍题目,我们可以列出几点关键信息:
- 需要返回客户 ID
- 条件是:“商机和案例处于开放状态”——这是一个可以向面试官追问的问题,如何判定"开放"。我回头在我的开发者组织里检查了一下,对于商机对象,目前我只有"阶段"字段,因此我将以此作为判断"开放"的依据。案例有"状态"字段,我也将以此作为依据。
- 三个对象之间的关系应该是:客户是父对象,案例和商机是子对象:

关系图(Schema Builder 截图)
现在来写代码:
// 方法定义
public static List<sobject> getAccountId() {
list<opportunity> oppList = new list<opportunity>();
list<case> caseList = new list<case>();
list<account> accountList = new list<account>();
//假设以下查询条件已知
oppList = \[Select AccountId from Opportunity where StageName = 'Open'\];
caseList = \[Select AccountId from Case where Status = 'Open'\];
accountList = \[Select Id from Account where Id in: oppList AND Id in: caseList\];
return accountList;
}
有人指出,应该使用"未关闭"而不是"状态/阶段 = 开放"作为条件,因为每个字段都有多个不代表关闭的取值。这确实是一个很好的观点,也是面试时值得向面试官提出的好问题。这不仅体现了你对条件的深入理解,也说明你在考虑所有可能的情况。
我使用"开放"的原因,主要是因为面试时题目提供了示例条件如下:
// 条件:
// Opp_status == 'Open'
// Case_status == 'Open'
正因题目已经明确说明,所以我在这里只使用了"Open"。
以上就是我的答案。如果发现任何错误,欢迎指出。
第二题:触发器 链接到标题
触发器:假设有两个对象 Parent__c 和 Child__c,当 Parent__c 上的复选框(Parent_checkbox__c)被勾选时,应自动勾选 Child__c 上的所有复选框(Child_checkbox__c)。
第一反应应该是问自己:“这个问题能用工作流规则和流程生成器解决吗?“因为能用点击配置解决的,何必写代码呢。
写触发器时,我有几个步骤可以帮助我更顺利地完成。以下是我的步骤:
- 判断这是更新还是插入?是 before 还是 after?
- 弄清楚对象之间的关系,谁是父对象,谁是子对象,以及如何访问数据
- 理清背后的逻辑
现在跟着我的思路走:
- 在我们的案例中,父对象的复选框必须先被勾选,子对象的复选框才会被勾选,因此必须是"after"触发器。所以是"after insert, after update”
- 关系很明确,父是父,子是子。因此至少需要两个列表
- 如果 parent_checkbox__c == true,则找到与该父对象关联的所有子记录,然后勾选所有 child_checkbox__c
trigger Parent\_Checkbox\_trg on Parent\_\_c (after insert, after update) {
private list<Id> parentId = new list<Id>();
for(Parent\_\_c p:trigger.new){
if(p.parent\_checkbox\_\_c==true) parentId.add(p.Id);
}
//假设 parentId 存在于子对象中
//我询问了面试官,是否只需要处理勾选所有复选框的情况,他们让我从这个场景开始
private list<Child\_\_c> childrenList = new list<Child\_\_c>();
for(Child\_\_c c:\[select id from Child\_\_c where parentId in:parentId\]){
if(c.children\_checkbox\_\_c == false) {
c.children\_checkbox\_\_c = true;
childrenList.add(c);
}
}
if(!childrenList.isEmpty()) update(childrenList);
}
以上是我对这道题的答案,下面是另一个条件——当父对象复选框取消勾选时的处理:(面试中没有涉及这部分,但以下是我的处理方式)
trigger Parent\_Checkbox\_trg on Parent\_\_c (after insert, after update) {
private list<parent\_\_c> parentList = new list<parent\_\_c>();
for(Parent\_\_c p:trigger.new){
parentList.add(p);
}
//假设 parentId 存在于子对象中
//这是复选框会自动取消勾选的情况
private list<Child\_\_c> childrenList = new list<Child\_\_c>();
for(Child\_\_c c:
\[select id from Child\_\_c where parentId in:parentList\]){
if(parentList.parent\_checkbox\_\_c == true) {
if(c.children\_checkbox\_\_c == false) {
c.children\_checkbox\_\_c = true;
childrenList.add(c);
}
}
else if(parentList.parent\_checkbox\_\_c == false) {
if(c.children\_checkbox\_\_c == true) {
c.children\_checkbox\_\_c = false;
childrenList.add(c);
}
}
}
if(!childrenList.isEmpty()) update(childrenList);
}
如果你发现任何问题或有任何建议,欢迎告诉我,我非常感激!
面试中的关键要点: 链接到标题
- 面试时保持冷静,尤其是解题类面试。
- 做真实的自己。面试官想了解真实的你,他们在寻找一个可以共事的朋友。
- 如果犯了错,没关系。解释你的思路,大声说出你的思考过程。面试官无法读你的心,你需要频繁而高效地沟通。
- 最后,也是最重要的一点:沟通。解题时永远不要停止说话。沉默在这里帮不了你,即便你需要一些时间思考,也要解释说明。
最后,我想用美剧《老友记》中的一句台词来结尾——还记得那集乔伊以为自己能演阿尔·帕西诺的替身,最后却落选的那集吗?在我找工作的过程中,我对此感同身受。请记住,你的大机遇终将到来,就像菲比说的那样:“不,我不认为这就是你唯一的机会。我甚至不认为你只有一次机会。我真心相信好事会降临到你身上,我真的相信!你只需要不断想着那一天,某个孩子会跑向他的朋友大喊:‘我拿到这个角色了!我拿到这个角色了!我要演乔伊·崔比安尼的屁股了!’“找工作的旅途很艰辛,总是夹杂着无数复杂的情绪,但永远记住:“你只需要不断想着那一天,某个孩子会跑向他的朋友大喊:‘我拿到这个角色了!我拿到这个角色了!我要演乔伊·崔比安尼的屁股了!’"(出自第一季第六集,“那集关于屁股的”)
祝大家找工作顺利!
永远记住,“你会成长的,只是需要时间”。
后记:以下是我为这次面试备考所用的所有 资料。

图片来源:Gelgas,来自 Pexels.com