2019年9月15日日曜日

17: LibreOffice/OpenOffice Basicのコードを構造化する1つの試み

<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>

LibreOffice/OpenOffice Basicでは、クラスを作成できません。ここには、それにもかかわらず、Basicのコードを構造化する1つの試みが記されています。

話題


About: UNO (Universal Network Objects)
About: LibreOffice
About: Apache OpenOffice
About: LibreOffice Basic
About: Apache OpenOffice Basic

この記事の目次


開始コンテキスト


  • 読者は、LibreOfficeまたはApache OpenOffice Basicプログラミングの基本的知識を持っている。

ターゲットコンテキスト



  • 読者は、自らのLibreOfficeまたはApache OpenOffice Basicのコードを構造化する1つの方法を知る。
ト書き
Hypothesizer 7、Objector 17A、Objector 17Bがコンピューターの前にいる。


オリエンテーション


Hypothesizer 7
本記事では、私が、自身のLibreOffice Basicコードを構造化するよう試みます。もしも、LibreOfficeまたはApache OpenOffice Basicのコードを構造化する方法をお探しであれば、これが手掛かりをもたらすかもしれません、これが提案する全てをを受け入れることはないにしても。

Objector 17A
「構造化する」とはどういう意味だ?

Hypothesizer 7
サー、LibreOfficeまたはApache OpenOffice Basicでは、クラス(オブジェクト指向プログラミング言語用語体系の用語として)を作成できません。その事実は、自身のコードをクラス群という形に組織化するように順応している私を途方にくれさせます。

Objector 17A
それじゃあ、LibreOffice Basicではクラスは作れないのか...

Hypothesizer 7
私が知る限り、そのように思われます。実は、正直なところ、私はLibreOffice Basicにそれほど通じていません。もっと正直に言うと、私はLibreOffice Basicがあまり好きではありません。さらに正直に言うと、私はLibreOffice Basicが嫌いです、とても。

Objector 17B
...なんで嫌いなわけ?

Hypothesizer 7
マダム、理由は、オブジェクト指向でないこと、機能が貧弱なこと(リストが無い、マップが無い、スレッドが無い、GUIが貧弱、等)、変数タイプシステムがルーズであること('Variant'や'Object'のような包括的すぎるタイプを多くのケースで使わなければならない)、そして、最後に(重要性が最後なわけではありません)、ドキュメントが貧弱であること(私が見つけたどのドキュメントもそのプログラミング言語のいくつかの本質的特徴を明確にしていない)。

Objector 17B
あなた不愉快な人ね!嫌いなら使いなさんな!

Hypothesizer 7
実のところ、私はそれを、やむを得ない場合にしか使いません: 確かに、私は メインロジックをJavaまたはC++のUNOコンポーネントに実装できるし、喜んでそうしますが、LibreOfficeは、ボタン等のイベントハンドラーにマクロを要求するので、そうした UNOコンポーネントを呼び出すモジュールとしてのみ、私はLibreOffice Basicでマクロを作成します。

Objector 17B
どのみち使うんなら文句を言いなさんな!

Hypothesizer 7
使わなければならないから苦情も言うわけです: 近寄らなければ済むものについて苦情(または何か)を言うほど私はお節介ではありません。

Objector 17B
...

Hypothesizer 7
LibreOffice Basicを少なくともある程度は使用しなければならず、そうしたコードを私は構造化したいわけです。


本体


1: Java(またはC++、C#)構造をLibreOfficeまたはApache OpenOffice Basicにマッピングする


Hypothesizer 7
Java構造をLibreOfficeまたはApache OpenOffice Basicにマッピングしてみましょう。

Objector 17A
「Java構造」?

Hypothesizer 7
Javaの世界では、いくつかプロジェクトがあり(各プロジェクトが1つのJarファイルに対応すると仮定しましょう)、各プロジェクトにいくつかパッケージがあり、各パッケージにいくつかクラスがあります。

Objector 17A
ああ、...しかし、なんで私がJavaプログラムをLibreOffice Basicに翻訳しなければならないのだ?

Hypothesizer 7
既存のJavaプログラムを翻訳するという話をしているのではなく、LibreOffice BasicプログラムをJavaライクな構造で作成するという話をしているのです。

Objector 17B
ナンセンスよ!Basic構造で作りなさい!

Hypothesizer 7
実のところ、「Basic構造」というのが何なのか、私は理解していません。'モジュール'があることは知っていますが、コードのどの部分がどのモジュールに行くべきでしょうか?「モジュールは、類似の機能をグループ化するために使われる」のような説明は、あいまいすぎて、実際的なガイドラインになりません。...どの2つのものが類似でありどの2つのものが類似でないのでしょうか?実際、どの2つのものも、類似でありかつ類似でないとみなすことができます。

現実には、「Basic構造」は、「単一のモジュールを作成して、すべてのものをそのモジュールにごた混ぜに入れ込む」ことになりがちですが、私はプログラミングをそういう風には決してしません。

Objector 17B
あなたは...うん太郎よ!

Hypothesizer 7
私は特にJavaをえこひいきしているわけではありません。私が触れるどのまともなプログラミング言語も、プロジェクト-パッケージ-クラスという同じ構造を持っており、私はその構造を求めます。

他方で、LibreOfficeまたはApache OpenOfficeの世界では、いくつかライブラリがあり、各ライブラリにいくつかモジュールがあります。

実際には、'コンテナ'というコンセプトもありますが、そのコンセプトにはここでは私は関心を持っていません、なぜなら、一部のコードをあるドキュメントにしまいこむというのは私の関心に無いので。したがって、私には、1つのコンテナしかありません。

Objector 17A
ははあ。

Hypothesizer 7
それでは、私は、Java構造をLibreOfficeまたはApache OpenOffice Basicにどのようにマッピングすべきでしょうか?

Objector 17B
そうしなければいいだけよ!

Hypothesizer 7
えーと、私は、各Javaプロジェクトを1つのBasicライブラリにマッピングします。

Objector 17A
それは自然に聞こえるな。

Hypothesizer 7
そして、各Javaパッケージを1つのBasicモジュールにマッピングします。

Objector 17A
うーん、どうだろう。選択肢としては、'各Javaパッケージを1つのBasicモジュールに'か'各Javaクラスを1つのBasicモジュールに'かだけだろうが。

Hypothesizer 7
はい。実は、後者を初めは採用したのです、クラスは不可欠なレイヤーですがパッケージはクラス群をグループ化するただのネームスペースですから。言い換えると、パッケージは、フルクラス名の一部分であるにすぎません。

しかしながら、その方法では、ディレクトリ構造無しに多すぎるモジュールを持たなければならなくなり、それはかなり扱いにくいことになるということが分かりました。

Objector 17A
ふーむ、どうだろう。


2: LibreOfficeまたはApache OpenOffice Basicで擬似クラスを作成する


Hypothesizer 7
オブジェクト指向プログラミングパラダイムは、問題領域におけるオブジェクト群を、プログラムにおける対応するオブジェクト群にマッピングするものです。私は問題領域を、オブジェクト群が生まれ、相互に作用し、そして死ぬ世界として認識するので、その認識の似姿としてプログラムを作るのが、最も自然で、最も容易です。

そこで、私はクラス群を作成したいのですが、LibreOfficeまたはApache OpenOffice Basicはそれを許してくれません。

Objector 17B
文句を言うなと言ってるのよ!

Hypothesizer 7
私の目的は、苦情を述べることではなく、次善の策を講じることです、現実認識に基づいて。

Objector 17B
みんながやっているようにコードを書けばいいのよ!

Hypothesizer 7
それは「みんな」ではありません、「みんな」がやっているように私はやっていないのですから。あなたが言われているのは'多数派'であって、「みんな」ではなく、私は、多数派がやっているからという理由で何かをやることはなく、リーズナブルであるという理由で何かをやります。

Objector 17B
あなたは...何者でもない!物の数ではありません!

Hypothesizer 7
あらまあ...

とにかく、私にとっての次善の策はあり、それを採用すべきでない理由はありません。

Objector 17B
あなたはうん太郎です!

Hypothesizer 7
淑女さん、ユーザー定義データタイプを定義することはできますが、それらはメソッドを持つことができません。

クラスの代わりに、私は、'Global'なユーザー定義データタイプを、そのメンバー変数をインスタンスメンバー変数として(そのクラスにインスタンスメンバー変数が無ければ、ユーザー定義データタイプは必要ありません)、定義します。

スタティックメンバーコンスタントの代わりには、私は、'Global'コンスタントを定義します。

スタティックメンバー変数の代わりには、私は、'Global'変数を定義します。

インスタンスメソッドの代わりには、私は、'Global'ファンクションを、そのユーザー定義データタイプの'this'インスタンスを第1引数として取るように、定義します。

スタティックメソッドの代わりには、私は、'Global'ファンクションを、そのユーザー定義データタイプの'this'インスタンスを取らないように(スタティックメソッドが、そのユーザー定義データタイプの'this'でないインスタンスを取るのは問題ない)、定義します。

コンストラクタの代わりには、私は、'Global'ファンクションを、そのユーザー定義データタイプの'this'インスタンスを取らないが、そのユーザー定義データタイプのインスタンスを返すように、定義します。

満足できる解決策を見つけられていない1つの問題は、スタティックメンバー変数用の'Global'変数を、理想的なタイミングで初期化できないということです。

Objector 17A
はあ?分からない。

Hypothesizer 7
何が分かりませんか?

Objector 17A
あなたのうわごと全体が。

Hypothesizer 7
えーと、多分、例を見るべきでしょう。

@LibreOffice or Apache OpenOffice Basic ソースコード
Option Explicit

' A class definition
Global Type ClassA
    ' An instance member variable
    i_memberVariable0 As String
End Type

'A static member constant
Global Const ClassA_c_memberConstant0 = "A string"
' The static initialization flag
Global ClassA_s_isInitialized As Boolean
'A static member variable
Global ClassA_s_memberVariable0 As String

' The static initializer
Global Sub ClassA_initializeStatically ()
    If NOT ClassA_s_isInitialized Then
        ClassA_s_memberVariable0 = "Another string"
        ClassA_s_isInitialized = True
    End If
End Sub

' A static method
Global Function ClassA_staticMethod0 (a_argument0 As String) As String
    ClassA_initializeStatically ()
    ClassA_staticMethod0 = a_argument0 + " altered"
End Function

' A constructor
Global Function ClassA_ClassA (a_argument0 As String) As ClassA
    Dim l_this As New ClassA
    l_this.i_memberVariable0 = a_argument0
    ClassA_ClassA = l_this
End Function

' An instance method
Global Function ClassA_instanceMethod0 (a_this As ClassA, a_argument0 As String) As String
    a_this.i_memberVariable0 = a_argument0
    ClassA_instanceMethod0 = a_this.i_memberVariable0
End Function

Objector 17A
...'ClassA_s_memberVariable0'は、'Global'でなければならないのか、そのスタティックメンバーを'private'にしたくても?

Hypothesizer 7
そうでなければなりません、そのスタティックメンバーが値を複数マクロ実行間の境界を超えて保持するようにするには: 'Global'であるというのは、スコープだけの問題ではなく、変数の生存期間の問題でもあります。Basicのその仕様のため、メンバーを'private'にすることはあきらめました。

Objector 17A
...スタティックメンバー変数の初期化の話は何なんだ?

Hypothesizer 7
変数を初期化する方法が、サブルーチンまたはファンクション中で行なう以外、見つけることができません。つまり、LibreOfficeまたはApache OpenOffice Basicは、"Global ClassA_s_memberVariable As String = "Another string""のようなステートメントを許さないようです、それは ほとんどのプログラミング言語でサポートされている機能なのですが。

Objector 17A
そうなのか?

Hypothesizer 7
少なくとも、方法を記載したドキュメントを私は見つけられません。

そこで、'ClassA_initializeStatically'というスタティックイニシャライザーを作成しましたが、それが、何らかのスタティックメソッドが呼ばれる前に1度だけ呼ばれるようにする方法を見つけられません。

そこで、全てのスタティックメソッドの各々に、その先頭行でそのスタティックイニシャライザーを呼ばせないといけません。

Objector 17A
ああ。...とにかく、その擬似クラスをどう使えばいいんだ?

Hypothesizer 7
以下が例です。

@LibreOffice or Apache OpenOffice Basic ソースコード
' A pseudo-class test
Sub testPseudoClass0 ()
    ' Calling the static method
    ClassA_staticMethod0 ("Test 0")
    Dim l_classA As Object
    ' Instantiating the class
    l_classA = ClassA_ClassA ("Test 1")
    ' Calling the instance method
    ClassA_instanceMethod0 (l_classA, "Test 2")
End Sub

Objector 17A
...'l_classA'は、'ClassA'タイプで定義できないのか?

Hypothesizer 7
できないようです: ユーザー定義タイプ名、"ClassA"は、その擬似クラスのモジュール以外のモジュール内では使えないようです。実際、コンストラクタは、擬似クラスが'Object'タイプ変数を介して使われるという仮定に基づいて定義されています。

Objector 17A
どういう意味だ?

Hypothesizer 7
ユーザー定義タイプ変数を定義すると、自動的にそのタイプのインスタンスができるので、仮に、ユーザー定義タイプ変数が使われるとすれば、その既存インスタンスを初期化するインスタンスイニシャライザーが必要になるでしょう、新たなインスタンスを作成するコンストラクタではなく。

Objector 17A
ああ。


3: 結びとその先


Hypothesizer 7
今や、私たちは、自らのLibreOfficeまたはApache OpenOffice Basicコードを、よりオブジェクト指向的に構造化できます。

ト書き
Objector 17Bの叫び声が聞こえる、「ナンセンス!」。

Hypothesizer 7
...私は、LibreOfficeまたはApache OpenOffice Basicにそれほど通じているわけではありませんし、...

ト書き
Objector 17Bの怒鳴り声が聞こえる、「大口たたくな、通じてないくせに!」。

Hypothesizer 7
...LibreOfficeまたはApache OpenOffice Basicを控えめにしか使いませんが、...

ト書き
Objector 17Bの金切り声が聞こえる、「黙れ、話す資格がない!」。

Hypothesizer 7
...どのマニュアルも言及していないように思われるいくつかの基本事項を明確にしなければなりません。

そうした事項に将来の記事で取り組みましょう。


参考資料


<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>