Chonaso's Commentary

InternetやIT技術などについて知ったこと、試したこと、考えたことを書いていきます。

近況など(2018年末)

引き続き、昨年異動したグループ会社で働いています。 といいながら事実上別のグループ会社に派遣状態になっています。 資本関係がややこしく、出向先は自分の籍を置いている会社の孫会社、作業場所は自分の籍をおいている会社の子会社(最近になって子会社じゃなくなりましたが)という感じです。

昨年から取り組んでいるのはとあるスマホ向けゲームの開発です。 細かいプロジェクト体制の説明は割愛しますが共同開発という体で他社のプロジェクトへ参画しています。 プロジェクト推進のイニシアチブを持たないため事実上派遣社員のようなポジションです。

サーバサイドのプログラムを担当していましたが、新規ゲーム開発としてはかなり少人数で作ったな感がかなりあります。 どうにかサービスインに漕ぎ着けることができましたが、ローンチ直後は様々な問題が発生し、自分の力の及ばない外的要因が多々あったとはいえ最初の1週間は生きた心地がせず、久々にB2Cサービス運用で内臓をキリキリバクバクいわせる日々でした。 自分としてはなんとか早期に諸問題を収束させることはできたと思っていますが、この間プレイヤーの皆さんにもかなりご迷惑をお掛けしてしまった部分も多々あり反省しきりでした。

よく考えてみると自分のキャリアの中で他社のプロジェクトを他社内で開発するという経験は初めてでした。 新卒時はSIerでしたがすべて自社内での開発作業でしたし、その後は多くの仕様決定やほとんどの技術要件については強い影響力を持つ立場でやってきたこともあり、あまりの勝手の違いに戸惑い納得のいかない日々を過ごしました。 特にプロジェクトマネジメントに関してはフラストレーションが溜まるものではありましたが、アンチパターンの数々を身をもって知ることが出来たともいえます。 また、これまでそういう立場で一緒に仕事をしていた人たちが何を感じてきたか、ということも少し理解できた気がします。

逆にサービス運営については知らないことばかりで、今所属している会社の社長からは配属直後に「スマホゲームはリリースした時点でスタートライン、リリース以降どれだけ熱をもって盛り上げていくかが重要」的な教えをいただきましたが、いざローンチしてみるとその施策は私の知らないことばかりでした。 今回ローンチしたゲームは手前味噌ながら非常に面白いゲームだと思っていますが、ただ面白いだけでは広がらない未プレイの人に届かない、続けられるだけの要素がなければ続けてもらえない、そして基本プレイ無料でも誰かに課金してもらわないと運営が成り立たないわけで、これを決して大きくない組織で他のビッグタイトルと渡り合っていかないとならないというハードな運営が続いていきます。

前職でもそれまで知る機会もなかった営業の大変さを知ることができましたが、「こんな機能要らないだろ」と思いながら作っていたものがゲームに不可欠な要素あるいは非常に意義深いものであったことをローンチ後になって初めて気付かされることもありました。 これまでも事業会社に身を置いていた者としてある程度俯瞰できていると思っていた「事業」というものに対して自分の見識の狭さ・浅はかさを改めて痛感させられています。


この体制下での作業については1~2月には撤収、徐々に引き継ぎモードに入りつつあります。 その後はようやく自社での作業となり1年半ぶりのプロマネ業に戻る見込みです。

自分の本籍である出向元の会社はその親会社の植民地化が進み、今年は古くからの知り合い(特に管理職)の多くが会社を去っていきました。 私が戻れるところももはや無さそうです。2019年は背水の陣と思って取り組んでいきたいと思います。

JJUG CCC 2018 Fallに行ってきました #jjug_ccc

ここのところ、仕事の大半がPHPなのでJavaの話題に触れたい&刺激をもらいにJJUG CCC 2018 Fallに足を運びました。 所用があったので後半からでしたが非常に興味深い内容ばかりでした。


Deep dive into instanceof #ccc_a5

Deep dive into instanceof

広告配信システムを担当している登壇者が指摘された 「ハイパフォーマンスが求められる環境においてinstanceofは悪手、そもそもdowncastはoop的に設計が間違っているケースが多いのでは」 というレビューコメントを端緒にJavaVMのコードを追ってみた、という内容で、 単なるループで回している(辿る)わけではなく、実際にはinstanceofに耐えうるKlassのクラス設計(紛らわしい)や継承/実装の違いやツリーの深さなどでアルゴリズムを変えるなどのそれなりの考慮がなされているということでした。

Javaとは縁遠いプログラムカウンタやスタックポインタなどを知らないと即死するような内容でしたが、 デバッガを使っているとたまによく見るKlassが出てきたり、 instanceofのパフォーマンス向上についてはそれなりの紆余曲折があった*1のだな、ということを知りました。

思えば学生時代はC言語のライブラリのソースコードを読んでいたのにJVMのソースとか読む気が起きたことがなかったなぁ。 (PHPは必要にかられて読むことがある…)

ただ、あの内容だと場合によってはレビューコメント論破できる(instanceofでもいい)ケースもあるのでは?という気もしなくない(笑)


オイラ大地の18年拡張し続けているECサイトをSpring Bootとk8s on Azureでマイクロサービス化する事例 #ccc_a6

オイラ大地の18年拡張し続けているECサイトをSpring Bootとk8s on Azureでマイクロサービス化する事例

  • 品質の維持
  • ローンチスピード
  • スケーラビリティ

この3つを満たすシステムを開発・保守していくにはという問題に対し、マイクロサービスアーキテクチャでアプローチしていくことを決め、 kubernetes on Azureに辿り着いて絶賛マイグレーション中です、という内容。

自分も以前とある死にかけの会社にブチこまれて上記3課題を解決するよう命ぜられ、マルチクラウド移行やマイクロサービス(当時はこの呼び方はまだなかった)を絡めたシステム移行を手がけたので色々思うところがありました。 そしてECでJavaでモノリシックでOracleで…とこれまた構成も似てて「歴史のあるJavaシステムってなんだか知らないけどOracle多いよね!」と色々と思い出しました。

マルチクラウドあるあるとしては「サービスがクラウド越えするのでレスポンスが悪化する(下手すりゃ複数回往復する)」「これまで磨き上げたCD(継続的デリバリ)が使えない」など、マイクロサービス化あるあるとしては「トランザクションが越えられない」「今まではDB上でjoinしてた」などあり、これらの問題は、個々に少しづつ解決・移行していっているとのこと。

マイクロサービス化のフレームワークとしてのSpring bootは割愛だったのでもはやJavaとは直接関係ないセッションになっていましたが、Javaを使う会社は硬い感じがするので一度動いてるシステムに手をいれるということに難色を示す非エンジニアリング部署(ともすればシステム担当も)との云々も多いでしょうから皆感じ入るところが多かったのではないでしょうか。


GCを発生させないJVMとコーディングスタイル #ccc_a7

GCを発生させないJVMとコーディングスタイル

タイトルからすると「こういう処理はこういうコードを書けばGCは起こらない!」的な内容に見えますが、このセッションではJVM(GC)の種類やコンパイラオプションによってどのように変わるかという内容でした。

昔とあるJavaの勉強会で何度かJavaのメモリ設定やGCについての内容を発表したことがありますが、その辺とはレベルが全く異なり2つ前のセッション同様PCやSP、ニーモニックが普通に出てくる内容でした。 また、デモが多かったのですがJVMオプションを手打ちでバシバシ入れていく姿はさすがJVM開発者ですね...

恥ずかしながらTLAB(Thread-Local Allocation Buffer)やEscape Analysis(EA)は初めて知りました。 説明は非常にわかりやすかったです。 ただ、正直この動きを読みながらチューニングしたりできるかと言われると・・・今度Javaシステムのお世話をした時に妙なGC挙動があったとき思い出せればいいなと思います。

つまるところGC抑止の唯一無二の策というものは存在せずJVMの種類やインライン状況によってはGCが発生したりしなかったりするもので、コンパイラの動きを予測してトリッキーなコードを書くのではなく「まずは見やすいコードを」とのことでした。 おそらく見やすい素直なコードが日々進化していくJVM進化の恩恵を一番受けやすいということなのでしょう。


※発表スライドが公開されたら更新します

近況など(2017年末)

今年夏ごろに異動しましてグループ会社で働いています。 転職後、配属部署→グループ会社に出向→帰任、からの出向なので新卒入社を会社から通算して感覚的には5社目です。

それまでは新規事業のシステム担当でした。 ロクに要件も無い中から開発1年でローンチ、その後も膨大な数のシステムを作り続け、膨大な数の障害連絡をもらいました。 結果5年半携わりましたが自分の中では最長記録です。

今回は初めて自分で希望を出しての異動です。 元々B2C志望だったのにいつの間にかどっぷり基幹/業務システムに漬かってしまっていて、いいかげん軌道修正したいという思いがありました。 あと体調面。はっきり言ってしまえば電通顔負けのブラック部門だったのでこの最初の3~4年で心身共にだいぶやられてしまっています。 最近は親会社の強い圧力でオフホワイトくらいにはなっていると思います。

そもそもローンチさせたらすぐ抜けられると思っていたのですが、先に周りが脱落していくという状況だったため自分の中でいいタイミングがつかめませんでした。 そこで「この事業が黒字になったら辞めよう」と決めていました。自分の中のケジメみたいなものです。 そしてようやく昨年度に黒字がほぼ決定的になったので異動の希望を出しました。 自分が携わっている事業がブレイクイーブンに到達したのは初めてですが、思ったほど感動はなかったです。 (その前の事業は債務超過状態からの参画でしたが黒字転換の1か月前に帰任でした)

異動については強制力のある制度を使ったので異動自体は上手く行きました。 思えばこれまで社内やグループ会社からのオファーは私に降りてくる前に全部潰されてるんですよね。 社内ハックとしてこの制度をうまく使えばよかったなとかなり後悔しています。

異動の際、上司に「ここで得たものはあるのか」と聞かれ、答えに詰まってしまいました。 技術的な部分は誰かから教わったものはほぼ無く、やっていく中で自ら勉強して身に付けたものばかり。 強いて挙げれば業務システムを作る上での経験則でしょうか。 今思い返すと細かいレベルでは色々ある気がします。

というよりも、社会人になって以来何か直接的に教わったことはほとんど無く、ただひたすら試行錯誤と実践の場を与えてもらっただけだなぁ、と改めて感じました。 もちろんそれだけでも恵まれているとは思います。

で、今はとあるスマホ向けゲームの会社でゴリゴリPHPを書いています。 同年代は少ないですが、周りはオタクばかりで楽しいです。

プロジェクト管理や定例MTGなどは無く、1日中コーディングしてるなんて新卒の時以来かもしれません。 PHP自体はPHP4の時代に仕事でちょろっと書いていたくらいなので、ほぼゼロから始めたようなものですがなんとかやれています。 さすがに数か月PHPを触っていると思うことも色々あるのでそのうちエントリにしたためたいと考えています。

JJUG CCC 2017 Spring #jjug_ccc に行ってきました

ここ1年、業務へのモチベーションが全く上がらず、それにつられて業務外での情報収集も怠っておりました。

環境も変わる兆しが見えてきたところで少しはモチベーション上げていかないとなぁ、ということで刺激を求めてJJUG CCC 2017 Springへ参加してきましたので感想などを。

スライド関連はまだ出そろっていないようなので、随時補完していきます。


#ccc_c4 Unified JVM Logging: Java 9 から変わる JVM ログ

Java 9にはJVMログ出力の新オプションである-Xlogオプションが追加されるという話です。

JVMログ、といっても個人的にはGCのログくらいしか扱ったことがないですが、 人に説明するにも難儀するあのGCログが読みやすくなるようなら良さそうですね。 過去記事でもGCログをパースしてメモリリークの検出する、みたいなことを書いてますが、 「とはいえGC設定変えるだけで書式変わるしパーサ書くのつらいんですが」みたいなことを言われても「仕方ない」の一言で済ませてましたし。

-Xlog[:[what][:[output][:[decorators][:output-options]]]]

  • what:出力項目
    • tag:ログ種別(カテゴリ)
    • loglevel:debug,infoなど
  • output:出力先
  • decorator:ログ行頭に出力する情報(日付など)
  • output-options:ローテーション設定など

どのタグを出力するか、という設定は論理式っぽいもので指定するのですが、 -Xlogは複数書けるので種類ごとにファイルを分けちゃった方がわかりやすいんじゃないかなと思った次第。

あと、jcmdでログ設定の変更や強制ログローテート可能、ログ内でpauseを含む行に記載されている秒数はいわゆるstop the world状態とのこと。


#ccc_g5 Introduction of Project Jigsaw

Java 9に組み込まれる(かどうか不明になってしまった)注目機能。 仕様検討自体はずいぶん前からあったわけですが、Java 9になっていよいよ組み込まれるということになっています。

Javaでは関連するクラスファイルをJARファイルにまとめることである機能毎のライブラリとして管理していますが、 JARファイルの連鎖的な依存関係、パッケージ内クラスのスコープの制約(どうしてもpublicにせざるを得ない問題)が運用上の課題です。

このソリューションとしてModuleという新概念が作られました。

  • module-info.javaにrequires(依存パッケージ)とexports(公開するパッケージ)を記述
  • jarコマンドでmodule化(suffixは.jar)
  • Javaランタイムも機能グループ毎にモジュール化される
    • jlinkコマンドで任意のモジュールのみを含めたオリジナルJREが作れるようになる
    • 既存のスコープにも影響が出てくる。リフレクション系など
  • 既存のJARファイルは一定ルールに乗っ取って自動的にmoduleのように扱われる

逆にmoduleをJARとして扱われた場合にはおそらくスコープ等は関係ないことになってしまいますね...

ところがこのJSR376 JigsawはJavaコミュニティの投票でNGとなってしまいました。 (Jigsawが含まれるJSR379 Java9がOKにもかかわらず、です)

ざざっと話を聞いた限りでは拙速感は否めず、NGを出されたのも理解できます。 (元々の問題の全てを解決できてない部分もあるような…)

あと、最新版では以前あったオプションや機能が変わったりオミットされていたりするようで、 数か月前以上の記事等はあまりアテにならない部分が色々出てきているようです。

そもそも今書いているこの内容すらウソの可能性もありますが…


#ccc_c6 劇的!データベース・ビフォーアフター 時代はディスクからインメモリーへ――

10年くらい前にOpen terracottaが話題になったなぁ、というのをふと思い出しました。 (あの頃は多くの人が「アレ面白そうだよね!」で終わっていた気がします)

RDBMSディスる体でのプレゼンでしたが、インメモリデータグリッドの効果的な適用シーンの紹介という内容です。 NoSQLに置き換えても文脈がかわらない内容なので、NoSQLとの比較が欲しかったと個人的には感じました。 (この内容でもNoSQLより速そうだというのはわかるんですが)

  • 複数VM間で同一Mapオブジェクトを共有するイメージ
  • メモリが主、RDBMSがバックアップ(非同期で書き出す)
  • データは複数台で冗長して保持、1つが落ちても自動的にPrimaryが移行・他にバックアップ作成
  • キャッシュミスしたものはDBから取り出すことで大容量データに対応
  • 高速処理が可能、スケールアウトが可能
  • Spark+HDFSにおいてspark workが多いときのメモリ利用効率向上
    • ダブったデータが集約される
  • SQLライクなクエリはRDBより遅い

SparkとHDFSの間に挟めるというのは面白い活用だと思いました。 他のクラスタを組むJavaプロダクトへの活用もありそうですね。

成功事例を聞くと明日からコレ使うわwwwみたいな感じになりがちですが 遍く全てのアプリがインメモリへマイグレートしていくことはなく、 現実的には効果的な部分に適宜適用していく形になるのでしょう。

細かいところですと、開発においてはVM立ち上げた直後のデータはどうしているのか、 プレゼン中では表面だけ説明したトランザクションの中間処理はどのように解決したのか、 この辺りが気になるところです。

Doma勉強会 in 東京に行ってきました #doma_tokyo #eventdots

DomaJava のDBアクセスフレームワークです。(Welcome to Doma — Doma 2.0 ドキュメントより)

私が仕切る案件では基本的にDomaを使っています。 部門的にはSeasar2+S2JDBCがスタンダードでしたが、Seasar2が公式アップデートはぼちぼち終了になるので、 今後の案件はおそらくSpring+Domaという組み合わせになるでしょう。

ちなみに私がDomaを選んだ理由は以下の通りです。

  • JavaコードとSQLを完全分離できる
  • SQLを知らないと使えない(強く意識させる)
  • 2Way SQLが使える
  • 特定のフレームワークにロックしない
  • 多くのRDBに対応している

また、実際に使っていてよいと感じた点が以下の通りです。

  • 静的チェックが強力
  • SQLJavaコードの行き来が簡単
  • ドメインクラス機能が超便利

では本編。主に感想です。

Domaの紹介

http://backpaper0.github.io/ghosts/doma-intro.html

  • Domaの機能の紹介ですが、Domaは結構ハイペースでバージョンアップを続けていてフォローしきれていない機能(Embeddableなど)があったので、改めて勉強になりました。
  • EntityListenerでDIってよさげですね。たぶん今度使います。
  • どこかで発表があったかもしれませんが、doma-genなどの細かい(深い)話も聞いてみたいなぁ、と個人的に思いました。

ドメインクラスの話

http://backpaper0.github.io/ghosts/doma-domainclass.html

  • Domaという名前の由来でもあるドメインクラスの話。
  • ドメインって意味が広すぎてつらい、っていう意見ももっともですが、仕方ないですね。
  • 私の身の回りではDomaのおかげで「Enum値をgetValueして比較する」みたいな悲しいコードが無くなりました。
  • 「どこまでドメインクラス化するか」問題は皆共通の悩みだったようです。設計書にドメイン一覧とか書く案件だったら全部クラス化してもいい気がしますね。

とあるDoma2の使い方

http://gakuzzzz.github.io/slides/doma_practice/

  • 関数型ゴリゴリなDoma2の使い方。Java8 Stream APIを理解していない人は見ても仕方ないスライドです。逆に理解している人にとっては非常に面白い教材ですね。
  • というかDoma 2 素案 · GitHubで見かけたやり取りに対するアンサーだなぁ、と思ったら発表者はコメント付けた方でした。
  • IN句、NOT IN句にNULL入れた時の挙動って調べたこともなかったなぁ。

Domaの開発で大切にしている10のこと - Qiita

http://qiita.com/nakamura-to/items/099cf72f5465d0323521

  • Doma開発者の中村さんの発表。Domaの開発ポリシーについてです。
  • さりげなくJPA以外のCriteriaフレームワークにフォローを入れつつも、どの程度Criteriaを使うか、に対する一つのアンサーとも言えます。
  • 個人的には概ね同意というか、S2DAOからS2JDBCに移ることに納得のいかなかった人々へのノアの方舟といった感じです。
  • 逆に全体的に同意しかねる!っていう人は他のフレームワークに移った方がいいかもしれない、そんな内容です。(この辺りは唯一の正解は無い話ですね)
  • 実は私もツイートを拾ってもらって、Domaに反映されたことがあります。(たまたまリリース候補と合致してただけかもしれません) https://twitter.com/chonaso/status/683506363553583104

(LT)Doma2とMVC1.0でJava EE Webアプリを作ろう! // Speaker Deck

https://speakerdeck.com/masatoshitada/doma2tomvc1-dot-0dejava-ee-webapuriwozuo-rou

  • SpringBoot with Doma2対抗のPayara Micro with Doma2。
  • Domaとは全然関係ないですが、JerseyMVCじゃなくMVCでもいいかもね、ってちょっと思いました。

(LT)Doma2 with Kotlin

http://www.slideshare.net/yyyank/doma2-with-kotlin

  • Kotlinって正直ほとんど言語仕様をフォローしていないんですが、KotlinがサポートしてるのってJava6なんですね...
  • Kotlin関係ないですが、Domaって手軽にJDBCを使うツールとしても使えるんだなぁと認識させられました。

その他質問など

  • Q:せっかくなのでちょっと気になってた件。

    A:データソースごとにパッケージ分けた方がいいです。

  • あの場では特に聞かなかったですが、ドメイン使いだすとありがちな「DAOメソッドをオーバーロードしたい」問題って私だけですかね?

まとめ

  • Domaを好んで使う人たちの集まりだけあって「Doma最高!」連呼の若干宗教じみた雰囲気を感じました。
  • 今回発表されたスライドではないですが、これも面白いです。

Domaで複数データベースを扱う

きちんと探せばサンプルありそうな気がするんですが、こんな感じで解決しました、という一例として残しておきます。


Domaを使い始めて2年以上経ってるはずなんですが、振り返ると複数データソースは初めてでした。

daoやentityのパッケージングはどうしたものかなぁ、という課題を残しつつもとりあえず2つのデータベースを同時に扱えるようにConfigクラスやbuild.gradleを2つ準備してDoma-genまで上手く行ったのでアプリ起動!

と思ったらエラー。

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.seasar.doma.jdbc.Config] is defined: expected single matching bean but found 2: HogeDatabaseConfig,FooDatabaseConfig

まだSpringは慣れてないけど、DI候補が2つあるからDIできないぞ、と怒られているというのは何となくわかりました。

問題の箇所はDAOから生成されたクラス(XxxDaoImpl)内のコンストラクタで、ConfigをDIしようとしている部分です。

    /**
     * @param config the config
     */
    @org.springframework.beans.factory.annotation.Autowired()
    public HogeDaoImpl(org.seasar.doma.jdbc.Config config) {
        super(config);
    }

DBが一つなら型インジェクションが普通に決まるので問題無く動くのですが、 エラーメッセージにあるHogeDatabaseConfigとFooDatabaseConfigはそれぞれorg.seasar.doma.jdbc.Configを実装したクラスなので確かにこれは動かないですね。

ってことで、それぞれのConfigクラスに名前を付けて、 DAO側では@Qualifierでその名前を指定するようにしました。

その結果、自動生成部分はこのようになりました。

    @org.springframework.beans.factory.annotation.Autowired()
    public HogeDaoImpl(@org.springframework.beans.factory.annotation.Qualifier("HogeDatabaseConfig") org.seasar.doma.jdbc.Config config) {
        super(config);
    }

これできちんと動いたので、doma-genのdao.ftlも修正しておしまい。


追記

確かに!

ということで修正しました。

S2DBCPのコネクションプール状態の取得

今さらSeasar2関連です。 HikariCPのデバッグログではコネクションプールの状況を逐一ログに出してくれるのですが、 S2DBCPはそういう機能が見つからなかったので作ってみました。

SAStrutsのアクションとして実装しています。

一つのアプリで複数のプールを使うこともありますので、全部出すようにしています。