EOS 学習メモ:custom dispatcher 編 ③ の続き。
今回は dispatcher を直接実装するのではなく、custom macro を定義してそれを利用するパターンを書いてみる。実際のコードは こんな感じ で、macro だけ抜き出すと以下。
#define EOSIO_DISPATCH_CUSTOM(TYPE, MEMBERS) \
extern "C" { \
void apply(uint64_t receiver, uint64_t code, uint64_t action) { \
bool self_action = code == receiver && action != "notify"_n.value; \
bool notify = code == "addressbook"_n.value && action == "notify"_n.value; \
if (self_action || notify) { \
switch (action) { \
EOSIO_DISPATCH_HELPER(TYPE, MEMBERS); \
} \
} \
} \
} \
なお、この macro は、EOSIO_DISPATCH
と同じように使用できる。
EOSIO_DISPATCH_CUSTOM(test, (a)(b)(c)(notify));
前回までの dispatcher は、例えば action が増えた場合に dispatcher を修正して条件分岐を追加する必要があるなど、action 数とともに dispatcher が肥大化し、コードの保守性が低くなってしまいがちであった。当然、保守性が低いコードは脆弱性を孕みやすくなってしまう。複雑な条件分岐が必要な場合などはそれもやむなしかもしれないが、例えば今回実装した contract のように、
- 外部から飛んでくる action に関しては、特定の action(
addressbook
account から飛んでくるnotify
action)以外は弾きたい - 内部的に実行される action に関しては、特に気にすることはない(処理を共通化しても問題ない)
というような場合には、上記のような macro を書いておけば、内部的に実行される action が増えた場合に関しては macro の中身を修正する必要がなくなるため、保守性の向上が望める。ただ、上記「外部から飛んでくる特定の action」が増えた場合などは、macro を修正しなければならない。結局修正しなければならないのであれば、状況によっては、前回までで実装してきたような macro を使わないパターンの方が保守性が高くなることもあるだろう。
安っぽい結論になってしまうが、「複数の dispatcher 実装パターンのメリット・デメリットを把握し、要件に合わせて適切なパターンを選択できるべき」ということだろう。
以上、少しずつ進めていたのでそれなりに時間がかかってしまったけど、無事 チュートリアル 完走ッス。