NI製品ディスカッション

キャンセル
次の結果を表示 
次の代わりに検索 
もしかして: 

オブジェクト指向(クラスの)の使い方(非線形LMフィティング関数を使ったデータ解析のプログラム)

解決済み
解決策を見る

TailOfGon様

詳細までご教授いただき大変感謝しております。こんな方法があるのかと、ただ、見とれていました。

具体的には、
フォルダーの使い方とプロジェクトの使い方
パスの使い方
クラスの作り方
です。

オブジェクト指向の良い点は、一度作ったオブジェクト(クラス)をほかのプログラムでも使いまわしできる点ですが、アドバイスのようにフォルダーやパスを作ると、より使い回しがしやすくなります。これらの使い方は大変参考になります。

私が、このプログラムを作る上で、一番考えたのがクラスをどうするかでした。
クラスは、データを格納する部分(プライベートデータ)と動作する関数部分(メソッド)からできています。
メソッドでは継承関係を使うことで、ダイナミックディスパッチが使えますのでどのメソッドをダイナミックディスパッチにすれば効率が良いかというところがひとつ。
もうひとつは、データ格納部分には何をいれたらよいかというところです。

ご指摘の通り今回ではあまり問題ないかもしれませんが、Labviewオブジェクト指向では、クラスは、そのままワイヤー配線を流れていきますので、あまり大きなものですとメモリ不足を起こしてしまうかもしれません。また、クラスは継承でどんどん増やすことができますので、多くのクラスがロードされる可能性もありますので、できるだけクラスは最小限にそして過不足なくということになります。このことが初心者には、大変難しかったので、今回は、このことはあまり考えなしで作成していました。アドバイスいただいた「外部から変更することがなく定数扱いのものはデータに入れなくてもよい」はクラスを作る上で、ひとつの指針のように感じます。

これからこのプロジェクトをどう発展させるかについては、あまりアイデアはないのですが、もう少しオブジェクト指向のテクニックが導入できるかどうか考えていきたいと思います。
私は、LabVIEWの使用は制御や集録よりも、得られたデータの解析に使っています。(数学や、解析関数、応用数学の関数が結構あります。また、配列操作も簡単にできます。)同僚の認識では、LabVIEWは計測制御のものということが強いので、解析にも使えますと主張したかたので、このようなプログラムを作っていました。

あらためて、いろいろとご教授していただきありがとうございました。また何か投稿したときには、ご教授いただけると大変ありがたいです。

P.S.日本のディスカションフォーラムでは、基本的に問題解決の場みたいですが、「やってみました。作ってみました」みたいなコーナーがあれば面白いかなとも思います。(検索してみると皆さんご自身ホームページでいろいろと参考になるプログラムは公開はされているようですが。)

メッセージ11/17
3,519件の閲覧回数

クラスの設計時には、いったい何をプライベートデータにするのか悩むことが多いです。私もクラス名をプライベートデータに入れていたことがありますスマイリー ハッピー

 

プライベートデータの本来の目的は「状態」データを入れておくことだと思っています。例えば、ログを行うクラスを作る場合、プライベートデータとしてふさわしいのは、ファイルパス、ファイルリファレンス、現在のログ回数、デリミタのユーザ設定などあって、実際にログされた文字列ではないと思います。

 

それではクラス内の定数のデータはどうするのかというと、私のよく使う方法があります。例えば、クラス内で複数のVIがある定数を扱うとしましょう。このとき、定数をブロックダイアグラムにおくのはリスクがありますね。変更する必要が出てきた場合、すべての定数を一度に変える必要が出てきます。これをさけるためにはグローバル変数が使えます。ちなみに私はグローバル変数は基本的には使わない立場ですが、この場合だけは使います。ただしグローバル変数をクラスツリーの中においてプライベートスコープにしてしまいます。クラス専用のグローバル変数とすることで外部からアクセスされ勝手に変えられることを防ぐことができるので安心して使うことができます。

 

さて、後で継承することを前提に抽象クラスを作るのですが、なかなか難しいですよね。私がよく突き当たるのが、複数のサブクラスを作ったものの、一つのサブクラスのメソッドに特別なパラメータが必要になり、コネクタペーンが変えられないので困ってしまう。コネクタペーンを無理に追加すると、抽象クラスおよび他のサブクラス全部変える必要が出てくる(もちろん意味のない端子なのでクラスを使うユーザの混乱の元になる)それをさけるため、特別なメソッドVI

を作るが、それを呼び出すにはアプリケーションレベルでキャスト(?)する必要がでてくるので面倒になる。ファクトリパターンでは、すべてのインタフェースが一緒という前提で設計することになることが多いので悩みどころですね。

 

LabVIEWのオブジェクト指向といっても、他のプログラミング言語のそれと概念は一緒なので、私は一般的なオブジェクト指向の概念について書かれている本を読みました。インタフェースと実装の違いやカプセル化、パブリック/プライベートのスコープの概念について学ぶことができました。それはそのままLabVIEWにも当てはまり、今ではとても役に立っています。

 

クラスを使うことで、プログラムを組織化する癖がつくのが最大のメリットだと思います。LabVIEWは一つの関数が一つのファイルという世にも珍しいシステムですから、大きなアプリケーションを作ろうとすると、その管理がかなり面倒になりますがクラスを使うと自然に管理されていきます。クラスを使わない場合は、どんなデータも操作し放題でその場その場で対処できる(そのため煩雑になりやすい)ことが多いのですが、クラスを使う場合は外部からプライベートデータにアクセスできないのでそうは行きません。となるとクラスの中にVIを追加してそれを使うしかなくなり自ずとクラスの機能が豊富になりしかも一カ所に固まるので自然と組織化されていきます。

 

長くなりましたが、私はLVオブジェクト指向のファンなのでこのスレッドに飛びついてしまいました。すいません。。

 

私もディスカッションフォーラムでは問題解決だけではなく「こんなの作ってみました」というような投稿がもっとあってもいいなと思います。

TailOfGon
Certified LabVIEW Architect 2013
メッセージ12/17
3,479件の閲覧回数

TailOfGon様

このスレッドでたくさんアドバイスやアイデアを頂きありがとうございました。
(無料ですごい高度なプログラミングコースを受けた感じです。)

これから、オブジェクト指向を使う方が増えると面白いですね。
オブジェクト指向はとても有用な手法だと思いますので、それには、もう少し使い方のドキュメントとか、やさしい練習問題などがあればよいかなと思います。

懲りずに、恥を忍んで私の作ったプログラムを参考までに添付いたします。


TailOfGon様が前のスレッドでアドバイスいただいたことをプログラミングしたファイルをアップいたします。
(O_DemoFit6_edit3)いくつかの部分がスマートにできていません。

ご提案いただいた、クラス内の定数のデータの取り扱いについてですが、グローバル変数の他に機能的グローバル変数の使用はどうでしょうか?
(以前使い方がよく分かっていないころにグローバル変数を使って大変な目にあって以来グローバル変数にはアレルギーがあります。)
異なるVi間でデータのやり取りができるものとしては、メモリ機能を持つものということになると思います。そうしますと、グローバル変数、シェア変数、機能的グローバル変数と言うことでしょうか。(機能的グローバル変数は、場合によっては、再入実行が必要かどうか考える必要があるかもしれません。)試しに、DemoFit3で機能的グローバル変数で定数を作ったプログラムを添付いたします。

また、前後してしまいましたが、オブジェクト指向の初心者向けの参考としまして、DemoFit1バージョンのクラスを使わないプログラミングを添付します。
N_DemoFit(途中まで作成しています。Fitting部分は入っていません。作り方は、いろいろあると思いますが一例と考えていただければと思います。)
ダイナミックディスパッチを使わない場合は、初期値を決めるケースでケースストラクチャーで分岐を行うことになります。
この程度のプログラムでしたら普通にプログラミングした方が断然早いと思います。もう少し関数を増やす、それらの関数群を使い回しを考えるとクラスを使うほうが良いかもしれません(関数郡を整理すると言う意味でも。)。

再度、クラスを使うメリットしては、
機能をまとめられ組織化できる(使い回しができる)。
アクセススコープを付けることができる。
継承関係を付けることができる(ダイナミックディスパッチが使える。)
クラス(オブジェクト)を考えることで、よりモジュール化を意識したプログラミングができる。
などでしょうか。

しかし、クラスを使うには、従来のLabVIEWの考え方やテクニックとは多少違うのでなれる必要がある。
といったところでしょうか。

すべてをダウンロード
メッセージ13/17
3,457件の閲覧回数

懲りずに再度投稿します。

これまで作ってきたプロジェクトでは、途中でFittingのモデル関数のViを動的に呼び出しています。動的に呼び出したので使い終わったら解放してやった方が良いのではとのアドバイスをいただきました。

そこで、ファクトリモデルが実装されていて、プリミティブなVersion3あたりで、お試しで、いくつかリファレンス解放のViを足してみました。

このプログラムで、実際に解放されているかどうか確認の仕方が分からないので、確認の仕方をアドバイスいただければと思います。もし解放されていないようでしたら、解放の方法をアドバイスいただければと思います。

 

3つのバージョンを作ってみました。

O_DemoFit3_1では、これまでのものを踏襲しています。

親クラスFunctionParaName(文字列配列)、Para(数値配列)、Ref

子クラスGaussJSUParaName(文字列配列)、Para(数値配列)、Ref

クラス内のプライベートデータタイプとメンバーはすべて同じです。

すべて、親クラスをオーバーライドしています。(各クラスに同じVi名のものがすべてあります。)

増えたのは、初期値を決める前にモデル関数を動的に呼び出すメソッド(CallLMRef)、Fittingの後にViを開放するメソッド(Dispose)です。

 

O_DemoFit3_2では、親クラスと子クラスで持っているデータメンバーを変えてみました。(Classはデータメンバーが違っていても、同じ配線を流すことができるのを利用しようとの試みです。)

親クラスFunctionParaName(文字列配列)、Para(数値配列)、Ref

子クラスGaussJSUParaName(文字列配列)、Para(数値配列))

子クラスにはRefがありません。従って呼び出したリファレンスは、親クラスのデータに入れることになります。各クラスのプライベートデータにはほかのクラスから直接書き込むことができないので、継承している子クラスから書き込めるように親クラスに、アクセサメソッドを追加しました。(GetSet

結果として、Disposeメソッドだけ子クラスは作成しておらず、親クラスのをもの使っています。

 

O_DemoFit3_3では、デモンストレーションとして、2と同様に親クラス子クラスで持っているデータメンバーを変えてみました。(ほぼ内容は1と同じです。)

親クラスFunction(なし)

子クラスGaussJSUParaName(文字列配列)、Para(数値配列)、Ref

親クラスはテンプレートとして使用しています。継承設定(親クラスのプロパティーの継承設定内にある)で、子クラスにオーバーライドを強制させています。(子クラスで同じメソッド名がないとエラーになります。)

 

すべてにおいて、以前アドバイスいただいた、定数(モデル関数のファイルパス)としてグローバル変数を使用しています。

アクセススコープはプライベートです。プライベートグローバル定数(PGC???)にしています。PGCは確かに使いやすいです。(以前多用して大変な目にあったので固く使わないと決めていたのですが、プライベート設定なら良いかもと今では思っています。)

 

 

アドバイスをいただけると大変助かります。よろしくお願いします。

 

すべてをダウンロード
0 件の賞賛
メッセージ14/17
3,341件の閲覧回数

勉強ついでに、Viの呼び出し方についてまとめた動的・静的呼び出しViを添付いたします。

(まだ他にも呼び出し方はいくつかあるようです。)

数学パレットにあるベータ分布を呼び出しています。Viは、2012 SP1で作っています。

間違っているかもしれませんので、ご指摘お願いします。

 

Fitting 関数の場合、サンプルでは、スタティックViリファレンス呼び出し(タイプ定義)になっていますが、今回のプロジェクトの場合、ダイナミック呼び出しに しています。それは、前にもご指摘があったように、モデル関数をクラスのメンバーに入れていますので、スタティックの場合、Mainがロードされると同時にロードされてしまうので、 ファクトリーメッソド(クラスの動的呼び出し?)の意味がなくなってしまうからと思ったからです。

 

0 件の賞賛
メッセージ15/17
3,340件の閲覧回数

たびたびすいません。

一部勘違いしていました。

今回のリファレンス関数の呼び出しは、スタティックViリファレンスの呼び出しでも良かったのかなと思います。Gaussクラス、JSUクラスは最初にロードされた時点で呼ばれていないし、他でつかってなかったので。モデル関数は他のViから呼び出されないように、アクセススコープをパブリックではなくプロテクトにした方が良いのかもしれません。

 

よろしくお願いします。

0 件の賞賛
メッセージ16/17
3,329件の閲覧回数

LabVIEWでのオブジェクト指向プログラミングについて勉強中なので

現時点ではあまりコメントできませんが、いずれこのスレッドの内容を参考にしたいと思ってます。

 

これからも時間があるときに投稿してくれたら嬉しいです。

0 件の賞賛
メッセージ17/17
3,321件の閲覧回数