どのような言語であり汎用的な関数の設計は
SOLID原則の単一責任の原則に基づいたほうがいいと思っています。
ただ、ビジネスロジックが入り込むと特定の処理に対し、ログやメール送信するなど
いわゆる付随する組み合わせ(Compound)な処理になっていきます。
すると、本質的な処理から付随した処理を分離しづらくなっていきます。
このようなオブジェクト指向ではうまく分離できない特徴(クラス間を横断 (cross-cutting) するような機能)をアスペクトと呼びます。
JavaScriptでは関数に対してProxyを使うことで体系的に本質でない処理を関数から分離することが出来ます。
// 単体テストするのはこっち(本質的な処理)
function sum(a, b) {
return a + b
}
const handler = {
// ロギング、メール送信などの処理を分離する
apply: function(target, thisArg, argumentsList) {
// 実行前にログを残す
console.log(`args: ${argumentsList}`)
// 引数をそのまま渡す
const result = target(...argumentsList)
// 結果のログや付随するメール送信などの処理など
console.log(`result: ${result}`)
return result
}
}
const wrapSum = new Proxy(sum, handler)
wrapSum(1, 2)
次のように書いても同じやんと言われたらそうなんですけど、
Proxyのほうが体系的に書けるのがいいのかなと思います。
// 単体テストするのはこっち(本質的な処理)
function sum(a, b) {
return a + b
}
function wrapSum(target, ...argumentsList) {
// 実行前にログを残す
console.log(`args: ${argumentsList}`)
// 引数をそのまま渡す
const result = target(...argumentsList)
// 結果のログや付随するメール送信などの処理など
console.log(`result: ${result}`)
return result
}
wrapSum(sum, 1, 2)