tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトル長くなりすぎるプロシージャ名
記事No7638
投稿日: 2008/05/30(Fri) 14:46
投稿者ひでと
お世話になります。
Privateなプロシージャを処理の分岐に応じて複数作っています。
プロシージャ名をそれぞれの処理を _ でつなげて表現しています。
 
Private Sub 処理1_処理11_処理111() といった感じです。

End Sub

処理の分岐が多くなると当然プロシージャ名が長くなり、
返って分かり辛くなってしまいます。

短いプロシージャ名 この場合は 処理111 を使い、
Private Sub
     処理1.処理11.処理111
End Sub
のような形で呼び出したいのです。
namespace を使えないかと

Namespace 処理1
    Namespace 処理11
        Public Sub 処理111()

        End Sub
    End Namespace
End Namespace
とやってみたんですが

「名前空間のステートメントが無効です。」
のエラーが出てしまいます。どのようにしたらよいのでしょうか?

[ツリー表示へ]
タイトルRe: 長くなりすぎるプロシージャ名
記事No7639
投稿日: 2008/05/30(Fri) 14:58
投稿者よねKEN
こんにちは。

> Privateなプロシージャを処理の分岐に応じて複数作っています。
> プロシージャ名をそれぞれの処理を _ でつなげて表現しています。
>  
> Private Sub 処理1_処理11_処理111() といった感じです。
>
> End Sub
>
> 処理の分岐が多くなると当然プロシージャ名が長くなり、
> 返って分かり辛くなってしまいます。

適切な(適当な)単位でクラスになっているでしょうか。

VB.NETではクラスを定義して、その中にメソッドを定義します。
(VB6以前にもクラスはありますが、.NETではより本格的にオブジェクト指向で
設計/実装ができます)

データ+そのデータに対する操作をクラスとしてまとめますが、
その単位が適切に設計されていれば、無闇にメソッド名が長くはならないと思います。
メソッド名が無闇に長くなっている場合は、一つのメソッドで複数のことを
行っていないかを見直すとよいと思います。

> Namespace 処理1
>     Namespace 処理11
>         Public Sub 処理111()
>
>         End Sub
>     End Namespace
> End Namespace
> とやってみたんですが
>
> 「名前空間のステートメントが無効です。」
> のエラーが出てしまいます。どのようにしたらよいのでしょうか?

名前空間>クラス>メソッド
という形で入れ子になっている必要がありますが、
上記の例ではクラスがありませんので、文法エラーになります。
処理11に当たる単位でクラス(またはモジュール)にならないか
検討してみてはいかがでしょうか。

ただし、クラスはその単位で一つのモノを表しますので、
関係のないメソッドを一括りにしないように注意する必要があります。

[ツリー表示へ]
タイトルRe^2: 長くなりすぎるプロシージャ名
記事No7640
投稿日: 2008/05/30(Fri) 16:15
投稿者ひでと
ありがとうございます。
>
> データ+そのデータに対する操作をクラスとしてまとめますが、
> その単位が適切に設計されていれば、無闇にメソッド名が長くはならないと思います。
クラスとして作ってみようとすると、クラスの中に含まれるデータが無いようなのです。
そういう場合もクラスを作るべきなんでしょうか?

> メソッド名が無闇に長くなっている場合は、一つのメソッドで複数のことを
> 行っていないかを見直すとよいと思います。
分岐処理を繰り返していますが、されを処理為にたくさんのプロシージャが
できてしまいました。その意味では ひとつのプロシージャの処理は比較的単純に
作ったつもりです。

> > 「名前空間のステートメントが無効です。」
> > のエラーが出てしまいます。どのようにしたらよいのでしょうか?
>
> 名前空間>クラス>メソッド
> という形で入れ子になっている必要がありますが、
> 上記の例ではクラスがありませんので、文法エラーになります。
> 処理11に当たる単位でクラス(またはモジュール)にならないか
> 検討してみてはいかがでしょうか。


実際は例でいくと 処理1111111 位(7階層?)位の処理がありますので、
教えていただいた方法ですと、ほとんど全ての処理で
データを持たないクラスを作り、そのメソッドとしてプロシージャを記載
することになるような気がします。
クラス間のやり取りを処理するが難しそうですが、もう一度見直してみます。

>
> ただし、クラスはその単位で一つのモノを表しますので、
> 関係のないメソッドを一括りにしないように注意する必要があります。

[ツリー表示へ]
タイトルRe^3: 自己レスです
記事No7642
投稿日: 2008/05/30(Fri) 17:14
投稿者ひでと
>
> 実際は例でいくと 処理1111111 位(7階層?)位の処理がありますので、
> 教えていただいた方法ですと、ほとんど全ての処理で
> データを持たないクラスを作り、そのメソッドとしてプロシージャを記載
> することになるような気がします。

下位のクラスを取得するために、そのインスタンス?用に
少なくとも一つの変数が必要になるんですね。

Public Class 処理11
 Public 処理111 as 処理111
End Class

(処理111 は 処理111を返すプロパティとした方がいいですね)
今はクラスシート1枚に1個のクラスをPubulicで記載していますが、
最終的には、Privateにして1枚のクラスシートに入れ子で記載すれば
他からは参照できないようにできそうです。
手法としては、合っていますでしょうか?

[ツリー表示へ]
タイトルRe^3: 長くなりすぎるプロシージャ名
記事No7643
投稿日: 2008/05/30(Fri) 17:14
投稿者よねKEN
具体的な処理がわからないので一般論になってしまいますが参考までに。

> > メソッド名が無闇に長くなっている場合は、一つのメソッドで複数のことを
> > 行っていないかを見直すとよいと思います。
> 分岐処理を繰り返していますが、されを処理為にたくさんのプロシージャが
> できてしまいました。その意味では ひとつのプロシージャの処理は比較的単純に
> 作ったつもりです。

'イメージ図のため引数は省略。また戻り値の有無もここでは区別しないので仮にSubとしている
Public Sub 処理()
   処理1
   処理2
    :
   処理N
End Sub

Public Sub 処理1()
  処理11
  処理12
    :
  処理1N
End Sub

Public Sub 処理11()
  処理111
  処理112
    :
  処理11N
End Sub

例えば、上記のようなイメージなのだと思いますが、
末端の処理111〜処理11Nが比較的単純だとして、
それを束ねる処理11や処理1は1つの機能だけを実現しているでしょうか?
処理1が複数の機能を備えているとしたら、大元の構造から見直した方がよいかもしれません。

また、例えば、この中で処理111は処理1の中の処理11から呼び出されるわけですが、
処理111は処理1や処理11に依存した内容でしょうか?
依存しない内容であれば、処理1_処理11_処理111という名前にする必要はなく、
単に処理111でよいはずです。

例えば、ある文字列が数値かどうかを判定するメソッドを考えるとき、
Public Function IsNumber(ByVal stringValue As String) As Boolean
のような名前にし、処理1_処理11_IsNumberとは命名しないですよね。

逆に処理1_処理11_処理111という名前にしかならないようなメソッドであれば、
処理1_処理11の中に直接記述すればよいのではないでしょうか?

機能を切り出してメソッド化するときは、呼び出し元のメソッドや
呼び出し元のメソッドから呼び出される他のメソッドに依存してはいけません。
こういうような状況で強引に切り出されるメソッドはたいてい
機能で分割されたメソッドではなく、長い長いメソッドを短く見せかけるためだけに
分割されたものである場合が多いです。短いから良いとは限りません。

[ツリー表示へ]
タイトルRe^4: 長くなりすぎるプロシージャ名
記事No7644
投稿日: 2008/05/30(Fri) 18:09
投稿者ひでと

ありがとうございます。(自宅から レスしてます)
>
> 'イメージ図のため引数は省略。また戻り値の有無もここでは区別しないので仮にSubとしている
> Public Sub 処理()
>    処理1
>    処理2
>     :
>    処理N
> End Sub
>
> Public Sub 処理1()
>   処理11
>   処理12
>     :
>   処理1N
> End Sub
>
> Public Sub 処理11()
>   処理111
>   処理112
>     :
>   処理11N
> End Sub
>
> 例えば、上記のようなイメージなのだと思いますが、
> 末端の処理111〜処理11Nが比較的単純だとして、
> それを束ねる処理11や処理1は1つの機能だけを実現しているでしょうか?

「1つの機能」の概念が理解できないのですが?

Public Sub 処理11(選択 as Integer)
  Select Case 選択
 Case1:   処理111
  Case2:   処理112
     :
  CaseN:   処理11N
 End Select
End Sub
この場合は1つの機能とは言えないのでしょうか?
実際にはこのような処理ばかりです。

>
> また、例えば、この中で処理111は処理1の中の処理11から呼び出されるわけですが、
> 処理111は処理1や処理11に依存した内容でしょうか?
> 依存しない内容であれば、処理1_処理11_処理111という名前にする必要はなく、
> 単に処理111でよいはずです。

上記のように選択肢で分岐してますので、依存した内容です。

>
> 例えば、ある文字列が数値かどうかを判定するメソッドを考えるとき、
> Public Function IsNumber(ByVal stringValue As String) As Boolean
> のような名前にし、処理1_処理11_IsNumberとは命名しないですよね。
>
> 逆に処理1_処理11_処理111という名前にしかならないようなメソッドであれば、
> 処理1_処理11の中に直接記述すればよいのではないでしょうか?
>
> 機能を切り出してメソッド化するときは、呼び出し元のメソッドや
> 呼び出し元のメソッドから呼び出される他のメソッドに依存してはいけません。
> こういうような状況で強引に切り出されるメソッドはたいてい
> 機能で分割されたメソッドではなく、長い長いメソッドを短く見せかけるためだけに
> 分割されたものである場合が多いです。短いから良いとは限りません。

おっしゃるとおり長いメソッドを見せかけだけ短くしたものと言えると思います。
プログラムの途中で入力の必要が無く、一連の内容を順序どおりに実行される
部分なので、手続き型のプログラム部分です。
直接記述していくと、正直自分でも処理が分からなくなる為、短い処理に分割しています。
このような場合に、他のメソッドに依存しないように作るにはどのように
すればいいのでしょうか?

自己レスで入れたように、クラス単位で分割を試みていますが、
手続き的な処理の本質は変えられないのですが、こういうのはまずいのでしょうか?

プロシージャが上位の処理に依存した処理の為、クラスをPrivateで上位のクラスの
中に記載したいと考えています。
そうすると、また見た目のクラスが長くなり、自分でも混乱しそうですが、
他から参照できないようにしたいのです。
そのような手法はありますでしょうか?

[ツリー表示へ]
タイトルRe^5: 長くなりすぎるプロシージャ名
記事No7653
投稿日: 2008/06/02(Mon) 09:58
投稿者よねKEN
> 「1つの機能」の概念が理解できないのですが?

機能という言葉は役割や仕事と言い換えてもいいです。
1つのメソッドは1つの機能だけを実現する。
1つのメソッドは1つの役割だけを実現する。
1つのメソッドは1つの仕事だけを実現する。
 :

先ほど例に出したIsNumberメソッドは数値かどうか判定するメソッドで、
「数値かどうか判定する」だけの1つの機能しか持ちません。
このメソッドに判断対象データが何進数として検査するか?
ということを指定できる引数を追加しても、あくまでこのメソッドは
「数値かどうか判定する」という1つの機能だと言えるでしょう。

' stringValue->検査対象、base→基数を指定 16を指定すると16進数としてチェック
' 例えば、16進数の場合、FFは数値である。
Public Function IsNumber(ByVal stringValue As String, ByVal base As Integer) As Boolean

しかし、下記のようなメソッドはどうでしょうか?

' stringValue->検査対象、number->検査対象で整数として読み取れる部分までを変換した整数を返す
' 例えば、"123XX"という文字列を渡した場合、numberは123、戻り値はFalse
Public Function IsNumber(ByVal stringValue As String, ByRef number As Integer) As Boolean

このメソッドに違和感を感じませんか?
stringValueを検査するという機能と、stringValueから整数と読み取れる箇所を抜き出す機能という2つの機能を持っています。
この機能面に基づいてメソッド名を変えるとIsNumberAndCutNumberのような
妙な名前のメソッドになるかもしれません。

こういうような意味での「1つの機能」です。

> Public Sub 処理11(選択 as Integer)
>   Select Case 選択
>  Case1:   処理111
>   Case2:   処理112
>      :
>   CaseN:   処理11N
>  End Select
> End Sub
> この場合は1つの機能とは言えないのでしょうか?

というわけで具体的な処理を説明いただかないと私には判断できません。

> 実際にはこのような処理ばかりです。

必然的にこのようにしか実装できないロジックもないとは言えないので、
実例で話をしないと指摘は難しいです。

例えば、一般的な業務アプリではfor文による多重ループはせいぜい3重程度までで
それ以上のループになるとしたら、ほぼ間違いなく整理されていないロジックです。
しかし、数学の問題などを解くロジックだと8重ループとか平気で出てきたりして、
それでいて、そういう処理を書くのが素直な場合もあります。

長い記述になるコードでも、それが十分素直な記述であれば、
それでよいという判断をする場合もあります。

> > また、例えば、この中で処理111は処理1の中の処理11から呼び出されるわけですが、
> > 処理111は処理1や処理11に依存した内容でしょうか?
> > 依存しない内容であれば、処理1_処理11_処理111という名前にする必要はなく、
> > 単に処理111でよいはずです。
>
> 上記のように選択肢で分岐してますので、依存した内容です。

依存しているというのはわかりましたが、上記のイメージだけを見ると
処理11メソッドは必要なくて、処理1にSelect Caseをそのまま書くという選択肢も
考えられます。(あくまで上記のコードイメージを見ての判断ですが)

> このような場合に、他のメソッドに依存しないように作るにはどのように
> すればいいのでしょうか?

#本質的に依存するものであれば切り出せない場合もあります
よくある蜜に結合されているメソッド群は、メソッドの引数を通じてデータを
やりとりせず、モジュールレベルの変数にデータを持たせて、
そのモジュールレベルの変数を介して連携しているものがあります。
こういう場合では、モジュールレベルの変数を介して処理をするのを
やめてメソッドの引数、及び、戻り値を使うようにすれば、そのメソッドの
独立性が高まります。

> 自己レスで入れたように、クラス単位で分割を試みていますが、
> 手続き的な処理の本質は変えられないのですが、こういうのはまずいのでしょうか?

クラス単位に分けることを先ほどは提案しましたが、今回話題にしているメソッド群が
一連の手続きなのであれば、それらはすべて1つのクラスの中のメソッドにしか
ならないかもしれませんので、無理にクラスに分けるのはお勧めできません。

[ツリー表示へ]
タイトルRe^6: 長くなりすぎるプロシージャ名
記事No7659
投稿日: 2008/06/02(Mon) 12:30
投稿者ひでと
ありがとうございます。
> しかし、下記のようなメソッドはどうでしょうか?
>
> ' stringValue->検査対象、number->検査対象で整数として読み取れる部分までを変換した整数を返す
> ' 例えば、"123XX"という文字列を渡した場合、numberは123、戻り値はFalse
> Public Function IsNumber(ByVal stringValue As String, ByRef number As Integer) As Boolean
>
> このメソッドに違和感を感じませんか?
> stringValueを検査するという機能と、stringValueから整数と読み取れる箇所を抜き出す機能という2つの機能を持っています。
> この機能面に基づいてメソッド名を変えるとIsNumberAndCutNumberのような
> 妙な名前のメソッドになるかもしれません。
>
> こういうような意味での「1つの機能」です。
戻り値が二つあるようなら 機能が二つあるという感じですね。
関数としての「1つの機能」は理解できました。ありがとうございました。

>
> > Public Sub 処理11(選択 as Integer)
> >   Select Case 選択
> >  Case1:   処理111
> >   Case2:   処理112
> >      :
> >   CaseN:   処理11N
> >  End Select
> > End Sub
> > この場合は1つの機能とは言えないのでしょうか?
>
> というわけで具体的な処理を説明いただかないと私には判断できません。
具体的な説明ではないのですが、上記の例は
「処理11」は「選択」の値に応じて「処理111」「処理112」等の処理をする
という処理です。
「ある値に応じて処理をする」という意味で「1つの機能」であると言えるのかな?
という疑問でした。Functionの場合より「1つの機能」の意味が分かり辛いです。

>
> > > また、例えば、この中で処理111は処理1の中の処理11から呼び出されるわけですが、
> > > 処理111は処理1や処理11に依存した内容でしょうか?
> > > 依存しない内容であれば、処理1_処理11_処理111という名前にする必要はなく、
> > > 単に処理111でよいはずです。
> >
> > 上記のように選択肢で分岐してますので、依存した内容です。
>
> 依存しているというのはわかりましたが、上記のイメージだけを見ると
> 処理11メソッドは必要なくて、処理1にSelect Caseをそのまま書くという選択肢も
> 考えられます。(あくまで上記のコードイメージを見ての判断ですが)
>
> > このような場合に、他のメソッドに依存しないように作るにはどのように
> > すればいいのでしょうか?
>
> #本質的に依存するものであれば切り出せない場合もあります
> よくある蜜に結合されているメソッド群は、メソッドの引数を通じてデータを
> やりとりせず、モジュールレベルの変数にデータを持たせて、
> そのモジュールレベルの変数を介して連携しているものがあります。
> こういう場合では、モジュールレベルの変数を介して処理をするのを
> やめてメソッドの引数、及び、戻り値を使うようにすれば、そのメソッドの
> 独立性が高まります。

今回のケースは、それに当たる気がします。モジュールレベルでの変数によって
全ての処理が決定されてしまいます。
「メソッドの独立性」とは、別の箇所で使いまわしする為に必要な事ですよね。
今回は、使いまわしはしない予定で、逆に関係ない部分からアクセスすることが
できないようにしたいので、「蜜に結合されている」状態だと思います。
>
> > 自己レスで入れたように、クラス単位で分割を試みていますが、
> > 手続き的な処理の本質は変えられないのですが、こういうのはまずいのでしょうか?
>
> クラス単位に分けることを先ほどは提案しましたが、今回話題にしているメソッド群が
> 一連の手続きなのであれば、それらはすべて1つのクラスの中のメソッドにしか
> ならないかもしれませんので、無理にクラスに分けるのはお勧めできません。

クラス分けしようとしていましたが、非常に混乱して「にっちもさっちも」
という感じになっていました。
今回は「すべて1つのクラスの中のメソッド」にしたいと考えてますので、
クラスの使用をあきらめてみます。

漠然とした質問に、丁寧にお答えいただきありがとうございます。

[ツリー表示へ]
タイトルRe^7: 長くなりすぎるプロシージャ名
記事No7661
投稿日: 2008/06/02(Mon) 14:00
投稿者魔界の仮面弁士
# 誤記とはいえ、間違えて覚えると厄介なので、一応ツッコミ。

> > よくある蜜に結合されているメソッド群は、メソッドの引数を通じてデータを
> > やりとりせず、モジュールレベルの変数にデータを持たせて、
> > そのモジュールレベルの変数を介して連携しているものがあります。
> 今回は、使いまわしはしない予定で、逆に関係ない部分からアクセスすることが
> できないようにしたいので、「蜜に結合されている」状態だと思います。

蜜結合 ではなく、密結合(tight coupling) です。

疎結合 (loose coupling) の対義語。

[ツリー表示へ]
タイトルRe^8: 長くなりすぎるプロシージャ名
記事No7662
投稿日: 2008/06/02(Mon) 14:47
投稿者ひでと
ありがとうございます。
> # 誤記とはいえ、間違えて覚えると厄介なので、一応ツッコミ。
>
> > > よくある蜜に結合されているメソッド群は、メソッドの引数を通じてデータを
> > > やりとりせず、モジュールレベルの変数にデータを持たせて、
> > > そのモジュールレベルの変数を介して連携しているものがあります。
> > 今回は、使いまわしはしない予定で、逆に関係ない部分からアクセスすることが
> > できないようにしたいので、「蜜に結合されている」状態だと思います。
>
> 蜜結合 ではなく、密結合(tight coupling) です。
>
> 疎結合 (loose coupling) の対義語。
誤字多くて、申し訳ないです。専門用語なんですね。

[ツリー表示へ]
タイトルRe^7: 長くなりすぎるプロシージャ名
記事No7663
投稿日: 2008/06/02(Mon) 15:00
投稿者よねKEN
#弁士さんフォローありがとうございます。
#ご指摘のとおり蜜→密が正しいです。

> > ' stringValue->検査対象、number->検査対象で整数として読み取れる部分までを変換した整数を返す
> > ' 例えば、"123XX"という文字列を渡した場合、numberは123、戻り値はFalse
> > Public Function IsNumber(ByVal stringValue As String, ByRef number As Integer) As Boolean
> >
> > このメソッドに違和感を感じませんか?
> > stringValueを検査するという機能と、stringValueから整数と読み取れる箇所を抜き出す機能という2つの機能を持っています。
> > この機能面に基づいてメソッド名を変えるとIsNumberAndCutNumberのような
> > 妙な名前のメソッドになるかもしれません。
> >
> > こういうような意味での「1つの機能」です。
> 戻り値が二つあるようなら 機能が二つあるという感じですね。
> 関数としての「1つの機能」は理解できました。ありがとうございました。

あまりいい説明でなかったかもしれませんね。
戻り値の数は重要なポイントではなく、あくまでその機能面に着目して、
・数値かどうか判定
・数値部分の切り出し
という2機能を一緒に行っているところがあまり好ましくない点です。

- 何らかの処理と一緒にファイルへの書き出しも行う
- 計算をしつつ、画面にも表示する
といったようなものであればSubプロシージャで
2つ以上の機能を兼ねたものを作れますので。

[ツリー表示へ]
タイトルRe^8: 長くなりすぎるプロシージャ名
記事No7664
投稿日: 2008/06/02(Mon) 15:05
投稿者ひでと
> 戻り値の数は重要なポイントではなく、あくまでその機能面に着目して、
> ・数値かどうか判定
> ・数値部分の切り出し
> という2機能を一緒に行っているところがあまり好ましくない点です。
>
> - 何らかの処理と一緒にファイルへの書き出しも行う
> - 計算をしつつ、画面にも表示する
> といったようなものであればSubプロシージャで
> 2つ以上の機能を兼ねたものを作れますので。
理解できました。

[ツリー表示へ]