電子マネー決済ゲートウエイ

ちょっと前に、ある機器での電子マネー決済サービスがはじまりました(・ω・)
そのサービス用の、ゲートウエイサーバを作ったりしたわけですが。
決済サービス自体のサーバ群は元々あるものを使い、サーバ向けのプロトコルと機器向けのプロトコルの変換を行うだけのものなので大したものではないんですが、そのアーキテクチャについてなんか少し雑記。

基本構造

ゲートウエイはJava*1でてきています(・ω・)


Webサービスとかではなくて、パフォーマンスが要求されるAPサーバー/ミドルというと、速度の観点からC/C++でみたいなイメージがあったりしますが。
今回のゲートウエイ開発の前にも、Android向け決済でのミドルやサーバー開発なんかをしており、その段階でC++での性能検証なんかもしていて。
やはりC++だと開発環境面などでの面倒さなどもあり、若干の工夫は必要ですがJavaでも十分な性能を出せることを検証した上で、Javaを選択しています。*2

通信のI/Oモデル

構成とししては、非同期I/Oとスレッドプールの合わせ技です。
ゲートウエイの特性として、機器側の通信と上位サーバ側の通信という、2方向/複数TCP及びUDP通信を非同期I/Oで処理しています。
非同期I/Oなのは、性能面での工夫もありますが、プロトコルがリクエスト/レスポンスのような単純なものではなく、双方向から任意の時点でデータ受信が発生するものであるので、それを処理するためでもあります。


また、セッションはステートフルであり、非同期I/Oとステートフルという点については、プロトコルスタックや変換レイヤをそれぞれステートマシンとして実装し、ステートマシンを大小さまざまな歯車を組み合わせるようなイメージでセッションの処理を構成しています。
このアーキテクチャ、何気に気に入ったりしています(・∀・)

オブジェクト指向

例えば、GoFデザパタ的に言えば、十数個のパターンを使用していますが。
これは。別に厨ニ的にそうしているわけではなく、必要な問題解決の手段を考えていけば必然的にそうなるというだけの話です(・ω・)


また、マイクロカーネル的というか、各コンポーネントを組み合わせてアプリケーションを構築するような構造としていますが、その点についてはコンポーネント管理機構を使ってDependency Injectionパターンなんかも使用しています。
これも、よく聞くように、DIはテストのためとか言ってみたり、わけもわからずインターフェースと実装を分離しているというような話ではなくて、問題解決に適した手段だから使用しているのであり、本当にプロバイダーもでるが必要なところでしかインターフェースと実装は分離していません。
DIについては、Webの初期に流行った後、disりが聞こえるようになったりもしましたが、DIパターンとAOPの話がぐっちゃになっていたり*3、インターフェースと実装の分離の意味や適用箇所をわかっておらずにdisっているケースが多くて、ちょっとぐんにょりした記憶があります(´・ω・`)


また、よく、糞詰まんないLOBアプリのWebアプリを基準にしてOOをdisったりする話もありますが(´д`;)
必要なケースでは普通にオブジェクト指向の知識は必要になるので、LOBアプリ開発者も、一度はエディタ、言語(スクリプト含)、サーバーミドル、ゲーム等を開発してみるべきだ、っというのが私の持論です。
そんな知識はなくてもLOBアプリを作ることはできる、っというのは単に見識の狭さと自分が土方作業者であることを露見させる発言でしかなく、こういった知識を応用して問題を解決するのが本当のSIだと自分は考えます、なんつって(・∀・)


なお、ドメイン的な話や、ファンクショナル的な話については、変換部分については割とドメインドメインしていたり(なんのこっちゃ)、Action/FunctionインターフェースやMaybe的な実装も普通にあるのですが、そこは今回はたいした話は無いので省略します。


…っと、その一方で、OOとは少し違う工夫をしている部分もあります。

JavaらしくないJava

パフォーマンスについて、基本的な部分についてはJavaの速度で問題無いのですが、それでもアプリケーションの特性的に注意が必要な部分もあります。
決済という特性上、カードとの通信、ユーザへのインタラクション、非同期I/OやUDP通信とタイムアウト等を考慮した場合、処理の遅延はなるべく排除したい所です。


そのため、プールできるものはプールして再利用するような構成にはしています(`・ω・´)
ただし、細かい部分までチューニングした作りにしているわけではなく、プロファイルによる分析をしたうえで、影響の大きいオブジェクトについてのみ工夫を行い、JavaらしくないJava、CみたいなJava、っという所まではチューニングしていません。


感覚的に言うと、負荷100%の状態になった状態で、結構な頻度で100msの遅延が発生する、は許せないが、まれに10msの遅延が発生する、くらいなら許容できる、っというくらいには工夫をしている、っという所でしょうか。

CPUバウンドなの?

負荷100%という話が出ましたが、ゲートウエイがCPUバウンドな作りなのかというと、そうです(・ω・)
機器側及び上位側に対して、1決済につき複数回の暗号化/署名が発生するため、CPUバウンドな処理になっています。


性能的には、Core i7 4770な環境で450決済/sといった程度でしょうか。
通信について言えば、1決済あたり50パケットと前述しましたが、単純に計算して1秒あたり22000〜23000パケットを捌いているわけで、通信性能的にはたいしたことはありません。


CPUが余っているのに通信性能が頭打ちになるのはプログラムの通信モデルの問題ですが、非同期I/Oのあたりをちゃんと考慮すれば、Javaでも.NETでも100,000 reqres/sくらいは普通に処理可能です。*4

その他の工夫や周辺ツールについて

後は、その他のトピックについて少し。


ゲートウエイサーバには、運用面を考慮して、管理ポートに接続すると使用できる簡易シェル機能や、JMXによる各種メトリクス値の取得や動的な設定値変更機能などは提供しています(`・ω・´)
今時だと、Webアプリなどにおいても、運用の改善や問題の兆候を捉えるため、アプリケーション固有のメトリクス値の提供等は必須であるともいえるかと思います。


また、ログについても、メトリクス値同様、収集して分析することで、問題の兆候の発見や設定値の改善に役立てることが可能な情報を出力するようにしています。
ただし、ログの粒度、項目、形式などについては、昨今のログ分析等におけるトレンドを踏まえ、最適な形とはどのようなものなのかについて、もう少し学んでみたいところです(・ω・)


ところで、ゲートウエイ自体はJava製なんですが、テストツール等、周辺ツールC#で作っていたりします。
機器の変わりのダミークライアントは普通のWPFアプリでMVVMとかしてますし、機器のクライアントミドル相当品もC#で作ってあって、それを使えば機器の決済と同様の事ができるものにはなっています。*5


あとは、ベンチマーク用の疑似クライアント、疑似サーバなんかも、C#で作ってそれをMono上で動作させたりもしています。
これら疑似クライアント、疑似サーバの通信I/Oモデルについては、Java側の作りと共有できる部分は共有した作りにするため(単に手抜きのため)、libeventモドキな抽象化機構で作っていたりします。


そげな感じ(・ω・)

*1:開発時期は一年前くらいから去年の末までくらい。Java 7で、7的な機能は普通にしようしています

*2:検証時には、PythonC#+Monoなんかでも性能検証をしていたり

*3:AOPは糞( ゚д゚)、

*4:ただのEchoサーバとかなら(・∀・;)

*5:別に不正ができるわけではなく、普通に金額が引き去られちゃうだけですが(・∀・;)

Java EE

Java EEがどうすれば流行るかなんて、実はとても簡単なことで(・ω・)


アクションベースのフレームワークが仕様化される or JAX-RSのビューが仕様化されて、ビューヘルパーやセキュリティ周りの仕様も整備されたり、拡張ポイントやユーティリティも十分にこなれて、…例えるなら、各種実装系の便利機能による差異がないくらいになって*1、後はMicro-ORMも仕様化されて、…っとなれば、みんなJava EEに移行すると思いますよ、きっと(・ω・)


だからきっと、Java EE 11になるくらいの頃には、Javaをやっている人はみんなJava EEを使ってるんじゃないですかね(・∀・)
その頃にはSpringもJava EE準拠になっているだろうし(・3・)

*1:っというか、ミドルみたいにプロバイダーモデルを使う意味のあるものならともかく、なんでプレゼンテーションや永続化のフレームワークに仕様と実装の分離が必要なのかがそもそもよくわかりませんが(・∀・;)

Javaとラムダ

使えるようになったら、規約で禁止系のネタとかがありますが。


しかし、Guavaが普通に使われているんだから、ラムダが使えるようになったところで、よくネタにあるような変な話は起こらないと思っているぉ(・ω・)
規約的な話とかは、LINQの時は「宣言的に書けるので○」で済んじゃったけどな(・ω・)


まあ、Javaでラムダが普通に使われる未来を作るには、R#さんが「そこはLINQで書けるよね?」っと言うかが如く、IDEや静的テストツールがサジェストもとい警告を出しまくるようになれば、そういう世界になるかもかも(・∀・)?
PMDやCheckStyleさんが「そこはラムダ使えんぞゴルァ」と警告してくれるようになれば、その部分のレビューはJenkinsさん任せにできるし(・ω・)


個人的に、8への移行の最大障壁になると思うのは、実はそのあたりというか、静的テストツール等のエコシステムが、Java 8構文へなかなか対応しない状況が続くのではないかというあたりだったりもして(・ω・;)
その問題がクリアされれば、8構文の導入にGoを出すし、逆にラムダを使っていなかったらレビューで指摘も飛びますが。(Jenkinsさんに任せだけど)


しかし、これでやっとJavaしかやっていない人も、C#Javaの両方をやっている人がJavaを書くときの苦痛を理解できるようになる(・∀・;)?
.NETもJavaもやっている人の多くは、StreamはLINQの(以下略)、JavaFXWPFの(以下略)、JSFASP.NET Web Formasの(卑語削除)くらいにしか思っていないという現実(´・ω・`)


.NETとか、使える言語ではロジックを書くときにラムダを使うのは普通になってきていると思うのよ。
あるプロジェクトのロジック層における「=>」の出現率(非ドメイン層を含まないドメイン層の中だけの数値)はNCSS:3376に対して360で、約11%、今時だとまあこんなもんかしら(・ω・)?
もにゃど(。・ω・。)ニャーンとかを意識したコードはまだそれほどでも無い感があるので、それが入ってくるともう少し数値はあがる気もしますが。


ちなみに、ラムダというかLINQ(LINQ to Objects)さんとかが活躍するのは、コアドメイン層のロジックの他に、データストアモデルの構造からレゼンテーション用に変換するプレゼンテーションモデルのあたりとか(・ω・)
プレゼンテーションモデルについても、ぶつぶつつぶやいている気がするので、それもそのうち再録するる。

DIと、時々テスト

「DI嫌い」っていう話をよく聞くと、「IFと実装の対応が分かりにくい」みたいな理由は多いけど(・ω・)


それって、なにも考えずに「全ての要素はIFと実装はセットで用意すべき」だと思い込んでるアホな設計の話とか、DIパターン及びコンテナの話を混同しているだけだったりすることも(・ω・)?
なんでもIFと実装分離パターンに対するイライラを、DIやデータアクセスパターンのせいにするケースを未だに見るけど、それってDIやパターンの問題じゃ無いと思うのよ。
自分んらの所の、設計と(使っている)実装の問題にすぎねーからな、なんつったりもして(・∀・;)


あと、未だにDIとAOPを混同しているケースがあるのはどうしたもんかしらん。
IFと実装をセットで用意するものだと思い込んでいるケースもそうだけど、変な理解をしているケースの方がタチが悪い(´・ω・`)
DIなんか使うから問題なんだというのは、Dependency Injectionパターンと、AOPの話と、コンポーネント管理(アプリケーション固有の設計方針)の話を混同した、割とありがちな話じゃないかと思うの(・ω・)


コンポーネント管理としてのDIは必要、AOPが出てくるのは拡張ポイントが不十分な証拠、もしくは対象の前後に処理を挟みたいものはRAII的な手法でスコープを使ってやれ、
…っという考えは前から変わっていないんだけど、最近はなにか変ってきているところもあるのかしら(・ω・)?


DIを使う目的として、テストを引き合いに出されるのはどうも違和感があるノ(・ω・)
テスタビリティの話は、コンポーネントのモジュラリティの話で、DIを使うかはどうでも良いし。
単に、コンポーネントの組み立てに使うためにDIを使う、っというだけじゃイカん崎(・ω・)?


テストのために、ControllerやServiceみたいなものまでIFと実装を分離するとか、単に何も考えていない証拠だと思うのよ。
設計的に、本来プロバイダーモデルを用いるべき所だけモックに差し替えられれば、テストで困ることもない、っとも前から思っているのだけど(・ω・)


テストというと、Webだけやっていて、ユニットテストがピンと来ないというのは分らんでもないけど(・ω・)
単純に言ってしまえば、「ステート」も無ければ「ロジック」も無いからで(・ω・)
対象がステートやロジックを持っていないとユニットテストの価値は感じにくいわけで、ユニットテストのお勉強で自販機なんかがよく例題に出されるのも、その観点から適当な題材ということだし(・ω・)
シンプルなWebアプリの場合、バウンダリから永続化までが単純な呼び出しになるので、ルート、コントローラー、データストアとかのテストにたいした意味を見いだせないというのは、まあそうかなと。


Webのアプリケーション層においてその価値を感じやすいのは、データストアのモデルからプレゼンテーション用に構造変換するプレゼンテーションモデルの所や、パーシステントには依存しないコアドメインのロジックあたりかしらね(・∀・)?


後は、ユニットテストという範疇からは外れるけれど、データストア自体をステートとして、Mockをとかは使わずアプリは本物でVMとかを使って、ユースケースをテストとして書いてデータストアの中身を事後検証するとかね(`・ω・´)
これはCIで都度走らせるにはコストが高くなるので、Dailyでとか、コード/コンポーネントの検証というよりリリース状態を保てているかの検証になりますが(・ω・)
Webアプリの場合、ユニットというより、回帰テストという点を全面的に打ち出して、ユースケースの単位で、モックの代わりにVMを使い、ステートはDBとかにパーシストされたものを検証、っという方が良いと思うのよ(・∀・)
テスト内の処理の呼び口は、サービスファサードで、コストメリットがあると思えばコントローラー層に対する疑似リクエストからやっても良いけど。
UIレベルのテスト?、コストメリットがあると思えばね…。UIを含めたテストは変更コストが高くなるし(´・ω・`)


そもそも、モックの多いテストというものについては、そのテストに意味があるのかという以前に、そもそも構成が正しいのかという疑念があり(・ω・)


テストの話というか、責務の設計とかの話については、Webアプリを例にしても、たいした議論にならんだろうと思う面もあったりするけれど(・ω・;)
Webアプリの場合、アーキテクチャを単純化された公式に当てはめちゃっても、ぶっちゃけ困らないことも多いので、それで何か語るって言ってもな〜、つって(・∀・;)
テストの価値とか、責務の設計、機能の分割というよりオブジェクト間の契約について議論するのであれば、Web以外のドメインを例にしないと価値が伝わりずらいよね、っと(・ω・)


まあ、Webのアーキテクチャは単純だとかなんとか言うと、ちょっと反感を覚えないでもないけど。
しいて言うなら、注力するポイントはそこではないというべきかしら(・ω・)?
じゃあ、注力するポイントはどこなのかと言うと、あんまり良い回答じゃない気もするけど、ビュジュアリゼーションとか、スケーラビリティ、モニタリングとか(・ω・)?


まあ、テストを含め、責務の設計とか語るのは、他のドメインのソフトウエア開発を色々やってからでも良いと思うのよ(・ω・)
組み込み(といっても低レイヤの意味ではなく、ステートを持ったものの意味、自販機もこの範疇)とか、人のメンタルモデルのシミュレーションをして結果を得るようなアプリケーションだとか。


それまで、ステートと複雑なロジックの組み合わせによる決済系の処理をやっていた若者が、Webアプリケーションをやりはじめて、「Webアプリケーションって簡単ですね」っと言った言葉を、おじさん、忘れられなくて(・∀・;)


閑話休題、話をDIに戻して。


あと、いまいちよくわかっていないんだけど、.NETだからDI使っていないという話なんだけど、そういう人って違うレイヤのコンポーネントなりなんなりの参照をどう解決しているのかしら(・ω・)?
単にPoor Man'sとか自前Service Locator、あるいはstaticおじさん(・ω・;)なの?

Dependency Injection in .NET

Dependency Injection in .NET

えんたーぷらいず これが僕たちのリアル

「おまえ、それ大規模プロジェクトでも同じ事言えんの?ヽ(・∀・)ノガオー」っと、この業界ではやり方の正当性を示すために、「大規模」というキーワードがよく使われますが、これもだいぶ怪しい話で(・∀・;)


人によって大規模の境界は結構違うというか、例えば自分の感覚なんかだと、5億というか500人月くらいからが、やりかたをそれまでと変える必要のある境界という意味で、大規模の境になる感じですが(・∀・;)


しかし、規模としてはそこまで大きくないにも関わらず、単にプロジェクトのハンドリングが駄目で混乱を増やしているだけだったり( ゚д゚)
アーキテクトのテクニカルリードがヘボなだけで無駄が多いとか、そんな話も(・ω・;)


そういうものまでも、上手くいっていかないことの免罪符として「大規模」という言葉を使われることは多い気もするので、あまり人の言う「大規模」という言葉を信じるのはどうかなあと思ったりして(・∀・;)


あと、単純なものが、数が多いだけのものを大規模というのか?、という話もありますが。
それについては大規模かどうかという点についてはあまり興味を覚えず、それよりも、それって本当に価値のあるものなのかどうかという点に興味を覚えるところです(・ω・)

SI屋のWebなLOBアプリ

SI屋がやってるLOBアプリと、Web屋がやっているシステムは、使っているテクノロジーは似ていても、やっていることは大きく違うという話もありますが。
本当にそうか(・ω・)?、っというのが最近の自分の認識。


ぎょーむシステムなので、フォームやグリッドが量産できればそれで良いのかというと、そんなものに価値があるの(・ω・)?、っというわけで。


いつからそれがエンタープライズアプリケーションだと錯覚していた?(AA略)


フォームやグリッドだらけで、ドメインロジックが殆ど無さそうに見えるようなものをやって、エンプラです(`・ω・´)、っと言うのはチト恥ずかしい。



本当に価値のあるもの、その構築に必要なノウハウや技術って、Web系の先端スキルとそんなに差異ってないよね(・ω・)?、っといのが現時点でのとりあえずの結論。


使い勝手にしても、業務系なWebアプリでも、結局ソーシャルなWebアプリと同じようなものが求められるよね(・ω・)?、っというのが自分の観測範囲の結論で。
これは、利用者が、ソーシャル系のWebアプリみたいなものの使い勝手に慣れてきているから、っというのが大きいんだと思いますが。
もっとも、その一方で、世の中には汎用機的なUIを求められているWebシステムとかもあるんでしょうが(・∀・;)


LOBシステムにおけるJavaScriptの使い方とかも、時代とともにニーズは変わってきていて。


10年前、ぎょーむなWebシステムでJavaScriptなんて使ってはいけないと思っていた(・∀・;)
数年前、ぎょーむなWebシステムでもjQueryを使って効率的にユーザビリティを確保するようになってきた(`・ω・´)
そして今、ぎょーむなWebシステムでもクライアントサイドMVxフレームワークとリアルタイム通信が普通の事となりつつある( ゚д゚)


っという感じで。
つい最近までは、jQueryをちょこっとだけ書いて、費用対効果高めでUIをリッチにするという手法が定番だったのに(・ω・;)


今は、LOBアプリといえど、クライアントサイドのJSフレームワークが無いとやってられない感じ(´д`;)


JSのフレームワークは勝ち馬に乗っかりたいものの。
しかし、簡単に使えて(VMだけ用意すれば良くて)、data属性でバインディングできるものが良いなぁ、っというのが個人的な趣味で(・ω・)
Web APIとかコントローラー周りはあまり困っていないというか、今はクライアントサイドを作る技術の方が重要なので。
まあ、困っていないのは、あくまでアプリケーションのレイヤ内の話であって、外部サービス/データストアの先については悩むことも多いですが。


あと、LOBアプリついでに、以下についても(・ω・)


基本制御構造だけ知っていればLOBアプリは書ける的な意見は、ビジネスってやつを舐めすぎた認識なのではないかと思うのよ(・∀・;)
あたしゃ、LOBアプリ作るにしても、コンパイラを作る知識を知っているべき(出来ることに雲泥の差がある)だと思っている派なので(´・∀・`)
よくインフラ層とアプリ層のスキルは独立して見られがちだけど、インフラ/ミドルの設計スキルがあると無いとではアプリ層の設計にも大きな差異が現れるし、LOBアプリだから分岐や繰り返しが書ければOKといまだに思っているのはサッカリンの10倍くらい甘い考えよね(・ω・)


LOBアプリはパッケージを使え、それで満足できないものはエンドユーザが自分で特化した用途で生産性の高いツールを作って作れ、本物のプログラマアドホックな課題を解決するために働け。
…っという世の中が来ないのはなぜなんでしょうか(・∀・;)?
そういう世の中が、来ている会社もあるにはあるけど(・ω・)