2018年09月02日

なぜ引数の型宣言は必要なのか


初めての方はこちらを「はじめに

タイトルから今回はかなり具体的で実装的な話に思えるかもしれませんが、実はそうでもありません。

引数の型宣言とは


この言葉の意味が通じない人はあまりいないとは思いますが、もしかしたらインタープリター系の言語しか経験のない方は、そもそも「型宣言」自体が良く分からないかもしれません。それでも型という概念自体は意識している事でしょうから、この場では型宣言とは型を記述して明示する事だと理解しもらえばいいと思います。ここで言っているのは関数の定義を行う時に引数の定義に型を明示するという事です。
VBAだと以下の様な感じになります。
Func1(Arg1 As Integer)
引数Arg1に対してIntegerという型を宣言しています。「VBAなんて知らないよ」という人が多いかもしれませんが、特段言語に依存する様な話題ではないのであまり気にしないでください。厳密にVBAの文法に従う訳でもなく、概念的な記述ですので。

今回の話はこのIntegerの記述はなぜ必要なのかという話です。

宣言した場合しない場合の違いは何か


では、なぜ型宣言が必要なのかを考える為に、型宣言しない場合とした場合でどのような違いが起きるのかを見てみたいと思います。実はVBAには型を明示しない型というものが存在します。Variant型というものです。一応型なので他の型と同様に記述できます。つまり以下の様に記述できます。
Func1(Arg1 As Variant)
しかし形式的には型として記述していますが実体としては何の型なのかは不明です。はたしてArg1が数値型なのか文字型なのか、何も分かりません。

そして容易に想像がつくように以下の様に型の記述を省略した場合はこのVariant型が割り当てられます。
Func1(Arg1)

このVariant型の実際の型が決定するのは実行時です。つまり以下の様にFunc1に引数を指定して呼び出した時に、その内容に応じて、Arg1の実際の型(Integer)が確定します。
Main()

    Func1(1230)
 
つまり型を宣言する言語にも関わらず、Variantを使うと型宣言の無いインタープリターの様に内部的に自動的に型が処理されるという訳です。

それでは明示的にIntegerと型宣言した場合とVariantにした場合ではどの様な違いが起きるのでしょうか。その為にはFunc1の処理の内容も必要なので、ここでは以下の様にArg1を二倍にする処理だとします。Resultは変数だと思ってください。
Func1(Arg1)

    Result = Arg1 * 2
 

ではこの前提で型宣言がある場合と無い場合で文字型(String)の変数を引数に指定して呼び出したらどうなるか見てみたいと思います。

型宣言がある場合

Main()
    Value As String

    Func1(Value)
 
Func1(Arg1 As Integer)

    Result = Arg1 * 2
 
この場合コンパイルエラーになります。呼び出しの記述である「Func1(Value)」部分が型の不整合でエラーになります。

次に型宣言が無い場合です。
型宣言が無い場合

Main()
    Value As String

    Func1(Value)
 
Func1(Arg1)

    Result = Arg1 * 2
 
コンパイルはエラーになりません。Arg1の型が実行しないと確定しないからです。実行するとArg1の型が文字型(String)で確定して、処理の部分の「Arg1 * 2」で型の不整合でエラーになります。
つまり
    型宣言をするとコンパイル時にエラー
    型宣言をしないと実行時にエラー
という結果になります。

※VBAはインタープリターなのでコンパイルして実行形式のファイルを生成するような手続きはありません。しかしデバッグ用の機能に「コンパイルをする」という機能があり、これを使うと事前にコンパイルエラーが確認できます。

宣言する理由


以上の事から分かる様に引数の型宣言は
実行時エラーを回避するため
と言えます。
そしてなぜその様な必要があるかと言えば、より根本的な大原則である
問題点はより上流工程で潰す
為です。
もし製造の問題点を製造工程で退治する事ができずにすり抜けて、テストの工程に行ってしまうとそこで潰すのは何倍もパワーがかかってしまうという事です。それは実際に研究で明らかになっている事ですし、感覚的にも十分納得がいく事ではないでしょうか。リリース後のユーザー先での運用が最も下流の工程だと考えれば、そこまで問題点が流れ着いてしまったら、どれ程余分なパワーが必要になるかは誰の目にも明らかなはずです。そして型の宣言をしないと実行時にしかエラーが分かりませんから、もしテストの時にも見つけられなかったとしたら実際にユーザー先まで行ってしまう可能性があります。

今回は引数の型宣言を例にとって説明しましたが、実はこの大原則は至るところでお目にかかります。例えばクラスの定義でプロパティを作るのを端折って引数にしてしまったら同じ構図になります。
四角形の四辺の罫線のON/OFFをそれぞれプロパティとして定義する

Border.Left = TRUE
辺の名前(Left)が間違っていればコンパイルエラーになる。

辺を引数として指定する

Border("Left") = TRUE
辺の名前が間違っている場合は実行時にならないとエラーは出ない。

全ては問題点を下流に流さない為と言えます。

なぜ宣言をしないのか


以上のように引数の型宣言は開発工程全体で見た時のパワーを削減する為と言えます。よって基本的には宣言するべきですが、Variantの様なものが用意されている通り、宣言しない場合もあります。それは「型が確定しない」、「型を意識しなくて良い」ような時です。そのような時というのは設計されてそのような仕様になる訳なので、決して「型を意識するのが大変だから」とか「記述が面倒だから」とかではありません。もしそのように楽をしたいのが理由なら、それは問題を後ろの工程に先送りして、より大きな苦労を生み出しているだけです。そもそも設計をしないでまともに動くものができるはずは無いですし、記述と言ってもコーディングで純粋にキーを叩いている時間などというのは開発工程全体からすれば僅かなものです。(英文の文書をただ転記する為にキーボードで打ち込む時の速度を想像すれば、純粋に文字を打ち込む時間は極めて短時間だと分かるのではないでしょうか。ほとんどは考えている時間なのです)従って正しく型を宣言するべきですし、正しく宣言しないべきなのです。

インタープリター系のスクリプト等で型が必要ないのは、そのような用途の範囲に限られているからです。そのような言語で、もしシビアなシステムを組もうとしたら途端に難しい事になります。むしろ型が欲しくなります。「「自動」は簡単ではない」でも触れましたが自動というものは非常に難しいので、全ての局面で型を自動で処理するのは難しいのです。この先技術が進歩して型が世の中から無くなったら開発者にとってはありがたい事ではありますが…

自分自身の経験としてC言語のこのような変遷を経験した事があります。最初にC言語を学んだ時はいわゆる「K&R(カーニハンとリッチー)」の時代でした。(ちなみにデニス・リッチーはスティーブ・ジョブズが亡くなった三日後に亡くなったそうです)この時は記述に割と自由というかルーズな側面があったのですが、その後ANSIで規格化されたCに移行すると、プロトタイプ宣言と言って関数の本体とは別にI/Fだけを事前に宣言する事が義務付けられました。これによって関数の呼び出しに関してはかなり厳格にコンパイルチェックがされるようになったのですが、皆凄く面倒くさがって文句を言っていたのを覚えています。しかしANSI-Cになってから入って来た新人は勿論文句など言いませんし、文句を言っていた人達も直ぐに慣れてしまいました。コーディングに関して言えば何事も決めてしまえば実際は大して混乱はしないという印象です。

一覧


メニュー


記事を広める



posted by 善 at 15:27 | Comment(0) | 製造 | このブログの読者になる | 更新情報をチェックする
スポンサーリンク
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。