1.트리거는 아래와 같은 조건들이 감지될 경우 발동하게 된다.
- before insert
- before update
- before delete
- after insert
- after update
- after delete
- after undelete
트리거는 특정 객체의 동작을 감시하는 구조로
동시에 여러개의 트리거를 넣을 수 있으며
해당 트리거가 작동되는 경우 트리거 내부에 들어있는 코드가 실행된다.
trigger TriggerName on ObjectName (trigger_events) {
// code_block
}
하지만 point and click 자동화 도구 중 하나로 설정이 불가능한 경우가 아닌 이상
트리거를 사용한 작업 처리를 추천하지는 않는다.
또한 트리거를 생성할 경우 하나의 객체에 대한 트리거는 하나만 만드는 것을 권장하며
여러 조건에 따른 다른 반응이 필요한 경우에는 각각의 트리거를 모두 등록한 다음
트리거 내부에서 발동 조건을 if문으로 체크해 작동시키는 방식으로 구분한다.
trigger AccountTrigger on Account (before insert, before update, before
delete, after insert, after update, after delete, after undelete) {
if (Trigger.isAfter && Trigger.isInsert) {
AccountHandler.CreateNewOpportunity(Trigger.New);
}
}
2.과제에서 너무 갑작스럽게 많은 것들을 요구했지만
나름대로 잘 만들었다고 생각했는데 자꾸 통과가 되지 않아 확인하니
xx와 yy가 같음을 보장하라는 것은 xx와 yy가 같지 않을 경우 통과시키지 않는 것이 아니라
xx에 yy를 할당해서 넘기라는 이상한 요구사항이었다.
통과되지 않아서 뜨는 에러 메세지에서도 같은지 확인하는 내용이 없다는 식으로 나와서
당연히 같은지 확인 후 같은 것들만 insert accs; 처리를 했었기 때문에
많이 억울했는데 문제 뉘양스를 잘 이해하는 것도 중요하다는 생각이 들었다.
이번 문제에서는 단순히 답답하고 끝날 일이었지만
고객의 요청사항과 동떨어진 기능을 만들고 지나쳐버린다면
나중에 단계적으로 합쳐진 코드들을 전부 뜯어고쳐야 할 수 있기 때문에
의도를 확실히 파악해야곘다는 교훈을 얻었다.
통과한 클래스, 트리거, 테스트 코드
//class
public class AccountTriggerHandler {
public static void CreateAccounts(Account[] accList) {
for (Account a : accList){
if(a.ShippingState != a.BillingState){
a.ShippingState = a.BillingState;
}
}
}
}
//trigger
trigger AccountTrigger on Account (before insert) {
if (Trigger.isBefore && Trigger.isInsert) {
AccountTriggerHandler.CreateAccounts(Trigger.new);
}
}
//test
@isTest
public class AccountTriggerTest {
@isTest static void TestCreateNewAccountInBulk() {
List<Account> accts = new List<Account>();
for(Integer i=0; i < 200; i++) {
Account acct = new Account(Name='Test Account ' + i, BillingState = 'CA');
accts.add(acct);
}
Test.startTest();
insert accts;
Test.stopTest();
for (Account a: accts ){
System.assertEquals('CA', a.ShippingState, 'ERROR');
}
}
}
//아직까지 요구해서 사용하기는 하지만 isBefore, isInsert를 왜 넣어야 하는지는 모르겠다.
3.비동기 처리는 동기적 프로세스 제한보다 많은 수의 레코드를 처리할 수 있으며
동기적인 응답이 필요한 경우가 아니라면 비동기 처리를 통해 대기 없이 다음 작업으로 넘어가
더 좋은 사용자 경험을 만들 수 있다.
“@future” 주석을 추가해 비동기적으로 처리되는 메서드를 만들 수 있으며
public class MyFutureClass {
// Include callout=true when making callouts
@future(callout=true)
static void myFutureMethod(Set<Id> ids) {
// Get the list of contacts in the future method since
// you cannot pass objects as arguments to future methods
List<Contact> contacts = [SELECT Id, LastName, FirstName, Email
FROM Contact WHERE Id IN :ids];
// Loop through the results and call a method
// which contains the code to do the actual callout
for (Contact con: contacts) {
String response = anotherClass.calloutMethod(con.Id,
con.FirstName,
con.LastName,
con.Email);
// May want to add some code here to log
// the response to a custom object
}
}
}
배치 또는 스케쥴된 apex 처리 또한 사용이 가능하다.
global class MyBatchableClass implements
Database.Batchable<sObject>,
Database.Stateful {
// Used to record the total number of Accounts processed
global Integer numOfRecs = 0;
// Used to gather the records that will be passed to the interface method
// This method will only be called once and will return either a
// Database.QueryLocator object or an Iterable that contains the records
// or objects passed to the job.
global Database.QueryLocator start(Database.BatchableContext bc) {
return Database.getQueryLocator('SELECT Id, Name FROM Account');
}
// This is where the actual processing occurs as data is chunked into
// batches and the default batch size is 200.
global void execute(Database.BatchableContext bc, List<Account> scope) {
for (Account acc : scope) {
// Do some processing here
// and then increment the counter variable
numOfRecs = numOfRecs + 1;
}
}
// Used to execute any post-processing that may need to happen. This
// is called only once and after all the batches have finished.
global void finish(Database.BatchableContext bc) {
EmailManager.sendMail('someAddress@somewhere.com',
numOfRecs + ' Accounts were processed!',
'Meet me at the bar for drinks to celebrate');
}
}
마지막으로 Queueable Apex가 추가되었는데
기존과는 다르게 추적이 가능한 jobID가 반환되며 순차적 처리 또한 가능하고
사용자 정의 데이터 처리 또한 허용할 수 있다는 장점이 있다.
//Queueable Apex 호출
List<Contact> contacts = [SELECT Id, LastName, FirstName, Email
FROM Contact WHERE Is_Active__c = true];
Id jobId = System.enqueueJob(new MyQueueableClass(contacts));
//Queueable Apex class
public class MyQueueableClass implements Queueable {
private List<Contact> contacts;
// Constructor for the class, where we pass
// in the list of contacts that we want to process
public MyQueueableClass(List<Contact> myContacts) {
contacts = myContacts;
}
public void execute(QueueableContext context) {
// Loop through the contacts passed in through
// the constructor and call a method
// which contains the code to do the actual callout
for (Contact con: contacts) {
String response = anotherClass.calloutMethod(con.Id,
con.FirstName,
con.LastName,
con.Email);
// May still want to add some code here to log
// the response to a custom object
}
}
}
4.각각의 디버그 로그는 20MB가 초과되면 출력되지 않으며
조직마다 최대 1000MB의 디버그 로그가 유지되고 실시간으로 갱신되어버리기 때문에
디버깅은 신중하게 범위를 결정해야 하는데 아래의 범위 지정을 통해 통제할 수 있다.
- NONE
- ERROR
- WARN
- INFO
- DEBUG
- FINE
- FINER
- FINEST
기본적으로는 System.debug('My Debug Message')를 통해 출력하며
코드의 line 표시줄을 클릭해 check point를 생성할 수 있지만
실제로 중단되지는 않는다.
(1).백준 11023번 더하기3은 입력받은 모든 값의 합을 구하면 되는 문제였으며
조건의 갯수도 100개 이하에 1만보다 작은 자연수였기 때문에
간단하게 split을 통해 배열로 변경한 다음 map으로 number type으로 변경하고
각각의 숫자들을 for문으로 조회해 sum에 더해줬다.
const input = `5 4 5 4 2 3 1 2`.split(' ').map(Number)
let sum = 0
for(let i = 0 ; i < input.length ; i++){
sum += input[i]
}
console.log(sum)
'회고' 카테고리의 다른 글
[수습일지] - 22 (0) | 2023.04.17 |
---|---|
[수습일지] - 21(주말) (0) | 2023.04.16 |
[수습일지] - 19 (0) | 2023.04.14 |
[수습일지] - 18 (0) | 2023.04.13 |
[수습일지] - 17 (0) | 2023.04.12 |