CoffeeScript をクラス単位で分割
Meteor はフルスタックの PaaS であり、クライアントもサーバーも JavaScript が使えるお手軽なプログラミング環境です。小規模なアプリでもあれこれ機能を追加していくうちにコード量が増えていくのでコンパクトに書くためにも CoffeeScript を使いたいものです。Coffee 使うならクラス単位でファイル分割して見通しを良くしたいです。
Meteor では、クライアントとサーバーのコードより外側のスコープにクラスのインスタンスを生成するとファイルを超えて参照できるようです。ファイル結合して JavaScript にコンパイルするからでしょうけど。
このことを利用して、分割したファイルにクラス定義とインスタンス化のコードを書きクラスの初期メソッドをメインファイルから呼べば OK でした。クラス定義の必要ないオブジェクトなどは、1箇所にまとめることもできます。
なお、「クラス単位」と書いていますが、ライフサイクルの短いクラスや何らかのクラスに集約されるようなクラスは、ファクトリや集約ルートのクラスファイルの中で定義し、それらのファクトリや集約クラス内で生成するようにするとメインのクラスからは隠蔽できますし、他のクラスファイルからは単なるオブジェクト扱いにできます。
ファイル分割することで、メインのファイルからクラスのメソッドを呼び出す必要があります。Context 系のクラスであれば
class HogeContext
setUp: ->
@status = new HogeStatus ({
: # createContext
})
:
@hogeContext = new HogeContext
のように、初期構築にふさわしいメソッド定義ができて、メインから呼ばれるのは自然ですが、普通のクラスはちょっとわざわざ呼んでもらうメソッドを定義するのが微妙です。空の初期化メソッドでも作って呼んでおけばいいでしょう。
class Fuga
initialize: ->
: #nop
@fuga = new Fuga
メインのファイルからは、各クラスの初期化メソッドを適切な順序で呼び出します。
if Meteor.isClient
Meteor.startup ->
HogeContext.setUp()
Fuga.initialize()
if Meteor.isServer
Meteor.startup ->
:
ファイル分割のデメリット
ファイル分割のデメリットとして
- Enum 的な情報を1箇所に持てない。
- Factory クラスのように static にしたいものもインスタンス化する必要がある。
前者は、例えば
TicketStatus =
NEW : 0
ASSIGNED : 1
CLOSED : 2
のように定義して Ticket オブジェクトの属性に設定したりして使いますが、色々なファイルから参照したい場合は、グローバルなインスタンスとして扱うしかありません。
後者は例えば
class HogeFactory
@createHoge: ->
:
hoge
hoge = HogeFactory.createHoge()
のように使えなくなるということですが、Factory のインスタンスを生成してメソッドの定義から @
を外すだけなのでそれほど残念ではありません。
まあ、これらは見通しが悪いことに比べれば些細な問題と言えるでしょう。