まえおき
最近クラス設計に関して書いていたので、ついでにメソッド設計も軽く書こうかなと思います。
メソッドの構成要素
ざっくり以下に分けてグダグダ述べます。
- 引数
- 返り値
- フィールド
- 例外
- 大域変数
引数
関数にもある要素。
一般的に入力情報が渡ってくる場所。
ざっくりわけて以下の3種類がある。
- 値渡し
- 参照渡し
- ポインタ渡し
これらの種別は読み取りの場合にあまり気にする必要がないが、書き込みの際に気をつけないといけない。
参照渡し/ポインタ渡しの場合はメソッド内の変更が呼び出し元に反映される。
意図しない場合は読み取り専用として扱ったほうが無難。
値渡し
呼び出し元の値をコピーしたものが渡ってくる。
書き換えても元の値とメモリ空間が別なので影響しない。
巨大なデータを値渡ししてしまうとデータのコピーコストがハンパないので注意。
定数などのネイティブ型情報の受け渡しに使用される。
C++の場合オブジェクトをこの方法で渡すことができる。
その場合コピーコンストラクタという専用のコンストラクタ起動してオブジェクトがコピーされる。
参照渡し
呼び出し元変数への参照が渡ってくる。
参照なので書き換えれば元も書き換わる。
参照渡しやポインタ渡しの場合元、呼び出し元の値を書き換えることができる。
オブジェクトの受け渡しはだいたいこれ。
受け取ったオブジェクトのメソッド呼び出していい感じに変更する。
好き勝手変更しまくるとカオスになるのでクラス設計がカオスだと悲劇が生まれる。
ポインタ渡し
C/C++言語用。
ポインタが渡ってくる。
用途としては参照渡しと同様。
C言語でよくあるのが、確保したメモリのポインタ渡して、関数内で値をセットしてもらうとか。
返り値
関数にもある要素。
値を呼び出し元に返す。
複数の値を返せる言語もある。
こちらも引数と同様3種類ある。
返り値を返した後はローカル変数は消滅するのでうっかりローカル変数の参照やポインタを返すと悲劇が起きる。
フィールド
そのメソッドが関数ではなくメソッドであるからには、何かしらのフィールドアクセスが有って然るべきき。
メソッドの種類分けの際にはそのメソッドがフィールドに何をするのかで考えるといい。
getter/setterはシンプルな例。
いろんなフィールドにアクセスする場合は分割したほうがいい。
例外
例外オブジェクトを呼び出し元に返す。
返り値と違うのは受け取られないと、更に元の呼び出し元に帰って行くところ。
だからといって空catchなどで握りつぶしてはいけない。
一般的に異常系と言われる処理で使われるべきであり、正常系で投げてはいけない。
catchした側はそのtryスコープの責任範囲の処理(コネクション切断など)を行ってもう一度投げ直すか、例外事象を解決して正常系に復帰するかのどちらかをする必要がある、
誰にもcatchされないとシステム側でcatchされることになるが、これは例外中の例外であるべし。
せめてエラーログ吐き出してエラーステートで終了すべき。
ついでにいうと例外はコストが重い。
組み込み系でC++を使っていたが無効化オプションで無効化できるようになっていた。
大域変数
グローバル変数とか環境変数とか、その他の変数。
直接アクセスするのは極力避けたい。
読み取るには引数から渡せばなんとかなる。
書き込みは専用のクラス作ってそいつに専任させるのがベストか。