本記事は、Options Objectパターンでレベルアップしたコードを書こう【前編】の続きです。
こちらを読んでから、ご覧ください。
こちらのサイトを参考にしました。
キーワード引数とOptions Objectパターン
ここまでキーワード引数を学びました。
復習すると、キーワード引数とはPythonの機能で、引数名を使って「名前=値」の形式で引数を指定する方法でした。
しかし、残念ながらJavaScript、TypeScriptにはこれに該当する機能はありません。
その代わり、似たようなことがOptions Objectパターンで実現できます🙌
Options Objectパターン
それでは、実際にOptions Objectパターンの書き方を見てみましょう。
Options Objectパターンは複数の位置引数を受け取る代わりに、ひとつのオブジェクトを引数に受け取るように設計された関数を言います。
// 位置引数の関数
const normalFunc = (x, y, z) => {
console.log(x, y, z);
};
// オブジェクトひとつだけを引数に持つ関数
const func = (options) => {
console.log(options.x, options.y, options.z);
};
// 分割代入で書く
const func = ({x, y, z}) => {
console.log(x, y, z);
};
// 型も書く
const func = ({ x, y, z }: { x: number; y: number; z: number }) => {
console.log(x, y, z);
};
func({ x: 1, y: 2, z: 3 }); // => 1 2 3
分割代入で書くと聞くと、難しく感じてしまいますが、ReactコンポーネントでPropsを受け取って、関数を定義するときにいつも使っている書き方でした。
用語に苦手意識がある方は、実務で触っているソースコードと比べると身近に感じられるのではないでしょうか。
// 分割代入しないと、長くなって見栄えが悪い
export const Profile = (props) => {
return (
<p>私の名前は{props.name}です。{props.age}歳です。</p>
);
};
// 引数の段階で分割代入する
export const Profile = ({name, age}) => {
return (
<p>私の名前は{name}です。{age}歳です。</p>
);
};
次に、Options Objectパターンのメリットについてまとめます。
引数の値が何を指すのか分かりやすい
引数をbooleanで渡す場合を例にします。
determineDinnerMood({ true, false, false });
これでは引数の何がtrueなのか、何を指しているのかわかリません。
関数定義しているところを見に行かなければ、引数の意味が理解できないとなると、ソースコードで見るところが行ったり来たりして大変です😢
これをOptions Objectパターンで書くと、関数を呼び出しているところだけで、引数の意味が理解できます。
日本食が気分だったみたいです🍣
determineDinnerMood({ japanese: true, chinese: false, western: false });
引数追加時に古いコードを壊さない
これはイメージがつきにくかったのですが、要は「オブジェクトだから、将来引数を変えることになったとしても、キーとバリューの対応さえ合っていれば、順番はどうでも良い」ということだと解釈しました。
デフォルト引数が省略できる
Options Objectパターンを用いた場合は、デフォルトにしたい引数については何も書く必要がないそうです。
上書きしたい引数だけを書けばいいのは便利ですね!
const determineDinnerMood({
japanese = false,
chinese = false,
western = false,
}) {
console.log(japanese, chinese, western);
}
determineDinnerMood({ chinese: true });
// =>false true false
リファクタ
教えていただいた知識を使って自分が書いたコードをリファクタしました。
// どのプランからどのプランへ変更するか確認する
const isPlanChange = ({ from, to }: { from: Plan; to: Plan }) => {
user.currentPlan === from && user.nextPlan === to;
};
// プランA→プランBへの変更かどうか
const willChangePlanAToPlanB = isPlanChange({from: Plan.planA, to: Plan.planB});
// プランA→プランCへの変更かどうか
const willChangePlanAToPlanC = isPlanChange({from: Plan.planA, to: Plan.planC});
引数が何を表しているのか、関数を呼び出しているところを見るだけで意味がわかるようになりました🎉
終わりに
レビューを返してもらうと、自分では気づけないことや新しい知識を身につけることができます!
今後も、レベルアップした書き方を学んでいきたいです。