らしいです。最低限は必要だけど、かなり減るとか。
最近、javaとかCとか、Javascriptよりもお堅いオブジェクト指向言語の記事をかじり読みしては、こうするとメンテが楽なんだなあ、とイメージしてます。キーワードは「ポリモーフィズム」「Stateパターン」「条件分岐をなくす」など。
言語が違うので、例示されてるコードはあんまり読めないんですけどね。理屈は分かる気がしてます。
私は、オブジェクトを使いこなすまでは至っていませんが、条件分岐とループをなくすことはできました。
というわけで、ド初心者のコードと、初心者脱出したコードを並べてみます。
(偉そうに書いてますが、完全独学の趣味レベルですのでご了承を)
(でもタイピングサイトに組み込んで動くコード(の簡略化)です。動くは正義)
例示するコードについて
Javascriptで親指シフト入力を疑似体験できるサイトのコードです。(簡略化しています)
キーボードからの入力を元に、文字キーとシフト状態の組み合わせ表(=配列/オブジェクト)から、入力された文字を判別します。
ちなみに元のコードはこんなです。
今見ると、え?え?何やってんの? ってなります。
(ちなみに変数名も、もっと分かりにくいのが付いてたんですが、分かりにくい&恥ずかしいので直しました)
//元の配列:[通し番号] = [キーコード、シフトなし、左シフト、右シフト]
var keyMap = new Array();
keyMap[0]=[65,"う","を","ヴ"];
keyMap[1]=[66,"へ","ぃ","べ"];
keyMap[2]=[67,"す","ろ","ず"];
keyMap[3]=[68,"て","な","で"];
keyMap[4]=[69,"た","り","だ"];
//入力されたキーコードが、keyMap配列の何番目か得る
var kc=event.keyCode;
var n;
for ( n = 0; n < keyMap.length; n++){
if( kc == keyMap[n][0] ) break;
}
if (isLeft == 0 && isRight == 0){ //親指が押されていない時
charX = keyMap[n][1];
} else if (isLeft != isRight){ //片方の親指が押されている時
if (isLeft == 1){
charX = keyMap[n][2];
} else{
charX = keyMap[n][3];
}
}
直します
上記のコードを、今の私の知識と感覚で直していきます。ビフォーアフターです。
for文が消えた!
まずは、入力された文字キーを、判定できる状態に準備する部分です。
★ビフォア
当初は、for文で回して、しらみつぶしに探していました。
配列において、連番の数字以外をキーに使うことを、理解できなかったんです。
//元の配列:[通し番号] = [キーコード、シフトなし、左シフト、右シフト]
var keyMap = new Array();
keyMap[0]=[65,"う","を","ヴ"];
keyMap[1]=[66,"へ","ぃ","べ"];
keyMap[2]=[67,"す","ろ","ず"];
keyMap[3]=[68,"て","な","で"];
keyMap[4]=[69,"た","り","だ"];
//入力されたキーコードが、keyMap配列の何番目か得る
var kc=event.keyCode
var n;
for ( n = 0; n < keyMap.length; n++){
if( kc == keyMap[n][0] ) break;
}
★アフター
for文を使わず、キーで直接値を取るようにしました。
こうすることで、keyに関しては、特別な下準備が不要になりました。
コードが分かりやすくなったため、コメントも要らなくなりました。
//元の配列:実際は、もっと単純な文字列をもとに、スクリプトで生成
var kanaMap = {
a: {noshift: "う", left: "を", right: "ヴ"},
b: {noshift: "へ", left: "ぃ", right: "べ"},
c: {noshift: "す", left: "ろ", right: "ず"},
d: {noshift: "て", left: "な", right: "で"},
e: {noshift: "た", left: "り", right: "だ"},
}
//入力されたkey
var key = event.key;
※キーコード(数字)からキー(文字列)に変えましたが、キーコード(数字)でも同じ事ができます。でも、現在キーコードは非推奨になっているので、やらない方がいいです
条件分岐が消えた!
続いて、シフト状態を元に、入力されたかなを取得する部分。
★ビフォア
左右どちらがシフトしてるか/あるいはしてないかを、一々if文で判定してます。
//続き
kc
n //キーコードの配列要素番号
var charX;
//入力されたキーコードと、その時のシフト状態を元に文字を得る
if (isLeft == 0 && isRight == 0){ //親指が押されていない時
charX = keyMap[n][1];
} else if (isLeft != isRight){ //片方の親指が押されている時
if (isLeft == 1){
charX = keyMap[n][2];
} else{
charX = keyMap[n][3];
}
}
★アフター
先に、シフト状態を表す文字列を生成。
この文字列を当てはめると、一発で文字が出ます。
また、シフト状態を先に取ることで、照合中にシフト状態が万一変わっても問題ないです。(そんな事はないはずだけど)
条件に合わないときは、さっさとreturnすることも覚えました。
//続き
key
var charX;
//入力されたkeyと、その時のシフト状態を元に文字を得る
var L = thumbL_isShift; //boolean
var R = thumbR_isShift; //boolean
if(L && R) return;
var shift = L? "left": R? "right": "noshift";
var charX = kanaMap[key][shift];
ちなみにここも、シフト状態を”noshift””left””right”の3スイッチにできれば、直接値を突っ込むだけで済みます。
が、左右のシフトは独立してon/offするので、ちょっと難しいと思いました。
直したコードの全容
スッキリしたし、for文がなくなった分、動作(速度)も安定しました。
var kanaMap = {
a: {noshift: "う", left: "を", right: "ヴ"},
b: {noshift: "へ", left: "ぃ", right: "べ"},
c: {noshift: "す", left: "ろ", right: "ず"},
d: {noshift: "て", left: "な", right: "で"},
e: {noshift: "た", left: "り", right: "だ"},
}
//入力されたkeyと、その時のシフト状態を元に文字を得る
var key = event.key;
var L = thumbL_isShift;
var R = thumbR_isShift;
if(L && R) return;
var shift = L? "left": R? "right": "noshift";
var charX = kanaMap[key][shift];
どこかで分岐はしている
以上、見ていて思ったかもしれませんが、全く分岐がなくなったわけではないです。
オブジェクトのプロパティにうまいキー名を付けたり、変数の下処理をしたり、とどこかで分岐する準備をしています。
そうすると、動作の中心となるコードでは、ごくシンプルに記述できます。
追加や変更にも対応しやすくなります。
うまくすると、変更があったときに肝のコードは全く変えず、オブジェクトを変えるだけですむらしいです。
うちのサイトはそこまで出来てないですが。
ゆくゆくは、もっと扱いやすいコードを書きたいものです。
終わります。
コメント