クライアントエンジニア一年目で気づいたこととか

BackendなRailsエンジニアやってた去年とは打って変わって東京に転勤してクライアントエンジニアの仕事し始めてから約一年経つので、日々接してる技術スタックなどに対してつらつらと思ってることなど書いておこうかなと。

お品書き

Clean Architecture

チームの中でClean Architectureへの共通認識があまり持ててない気がする。膨大なファイル数に揉まれてなんだこれは…となりながらもこれはどうやらClean Architectureというアーキテクチャらしいとおぼろげに悟りながら無限にファイルを作り続けてる。

アーキテクチャについては不勉強なので、勉強しないとなぁと思ってはいるのですが、一つだけ確かなのはアーキテクチャを採用する理由を確かに持ち続けて居ないといけないなと。

なんかこのアーキテクチャ流行ってるらしいし、これ採用したらいい感じになるのではみたいな銀の弾丸は無いということですよね。我々は何故Clean Architectureを採用してるのか…。

後述するインゲームのロジック周りの単体テスト書くのに役立ってるとは思うけど、正直テストが書かれてないアウトゲームでこの重厚なアーキテクチャ採用する意味はどれ程あるのか?と最近思いつつある。*1

みたいなもやもやした気持ちを抱えてたところ下記の記事に出会った。

hadashia.hatenablog.com

ゲームでは、部品そのものを自作することが多い関係上、Viewコンポネに対してのデータのマッピングを土台にする MVVM とか React のようなものを爆誕させても、その先のViewへの適用方法を自前で書く必要がでてきたりするのでかなりの手間になる。 また、Viewあたりの部品を自前で書くことに比重がある関係上、ドメインモデルだけの保守性を上げても全体として保守性が上がるかは疑問だし、 レイヤ間の依存関係を完全分離する(絶対に抽象のみにしか依存させない)ことは意義に対しての高い買い物になりがち。

Unityを使っているならUnityEngineに依存した自作コードが8割なので、それを分離したからといってその8割の保守性の高まりは感じないし、 自作の実装依存パーツを大量につくっているなか、さらにそれぞれに全てインターフェイスとかを切っていくのは単に手間である。

依存をどこまで綺麗にするかを完璧にやっても割に合わなすぎるので、もっと軽いノリのバランスに普通はなるであろう。

もやもや抱いていた違和感をズバッと言語化してくれたエントリなので、何遍も読み直した。やっぱ高い買い物してる割に、あまり恩恵得てる気がしないんですよね。

このあたりの違和感をもっと言葉にしていきたい。*2

他気になった記事。

note.com

アーキテクチャの採用について、一番しっくり来た記事。

qiita.com

出島の例えがわかりやすい。

UniRx/UniTask

Rxは様々なレベル、バックグランドを持つエンジニアが多数居るチームでは共通認識を保つ為のコスト高いなと感じる。

パラダイムが手続きな書き方とはかけ離れるので、やはり学習コストは高めになるのかなと。Operatorの種類もわんさか有るし。自分もプロジェクト入ってから暫くRx何も分からん状態になってた。

Rxはイベント処理を記述するのに非常に強力なツールだけど、書き方によっては容易にスパゲティなコードになるので気をつけたい。

幾つもメッセージを合成したり、Operatorが継ぎ足されたりして、一つのストリームの複雑度が限界を超えると、とてもつらい。コンパクトに多彩な表現が出来るので、ついつい詰め込みがちなのかなと。

他には、レビューの際、下記エントリで書かれてることが定期的に指摘されたり。(Subscribe in Subscribeとかもやばい)

developer.aiming-inc.com

async/awaitで書けるところは書き直したほうが見通し良くなるケースもある。Rxで何でも書こうとしない。

UniRx&UniTask とは何なのか#UniTaskを使うべき場合

  • 非同期処理の結果通知が「1回」で済む場合
  • 処理を手続き的に記述したい場合

UniTask v2で追加されたUniTaskAsyncEnumerableも気になる。pull型の非同期ストリームがどうハマるのかまだ理解しきれてないけど、受信側でメッセージをコントロール出来るのは魅力的に映る。

インゲームについて

チームに参加してから暫くはアウトゲーム周りを中心に担当してたが、ひょんなことからインゲーム周りの担当を割り振られることが多くなった。

もともとコアなゲーム部分をもっと実装していきたいなぁという気持ちが強かったので、やりたいことやれてるって感じはあるがまぁこれが難しい。

仕様がジェンガのように積み上げられていくので、何か新しく要素を実装する度に新規要素Aに対してBとCとDはどう反応するのかみたいなものが永遠に増えていく。

長期運営してるゲームとか多分山程こういう問題あるんだろうなぁって。

エンジニアも出来る限り問題を分解してって何とか収めていくが、複雑なものはどう頑張ってもある程度複雑なので…。属人化は避けられず、インゲーム触る班の残業時間がやばい。

どうやって複雑さに対抗するか。後述する単体テストと、ドメインの関心を掘り下げることが大事になってくる。

単体テスト

インゲーム周りでロジック全般に単体テストが整備されていて、お陰でかなり助けられている。(デグレ防止、様々なエッジケースを潰せる、など)

アーキテクチャの恩恵でロジックがドメインに分離されており単体テストが書きやすい環境になっているのも大きい(整えてくださった先輩方に圧倒的感謝…!!)

テストの恩恵を日々感じてると下記スライドの言ってることが染み渡る。

speakerdeck.com

ドメインの関心を掘り下げる

qiita.com

最近見た記事だとこのあたりの話っぽい。

新規実装で設計について考えてるときに、既存コードと対話して落とし所を探る。やりたいことや命名と関心についてひたすら咀嚼して、噛み砕いてから組み立てていく。

ゲームエンジニアやってると、ゲームなんて日々接してるものなので、ドメインの把握が比較的楽なのは良いなあと思う。畑違いのことを設計するとなると結構大変そう。

関心を分離して、正しい命名が出来るってだけでエンジニアとして値千金なのでは無いかと最近思う。最重要スキル。

まとめ

経験を積んだことで、前より正しく技術を見据えれるようになってきたなぁと思う反面、知識のアップデートが疎かになっている気もする。例えば、C#の理解がかなり怪しい。

そして何より怖いのは、 知らない言葉が出てきても何とも思わなくなってしまうことです。 ふつう、 相手の話の中に意味が取りにくい言葉があれば気持ち悪く感じ、 なんとかその気持ち悪さを解消しようと思うものだと思うのですが、 「後で調べればいいや」 と思ってるとだんだんこの 「気持ち悪さ」 が無くなってきます。 この 「不感症」 が最初のステップです。

仙石浩明の日記: 「無知の無知」への 3ステップ

現場の忙しさにかまけて不感症が加速してしまうのが何より怖い。そうなったらエンジニアとして終わりだと思う。

あとは、技術の文脈に対してもっと興味を持っていたいなとも思う。文脈把握してないと足をすくわれることがあるので…。(去年触ったRailsも文脈が大事だった)

来年は、もっと上手く戦えるはず。

*1:追記。インゲーム、アウトゲームと区分してるけどこれはゲームによると思う。クライアントのインゲームに守るべきコアロジックが存在してて、クライアントのアウトゲームにはそこまでコアロジックが乗ってない場合といった前提で話してます。

*2:追記。この項目で少し否定的な書き方したけど、Clean Architectureという考えは尊重したい。コアロジックが有る箇所ならちゃんと外界から守るべきだと思う。教科書的な話に引きづられずに適切な戦略を取りたいといった気持ち。