FileMaker使いに聞いて欲しい4Dの話

# 背景

## 昔は良かった

FileMakerはファイルメーカーPro 2だか3の頃からのお付き合い。そんなオイラがかつての4th Dimensionを知ったのはほぼ同時期でした。知った当時サンプル例をいくつか触って感じたのはMacOSのUIから逸脱した感・・・4DもファイルメーカーもMacOS UIデザインコンセプトとは合致しない50歩100歩といえばそうなのですが、とにかく4Dのイケてない感が印象深かった

MacOS向けのデータベースソリューションとして古くは68k Mac時代から切磋琢磨してきた両者ですが、敷居の低さは圧倒的にファイルメーカーに軍配が上がりました。込み入ったコーディングは当時WindowsのDelphiやVB4〜6がメインだったので、自分にとって共有できるDBとしてはファイルメーカーがお手頃でした。そんなこんなで4th Dimensionからは遠ざかっていました。

## 今回の記事は

- デスクトップDBとして、簡単な物を作るなら、FileMaker最強（異論は認める）
- クラサバとして簡単なDBを共有するならFileMaker最強
- クラサバとしてメチャ複雑なDBアプリを作るなら、SQL + .NETでもJavaでもイイからアッチ行けw
- 三階層アプリとしてメチャ高尚なシステムを作るなら、　　　　　　　〃

でも、ソコソコの規模でFileMakerじゃシンドイと感じたかた向けの内容になっております。なので、FileMakerでゴリゴリ組んで問題ないわーって方、4Dなんてケッ！.NETじゃなきゃ認めん！って方、いや4Dの魅力はそうじゃないだろわかってねーなーって方、生暖かく見守ってね。

## 4Dのすごさを感じたのは？

### Macだけで動いている

MacOS9で工場が動いていた・・・FA制御を含めた受注出荷処理、経理処理、勤怠処理などなどが1システム上に構築されているのを目の当たりにして・・・へぇ〜Mac"だけ"でここまでできるんだ〜

### 標準コマンドだけで？

4DプラグインSDKには、4Dで作成されたウイザードアプリが付いてて、欲しいプラグインコマンドを設定して引数を設定して実行すると、XcodeやVisual Studioのプロジェクトが作成されSDKのヘッダーファイルやライブラリが書き出されてそのまま未記述でコンパイル可能。あとな中身を作るだけ（そうバイナリ操作も圧縮解凍操作も標準コマンドで難なくこなせたのです）プラグインを作る手前まで標準コマンドで解決できたのでした。

### DBと開発環境とHTTPサーバーが一体になってる

HTTPサーバーでは、特定のURLにバインドされる処理を標準メソッドで処理できて、その際自由にテーブル、フィールド、レコードにアクセスできる。そうDBサーバーが別だと接続処理、レコードセット処理、バインド処理など面倒なおまじないが不要で、ごった煮で書けちゃう節奏の無さ。

### トランザクションが

エラーハンドリングとトランザクションが自由に書ける。トランザクションはネストしても良い。エラートラップはOn Error Callをインストールするタイプだけど、4Dコードの書き方からするとまぁ及第点。ファイルメーカーではトランザクションが無い（暗黙のトランザクションは存在する）ので、自由にロールバックできる仕組みを作ろうと思うとまぁ苦労する。エラー処理もトラップやTry/Cacheとは毛色が異なるのでいちいちエラー情報を取り出して判別するifブロックを作らなければならない。


# 4Dって何ができるの？

## 何でもできる

プログラムのコーディングを自由に行えるので、実現したいことはほぼ何でもできるといって良い。なにより、FileMakerではトリッキーなパズル組み立てとややこしいリレーションを全て把握していないと破綻するような事も、気をつけてコーディングしていればスンナリできてしまいます。

## ストラクチャー（設計／プログラム）とデータの分離

4Dではストラクチャーファイルと、データファイルに分かれていて、DB定義やプログラムコードを纏めたストラクチャーと、それと一対になるデータファイルの構成になります。（ファイルシステムの制限でセグメントに分かれたデータファイル運用時期もありましたが）特筆すべきは、そのストラクチャーを適用する柔軟性。開発用と運用用を分けていたとしても、開発用のストラクチャーを運用用と入れ替えるだけでサクッと改修が適用できます。それはDB構造の追加修正が行われてもOK、プログラム修正が行われてももちろんOK。ファイルを入れ替えるだけで完了します。超ラクチン。

## オブジェクト指向じゃないじゃん

そう、4Dにはオブジェクト指向への移行プロジェクトが存在したが頓挫したらしい。はっきり言って美しいとは言いがたいコマンド群が溢れてて、特性や作法に慣れないとやりたいことができる気がしない。しかし言語仕様としてはシンプルで初心者が陥りやすいややこしい処理に触れること無く、まるでファイルメーカーのスクリプトステップを羅列するように記述することで、とりあえず動くコードが書けてしまう。

## MVC分離ができなくはない

DB構造をModel、フォームをView、メソッドをControllerと捉えると自然と分離できているw
ただフォーム上のオブジェクトに自由にメソッドが書けてしまうのだが、そちらに処理をゴリゴリ書いていくと直ぐにカオスに陥る。そこで、コントローラー専用メソッドを作成し、フォーム上のオブジェクトメソッドはコントローラーを必ず介するような記述に徹する。コントローラー経由でないとサブルーチン呼び出しもしないルールを徹底すると、意外と可読性が上がってMVC分離モデルな構成ができるようになる。

## マルチスレッドが簡単に？

4D内部ではプロセスと呼ばれるが、4Dがプラットフォームとなって、その内部にプロセス（＝スレッド）を生成する。プロセスとプロセスのコミュニケーションは、幾つかのメッセージやり取りコマンドを介する、グローバル変数を介する、レコード情報を介するなど自在に書ける。後始末など厳密には気をつける事は確かにあるが、意外と破綻無くマルチスレッド処理が書けてしまう。そしてプラットフォーム全体を協調させるセマフォ構造を備える。これが、複数端末におけるマルチスレッド処理で解決をラクにしてくれる。

## SQLが書ける

コーディングしている中で、Begin SQLとEnd SQLに挟まれた間には、自在にSQL文が書ける。4Dコードを書いている途中にだ。コーディングのモードが4DモードとSQLモード切り替えできるイメージか？SQLからは4D変数へのアクセス手法が用意され、SQL文の方がシンプルにかけるならそうすれば良いということになる。

SQLのコンテキストは4Dコードのそれとは別空間で稼働するので、利点として積極利用できる。つまり現在対象になっているカレントレコードセットを崩さずに、他のレコードへのアクセスしてデータ取得も自在。


## コンパイルできる

4Dのコードはコンパイルして動作速度を上げる事ができる。インタプリタからコンパイルされたコンポーネントを呼び出した際も速度向上の恩恵に預かる事ができる。コンパイルしたコードは保護され改変を防ぐ事ができる。だけど自分はインタプリタの利便性からは離れられないw


## 正規表現

昔、正規表現が使えない頃は、そのためにプラグインを作ったりもしたが、今は標準コマンドでサポートされ使用できる。ただし後方参照による置換はできない。PHPコマンドとしてpreg_matchとか呼び出して使うこともできる。

## コードレス

そんな4Dだけど、簡単なテーブル情報なら組み込みレイアウトに任せて、リスト表示と編集画面を自動生成させる。あとは、そのウインドウを表示させるコードを一寸書くだけでデータメンテナンス用途なら十分な画面がサクッと作れる。

## コンポーネント

自分が作ったストラクチャーを、そのままコンポーネントとして再利用できる。ウマくすればかなり効率的なコーディングができるようになる。



# でも結局コーディングなしじゃマトモに動かないじゃん

## たしかに

4Dではメソッドのコーディング無しでは何もできない。確かにそれはあるかも。ただ気の利いたライブラリを構築できれば相当簡単に作りたい物が作れる様になる。

## ほほう、それはホント？

### 値一覧。

レコードのリストから値一覧を作ってポップアップに表示するだけなのに、プログラムコード書かなきゃイケないの？ファイルメーカーだったら値一覧の設定でどのフォールドからデータを取り出すか指定するだけじゃん。だからテーブルとフィールドを指定したら値一覧を作ってくれるルーチンを用意してみた。


### リストボックス

リストボックスの任意のセルに値を用意してエクセルっぽく処理したいけどメチャプログラムが多くなるよね？一部不正解。なんとテーブルとフィールドをバインド指定して現在のセレクション（検索結果）を表示すれば、ほぼコードレスで使用できる。もっと自由に使いたければ、GUIで設定した列名と値をJSON配列からサクッと適用できるようになるライブラリを作ってみた。

### ツリービュー

ファイルメーカーだと難しいツリービューも標準コントロールにある。今回はその構成をレコード情報からサクッと作ってくれるライブラリを用意してみた。

### CSVの読み書き

そうインポート／エクスポートならそのままCSVを操作できるが、毎回設定に手間取られる。リストボックスの状態をそのままCSVに書き出したり、逆にCSVの内容からリストボックスを自動構成したりできるライブラリも作ってみた。


### プログレスバー

While文やFor文に組み込んで自動的にプログレスバー表示を別プロセスでしてくれるサンプルも作ってみた。


### ウインドウ

Inputフォーム（詳細フォーム）とOutputフォーム（リストフォーム）という独特の考え方があるが、標準命名されたフォームであれば１命令で新しいウインドウを開いて制御するライブラリを作ってみた。


### コーディングって楽しい？

コンポーネントにはよく使うコードをライブラリとして汎用的に呼び出しできるようになる。また、これらのライブラリを系統別に呼び出ししやすく分類することにより、コマンド呼び出しや整理が簡単になる。ラクに作れるようになるとそれなりに楽しいんじゃね？



# 4Dって、そんなにバラ色なの？

決してそんなことはない。欠点沢山あったりする。

## 開発言語としては

- 変数のスコープが決められない。ローカル or グローバルのみ
- 多態体メソッドの引数は定義を変えられない
- メソッドの途中でリターンして抜けられない
- プロジェクトメソッド内にファンクションを作れない
- オブジェクト指向じゃないw
- マイナーだ
- ライセンスが高い


## DBとしては

- SQLが弱い（自分はJOINができれば取り敢えず満足かな）
- レコードのループ処理を書くと必然的に重くなる（サブクエリでサクッと処理したい所）
- 検索が遅い（決してそんなことは無いが作法を誤るとクッソ重いコードが量産できる）
- スケーラビリティが無い（コンパイルしたDB同士であればレプリケーションできるらしいがハードル高杉）
- マイナーだw
- ライセンスが高いw

## Webサーバーとしては

- いうほど速くない
- PHPが組み込まれているのに、index.phpがPHPとして動作しない。
- 実行バイナリは結構デカい。ICU取り込んだりPHP取り込んだり
- マイナーだwww
- ライセンスが高いwww

## サンプル

四の五の言わずにサンプル見せろやw [ダウンロード](https://www.dropbox.com/sh/k0q1aczkcbby0qc/AAD3-ChUbWuE0f5s1PtCwJxaa?dl=0)
[4D社](https://jp.4d.com/4d-free-trial)より無料試用版をダウンロードして開くことができます。既にライセンスをお持ちの場合はv16〜v18の適宜バージョンのあったファイルでお試しできます。


# まとめ

だけど欠点を補う魅力があるのも事実だ。様は適材適所かな。

見てきたシステムでは100万レコードを超えたテーブルが10個ほどで最大で800万件に達しようとしているテーブルも。それがMac miniサーバー（Core i7 32GBメモリ 512GBストレージ）で過不足無く運用され常時20〜30クライアント、最大50弱のセッションが確立している。その情報はWebシステムに公開され、リモートからログインして情報を更新。パーミッションによって制御された監視カメラの閲覧など。自動処理では定期処理で他サーバーとのWebサービス等、一部FileMakerとも連携してデータ入力が行われてたりする。

[こっちの記事](https://qiita.com/osaruda/items/f875125f79123886d62e)や、[あっちの記事](https://qiita.com/osaruda/items/d21284cb27364b3454b0)で書いたとおり4DとFileMakerは相互にJSON経由で連携させる事も比較的簡単だ。そうなれば両者は補完し合う関係性になってくる。簡単な物を簡単に作るならFileMakerに任せ、定型処理がカッチリしてきたら4D側にコーディングしちゃったりとか・・・。

68k → PPC → Intel そして今度はARMと、Appleに振り回されてきたけどここまで続いてくれておじさんウレシイヨ