『Cプログラミング診断室』目次次(第11章 奇っ怪な条件 まとめ)

第11章 奇っ怪な条件

難解な条件


最後に、この人ならではの特徴的なコーディングを紹介しましょう。リスト11−5を鑑賞して ください。中略していて申し訳ありませんが、このifの条件がどうなっているか、しっかり見極め てください。

リスト11−5 オリジナルプログラム 難解な判定条件

     1      switch ( event_action( event ) )
     2          {
     3          case    LOC_MOVE:
     4              if ( display_mode == DISPLAY_DISP ||
     5                   display_mode == DISPLAY_LINE ||
     6                   master_menu_mode == MASTER_ANGLE ||
     7                   master_menu_mode == MASTER_HORIZONTAL ||
     8                   master_menu_mode == MASTER_VERTICAL ||
     9                   ( master_menu_mode >= MASTER_DRAW_LINE &&
    10                     master_menu_mode <= MASTER_DRAW_FREE_LINE ) ||
    11                   ( ( master_menu_mode == MASTER_SAVE_PARTIAL ||
    12                         master_menu_mode == MASTER_CLEAN ) &&
    13                         menu_mode ) ||
    14                   ( ( ( master_menu_mode >= MASTER_COLOR_PAINT &&
    15                         master_menu_mode <= MASTER_COLOR_PLANE ) ||
    16                       master_menu_mode == MASTER_EDIT_BIGGER ||
    17                       ( master_menu_mode == MASTER_REGION &&
    18                         region_area_mode ) ||
    19                       master_menu_mode == MASTER_CORNOR_MASK ) &&
    20                     proc_stat != 2 &&
    21                     mouse_stat == 0 ) )
    22                  {
    23                          ........... 中略 ...........
    24                  }
    25                  ........... 中略 ...........
    26                  break;
    27          case    LOC_DRAG:
    28              if ( display_mode == DISPLAY_DISP ||
    29                   display_mode == DISPLAY_LINE ||
    30                   master_menu_mode == MASTER_ANGLE ||
    31                   master_menu_mode == MASTER_HORIZONTAL ||
    32                   master_menu_mode == MASTER_VERTICAL ||
    33                   ( master_menu_mode >= MASTER_DRAW_LINE &&
    34                     master_menu_mode <= MASTER_DRAW_FREE_LINE ) ||
    35                   ( ( master_menu_mode == MASTER_SAVE_PARTIAL ||
    36                         master_menu_mode == MASTER_CLEAN ) &&
    37                         menu_mode ) ||
    38                   ( ( ( master_menu_mode >= MASTER_COLOR_PAINT &&
    39                         master_menu_mode <= MASTER_COLOR_PLANE ) ||
    40                       master_menu_mode == MASTER_EDIT_BIGGER ||
    41                       ( master_menu_mode == MASTER_REGION &&
    42                         region_area_mode ) ||
    43                       master_menu_mode == MASTER_CORNOR_MASK ) &&
    44                     proc_stat != 2 &&
    45                     mouse_stat == 0 ) )
    46                  {
    47                          ........... 中略 ...........
    48                  }
    49                  ........... 中略 ...........
    50                  break;
    51          case    LOC_WINENTER:
    52              if ( display_mode == DISPLAY_DISP ||
    53                   display_mode == DISPLAY_LINE ||
    54                   master_menu_mode == MASTER_ANGLE ||
    55                   master_menu_mode == MASTER_HORIZONTAL ||
    56                   master_menu_mode == MASTER_VERTICAL ||
    57                   ( master_menu_mode >= MASTER_DRAW_LINE &&
    58                     master_menu_mode <= MASTER_DRAW_FREE_LINE ) ||
    59                   ( ( master_menu_mode == MASTER_SAVE_PARTIAL ||
    60                         master_menu_mode == MASTER_CLEAN ) &&
    61                         menu_mode ) ||
    62                   ( ( ( master_menu_mode >= MASTER_COLOR_PAINT &&
    63                         master_menu_mode <= MASTER_COLOR_PLANE ) ||
    64                       master_menu_mode == MASTER_EDIT_BIGGER ||
    65                       ( master_menu_mode == MASTER_REGION &&
    66                         region_area_mode ) ||
    67                       master_menu_mode == MASTER_CORNOR_MASK ) &&
    68                     proc_stat != 2 &&
    69                     mouse_stat == 0 ) )
    70                  {
    71                          ........... 中略 ...........
    72                  }
    73                  ........... 中略 ...........
    74                  break;
    75          case    LOC_WINEXIT:
    76              if ( display_mode == DISPLAY_DISP ||
    77                   display_mode == DISPLAY_LINE ||
    78                   master_menu_mode == MASTER_ANGLE ||
    79                   master_menu_mode == MASTER_HORIZONTAL ||
    80                   master_menu_mode == MASTER_VERTICAL ||
    81                   ( master_menu_mode >= MASTER_DRAW_LINE &&
    82                     master_menu_mode <= MASTER_DRAW_FREE_LINE ) ||
    83                   ( ( master_menu_mode == MASTER_SAVE_PARTIAL ||
    84                         master_menu_mode == MASTER_CLEAN ) &&
    85                         menu_mode ) ||
    86                   ( ( ( master_menu_mode >= MASTER_COLOR_PAINT &&
    87                         master_menu_mode <= MASTER_COLOR_PLANE ) ||
    88                       master_menu_mode == MASTER_EDIT_BIGGER ||
    89                       ( master_menu_mode == MASTER_REGION &&
    90                         region_area_mode ) ||
    91                       master_menu_mode == MASTER_CORNOR_MASK ) &&
    92                     proc_stat != 2 &&
    93                     mouse_stat == 0 ) )
    94                  {
    95                          ........... 中略 ...........
    96                  }
    97                  ........... 中略 ...........
    98                  break;
    99          ........... 果てしなく続く ...........

私は、これを発見したとき、このif文の条件判断にショックを受けるとともに、感銘してしまい ました。これは「新種発見」です。XViewのプログラムをMotif版への変更作業で、イベント処理部 分を書き換えていたときに発見し、かつどうしようか悩んだ個所です。でも、よくもこんなに長々 とand と or で条件式をつなぐものです。条件の一部には不等号も入っていますし、変数 menu_modeや region_area_mode はフラグのようです。そして、switch文のcaseによる場合分けの 中に何度もお目見えしています。それも、1文字も違わないものが現れるのです。このswitch文は、 オリジナルでは598行もある長いもので、有効な場合分けが7個所あり、そのうちの6個所に、こ の完全一致パターンが現れます。リストの方は、長くなりすぎるので、反復パターンの部分以外を 省略して掲載しています。原作の「迫力」が相当そがれていて申しわけないのですが、そのあたり は想像して補いながら鑑賞してください。

このように長ーい条件判定式を書く人って、広い世間にはいるのですね。条件式の長さが18行も あるif文が、同じswitch文中に何度も現れ、しかも、まったく同じ条件式とはね。まったく想像も つかない世界です。これは、間違いなくエディタでコピーしたのでしょう。今後プログラムのバー ジョンアップがあったら、この6個所の条件式を毎度変更していくのでしょうか。気の遠くなるよ うな、吐き気を催すような、とにかく表現力の乏しい私にはもはやどう書いていいか分かりません。

恐い話ですが、ちょっと条件を調べてみましょう。条件式全体は、8個の式が || でつながれて います。どこで分かれるかというと、4, 5, 6, 7, 8, 9-10, 11-13, 14-21 行(リスト11−5) で分かれるのです。最初の2つは、変数 display_mode の判定で、その値が DISPLAY_DISP か DISPLAY_LINE のときは真になります。それ以降は変数 master_menu_mode の判定です。11-13行は さらにmenu_modeも関係します。14-21行はさらに複雑で、region_area_ mode, proc_stat, mouse_stat が絡んできます。複雑過ぎて、私にもよく分かりません。本当によくここまで込み入っ た条件式が書けるものです。この人は本当の「天才」に違いないです。私なんぞ、生涯かけてもこ んな複雑な条件式を理解できるようになれるとは思いませんし、そんな複雑なことをしようなど横 着者の私には全く無理です。

ふつうのプログラマなら、条件式全体を関数かマクロにするでしょう。それでもまだ複雑怪奇な ので、意味のある単位に分け、それぞれをマクロにでもするのではないでしょうか。それとも、もっ と全体を見渡して、こんな判定の仕方をしなくても済むように最初考えて、まったく別の書き方を するでしょう。

さあ、私はこの部分をどのように書き換えたでしょうか。まず、各case毎に個別の関数に分けま した。500行を越すswitch文など、私の知能の限界をはるかに越えています。内容理解の前に、理 解できる単位に分割することが最初の作業です。私の場合、100行を越えると、頭がパニックになっ てしまいます。できれば、50行以下の関数がいいですね。

この条件式は、アプリケーション全体にからむ変数を参照しているので、まるでダイナマイトで も扱うように、可能な限りそーっと、分けた関数にそのまま移しています。本当は手をつけたいの ですが、ここまで「身の毛がよだつ」コーディングをされると、簡単には変更できません。せいぜ い条件式を関数にするのが限界です。一個所でも変更したら、どんな奇妙なバグが出てくるか分かっ たものではありません。まあ、そのうち、アプリケーション全体が理解できたら、気持ち良くこの 部分は廃棄処分し、気持ちを新たにして書き直してしまうでしょう。

本当に、こういう部分の相手までさせられると体調まで狂ってきます。


Copyright1996 Hirofumi Fujiwara. No reproduction or republication without written permission
『Cプログラミング診断室』目次次(第11章 奇っ怪な条件 まとめ)