Yeomanでgenerator-angularを使う方法でやってたり。
で、結構悩んで調べたことがあったので、メモ。
※使い始めて間もないので、間違いがあったらご指摘ください。
で、結構悩んで調べたことがあったので、メモ。
※使い始めて間もないので、間違いがあったらご指摘ください。
サービスを作るやり方、Angular.jsだと色々あります。
yeoman-generatorのREADMEを参考に挙げると
service, factory, provider, value, constant
と、実にたくさん。
providerとvalueとconstantは、名前からなんとなく使い分けが判るんだけど、
serviceとfactoryの違いって何よ?って結構悩んだ。
簡単な実装例だと、「結局どっちも書き方が違うだけで同じ事してるやん」って思ってしまって…。
悩んだ時はソース嫁、という事で読んで見ました。
実装はこのへん。
factoryは、渡したfunctionをfunctionのままサービスに登録する。
serviceは、渡したfunctionをコンストラクタとしてインスタンスを生成し、そのインスタンスをサービスに登録する。
という違いがある様子。
それで何が変わるのか?というと。
serviceはインスタンスにしてから登録する。
JavaScriptのオブジェクトにはprivateが無いので、serviceで登録したコンストラクタで定義したメソッドは、何処からでも参照する事が出来てしまう。
一方、factoryはfunctionをそのまま登録する。
そして、factoryで登録したサービスから見えるのは、function内でreturnしたオブジェクトだけ。
なので、以下のように書いておくと、privateのような事が出来る。
angular.module('sampleServices', []). factory('nyanService', function() { var privateValue = 0; var privateMethod = function() { privateValue++; }; return { publicMethod: function() { privateMethod(); return privateValue(); } }; });テストはこんな感じのが通る。
describe('factory tests', function() { it('publicMethodがサービス経由で見えること', function() { expect(nyanService.publicMethod).toBeDefined(); }); it('privateMethodがサービス経由で見えないこと', function() { expect(nyanService.privateMethod).toBeUndefined(); }); it('privateValueがサービス経由で見えないこと', function() { expect(nyanService.privateValue).toBeUndefined(); }); it('1回実行すると1が帰ってくること', function() { expect(nyanService.publicMethod()).toBe(1); }); it('2回実行すると2が帰ってくること', function() { nyanService.publicMethod(); expect(nyanService.publicMethod()).toBe(2); }); });なので、使い分けとしては
- service: ある程度まとまった関数群をまとめたUtilオブジェクト向け
- factory: ビジネスロジックをしっかり書いたりするようなモデル向け
Yeomanが作ってくれるfactoryのコードにも
return{}の前に"Public API here"ってコメント書いてあるし、この使い分けで間違いない…かな?