FileMakerでグローバル変数の管理法（自己流）

# はじめに
[ここ](https://qiita.com/Hi_Noguchi/items/250e19ddefff58ef6529)ら辺の記事を読んで、FileMakerでのグローバル変数管理が大切だと思い、試行錯誤の結果、自身がたどり着いた方法を記事にします。グローバル変数の管理に気を使う必要性については、[上記記事](https://qiita.com/Hi_Noguchi/items/250e19ddefff58ef6529)でよく説明されているので、省略します。もっと良い方法があるよ！って方は、ぜひ教えてください。

# たどり着いた過程
最初は、[上記記事](https://qiita.com/Hi_Noguchi/items/250e19ddefff58ef6529)を読んで、それに沿ってスクリプトで管理することにしました。多少パフォーマンスを犠牲にしても、開発時のメリットは大きいと考えました。その後、命名規則を考えたり、パフォーマンスをよくすることを意識していたら、カスタム関数で管理してもよいのでは？と思い立ち、現在は、カスタム関数で管理する手法を採用しています。今後、また変わる可能性も。

# FileMakerでグローバル変数の管理法（自己流）
- [命名規則の記事](https://qiita.com/siebenunddreissig/items/8cd1b3ecf22756fcb7ad)も参照。
    - 変数名は `$$GLOBAL.VARIABLE.NAME`
    - 変数設定関数名は`Set.GlobalVariableName ( %valueForm )`
    - 変数取得関数名は`Get.GlobalVariableName ()`
- `変数を設定`スクリプトステップは、原則使わない。
    - スクリプトステップで他の代替手法がない場合には、dummy変数に設定する形で、 `変数を設定`スクリプトステップを使うことも。
    - `現在のスクリプト終了`スクリプトステップのように引数があるものは、大体そこで足りる。他に頻用するのは`If`や`Exit Loop If`スクリプトステップの条件計算式。
- 動的に変数名を設定したい場合は別の方法で。
    - 動的変数名だと管理方法や意味合いも大きく変わってくるので、ここでは詳細は記載しない。
    - [サンプルファイル](#サンプルファイル)で使われている以下の関数を参照。
        - `Set.GlobalVariablesFrom ( %messageCode )`
        - `Set.GlobalVariablesFromMessageCodeWith ( %prefix )`
- 変数設定関数の実例

```JAVA:Set.IsFieldOpend&nbsp;(&nbsp;%boolean&nbsp;)
// Purpose
//   $$IS.FILE.OPENEDを設定する。
// Parameter
//   %boolean = これまでにファイルが開かれていなければnil、開かれていればTrue。
// Notes
//   結果は必ずTrueを返す。

Let ( [ $$IS.FILE.OPENED = %boolean
];
  True
)
```
Let関数内の`[ ]`は省略可能だが、[なくてもパフォーマンスには影響しない](#パフォーマンスの検証)のと、可読性・メンテナンス性を考え省略していない。
ちなみに`nil`はカスタム関数で、計算式には何も設定していない。`""`と同値。[命名規則の記事](https://qiita.com/siebenunddreissig/items/8cd1b3ecf22756fcb7ad)も参照。

使い方の実例
スクリプトの引数で変数設定関数を用いる場合。

```JAVA:
If (
  Set.GlobalVariableName1 ( Value1 ) and
  Set.GlobalVariableName2 ( Value2 );
  ParameterToSet
)
```
Let関数を用いる場合。

```JAVA:
Let ( [
  $variableName = Value1;
  %variableName1 = Value2
];
  Set.GlobalVariableName1 ( %variableName1 ) and
  Set.GlobalVariableName1 ( Value3 )
)
```
この場合は返り値が必ず`True`になる。
返り値を好きな値にしたいなら、Let関数、If関数の組み合わせも。

```JAVA:
Let ( [
  $variableName = Value1;
  %variableName = Value2
];
  If (
    Set.GlobalVariableName1 ( %variableName1 ) and
    Set.GlobalVariableName1 ( Value3 );
    ParameterToSet
  )
)
```
変数設定関数の返り値を必ず`True`にしているのがミソ。`and`で繋げることで1つの計算式で複数の変数設定を行える。

- 変数取得関数の実例

```JAVA:Get.IsFieldOpend&nbsp;()
// Purpose
//   $$IS.FILE.OPENEDの値を取得する。
// Parameter
//   なし。
// Notes
//   なし。

$$IS.FILE.OPENED
```

# 利点
- カスタム関数の管理で、ファイルで使用されているグローバル変数が一望できる。
    - 引数を見ればグローバル変数の形式も分かる。
    - ファイルを超えて変数の共有はできないので、ファイル単位で管理できれば問題ない。
- 計算式内でも取得できる。
    - スクリプトステップ方式だと計算式内ではハードコーディングが必要。
- コーディング時に自動補完が効く。タイプミスがなくなる！
- 変数名を変更したい場合はカスタム関数を処理するだけでよい。メンテナンス性がよい！
- スクリプトステップを減らせるので、スクリプトの見た目がすっきりする。
    - 1つの計算式内で同時に多数の変数を設定させることも可能。ローカル変数の設定も併記できる。
    - 引数、条件計算式は省略表記されてしまうので、若干可読性が落ちる可能性も。ただ、変数設定をやっている場所は明白になっているので、そこまで苦慮はしないか？

# 欠点
- カスタム関数の数が増える。
    - まぁ、許容範囲だと思います。
- ハードコーディングに比べると、若干パフォーマンスが落ちる？
    - 変数を取得する際で1呼び出しあたり2-3µsecぐらい（自己調べ）。

# パフォーマンスの検証
- パフォーマンス計測には[FM-SC]()使用。スクリプト引数には、1から1000までの自然数が順に指定される。

```JAVA:グローバル変数を関数で設定カッコなし(number)
現在のスクリプト終了 [ テキスト結果: test_Set.TestWithoutBrackets ( Get ( スクリプト引数 ) ) ] 

カスタム関数
test_Set.TestWithoutBrackets ( %text )
Let ( $$TEST = %text;
  True
)
```
```JAVA:グローバル変数を関数で設定カッコあり(number)
現在のスクリプト終了 [ テキスト結果: test_Set.TestWithBrackets ( Get ( スクリプト引数 ) ) ] 

カスタム関数
test_Set.TestWithBrackets ( %text )
Let ( [ $$TEST = %text
];
  True
)
```
```JAVA:グローバル変数を変数を設定で設定(number)
変数を設定 [ $$TEST ; 値: Get ( スクリプト引数 ) ] 
現在のスクリプト終了 [ テキスト結果: True ] 
```
![20211124_Set関数比較.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2283446/51a9c764-1a8e-03ef-9da7-767ad3ba842b.png)

```JAVA:グローバル変数を通常呼び出し(number)
現在のスクリプト終了 [ テキスト結果: Let ( $$TEST = Get ( スクリプト引数 );   $$TEST ) ] 
```
```JAVA:グローバル変数を関数呼び出し(number)
現在のスクリプト終了 [ テキスト結果: Let ( $$TEST = Get ( スクリプト引数 );   test_Get.Test ) ]

カスタム関数
test_Get.Test ()
$$TEST 
```
![20211124_Get関数比較.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2283446/e3e433d0-ae6a-c732-2de4-d160db3c0981.png)

- 結論。
    - `変数を設定`スクリプトステップを使用する方法と、カスタム関数を用いる方法にはパフォーマンスに差がない。
    - Let関数で`[ ]`を省略しても、パフォーマンスは改善しない。
    - カスタム関数でグローバル変数を呼び出すと、1命令あたり2µsecぐらいのオーバーヘッドになる。100万回で2秒ぐらい。

# サンプルファイル
こんな感じで使っているので参考にしてみてください。
<a href="https://github.com/siebenunddreissig/FM-SC"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/siebenunddreissig/FM-SC.png" width="460px"></a>
<a href="https://github.com/siebenunddreissig/FMDB-blue"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/siebenunddreissig/FMDB-blue.png" width="460px"></a>