開発プロセスにおけるアーキテクチャ設計

INTER-Mediatorに適した開発プロセスを考えていましたが、うまくまとまりません。なんでかなと考えたのですが、INTER-Mediatorを使うという前提なしで考えるべきであり、それを元にINTER-Mediatorへの適用をする必要があると考えます。つまり、一般的な意味でのWebアプリケーションだとかスマホアプリといったものを開発するときに、どんなアーキテクチャが前提となり、設計上何を考えれば要求・要件から実装に近づけるのかという一般論をまずはまとめるべきなのでしょう。最近、たまたま、いろんな仕事の中でアーキテクチャ関連の話題の基本を再勉強する機会があり、その中で一般論になんとなく近づいている感があるので、いっそのこと、考えながらブログでまとめていくという過程で進めようかと考えた次第です。

システム開発では、要求や要件を出発点として、仕様を策定して実装に持ち込みます。外部仕様、内部仕様という区分けがある場合もあります。また、データベースを使う場合は原則としてレイヤー構造になり、データベースが底辺を担うことからドメイン分析した結果をスキーマとして記述して、実装段階では確定したデータベース定義にすることになります。こうした、設計の定石とも言えることはたくさんあり、特定の開発チームや流派、カルチャーに応じてその表現は違うものではありますが、システムを意図した通りに稼働させるという意味では目指す方向は同じであり、場面によって言い方が違うだけの場合もよくあるわけです。一方、様々なノウハウがあるものの、ある要件を満たすようにシステムを作る場合の実装に向けた機能分解は、単一の答えが存在する問題ではありません。同程度に正しい解答はいくつも作れるでしょう。結果的に、「状況に合わせて最適化する」というなんとでも取れるようなアドバイスしか出てこないことにもなりかねません。しかしながら、機能をどのように分解して、それぞれの個別の動作をどのように実装するのかということが、開発の上では非常に重要な決定であることは言うまでもないことです。ベテランや才能のある人は、そういうことをスラスラとできるのかもしれませんが、初心者あるいはある領域の経験が浅いと悩むものです。手っ取り早く知りたいという要求は年々高まり、「ベストプラクティス」や「ティップス」といった情報が重宝されるようにもなります。

こうした設計を完成させるに至る知見は、例えばオブジェクト指向分析や、コンポーネント分析、パターンなど、様々な手法があります。それらをうまく束ねた統一的な開発手法も多数存在します。私が考えていることは、そうした開発手法の1つを作り上げることであり、その結果をもとにして、INTER-Mediatorでの開発手法を確立するということです。車輪の再発明っぽく見えるかもしれませんが、問題点を検討すると、やはり時代に応じた道具に対応した手法はその都度更新されていくものではないかとも考えられます。

現在の様々な開発手法が発展したのは、オブジェクト指向プログラミングが当たり前の時代になり、コンピューターの性能が高まり、そしてインターネットで世界中が繋がって、Webという基盤ができた頃の時代です。一方、現在はスマホ登場やフロントエンドの発展が著しく、サーバー単体での開発手法以上のものが求められています。従来はWeb開発とネイティブ開発、つまりOSのAPIを直接利用する開発は、大きく違っていたのに対して、現在は言語やフレームワークは違っても同じような実装をしているという感覚があります。この領域で業務をしている人は薄々気づいていることではないでしょうか。これは、何か共通のアーキテクチャを持ち込むべきではないかと考えました。まずは、そのための問題意識として持ったことを箇条書きにします。

  • Webシステムはサーバー中心なのは仕方ないとしても、クライアント側のアーキテクチャをどう表現するのが適切だろうか?
  • スマホアプリはサーバー接続する場合が多く、「サーバー側」「スマホ側」という2つのアプリケーションの連動を行っている。最近のWebも「スマホ側」が「JavaScript処理」に置き換わるだけの違いとも言える。つまり、今時のシステムは、サーバーサイド、クライアントサイドを統合的に議論できるアーキテクチャを基盤として持つ必要があるのではないか。
  • コンピューターが速くなり、メモリーも豊富になると、RDBである必要性は薄くなる一方、やはり安定した保存はRDBが理解しやすいとも言える。RDB前提のシステム設計はある意味安定するのだが、逆に必然としてRDBが出てくる理由付けはないのだろうか?
  • サーバーサイドのアーキテクチャはともかくMVCである。いろんなMVCが存在する一方、正しいとか正しくないとか、本物だとかそうじゃないという議論があるものの、MVCは大雑把な機能分類として考えれば、役立つ場面は多いのではないだろうか。
  • クライアントのアーキテクチャはMVCなのだろうか? 違うのだろうか? クライアントサイドの主要な機能はUIの運用とその高度化であるとしたら、MVVMがいろいろな意味で包括性の高いアーキテクチャではないだろうか? ただし、バインディングとオブザーバーを基調としているだけに、それらを実装していないフレームワークはMVVMとして俯瞰できるかどうかが難しい点であると言える。
  • MVCとMVVMを出発点に考えるとしたら、それらの中での機能分割の指標としては、ロバストネス分析をベースに検討できるのではないか、ロバストネス図の要素はビュー、コントロール、エンティティであり、ほぼMVCのコンポーネントに対応するものの1対1ではない。しかしながら、要件をロバストネス分析して、MVCやMVVMを基本としたアーキテクチャとして表現することは、オブジェクトし志向分析の結果を見ても可能であると考えられる。
  • MVCなどのアーキテクチャパターンで設計しても、実装できないかもしれないし、実装するために変形が必要な場合もあるのかもしれない。過去の様々な設計手法では、汎用化がされる一方で、使用するフレームワークの制約やあるいは特有のコールドポイントの扱いなどが考慮されたものは見たことはない。しかしながら、フレームワークによる制約は可能な限り早期に検討する必要がある事柄ではないだろうか。あるいは、フレームワーク制約を組み込む段階がいつなのかを明確にすべきではないだろうか。
  • サーバーとクライアントの分類はどうすべきだろうか? 最初はそれらは関係なく、要件満たすような必要な処理に分割し、あるところで「線を引く」という作業になるのだろうか? そうすれば、サーバーとクライアントの両方を巻き込むシステムの設計はスムーズにできそうだ。

とりあえず、思いつくまま挙げましたので、ポエムに近づきつつあります。これらの考えを少しずつほぐして、手法として使えるまでにすることが目標です。

(続く)

[IM] クロステーブルの作成

INTER-Mediator Ver.5.4-devでは、クロステーブルの作成ができるようになっています。ここでのクロステーブルは、表があって、いちばん上の列と、いちばん左の列がラベルとなっており、そのラベルの交差するセルには、ラベルに関連するデータが表示されるというものです。例えば、いちばん上の列には自社の「支店」が並び、いちばん左の列には年月が並ぶとすると、その交差するセルには、特定の支店の特定の年月の売り上げが見えるというものです。サンプルファイルはSamples/Practice/crosstable.htmlおよびcrosstable.phpにあります。

まず、クロステーブルを作るには、3つの異なるコンテキストを定義します。1つは列見出し(以下のコードではitem)、1つは行見出し(以下のコードではcustomer)、そして交差するセルに設定されるデータのコンテキスト(同じくsalessummary)です。列見出し、行見出しのコンテキストについては通常と変わりありません。また、列か行かの区別も、定義ファイル内では設定しなくても構いません。行列の見出しのコンテキストでは、検索条件や並べ替えフィールドの指定などももちろん可能です。以下の例では、元のデータが多いこともあるので、意図的に絞り込んでいます。交差するセルのコンテキスト「salessummary」では、relationキーの指定を必ず2項目行います。1項目は列見出し、2項目目は行見出しとの関連付けになります。item、customerともに、主キーはidフィールドです。これに対応するsalessumarryコンテキストのフィールドはitem_idとcustomer_idです。すなわち、列見出し、行見出しの対応するレコードとのリレーションシップを利用して、交差するデータの配置を決めています。

 array(
   'name' => 'item',
   'table' => 'dummy',
   'view' => 'item_master',
   'records' => 100000,
   'maxrecords' => 100000,
   'key' => 'id',
   'query' => array(
     array('field' => 'id', 'value' => 25, 'operator' => '>='),
     array('field' => 'id', 'value' => 35, 'operator' => '<='),
 ),
 'sort' => array(array('field' => 'id', 'direction' => 'asc')),
 ),
 array(
   'name' => 'customer',
   'table' => 'dummy',
   'view' => 'customer',
   'records' => 100000,
   'maxrecords' => 100000,
   'key' => 'id',
   'query' => array(
     array('field' => 'id', 'value' => 250, 'operator' => '>='),
     array('field' => 'id', 'value' => 259, 'operator' => '<='),
   ),
   'sort' => array(array('field' => 'id', 'direction' => 'asc')),
 ),
 array(
   'name' => 'salessummary',
   'table' => 'dummy',
   'view' => 'saleslog',
   'records' => 100000,
   'key' => 'id',
   'relation' => array(
     array('foreign-key' => 'item_id', 'join-field' => 'id', 'operator' => '=',),
     array('foreign-key' => 'customer_id', 'join-field' => 'id', 'operator' => '=',),
   ),
 ),

ページファイルのクロステーブルの部分は、2セルずつの2行の表として作ります。それよりも多い場合や少ない場合はダメで、要するに2行2列のテーブルを必ず用意します。そして、エンクロージャーになるtbodyタグのdata-im-control属性を「cross-table」とします。これら4つのセルと2つの行は取り除かれ、初期状態として、TRタグに左上のセルを入れた状態にします。この左上のセル内部は、ページファイル側での定義通りにレイアウトされます。

fig16

 <table>
 <tbody data-im-control="cross-table">
 <tr>
   <th></th>
   <th>
     <div data-im="item@id"></div>
     <div data-im="item@name"></div>
   </th>
 </tr>
 <tr>
   <th>
     <div data-im="customer@id"></div>
     <div data-im="customer@name"></div>
   </th>
   <td>
     <div data-im="salessummary@qty"></div>
     <div data-im="salessummary@total"></div>
   </td>
 </tr>
 </tbody>
 </table>

続いて、1行目のTRタグをエンクロージャーに、そしてページファイルにあった右上のセルをリピーターとして、ページ合成を行います。つまり、このBのセルには、列見出しになるコンテキストの名前と、データベースから得られるフィールド名をdata-im属性として持つターゲットノードを記述しておきます。その結果、データベースアクセスが発生し、この場合はitemテーブルから一部のレコードを取り出して、それらを列見出しとして並べます。

fig17

さらに行見出しの処理になります。今度は、TBODYタグをエンクロージャー、そしてTRタグにページファイルの左下のセルを入れたものをリピーターとして、ページ合成を行います。つまり、行見出しだけをまずは作成します。

fig18

ここまでは、エンクロージャーとリピーターの違いはありますが、通常のページ合成と同じです。クロステーブルでは、ここで、次の図のように、交差する部分のセルに、一旦、ページファイルのテーブルの右下のセルを全て並べます。そして、コンテキストに応じたデータベースアクセスを行い、交差する部分に入るデータがあれば、対応するセルに値を設定します。列見出しあるいは行見出しに登場しないレコードと対応するものは無視されます。

fig19

サンプルの出力結果は以下のようなものです。2つのセルにしかデータは入っていません。なお、ここでの交差するセルに対応したコンテキスト内に、同一のセルに対応するものが複数ある場合には、中途半端にマージされます。コンテキスト内は、例えばSQLのビュー等を使うなどして、1つのセルに対応するレコードは0ないしは1個になるようにしてください。

shot3220

El Captainでdocdiff

以前、2つの文書の比較結果をカラーリングで示せるdocdiffのことをMavericks向けに書きました。その後、Yosemite向けにも書きました。このポストは、そのEl Captain版です。/usr/binディレクトリがルートレスの機能により利用できなくなったので、docdiff自身も/usr/local/binに配備されるようになっています。それに合わせてドキュメントを書き直します。

まず、インストールは以前と同様にgemを使います。すでにファイルが存在すると、上書きしていいかを聞かれるので、yで上書きをしてしまいます。

sudo gem install docdiff

これで、/usr/local/bin/docdiffがコマンドとして機能するようになります。そのほかのライブラリファイル群は正しい場所に入っているということで、気にしないで行きます。

さて、svnで使うには、パラメータの組み換えが必要です。そこで、/usr/local/binにdocdiffsvnを作ってそれを実行用にします。もちろん、viでもemacsでもご自由なエディタで編集してください。もし、/usr/local/binが作られていないのなら、mkdirコマンドで作ってください。

sudo nano /usr/local/bin/docdiffsvn

中身はこのように書きます。

#/bin/sh
/usr/local/bin/docdiff --format=tty $6 $7

そして、もちろん、アクセス権を設定しておきます。

sudo chmod a+x /usr/local/bin/docdiffsvn

こうすれば、以下のようにsvnコマンドを打ち込むときに、docdiffを使って比較を行います。最後のパラメータはファイル名です。

svn diff --diff-cmd=docdiffsvn -r PREV _any_file_name_

もし、パス(echo $PATH で確認できます)が、/usr/local/binに通っていないなどの場合には、上記のパラメータの1つを「–diff-cmd=/usr/local/bin/docdiffdvn」のように指定します。

shot3219

 

Server.appとFileMaker Server 14を共存させる

FileMaker Serverのアップデータが途中で止まる件は、こちらのページにまとめました。FileMaker Serverは、自身でhttpdコマンドのプロセスを起動するため、アップデータを適用するためにプロセスを止めた状態でないと処理しないのはいいとしても、FileMaker Server以外のサービスがhttpdを起動していても、やはりアップデートは進まず、そこで単なるシェルスクリプトによる繰り返しでhttpdのプロセスがなくなるまで待ってしまい、フリーズのようになってしまうという状況です。

OS X 10.11にServer.app Ver.5を入れた状態で、一度Webサービスを起動し、その後停止した状態を見ることができたので、記録しておきます。FileMaker Serverのプロセスを完全に落としても、以下のような2種類のhttpdのプロセスが残っています。-fオプションで指定されている設定ファイルを見れば、だいたいどんな機能のものなのかはわかります。

$ ps -ef|grep httpd
0 235 1 0 4:14PM ?? 0:00.47 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
70 358 235 0 4:14PM ?? 0:00.02 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
70 359 235 0 4:14PM ?? 0:00.06 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
70 360 235 0 4:14PM ?? 0:00.11 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
70 361 235 0 4:14PM ?? 0:00.06 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
70 362 235 0 4:14PM ?? 0:00.02 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
0 472 1 0 4:14PM ?? 0:00.35 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/apache2/services/ACSServer.conf -E /var/log/apache2/services/ACSServer_error_log
70 476 472 0 4:14PM ?? 0:00.02 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/apache2/services/ACSServer.conf -E /var/log/apache2/services/ACSServer_error_log
70 20919 235 0 5:36PM ?? 0:00.01 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf -E /private/var/log/apache2/service_proxy_error.log
1026 28116 27955 0 5:57PM ttys001 0:00.00 grep httpd

apache_serviceproxy.confは文字通りプロキシで、通常のWebサービスやWikiなどのサービスを受け付けてプロセスに流すような設定になっています。つまり、リバースプロキシでしょうか。

ACSServer.confの方は、いろいろ見ていると、/AccountsConfigService/api/とかいったパスが出てくるので、ACSはAccounts Config Serviceだと思われます。いろいろな設定を追いかけると、/Applications/Server.app/Contents/ServerRoot/usr/libexec/scsdのプロセスがデーモンとして起動しているようで、それに対するWebインタフェースをApacheを使って稼働させている模様です。man scsdはきちんとドキュメントが表示され、「Accounts Config Service Daemon」とタイトルにあります。細かなことはわかりませんが、Webアプリケーションとして動くサービスとなっています。

何れにしても、これらのサービスが稼働していれば、FileMaker Serverのプロセスは起動しません。httpdを利用するサービスを全てなくすには、次のようなコマンドを打ち込みました。

$ cd /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/
$ sudo launchctl unload -w com.apple.serviceproxy.plist
$ sudo launchctl unload -w com.apple.service.ACSServer.plist

Server.appはいろいろな機能がありますが、Webサービスはもちろん、事実上はWebアプリケーションであるカレンダーやWikiなどの機能を一切使わないのなら、上記のようにしてリバースプロキシとACSServerはなくてもおそらくは問題ないと思われます。Server.appを、AFP/SMBのファイルサーバーとして、そしてTime Machineのサービスとして、さらにOpen DirectoryのMasterとして使う限りでは、上記のサービスを落とした状態でも利用できています。

ただ、これらのサービスは単純に「落としても構わない」とは言い切れないですし、皆さん自身が判断してください。ともかく、Server.appとFileMaker Serverを同時に使う場合には、Server.appのWebあるいはApacheを使っている一切の機能を使わないでおくようにするしかないと思います。ちなみに、聞くところによると、FileMaker社のサポートに問い合わせると「Server.appはアンインストールしろ」と言われるらしいです。それもどうかと思います。事実上、同じ会社の製品なんですけどね。

[IM] Ver.5.3よりサポートのsourceキー

Ver.5.3より、コンテキスト定義(定義ファイルのIM_Entry関数の第一引数の配列の要素)に、sourceキーを入れるようになっています。データベース上のエンティティ名に関連するキーとしては、name、view、tableがありますが、それにsourceが加わります。データベースから読み出しを行うときのFROM句に指定されるビューやテーブルの名前は、viewキーがあればその値、なければnameキーの値が使われます。CREATE/UPDATE/DELETコマンドの対象は、tableキーの値で、それがなければnameキーが使わます。例えば、nameキーにテーブル名があれば、そのテーブル名を指定しての読み書きはviewとtableキーの指定はしなくてもできます。しかしながら、表示は何かのビューを使い、更新はそのビューではない特定のテーブルを指定したいような場合に対処できるように、viewとtableキーを用意しました。

しかし、これだけでは問題があります。あるテーブルのあるレコードのあるフィールドが、ページ上の複数のリンクノードに展開された場合、それが例えば両方ともテキストフィールドであれば、一方の値を変えると、フィールド更新のためのサーバー通信が行われるとともに、クライアントサイドで同一フィールドの別リンクノードの値を更新できるようになっています。その時、何を手掛かりにして反映させるコンテキストを探しているかといえば、「viewないしはnameキーの値が同じだが異なるコンテキスト」です。例えば、住所録的なpeopleテーブルがあり、同一ページに全レコードの一覧と、その中で男性の一覧の両方があったとします。前者のコンテキストは、name=allmembers, view=people、後者のコンテキストはname=malemembers, view=peopleとして適切なqueryキーの条件を与えればいいでしょう。こうすれば、同一テーブルから異なるコンテキストを生成して、内容が異なる一覧を1ページ内で生成できます。

この時、男性の一覧にあるレコードは、必ず全員のレコードの一覧にもあります。どちらもviewキーがpeopleなので、男性のレコードの1つのフィールドを変更すると、対応する全員の一覧にあるレコードのフィールド値も更新されます。以下、この動作は「連動」と呼びます。同一のviewキーの値を持つコンテキスト同士なので、INTER-Mediatorにとっての手がかりがあります。

しかしながら、SQLのレベルで、peopleをもとにしたビューeveryoneとsomeoneがあったとします。それらで表を作るとしたら、nameやviewを使うにしても、everyoneとsomeoneがそれぞれのコンテキストに登場はしますが、コンテキストの情報から各々が同一のpeopleテーブルから導出されていることはわかりません。そうなると、同一のレコードがそれぞれの一覧に見えていて、一方の値を変更したとしても、その変更結果を伝達する手がかりがなく、連動はできません。

このような時には、一方のコンテキストを、name=everyone, source=people、もう一方はname=someone, source=peopleと定義します。ページファイル側は、everyoneあるいはsomeoneをdata-im属性に利用する点は変わりありません。このsourceの設定により、2つのコンテキスト定義から得られるコンテキストは、同一のテーブルから来ているものということがINTER-Mediatorに伝わるので、同一フィールド値がユーザーインタフェース上で連動するようになります。

FileMaker Serverのアンインストール

FileMaker Serverをどうしてもアンインストールしたい場合があります。インストーラが「先にアンインストールしないといけません」とメッセージを表示して、それ以上進めないとなると、仕方ありません。インストーラのExtraフォルダに前のバージョンのアンインストーラがありますが、こんな場所にも、現在インストールされているFileMaker Serverのアンインストーラがあることを知っていれば、便利かもしれません。

shot3216

ディスクのルートから、ライブラリ>Application Support>FileMaker>FileMaker Serverという場所にも、アンインストーラがあります。ご参考までに。

FileMaker Serverのアップデータがフリーズする理由

FileMaker Server 14.0.4bのアップデータがリリースされました。このところ、アップデートが頻繁にありますが、いざアップデートしようとすると、最初の部分でフリーズしてしまうことがあります。フリーズと言っても、マウスカーソルがレインボーになってしまう現象です(画面ショットではレインボー状態は撮影できないので、以下の図は普通のポインタになっています)。

shot3215

ちなみに、この現象は、14.0.4bのアップデータに限らず、13のアップデータでも発生することがあります。もちろん、いつまで経ってもこのまま進みません。さて、なんででしょうか? アクティビティモニタを見ると、パッチアプリケーションのCPU稼働率が100%近くになっています。ということは、本当にフリーズか、適切でない処理待ちをしていることが考えられます。

そこで、ターミナルを起動して、プロセスを見てみます。パッチアプリケーションのプロセスには「Patch」という特徴的な文字があります。以下のコマンドで、プロセスIDは27530だとわかります。(以下、コマンドラインの出力が長いので折り返して見えるようにしておきますが、見づらい点はご容赦ください。)

$ ps jax|grep Patch
root 27530 1 27523 0 0 S ?? 0:15.60 /Volumes/FileMaker Server 14.0.4b Patch 1/FileMaker Server 14.0.4b Patch.app/Contents/MacOS/FileMaker Server 14.0.4b Patch

次に、このプロセスが別のプロセスを起動していないかをチェックします。すると、以下のように、「/bin/sh /Users/msyk/Library/Application Support/1358455 0」なるプロセスがあります。最後の方の数値は起動ごとに違うものがつけられ、正常終了すると消されているファイルです。

$ ps jax|grep 27530
root 27530 1 27523 0 0 S ?? 0:15.60 /Volumes/FileMaker Server 14.0.4b Patch 1/FileMaker Server 14.0.4b Patch.app/Contents/MacOS/FileMaker Server 14.0.4b Patch
root 27545 27530 27523 0 0 S ?? 0:00.05 /bin/sh /Users/msyk/Library/Application Support/1358455 0

これは/bin/shつまり引数をシェルスクリプトとして実行しているということです。catコマンドで、ファイルパスにスペースがあるのでダブルクォートで囲むなどの対処をして、中身を読んでみます。パッチアプリケーションは、このプロセスが終了するのを、おそらく単なるループで待っているためにフリーズするのでしょう。psコマンドである種のプロセスが存在するかどうかを2秒ごとにチェックし、調べているプロセスがなくなれば、スクリプトを終了します。

$ cat “/Users/msyk/Library/Application Support/1358455”
#!/bin/sh

cd /Library/Application\ Support/FileMaker/FileMaker\ Server
./launcher -stop

while [ “`ps auwwx | grep -e fmserver_helperd -e fmsib -e fmslogtrimmer -e fmxdbc_listener -e fmsased -e httpd | grep -v grep`” ] ; do
sleep 2
done

whileの行を見ると、psコマンドの結果に、fmserver_helperd、fmsib、fmslogtrimmer、fmxdbc_listener、fmsasedという文字列があるかを調べています。つまり、FileMaker Serverの様々なプロセスが起動した状態なのかを調べています。さらに、httpdというプロセスまで存在するかを調べています。アップデートは、FileMaker Serverを停止させて行うようにということで、FileMaker関連のプロセスがなくなっているという条件はまあいいでしょう。ちなみに、FileMaker Serverのプロセスを事前に全部止めておくには、以下のコマンドでできます。

sudo launchctl unload /Library/LaunchDaemons/com.filemaker.fms.plist

しかし、httpdとなると、何らかのきっかけで動かしてしまっているかもしれません。あ!そういえば、Server.appで色々試したぞと思ってチェックすると、Server.appのソフトウエアアップデート、キャッシュ、Xcode Serverあたりがhttpを使っていました。しかし、Server.appは、それらのプロセスをオフにしても、httpdの稼働を止めません。仕方ないので、sudo launchctl unload <plistファイル>で順次落として、やっとFileMaker Serverのアップデータが動くようになりました。ちなみに、こうしたデーモンは、launchctlで起動しているので、killしてもすぐに再起動されます。そこで、/System/Library/LaunchDaemonsや、/Library/LaunchDaemonsに該当するファイルを探すわけですが、Server.appについては、/Applications/Server.app/Contents/ServerRoot以下の、/System/Library/LaunchDaemonsや、/Library/LaunchDaemonsにあるplistファイルを利用してデーモンを起動しています。これらのファイルから該当するhttpdを起動しているものを探して落とさないといけません。チェックすべきplistファイルのある場所は文中に記載しましたが、見づらいでしょうから以下に列挙します。

/System/Library/LaunchDaemons
/Library/LaunchDaemons
/Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons
/Applications/Server.app/Contents/ServerRoot/Library/LaunchDaemons

しかし、一番の問題は、「httpdが起動していたらアップデートをしない」という仕様です。つまり、結果的にFileMaker Server以外のhttpdの起動を許さないという仕様に問題があります。Server.app自体が色々なサービスでhttpdを使うのですが、80番ポートの取り合いになるのは確かにまずいでしょう。しかしながら、FileMaker Serverのインストーラーは、自分自身のhttpdのポート番号を指定することで、他のサービスとの同居の可能性を探っています。しかし、このスクリプトを見る限りは、「FileMaker Serverが起動したhttpd」ではなく、単に「名前がhttpd」のプロセスを探しているにすぎません。つまり、FileMaker Server以外でhttpdを使いっていればトラブルが発生する仕様なのです。これでは仕様の上で矛盾があると言えるでしょう。

もちろん、特定のサーバーではFileMaker Serverしか動かさないという前提でもそれはそれで構わないと思いますが、だったら、LinuxのVMで動かすようにして欲しいというのが総意ではないでしょうか。OS XとWindowsで、アプリケーションみたいなインストーラでセットアップするサーバーはもはや古さを感じます。現在のシステム構築環境にマッチしない仕様を早く改善しないと、先頭集団からさらに引き離されるでしょう。

Xcode 7.3で出るSwitf 3でなくなる機能

iPhone SEがラインナップに加わり、Xcode 7.3がリリースされました。Swift 2.2になったのですが、Swift 3でなくなる機能が、deprecatedとして出てくるようになりました。以前のように、いきなりコードに赤いエラーが出て動かなくなるより、はるかに気持ちの良い対応ですね。手元のいくつかのプロジェクトを早速開いてみました。

まずは、x++やx–演算子の廃止です。こちらに詳細がありますが、まとめると初心者にとってわかりにくく、トリッキーなプログラムになりがちということで、廃止すべきという意見が通ったということです。x++と++xの違いとか、C言語のクイズとしては面白いかもしれませんが、読みやすいコードにするには、解釈しづらい言語仕様の排除というところでしょうか。x++は、x += 1 に変換しろということになっていますが、++の前後の位置を利用している場合や、x++の返り値を利用している場合には、単に置き換えで済まないかもしれません。

shot3198

__FUNCTION__が使えなくなり、#functionに置き換えるように出てきています。プロポーザルはこちらですが、アンダーラインを使うC言語由来の方法ではなく、#をコンパイラによる置き換えを記述できるようにするということでの変化ということになります。

shot3199

タイマー等で使っていたセレクタ型はSelector(“メソッド名:”)みたいに書いていましたが、#selector(クラス名.メソッド名(引数))のように記述するようになります。メソッド名を文字列で記述するとなると、間違ったメソッド名かどうかの判断ができないので、記述を見直すのは確かに必要です。こちらにプロポーザルがあります。

shot3200

オープンソースとなったSwiftですが、早速多数のプロポーザルが行われ、それが言語仕様となり、Xcodeに反映されるというダイナミズムがこのようにすでに動き始めています。Swiftは過去に例を見ない速度で進化し始めているといえるでしょう。

FileMakerのWebビューアが、WebDirectで文字化け

最近ブログ更新していないので、小さなネタですが書いておきます。私がWebDirectの話をするのは予想外かもしれませんが、ちょっとハマったことがあったので書いておきます。FileMakerでのソリューション内で、複数の文書を並べるような機能が必要だったので、Webビューアを使いました。全文字を平面上に成り行きでレイアウト出来るので便利です。Webビューアには、dataスキームを利用して、フィールドの値などを合成したHTMLを与えてWebビューアに表示しました。FileMaker Pro上ではもちろん問題ありません。しかし、WebDirectでWebビューア部分が文字化けしました。理由はフォントではなく、文字セット指定がなかったからです。そこで、

data:text/html;charset=utf8,<!DOCTYPE html><html><head>
<meta http-equiv='X-UA-Compatible' content='IE=Edge,chrome=1'/>....

のように、charsetを入れればブラウザ上では文字化けは無くなりました。charsetを省略すると、us-asciiと同じになるそうですが、それはブラウザ上だからかと思われます。FileMaker Proでは指定なしでも文字化けないようにしているということでしょうね。

FileMakerのWebビューアは本当に「IE」なのか?

追加情報:社本さん、ありがとうございます。解決できました。ヘッダに「<meta http-equiv=’X-UA-Compatible’ content=’IE=Edge,chrome=1’/>」というタグを入れれば、Webビューア上でもflexの機能が動き出します。ということは、MS EdgeはこのmetaタグなくてもEdge動作をするのだけど、FileMakerはmetaタグがないとIE9互換動作をするという罠ってことですね。(以下の原稿公開後にこのパラグラフを追加しました)

最近、CSSのflexを理解したので、FileMakerのWebビューアでも使おうとしたら、思いがけない落とし穴がありました。Macは問題なくレイアウトされますが、Windows 10 + FileMaker 14.0.4では次の図のように、flexが機能しません。「ある記事」と「塚口…」の部分は、それぞれDIVタグ要素になっており、その2つのDIVをさらにまとめたDIVがあって、そこにdisplay: flexを記述してあります。上半分は、FileMaker 14のWebビューア、下半分はMicrosoft Edgeでの表示結果です。同じソースなのですが、このように、Edgeでは正しくflexの動作をしてDIV要素を横方向に並べますが、Webビューアでは、flex動作をしないで、単にDIVとして表示します。

スクリーンショット 2015-12-16 16.00.30

FileMakerのWebビューアコンポーネントは、Internet Explorerのものと言われていますが、もしかして、FlexboxはVer.10から対応なので、Ver.9相当のコードで構築されたコンポーネントが入っているということでしょうか?何れにしても、IE/Edgeのバージョンとは連動しないということかと思われます。

HTMLのソースは、IEの画面のURLから取得できるはずですが、貼り付けておきます。

<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<style>
.titlearea{font-size: 12pt; display: flex; display: -ms-flexbox;align-items: baseline; margin: 3px 0 3px 0;}
.title{font-weight: bold; flex: 10 0 auto;-ms-flex: 10;}
.credit{font-size: 10pt; flex: 1 1 auto;-ms-flex: 1;}
.content{font-size: 10pt; border-bottom: 1px dotted black;}
BODY{border: none;}
DIV{font-family: Arial, Roboto, “Droid Sans”, “游ゴシック”, YuGothic, “ヒラギノ角ゴ ProN W3”, “Hiragino Kaku Gothic ProN”, “メイリオ”, Meiryo, sans-serif;}
</style>
</head>
<body>
  <div class='titlearea'>
    <div class='title'>ある記事</div>
    <div class='credit'>塚口 三春[2015/12/15]</div>
  </div>
  <div class='content'>いいことばかりです。いいことばかりです。…いいことばかりです。いいことばかりです。いいことばかりです。いいことばかりです。いいことばかりです。</div>
</div></body></html>