見出し画像

【開発哲学3_16】〜『CODE COMPLETE第2版 第16章(上巻)』の感想〜ループの制御

感想

ループ処理が苦手な人多い。
階層増えるとコードを解読するのが難しくなるし。
にも関わらず、いざコードを自分が書くとなると、外から内へ書いて、ルーチン化も考えずにベタうちして深いコードになって、数日〜数ヶ月後に自分で改修に入る時に涙目になるんだよね。

高度なコードを書かなきゃいいだけなんだけど。

詳細

見出しとしては、

  1. ループの種類の選択

  2. ループの制御

  3. ループの作成ー内から外へー

  4. ループと配列の対応付け

  5. まとめ

て感じ。

かつての職場で、

動けばいいと思っているのか、、、

  • 3階層以上のループを作る

  • クロストーク(か入れ子)になってる

  • 適当な数値を上限値にする

  • ここがループだからとやたらループをループの中に使いたがるか初期化忘れ

よくいたなあ。

・3階層以上のループを作る

自分がいかに高度なことをしているかをひけらかしたいのか、動けばいいと思っているのかわからないんだけど、以前の職場やインターネットでも何かの調べ物をしている時でも、5階層とかでループをやっているコードをよく見てた。
SQLでクエリ組むにしろ、テーブル操作(CRUD)にしろ、見た瞬間に、はっきり言って

あ、この人わかってないなあ

と思ってた。3階層でも、

見にくい=実行される処理内容を把握しにくい

のに、5階層でやるとか正直、

ん?一旦、実行後に、再クエリでさらに別のクエリ組むとか、書き込んだ値を再取得して処理しちゃえばいいんじゃね?
なんで、いっぺんに済まそうとしてんの?
読む人のこと考えてんの?

ってがいっぱいになってた。
そんな人ほどエクセル関数も、

IFERROR(COUNTIF(VLOOKUP(OR(AND))))

てな感じで、

内から外

を実践して、やたら複雑なエクセル関数を組むのに、
コードでループ制御書くと、

外から内

になってる💦

3階層以上のループなんて、スクレイピングでどうしても必要な時以外使いません(キッパリ)✨。
以外で3階層以上になってる時点で、他の方法を検討します〜〜〜。

・クロストーク(か入れ子)になってる

これは他の記事でも書いたと思うけど、ループのカウント変数とかに、教科書どおり

i、j、k

で、
「読みにくくなるから、i、j、kは極力使わない方がいいし、処理の内容がわかっているなら意味のわかる名前つけた方がいいよー!」
て言っても、教科書を盲信してるのか自分はそんなミスはしないと思っているのか、そのまま

for(i = 1; i <= lastRow; i++){
  元々の処理1
  ...
  ...
  for(j = 1; j <= lastColumn; j++){
    元々の処理2
    ...
    ...
    for(i = 1; i <= 3; i++){
     今回の改修で追加した処理
       ...
       ...
    }
  }
}

てな感じで、追加した処理のループで本来、kを使うべきところにi(すでに使っている変数)を使ったり、入れ子にする人多かったなあ。

・適当な数値を上限値にする

これもよくいた。
例えば、最大行数が9000〜10000行のテーブルがあるとして、本来は、最終行数分だけ処理を繰り返して取得すればいい処理なのに、最終行を取得するコマンドを知らないのか汎用性を意識しないからか

for(i = 1; i <= 13000; i++){
   取得処理
}

てな感じで、ベタ打ちで13000とか数字を決めうちしてた。

これやると、普通は以下の疑問が湧いてくる。

【疑問(=デメリット)】

①9000回しか繰り返さなくていい時も余分に13000回まで必ず繰り返すから、ループ処理に時間かかるのでは?
👉こういう人ほど他の処理でも同様だったから、処理におっそろしく時間がかかってた。
②テーブルの行数が指定している数字を超えるたびに改修が必要になるし、取得しきれないのでは?
👉作った人は実際、よく書き換えしてた。

下のコードみたいにマジックナンバー対策で13000を引数にすればって意見もあるけど、

//繰り返しの回数
const rowNum = 13000;

...

for(i = 1; i <= rowNum; i++){
   取得処理
}

③数字をマジックナンバー対策でやると見落とすのでは?
👉改修者が実際、よく見落としていた。

そこまでやるなら素直に

//最終行取得
let lastRow = sh.getLastRow();

...

for(i = 1; i <= lastRow; i++){
   取得処理
}

で汎用的にやれば変更も少なくて済む。

動けばいいで処理時間を意識しなくていい環境もたしかにあるけど、
これに慣れちゃうと、
GASみたいな最大処理時間が限られてる言語やユーザーと対話するインタラクティブなアプリに移行すると、それまでの経験が使い物にならなくなる。

・ここがループだからとやたらループをループの中に使いたがるか初期化忘れ

改修作業に入って、ループの中にちょっとした条件を加える時とか、なぜか、さらにfor文を加えようとして、ウンウン唸っている人もよく見た。
なぜかループの中にはループを追加しないと処理がうまくいかないみたいな先入観でもあるのかな。
そんな人に限って、値の抜き出しや二次元配列への格納まではできても、処理後の配列やループを抜けるたびの値への初期化を忘れて、果てしない値で桁数エラーが起きて涙目になってたり、、、。

まとめ

高度なコードを書いて、いっぺんに全部解決しようとする人ほど、自分で(エクセル関数もコードも)複雑怪奇なモノにしてる。
(読みにくい(=変更しにくい)時点で、ややこしいことやってんなと思うだけで別に、高度だとは思わないけどな。)

ループにおいても基本は、

制御 = 指定した処理を繰り返すのみ

なので、

💃シンプルイズビューティフル
内から外に分かりやすく書く🕺

この記事が気に入ったらサポートをしてみませんか?