FileMakerコーディング規約（計算式）

「コーディング規約」とは複数人プロジェクトである程度ルールを設けてコーディングすることで、統一性・可読性・メンテナンス性を上げましょう。というものです。

この規約はあくまで私が少人数プロジェクトで利用しているのもです。
規模に応じてもう少し詳細に規約を作る必要があるかと思いますが、一例として参考にしてください。

## 方針

- シンプルな見た目であること（初見でも見やすいこと）
- FileMaker標準を尊重すること
- シンプルな規約であること

## 環境

複雑な計算式（3行以上）を書く際には [CotEditor](https://coteditor.com/) など外部エディターを使いましょう。

CotEditorの場合は私がメンテナンスしている[FileMaker シンタックスカラーリング](https://github.com/hazi/filemaker-syntax-coteditor)があるので、こちらを使うと見やすいです。
<img width="657" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2908/93fdcd6e-4dba-7506-08a8-3c09800dca32.png">


FileMaker用のシンタックスカラーがないエディターではJavaなどの言語を選ぶと比較的近いハイライトを行ってくれます。

## 変数

### 変数名

- アルファベットの小文字から始めること
  - 日本語の利用も可・その場合は先頭文字はとくに規定なし
- 単語の区切りは大文字を使うこと
  - 区切り文字として記号は使わないこと
  - 日本語の場合も区切り文字としての記号は使用禁止・接続詞などを使うこと
- 関数内変数（`Let`, `While`内の `$` を使わない変数）はチルダ（`~`）から始めること
  - フィールド名・カスタム関数の引数と見分けやすいようにするため
  - シンタックスカラーリングで見分けやすくするため
- `$n` などの短い変数名は狭いループ中などの利用に限ること
  - `$n` が何を意味するか数行後にはわかりづらいため
- 略語はできる限り使用しないこと
  - 一般的な略語であればいいが、システム内の用語やテーブル名などを略さないこと

```Java
❌$TOTAL COUNT
👍$totalCount

❌~value_1, value_2
👍~value1, ~value2

❌$NSSUCount
👍$NankaSugoiSystemUsersCount
```

### 変数スコープの使い分け方

- できる限りスコープの狭い変数を使うこと
  - スコープの大きい変数をいたずらに使うとバグを生みやすいため
  - そうすることで影響範囲がわかりやすいため
- グローバル変数（`$$`）はできる限り使わないこと
  - グローバル変数を使う前にスクリプト引数などで解決できないかを考えること
- 計算式外で使わない値はローカル変数（`$`）を使わず関数内変数（`~`）を使うこと

参考: [FileMaker 変数の使用 - FileMaker Pro 18 ヘルプ](https://fmhelp.filemaker.com/help/18/fmp/ja/index.html#page/FMP_Help/using-variables.html)

## スタイル

- スペースは `;` の後ろと`+`,  `-`, `<`, `>`などの演算子の前後1つのみにすること

```Java
❌Position ( text ; "A" ; 1 ; 1 )
👍Position(text; "A"; 1; 1)

❌If((total+1)/3>1;total;"")
👍If((total + 1) / 3 > 1; total; "")

👍 Date(Month(Get(日付)); Day(Get(日付)) + 7 * 3; Year(Get(日付)))
```

- 改行区切りの値を使う場合`List`関数を積極的に使うこと

```java
❌"1¶2¶3"
👍List(1; 2; 3)
```

- インデントはスペース2つを使うこと
  - TABは直接FileMaker上で入力する際に打ちづらいため
  - スペース2つで視認性が十分確保できる（タイプ数が減る）ため
- ひとめで何をしているかわからないような計算式では積極的に変数を使うこと
  - `Let`などを使って変数に値を入れることでラベリングを行う
  - ラベリングによって値の意味を明確化する
  - 適切なラベリングが行われているとコメントが不要になることが多い

```java
❌
// タイトルから"[]"で囲われたカテゴリ名を拾う
If(
  Position(Table::タイトル; "["; 1; 1) > 0
  and Position(Table::タイトル; "]"; Position(Table::タイトル; "["; 1; 1); 1) > 0;

  Middle(
    Table::タイトル;
    Position(Table::タイトル; "["; 1; 1) + 1;
    Position(Table::タイトル; "]"; Position(Table::タイトル; "["; 1; 1); 1) - Position(Table::タイトル; "["; 1; 1) - 1
  )
)
👍
Let([
  ~title    = Table::タイトル;
  ~start    = Position(~title; "["; 1; 1);
  ~end      = Position(~title; "]"; ~start; 1);
  ~category = Middle(~title; ~start + 1; ~end - ~start - 1);
_=0];
  If(~start > 0 and ~end > 0; ~category)
)
```

### 複雑な計算式

`Let`, `While`, `ExecuteSQL`は下記例文の書き方に統一すること

- 色々な書き方が出来すぎてしまうので統一性・見やすさを出すため
- 変数を1つしか使用しない場合など至極シンプルな場合はこのスタイルを守らなくてもいいものとする

※例文中の`_=0`は変数の順番を入れ替えた際に`;`を付け直さなくていいようにするための無意味変数

**Let**

```java
Let([
  ~title    = Table::タイトル;
  ~start    = Position(~title; "["; 1; 1);
  ~end      = Position(~title; "]"; ~start; 1);
  ~category = Middle(~title; ~start + 1; ~end - ~start - 1);
_=0];
  If(~start > 0 and ~end > 0; ~category)
)
```

**While**

```java
While(
  [
    ~n = 1;
    ~total = 1;
_=0];
  not IsEmpty($val[~n]);
  [
    ~total = ~total + $val[~n];
    ~n = ~n + 1;
_=0];
  "Total: " & ~total
)
```

**ExecuteSQL**

```java
ExecuteSQL(
  List(
    "SELECT T.category, COUNT(*)";
    "FROM \"Table\" T";
    "WHERE T.name = ?"
      "AND T.value IN(" & $sarchList & ")";
    "GROUP BY T.category";
  );
  ","; "¶";
  $targetName
)
```

## 終わりに

冒頭にも書きましたが初見でのわかりやすさ、見やすさ重視で作成しました。

例えば、型に応じて変数の表記を変えたりすると初見では「日付はどうすれば？！」と分からない部分が出てきますが、この規約の場合は大体前後の計算式を見れば書き方がわかるスタイルになってます。

FileMaker 標準と大きく違うのはスペースを入れる場所です。FileMaker の標準的な書き方はやたらスペースが増えます。
あのスタイルはシンプルな計算式だと見やすいのですが、少し複雑になると途端にどこが区切りかわかりづらくるので、今回のように必要最低限のスペースを入れる方法を使ってます。

コードを読めば何をしているのか分かりやすいようにという意味でラベリングを積極的に行ったり、値一覧に`List`関数を使ったりというのはバグを生みづらくなるし、コメント更新忘れを防げるのでオススメです。

何よりも美しさを大切にしたいですね。

## 宣伝
Discord の「FileMaker Casual」サーバーで気軽に FileMaker 開発者と交流しませんか？
@Hi_Noguchi さんが立ち上げた FileMaker 中心の情報共有チャットです。

どなたでも参加できて、気軽に質問できる空間です。是非ご参加ください。
招待リンク=> https://discord.gg/g2gp6Ez