月別アーカイブ: 2022年3月

リファクタリング、ループの話

前回、リファクタリングのことを書いていたらいくつか書き留めておきたくなった。今回はループの話。

コードを組み立てていく時、最初からループがうまく回る保証はない。だからコーディング中はfor文に繰り返す回数を与えて、その数をデバッガーで見たり、アラートやログ出力して確認することになる。たとえば次のようなコードでは$sizeOfAryに何が入っているか、プログラマなら興味があるだろう。

//code A	xxxは配列
C_LONGINT($i;$sizeOfAry)
$sizeOfAry:=size of array(xxx)
for ($i;1;$sizeOfAry)
	...
end for

昔やっていたのが、上のように書いて動作検証した後で、次のようにリファクタリングすることだった。

//code B
C_LONGINT($i)
for ($i;1;size of array(xxx))
	...
end for

これでコードが一行減って、ローカル変数が1つ減って、読みやすくなった、と思ってた時期があった。散らかってたのを片付けました、、下書きを清書しました、という感覚。

...? 多分、そうじゃないよね。

何らかの不具合が原因でこのコードを「後で」見ることになった場合、実行環境が変わったり、データの仕様が変わったり、未配慮の状況に遭遇しているかもしれない。そのとき最初に見たいのはfor文が想定通りに回っているかではないだろうか。つまり元のコードの$sizeOfAryに何が入っているか、だ。それで値の中身を見るためにcode Bにコードを追加したりして、つまりはcode Aに近い形に修正し直す、ことになる。

あーあ、最初からcode Aの状態にしておいてくれればよかったのに。ってね。

回数をアラートに表示するとか、繰り返す内容をログ出力したり、$sizeOfAryに小さな値を代入して少ないループでテストするとか、ローカル変数に取得しておくとデバッグ時に都合が良い。だからデバッグしやすい「code Aのまま」にしておくことはそれほどコストはかからないし合理的と言えるのではないか。えっ、「コードが長くなって、あちこちでこのように書いてたら全体ではコード量が馬鹿にならない」って?

だから「やっていることの分だけコードはあるのだ」の原則を思い出そう。

ループの回数、と言う重要なファクターを我々は設計し、実装した経緯があるのに、リファクタリングによってその経緯がわからなくなる。短い方が可読性にプラスという思い込みのために、コードの品質を落としていないだろうか。「コードは道具」という側面があるので、清書して使いにくくするものではなく、使いやすい状態にしておくほうがいいと思う。

続きはまた後ほど。

図工室の椅子

図工室の椅子と呼ぶらしい。技術家庭室にあった椅子。

実はこれ、工作の時の作業台になるのだった(°-°)。横にして使うらしい。丸い穴はドリルで穴あけをするため。天板の縁がわずかに出ているのは、横にして木材をノコギリで引くときに木材を固定するため。万力を装着できるとか。背もたれのないのは片付けやすいため。学校用なので耐久力がありそう。(\^o^/)

作業台としては手頃な大きさ、30×30、高さは420と450の2種類、おそらく小さい方は小学校用だろう。材料はコナラ、ニラ、硬くて重い木だ。座面が平らなので補助椅子としてだけでなく、補助机、踏み台に使える。花台にしている画像も見つけた。木工作業する時にベランダに持っていくのも簡単。長尺ものを切る時は2脚使うらしい。そうか、2脚あれば一枚板天板の足にもなる。

学校から放出されたような、使い込まれた中古品をネットで探す。落書きがしてあるやつとか、かなりくたびれたのがある。値段は4,000円くらいから上。意外に高いなと思いながら「これでいいかも」なのはSold outだったりして、中古を探すのもだんだん面倒になってくる。骨董品屋でたまたま出物があればラッキー、のような気長に探すアイテムだ。

新品は7,000円から17,000円くらいで売っている。すぐに使いたかったので納期が早いのを一つゲットした。

仕事部屋に置いてみた

片手で移動させるのに便利そうなので、手掛け用のスリットがついているのにした。

見た目が可愛い

背もたれ付きの椅子と比べて邪魔にならない。ちょっと持ってきて座る、踏み台にする、物を置く。これはいい。あと2つ追加しよう。

河津桜

これでようやく満開の河津桜

伊豆河津では2月になると咲き始め、3月には終わっているはずの梅より早く咲く河津桜。梅はいつもより少し遅いくらいだが、こちらはかなり遅い印象。

ミザクラ

ミザクラは早く花が咲く桜。実がつくのも早い。梅雨前には食べられる。

ウメ

同じ日の梅。ウチで一番遅い梅。まだ蕾が多い。

やってることの分だけコードがある、のはフツーのこと。

WEB+DB PRESS vol.127」(以下、wdp127)にリファクタリングの話があったので読んでみたら良かった。

https://gihyo.jp/magazine/wdpress/archive/2022/vol127

知らない単語が出てきたのでメモしておく。

□ 凝集度(cohesion)
□ 結合度(coupling)

調べてみると、語源は1979年あたりにヨードンが提唱していたらしい。

□ DRY(Don’t Repeat Yourself)

コードの最適化、なんでもDRYというルールがあるそうだ。

プログラミングしていると、同じようなコードを何度も書くとき、共通化できるのでは?と考える。あちこちに書いておくと、あとでそこに修正が生じた場合にあちこち直さなくてはならないため不便だし、処理が同じならモジュール化すべきだという考えだ。

wdp127では凝集度について、論理的凝集は避ける、ようなことが書いてある。要はフラグを使った関数内分岐を避けよ、という意味と理解した。ウチでは同じような意味で「多機能関数はダメ」というルールがある。

結合度については値は引数で渡す、ようなことが書いてある。要はグローバル変数は避けよ、という意味と理解した。ウチでは「関数の中はローカル変数だけを使う」と「グローバル的な変数にはゲッターセッターを用意して関数を介して取得する」というルールがある。ただし例外として、画面に一覧を表示する際のフォームオブジェクトはグローバル参照をしていいというルールもある。画面に表示する情報についてゲッターセッターをすべて用意するのはあまりにも面倒だ。フォームオブジェクトは名前付のルールでわかるようにしている。

ウチでは上記のほかに、

・モジュール内の構造は原則2つまで

forやifの構造が3つ以上出現する場合は、さらなるモジュール化を検討せよ、という意味だ。

・処理の分だけコードはある

仕様がケース分岐しているのであればコードも分岐している、のがフツーだ。入り口から分岐させて、中に共通処理を見つけたら共通モジュール化する、のが良い。

・デバッグしやすいコード

できるだけ1行で書く、というコードはダメ。if文の中に関数を記述したり、引数に関数を記述するのはわかりやすいNGだ。デバッグする時にたとえばforループが何回回るのかは重要な要素だ。上手くいかないときは0回の場合が多い。これをデバッグするには繰り返し回数を見れば良いのだが、大体はなんかの関数の戻り値である。これをfor($i;1;myFunc())のように書いてしまうとmyFunc()の戻り値を見たくなる。$count:=myFunc()とか記述して$countの値を見ることになる。それなら最初からそういうコードにしておけば良い。

・プログラマに必要な機能はおそらくユーザにも必要

上記はソース内部の記述だが、表面的な仕様でもデバッグに便利な機能を実装しよう。あるテーブルの中身が見たいような機能は言われなくても作ってしまう。デバッグでよく使うツールであればプログラマは便利になる。そのままリリースして、ユーザに「削除して」と言われてから「隠す」ようにすればよい。

まだ語り尽くせないので、また思いついたら続きを書く。。。