LoginSignup
2
0

JavaScriptカスタマイズでは、イミュータブルにEventオブジェクトを変更しよう

Posted at

kintoneのJavaScriptカスタマイズでは、様々なイベントハンドラを利用してアプリの挙動を拡張します。これらのイベントハンドラ内で使用されるEventオブジェクトをイミュータブル(変更不可)に扱うことでバグを減らすことができます。

ミュータブルなコードとは

例えば下記のようなコードは、どのタイミングでも値の変更をゆるすことで、ミュータブルに値を扱っていることになります。

// イベントハンドラ
kintone.events.on('app.record.create.submit', (event) => {
    const record = event.record;
    record.fieldCode.value = 123; // 数値フィールドを変更
    return event;
});

問題点

パット見るとなにも問題ないようにみえますが、上記のようにeventで渡ってくるコードを直接書き換えてしまうと、ハンドラの中身が長くなったときにどうコードを変更したかがわからなくなり、 バグの温床になります。
間に、ミュータブルにレコードを操作する関数があると最悪で、いつどのように値が変わったかが追えなくなり、非常にやっかいなコードになります。
 

// イベントハンドラ
kintone.events.on('app.record.create.submit', (event) => {
    const record = event.record;
    record.fieldCode.value = 123; // 数値フィールドを変更

    // いくつかの処理をかく

    // ここで、オリジナルのデータを想定した処理をかいてしまう
    if(record.fieldCode.value > 100) {
      // 省略
    }
    
    return event;
});

イミュータブル(変更不可)なコードで表現する

例1

上記の例ですと、下記のように表現ができます。
structuredClone というオブジェクトのコピーをする関数があり、それを利用して、新しいレコードを先につくります。

// イベントハンドラ
kintone.events.on('app.record.create.submit', (event) => {
    const newRecord = structuredClone(event.record);
    const newRecord.fieldCode.value = 123; // 数値フィールドを変更
    // 省略

    // 最後に書き換え
    event.record = newRecord;
    return event;
});

例2

関数を作るときも、常に新しいオブジェクトを返すようにする(直接書き換えないようにする)ことでバグを減らすことができます。


// イベントハンドラ
kintone.events.on('app.record.create.submit', (event) => {
    const newRecord = structuredClone(event.record);
    // 省略

    // 最後に書き換え
    event.record = addValue(record, 10);
    return event;
});

function addValue = (record, value) => {
    const newRecord = structuredClone(event.record);
    newRecord.fieldCode.value = Number(newRecord.fieldCode.value) + value;
    return newRecord;
}


補足

少しでもイミュータブルに始めれるとよいですが、下記のように毎回新しい値を作るのが理想です。基本的には上書きをせず、値を新たに定義していくイメージです。
最後に使っているのはスプレッド構文というものです。

// イベントハンドラ
kintone.events.on('app.record.create.submit', (event) => {
    const record = event.record;

    // 処理Aをしたレコード
    const executedARecord = funcA(record);

    // 処理Aのあと処理Bをしたレコード
    const executedBRecord = funcB(executedArecord);

    // 結果
    const result = {
        ...event,
        record: executedBRecord;
    }

    return result;
});

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0