SSブログ

[境界要素法プログラムを設計する(境界積分サブルーテイン:策定編)] [境界要素法]

[境界要素法プログラムを設計する(境界積分サブルーテイン:策定編)]

 

1.サブルーティンは必要か?

 世の中には、何でもかんでもサブルーティンにすれば良いと思ってる人がけっこういますが、自分の意見は違います。メインルーティンの作業をサブルーティン化すれば、確かにメインは綺麗に整理されてプログラムのフローがわかりやすくなります。しかし代償もあります。それは具体的な作業コードが隠蔽化(カプセル化)されて、可読性(読み解きやすさ)が悪くなるケースもあり得るからです。

 特に大規模プログラムでは何10~何100というサブルーティンが現れ(大規模だからしゃーないんだけど)、こっちのファイルを読みあっちのファイル読んで、そっちのページを・・・とやってると、最弱マシンである人間は、それだけでバグ化します(^^;)。こういう場合は、メインの作業フローを組み直すべきなんですが、では次のような例はどうでしょう?。

 

 よくサブルーティンは引数付きが推奨されます。ローカル変数が使えるので、変数競合を避けられるからです。最強マシンであるPCが、最弱マシンである人間のミスから、その最弱マシンを自動で守ってくれます。

 

 メイン冒頭でxの値を評価し、その評価によって計算の行く末を決める、計算初期値yの値が変わるとします。

 

    If x < 0 Then
      y = 0
    ElseIf (0 <= x) And (x < 1) Then
      y = 1
    Else
      y = 2
    End If

    REM yを使った計算


 

 これはサブルーティン化すべきでしょうか?。するとしたら、こんな感じになりそうです。

 

    External Function y_Setter(x)

      If x < 0 Then
        y = 0
      ElseIf (0 <= x) And (x < 1) Then
        y = 1
      Else
        y = 2
      End If

      y_Setter = y
    End Function

 メインの側は、


    If x < 0 Then
      y = 0
    ElseIf (0 <= x) And (x < 1) Then
      y = 1
    Else
      y = 2
    End If

   REM yを使った計算


・・・と非常にすっきり(^^)。ところが入力仕様が変わり、yのケース分けが1個追加され、しかもケース境界も可変になる事がわかりました。それにともなって「yを使った計算」も変更されます。こうなると、

 

    External Function y_Setter(x)

      If x < 0 Then
        y = 0
      ElseIf (0 <= x) And (x < 1) Then
        y = 1
      Else
        y = 2
      End If

      y_Setter = y
    End Function

メインの側は、

    Declare External Function y_Setter
    y = y_Setter(x)
   REM yを使った計算

です。開発現場のトップ(土木では現場代理人)はたいがい、PMと呼ばれるプロジェクト・マネージャー(Project Manager)が行います。PMは顧客要求の聞き取り(ヒアリング)も兼任する事が多いです。そのPMが良くない知らせを持ってきます。「yの出力値も可変になる」と。

 

 だいたいこの辺りからPMは、PG(プログラマー)の恨みを買い出します(^^;)

 


    Declare External Function y_Setter
    y = y_Setter(x, z1, z2, z3)  REM z1~z3はケース分けの境界値
   REM yを使った計算_変更1

    External Function y_Setter(x, z1, z2, z3)

      If x < z1 Then
        y = 0
      ElseIf (0 <= z1) And (x < z2) Then
        y = 1
      ElseIf (0 <= z2) And (x < z3) Then
        y = 2
      Else
        y = 3
      End If

      y_Setter = y
    End Function

 

 事態はさらに最悪の方向へ向かいます。「開発が終わるまで入力仕様の変更は続き、ケース分けは何ケースになるかわからない。それに対処できるようにしといてくれ」。・・・頭に血が上ったPGは、こう叫びます。

 

 「わかった。配列で渡すようにする。後で汚いとかコードが重いとか、文句言うなよ!」

 

 引数付きサブルーティンは確かに推奨されるべきものです。でも、入力仕様の変更に非常に弱いという欠点も持ちます。だからやめなさいって、そんなもん。自分ならメインで単にこうします。

 


    If x < z1 Then
      y = y0
    ElseIf (0 <= z1) And (x < z2) Then
      y = y1
    ElseIf (0 <= z2) And (x < z3) Then
      y = y2
    Else
      y = y3
    End If

   REM yを使った計算_変更2
    REM ElseIfブロックは、何個でもコピーして増やせる!

 重要なのは、最後のREM文です。たぶんy_Setterの中でも同じ事が出来る、という意見はあると思います。でも駄目です。引数並びが、どんどん重く複雑になるからです。最悪の場合、コードを管理してるんだか引数並びを管理してるんだか、わからないような事態になります。そういう「捩れプロジェクト」は後で涙の嵐です。

 もう一つは、引数並びが重く複雑なサブルーティンは内容も複雑な訳です。しかもサブルーティン化したためにコードが隠蔽され、メインと並べて一目で見渡せなくなります。最弱マシンはそこで、必ず何かを見落とします。バグ特定がしずらいため、それはバグの連鎖反応も招きかねません。

 

 でもテスト技術者(TE)って、こういうコードが嫌いなような印象を受けます(規格物好き?)。確かに綺麗なコードの方が、テストしやすいですもんね。「何でサブ化しない?」ってけっこう言われました(^^;)

 

PG「だって仕方ねぇ~だろう。PMの野郎が仕様をどんどん変えるんだから」

TE「それとコードの可読性は別だ。サブ化しないから可読性が悪い」

PG「悪いだと?。上から順番に読めば、必ずわかるコードのどこが悪い」

TE「メインに1万行も書きやがって、この馬鹿ものがぁ~!」

PG「うるせぇ~!。順番に1万行も読めない奴は、PGでもTEでもねぇ~!」

PM「開発の最終段階でサブ化したら?」

PGTE「・・・・・・」

 

2.境界要素法プログラムは?

 で、境界要素法プログラムではどうでしょう?。とりあえず問題の部分は、

 

  REM (x0y0)(x1y1)(x2y2)から、要素kの境界積分値を計算

 

でした。ここで(x0y0)は特異点座標、(x1y1)(x2y2)は一つの境界要素kの端点座標です。これらは入力部で既に確定しています。という事は、仕様変更はほとんどなさそうです。

 

 ・・・ではサブ化しますか。でも自分の考えでは、これだけでは弱いと思います。境界要素法プログラムの[計算部]をサブ化せずに全部ベタ書きしても、1000行くらいだと思います。さっきのお馬鹿PGだったら「ベタ書きしろぉ~!」というでしょう。1000行くらいなら全体を一気に見渡せると思えるからです。なぜコードを隠蔽して、見にくくするのか?。もっと強力な理由が必要です。設計における方針決定には、明白な根拠があるべきです。

 

 「境界要素番号kで境界積分を行うLoop」が動的過程だからです。前回の該当部分を見て下さい。自分は十分に長いLoopだと思います。その最大の理由は、要素-節点対応表を使って積分値の重ね合わせをやってるからです。つまりこのLoopは一種の漸化式なんですよ。漸化式って短くても、すぐ訳わかんなくなりますよね?(^^;)。そういう部分は出来るだけ綺麗に見やすくしとくべきだ、と思うからです。境界積分値を計算する、サブルーティンを作ると方針決定します。

 これは、

  1) 動的過程を制御するメタな静的構造(今はLoop)の可読性を上げて確保する.

 

事でもあります。ほとんど意識されませんが、サブルーティンを用いる最も大きな理由の一つが上記だと自分は思います(コード自体は短くても)。y_Setterはそういうものではありませんでした。

 

 あとサブルーティンを用いる一般的理由としては、当然ながら、

  2) メインが長すぎて一気に読めない(1万行は多すぎる(^^;)).

  3) 再利用性を考えた.

などです。y_Setterは、2)3)いずれにも該当しません。

 

 3)は(オブジェクト指向も含めて)サブルーティン化の大きな理由とされますが、じつはバグの発生頻度とトレードオフの関係にあります。

 一般にコードは書けば書くほどバグ確率は比例して増加します。再利用すれば一回しか書かないので、良さそうに思えます。しかしコードは隠蔽されるので、潜在バグの発生確率が上がります。それに気づかぬまま潜在バグが発覚すると、今度はシステム全体で大被害です。大抵そこら中で使い回すからですよ。大被害が出るとバグの場所はわかりやすいですけれど、運用段階に入ってた銀行のシステムなんかだと、わかりやすいでは済みません(^^;)。一番困るのが、運用段階に入ったサブルーティン間の競合です。

 

 以上は全て人間の都合です。機械にとってはどうでも良い事です。なので2)などは、人間の限界を認めた話です。人間原理最優先で行きましょう(^^)。人間原理最優先なので、以後サブルーティンと関数にはローカル変数を持てる外部手続きのみ用います。タフな機械に守ってもらいます。

 

 


nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

浮動小数点とは何かホイン(Heun)法 ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。