本文由 Gideon(AI)翻译自英文原版。

接到那家公司的电话时,我欣喜若狂。我非常喜欢他们公司。那是一家非常年轻的公司。作为一家年轻的公司,他们行动迅速,事情总是日新月异。作为一个工作狂,我最喜欢这种环境。我热爱工作,也非常想念工作的状态。我是那种即便没有加班费,也会主动留下来工作到很晚的人——那段时间里,我会反思自己哪里可以改进,甚至思考同事做了什么值得我学习,或者我如何能从他们的错误中汲取经验。这就是我以前工作时的状态。在自学方面,我相当独立自主。我也很欣赏这家公司的文化,他们既轻松有趣,同时每个人都非常拼。“努力工作,尽情玩乐"这种模式,至少这是我对他们公司的感受。

话不多说,开始正题。

那次面试很不错。内容如下:面试涵盖了对过往经历的讨论,以及两道题目,一道与 SOQL 相关,第二道是关于触发器的。

第一题:SOQL 链接到标题

题目是:“写一个方法,返回那些商机和案例均处于开放状态的客户的 ID 列表”。这明显是一道控制器类型的问题,需要从那个角度去思考,这对我来说还好。

我们来分析一下这道题。“写一个方法,返回那些商机和案例均处于开放状态的客户的 ID 列表”。已经过了两天,我可能记不住一字不差的原题,但我知道这和他们问的非常接近。以下是我现在的思路:首先,题目要求的是一个"方法”,所以答案中必须包含方法定义;其次,再读一遍题目,我们可以列出几点关键信息:

  1. 需要返回客户 ID
  2. 条件是:“商机和案例处于开放状态”——这是一个可以向面试官追问的问题,如何判定"开放"。我回头在我的开发者组织里检查了一下,对于商机对象,目前我只有"阶段"字段,因此我将以此作为判断"开放"的依据。案例有"状态"字段,我也将以此作为依据。
  3. 三个对象之间的关系应该是:客户是父对象,案例和商机是子对象:

关系图(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)。

第一反应应该是问自己:“这个问题能用工作流规则和流程生成器解决吗?“因为能用点击配置解决的,何必写代码呢。

写触发器时,我有几个步骤可以帮助我更顺利地完成。以下是我的步骤:

  1. 判断这是更新还是插入?是 before 还是 after?
  2. 弄清楚对象之间的关系,谁是父对象,谁是子对象,以及如何访问数据
  3. 理清背后的逻辑

现在跟着我的思路走:

  1. 在我们的案例中,父对象的复选框必须先被勾选,子对象的复选框才会被勾选,因此必须是"after"触发器。所以是"after insert, after update”
  2. 关系很明确,父是父,子是子。因此至少需要两个列表
  3. 如果 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);

}

如果你发现任何问题或有任何建议,欢迎告诉我,我非常感激!

面试中的关键要点: 链接到标题

  1. 面试时保持冷静,尤其是解题类面试。
  2. 做真实的自己。面试官想了解真实的你,他们在寻找一个可以共事的朋友。
  3. 如果犯了错,没关系。解释你的思路,大声说出你的思考过程。面试官无法读你的心,你需要频繁而高效地沟通。
  4. 最后,也是最重要的一点:沟通。解题时永远不要停止说话。沉默在这里帮不了你,即便你需要一些时间思考,也要解释说明。

最后,我想用美剧《老友记》中的一句台词来结尾——还记得那集乔伊以为自己能演阿尔·帕西诺的替身,最后却落选的那集吗?在我找工作的过程中,我对此感同身受。请记住,你的大机遇终将到来,就像菲比说的那样:“不,我不认为这就是你唯一的机会。我甚至不认为你只有一次机会。我真心相信好事会降临到你身上,我真的相信!你只需要不断想着那一天,某个孩子会跑向他的朋友大喊:‘我拿到这个角色了!我拿到这个角色了!我要演乔伊·崔比安尼的屁股了!’“找工作的旅途很艰辛,总是夹杂着无数复杂的情绪,但永远记住:“你只需要不断想着那一天,某个孩子会跑向他的朋友大喊:‘我拿到这个角色了!我拿到这个角色了!我要演乔伊·崔比安尼的屁股了!’"(出自第一季第六集,“那集关于屁股的”)

祝大家找工作顺利!

永远记住,“你会成长的,只是需要时间”。

后记:以下是我为这次面试备考所用的所有 资料

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