- PR -

複数の情報の値を返す場合のインターフェース設計について

投稿者投稿内容
taa
常連さん
会議室デビュー日: 2005/08/29
投稿数: 44
投稿日時: 2005-11-06 16:50
こんにちは。VB.NETの初心者です。
今、クラサバソフトの開発をしており、VB.NETから既存のC++のAPIを実行し、
値を返却するユーザクラスを作成したいと思っています。
しかし、既存のAPIを実行した際に複数の情報が返却される為、作成するユーザクラスを
どのようなインターフェース(メソッドの戻り値、メソッドのByRef返し、プロパティなど)にしたらよいのか困っています。
そこで、一般的にどのようなインターフェースにしたら良い(万人が使いやすく、わかりやすい)のか皆さんの意見を頂きたいと思います。

ちなみに今、考えている案は以下の4つです。

1.構造体配列にて、メソッドの戻り値とする
2.配列や構造体配列にて、メソッドの引数(ByRef)とする。
3.APIから返却される複数の情報の種類別にGetプロパティを作成する
4.APIから返却される複数の情報の種類別にメソッドを作成し、戻り値として返却する
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2005-11-06 20:49
引用:

今、クラサバソフトの開発をしており、VB.NETから既存のC++のAPIを実行し、
値を返却するユーザクラスを作成したいと思っています。
しかし、既存のAPIを実行した際に複数の情報が返却される為、作成するユーザクラスを
どのようなインターフェース(メソッドの戻り値、メソッドのByRef返し、プロパティなど)にしたらよいのか困っています。


インターフェースのもち方として、(名前は忘れましたが)
(1)
Class1.x1 = 1
Class1.x2 = 1
Class1.y1 = 10
Class1.y2 = 10
Class1.Line()
(2)
Class1.Line(1,1,10,10)
の2通りがあります。
(1)は内部に保持した値に依存するタイプです。
(2)はメソッドで完結するタイプです。
混在しないほうがベストですし、同系のインターフェースで混在するとユーザーが混乱します。
私観としてはAPIのラッパーがメインなら(2)のように完結するほうがよいかもしれません。
InitializeやCloseなどセットもののAPIでも順に呼び出すというのはユーザーへ求める規則ですし。
情報の返し方としては
コード:
Public Class1
    Public Function Method1() As InfoClass1
    End Function
End Class
Public InfoClass1
End Class


とするとか。
返すだけならInfoClass1のコンストラクタをPrivateにすればよいし。
いずれにしろ、公開するクラスはAPIに関係なく、業務仕様として抽象化するのが大事でしょう。
taa
常連さん
会議室デビュー日: 2005/08/29
投稿数: 44
投稿日時: 2005-11-06 22:28
まどかさん回答ありがとうございます。
以下に(★)コメントします。

引用:

インターフェースのもち方として、(名前は忘れましたが)
(1)
Class1.x1 = 1
Class1.x2 = 1
Class1.y1 = 10
Class1.y2 = 10
Class1.Line()
(2)
Class1.Line(1,1,10,10)
の2通りがあります。
(1)は内部に保持した値に依存するタイプです。
(2)はメソッドで完結するタイプです。
混在しないほうがベストですし、同系のインターフェースで混在するとユーザーが混乱します。
私観としてはAPIのラッパーがメインなら(2)のように完結するほうがよいかもしれません。
InitializeやCloseなどセットもののAPIでも順に呼び出すというのはユーザーへ求める規則ですし。


★そうですよね。(2)の方が見た目はスッキリするんですよね。
ただ、複数の値を返す場合は以下のどれが良いのかわかりますか?

1.構造体配列にて、メソッドの戻り値とする
2.配列や構造体配列にて、メソッドの引数(ByRef)とする。
4.APIから返却される複数の値毎にメソッドを作成し、それぞれの値を
戻り値として返却する 。

私は「1」のように戻り値として構造体配列を返却したい思っていますが、
戻り値を構造体としては返却できるのですが、構造体配列として
は、返却できませんでした。
なにか良い方法はご存じないでしょうか?
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-11-06 23:37
引用:

taaさんの書き込み (2005-11-06 22:28) より:

私は「1」のように戻り値として構造体配列を返却したい思っていますが、
戻り値を構造体としては返却できるのですが、構造体配列として
は、返却できませんでした。
なにか良い方法はご存じないでしょうか?


詳細は判りませんが、私も通常は 1 にすると思います。
構造体の配列となると参照型になるので、クラスにしそうですが。

ところで、現状どうやって返して出来ないでいるのかを教えていただけませんか?
でないと、どなたも助言できないと思うのです。

# 構造体の先頭アドレスのポインタで返してるのかな?

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2005-11-06 23:45
引用:

★そうですよね。(2)の方が見た目はスッキリするんですよね。


すっきりするというか、クラスの性質によります。

引用:

ただ、複数の値を返す場合は以下のどれが良いのかわかりますか?

1.構造体配列にて、メソッドの戻り値とする
2.配列や構造体配列にて、メソッドの引数(ByRef)とする。
4.APIから返却される複数の値毎にメソッドを作成し、それぞれの値を
戻り値として返却する 。

私は「1」のように戻り値として構造体配列を返却したい思っていますが、


2は一般論として禁じ手と思ってよいでしょう。
4はちょっと具体的にイメージできません。
列挙なら配列で返せばよいし、
「複数」が種類であれば結果クラスのメンバがそれぞれのクラスにすればよいのではないでしょうか。
コード:
Public Class Kekka
    Public Info1 As Info1Class
    Public Info2 As Info2Class
End Class


Structureはそれを使ったほうがベストという場面で使ったほうがよろしいかと。

#もしかしてAPIが返すものをそのまま返そうとしてるのですか?

引用:

戻り値を構造体としては返却できるのですが、構造体配列として
は、返却できませんでした。


Public Function aaa() As Struct1()
ではだめでしたか?
taa
常連さん
会議室デビュー日: 2005/08/29
投稿数: 44
投稿日時: 2005-11-07 02:17
まどかさん、じゃんぬねっとさん、返答ありがとうございます。
質問が判り難くすみませんでした。
以下のコード(※サンプルコード)のように、1つのメソッドより複数の値を返却したい場合、
どのようにして返却すればよいのかという質問です。


【サンプルコード】

'<C++のdllのインターフェース>
'(Result : 正常終了は0、負の値はエラーコード
'(IN : strDir As String ;サーバのディレクトリ
'(IN : FileCount As Integer ;ファイル数
'(OUT : FileNames() As Integer ;ファイル名配列
'(OUT : FileAttrs() As Integer ;ファイル属性配列
'(OUT : FileSizes() As Byte ;ファイルサイズ配列


Public Class ServerControlApi

 Private Declare Function GetServerFiles Lib "server.dll" ( _
  ByVal strDir As String, _
  ByRef FileCount As Integer, _
  ByVal FileNames() As String, _
  ByVal FileAttrs() As Byte, _
  ByVal FileSizes() As Integer _
 ) As Integer

 'メソッド定義(指定したディレクトリに存在するファイルリストを取得)
 Public Function GetFileList(ByVal strDir As String ) As FileInfo() ★戻り値を構造体配列とする

  Dim rc As Integer
  Dim intFileCount As Integer
  Dim strFileNames(1024) As String
  Dim bytFileAttrs(1024) As Byte
  Dim intFileSizes(1024) As Integer
  rc = GetServerFiles(strDir, intFileCount, strFileNames, bytFileAttrs, intFileSizes)
  For i As Integer = 0 To intFileCount
   GetFileList(i).Name = strFileNames(i) ★代入する際に引数が不正でエラータスクが表示される
   GetFileList(i).Attr = bytFileAttrs(i) ★代入する際に引数が不正でエラータスクが表示される
   GetFileList(i).Size = intFileSizes(i) ★代入する際に引数が不正でエラータスクが表示される
  Next
  GetFileList.Count = intFileCount

  Return GetFileList

 End Function

End Class

'構造体定義
Public Structure FileInfo
 Dim Count As Integer ' ファイル/ディレクトリ数
 Dim Name As String ' ファイル/ディレクトリ名
 Dim Size As Integer ' ファイルサイズ
 Dim Attr As Byte ' 属性
End Structure


ちなみに、お二人のアドバイスにて、現在までにわかったことは以下の通りです。
1.構造体配列をメソッドの戻り値として返却する
⇒うまく動作していない。
2.配列や構造体配列にて、メソッドの引数(ByRef)とする。
⇒一般論として禁じ手。
3.APIから返却される複数の情報の種類別にGetプロパティを作成する
⇒メソッドで完結するタイプの為、一般的には行わない。
4.APIから返却される複数の情報の種類別にメソッドを作成し、戻り値として返却する
⇒説明がわかりにくかったので回答なし。
GetFileCount、GetFile、GetFileSize、GetAttrsの3つのメソッドを作成し、
それぞれのメソッドで値を返却するという事です。
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2005-11-07 03:28
引用:

コード:
 'メソッド定義(指定したディレクトリに存在するファイルリストを取得)
 Public Function GetFileList(ByVal strDir As String ) As FileInfo()   ★戻り値を構造体配列とする

  For i As Integer = 0 To intFileCount
   GetFileList(i).Name = strFileNames(i) ★代入する際に引数が不正でエラータスクが表示される
  Next
  GetFileList.Count = intFileCount

  Return GetFileList

 End Function

End Class




まず基本的なことなので。。。
「Return GetFileList」これ、もろVB6ですね。
次のようにします。
コード:
Public Function GetFileList(〜) As FileInfo()
    Dim NewFileInfo() As New FileInfo

    Return NewFileInfo
End Function



引用:

GetFileCount、GetFile、GetFileSize、GetAttrsの3つのメソッドを作成し、
それぞれのメソッドで値を返却するという事です。
コード:
'構造体定義 
Public Structure FileInfo 
 Dim Count As Integer ' ファイル/ディレクトリ数 
 Dim Name As String ' ファイル/ディレクトリ名 
 Dim Size As Integer ' ファイルサイズ 
 Dim Attr As Byte ' 属性 
End Structure 




Countを含むのであればその他のメンバを配列にすべきでは?

値の返し方についはそれでよいと思いますが
VB6からの変更点と構造体とクラスの違いについて理解したほうがよいでしょう。
「値型と参照型」などで調べてみてください。
#通常はクラスで十分でしょう。構造体の使い道を誤るとパフォーマンスが劣化します。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-11-07 07:16
引用:

まどかさんの書き込み (2005-11-07 03:28) より:

まず基本的なことなので。。。
「Return GetFileList」これ、もろVB6ですね。


VB6 って Return キーワードないですよね。
それと、これって関数の「再帰呼び出し」に見えてしまいますね。

For ステートメントで GetFileList の戻り値そのものに値を設定しているので、
Return を使う必要がない、もしくは別の変数を使うべきということですね。

こうなりますね。

コード:

    Public Function GetFileList(ByVal sDir As String) As FileInfo()    
        Dim fileInfos As FileInfo = New FileInfo(intFileCount) {}

        For i As Integer = 0 To intFileCount
            fileInfos(i).Name = strFileNames(i)
        Next i

        Return fileInfos
    End Function


_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌

スキルアップ/キャリアアップ(JOB@IT)