エンジニアチームのリーダーとして考えてきたこと：運用フェーズチーム編

[前提編](https://qiita.com/tunacook/items/770252ea3c644b6cb2eb)の続きになります


リリースを終えて開発フェーズから運用フェーズとなったチームには、~~(内容の善し悪しにかかわらず)~~開発フローがすでに存在しているものです。

1. お客さんないし運営チームから調査や新規実装・修正の依頼
1. 仕様の策定とすりあわせ
1. 実装開発とユニットテスト
1. 受け入れテスト
1. デプロイ・リリース

ソーシャルゲームならサーバ実装とクライアント実装のつなぎ込みやらなにやらも入ってくるかとは思いますが、大雑把にはこんな感じです。

チームとその状況によって手順が増えたり減ったりしていきますが、基本的に運用フェーズではそのフローに乗っかりながら業務を進めていきます。


# 開発チームにおける状況

私が経験したプロジェクトは前の記事で書いた通りですが、運用における状況はこのようなモノでした。

* 2012年から運用しているサービスと2015年から運用しているサービスとがあり、平行しながらサービスを運用している
* 共通の処理が存在する。それは2012年に作られたもので、レガシーではあるが捨てられない
* インフラはAWS
* バージョン管理はGit、リポジトリはGitlab
* 基本的にGithub Flowで開発が行われ、オンサービスでのデプロイがメイン。ユーザーを追い出したり、ALTER TABLEをかける必要がある場合はメンテナンスを入れる
* 構成としてはよくあるMySQLのMaster-Slave方式、
* メンテナンスの内容や入れる入れないの判断は（受託開発なのに）こちらが判断できる
* QAはテスター氏が行い、テストコードを書く習慣はなかった
* CIも存在しなかった

# 開発フェーズのミッション

運用中のチームについては、 <b>いかに安定稼働させつつ改善をしていくか</b>ということにつきます。

なまじっか稼働できているし一応業務フローもできているので、ルーティン通りやっていれば給料をもらえてしまいます。何もせずに楽して暮らしたい、技術的運用的負債があっても前任者への文句だけ言ってれば良い……そんな考えであれば本来ならなにもしなくて良いでしょう。

ですが私は効率よく仕事したかったので、開発フェーズにおいてカイゼンをしていけるようにしました。

# 運用エビデンスを増やす

## エビデンスとは

~~エビのダンスではない~~

[エビデンス - Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%93%E3%83%87%E3%83%B3%E3%82%B9)

直訳すると「証拠」「証言」となり、IT分野での使われ方は<b>システムの開発分野において、作成したプログラム、サブシステムが想定どおりに動く（動いた）ことを示す証拠や検証結果</b>というもの。

Webサービス運用の場合は

* なぜこのような設計・実装になっているのか 
* 必要とされる手作業運用
* TODO項目

といったものが挙げられます。

定期運用ものはいかに人の記憶に頼らずに漏らさず運用できるようにするか。ドキュメンテーションを進めるなど、一回あたりの対応コストを下げていきます。

具体的には定期的にやってくるイベントの準備方法や、稀によくあるトラブル・お客さんからの問い合わせについて対処法を記事化しておくことなどです。

<b>同様のお問い合わせが今後も来るかもしれない</b>という予想を立てて、その対応や状況を記しておきましょう。

## そもそも人間の記憶力というものを過信してはならない

「去年は確かこうやってたからこれで良い」「似たような問い合わせがあっても覚えているだろうから対応方法を明文化させなくても良い」

もしそんなやり方で運用業務をしているのであれば改めるべきです。

人間の記憶というものをあてにしてはいけないし、ましてそれを元に運用業務をしていくのは危険です。


このような運用や特殊な対応事例について、ひたすらドキュメントを書いていくことがかなり多かったように思います。

* 一通りの定例イベントに対して流すSQLやコード上で対応するべきところ
* 影響範囲の記載
* 対応開始時期
* 質問することが決まっていれば質問すること

を記載していきます。

汎用的な知識ではなく、応用の利かない業務知識（特にそのプロジェクト固有の事象や、特有の現象について）については積極的に記事化していくべきです。

チーム内向け記事を書き進めていくことで、業務知識の偏りや、人間の記憶に頼る運用を防いでいくことができます。また次回対応分以降の運用コストが格段に下がります。
脳死プレイも可能に……

もしどうしてもエビデンスやドキュメントがなく、記憶に頼らざるを得ない場合は、

* 記憶は参考程度にとどめる
* ソースコードを追うなどして裏取りを進めていく

というやり方をするのが良いです。

もし記憶に頼って一時的にその仕事を乗り切ったとしても、同じようなケースに遭遇した際にまた同じことを繰り返してしまう可能性があります。

# 設計の共有

中規模以上の機能実装では、設計段階でissueを発行し共有できるようにしました。

設計段階でチームメンバーにレビューしてもらうことで、実際に手を動かす前に問題点に気づけるようになります。

基本的なユビキタス言語やテーブルのスキーマ設計について、実際に作ってしまう前にレビューを受けてもらうのです。

<b>そんなのコードレビューで指摘してもらえばええやん</b>と考えている方もたまーに見かけますが、案外コードレビューというものはレビュアーの負荷が高いものです。<b>なんでもかんでもお見通しなんて無理！</b>

設計段階でレビューを行うようにし、またそれをコードに落としたものをさらにコードレビューするようにすることで、

* 後から見返した時に設計意図や考え方がわかる
* レビュイーの作ろうとしているものを把握した状態で相談ができる
* 設計の考え方が早い段階で共有される
* もし勘違いや設計ミス、技術検討不足があっても手戻りを少なくできる

という効果が見込めるので有用です。

このときはできなかったのですが、設計時にCRCをするのも良いでしょう。

[CRCカード - Wikipedia](https://ja.wikipedia.org/wiki/CRC%E3%82%AB%E3%83%BC%E3%83%89)

# 業務改善活動

お客さんからの要望や施策上の新規開発だけでなく、負債の返却や開発環境改善と行った業務改善活動も運用フェーズチームには必要になります。

開発時どんなに設計をきちんとしても、技術的負債や運用的負債というものは残っていくものです。それを解消していくのが運用フェーズチームのメンバーに与えられた仕事になります。

## 運用フェーズチームの業務改善あるある

* 安定運用をするため、改善をするにしてもあまり派手なことはできない
* インフラレベルの移行やアーキテクチャの改善などは現実的に難しい
* またお客さんから人月をもらって行う業務なので、開発都合での改善はなかなかおおっぴらに行うのが難しい

人数が多かったり規模が小さければわりとなんとかなってしまう部分も多いですが、(人数)パワープレイで解決　できないとか、現場が人手不足などといった問題はよくあることです。<b>なのでphpのメジャーバージョンアップには結構困りましたが、運良く開発フェーズで対応することができました（開発フェーズについては別の記事に書きます）</b>

もちろん業務改善のための工数や人手があればそれに越したことはないですが、現実と折り合いをつけながら<b>少しずつ</b>進めていくことになります。えいやっとできれば一番良いのですが。


## ユニットテストとCI環境を仕込んでいく

リーダー自らがやってもいいし、人員に余裕があれば業務改善大臣を立てるのも良いでしょう。

このような環境を作っていくことは最初にやればやるほど後が楽になります。

CI環境と言ってもそこまで凝ったものではなくて、

* Jenkins氏にユニットテスト実行ジョブを立てる
* GitlabのMergeRequestがopenされたらジョブを実行するようにする
* ジョブの結果がMergeRequestにコメントされる
* Slackにもそれを通知する

というだけのものでした。本来は静的解析やなんかも必要でしょうが。

しかしこのようなものであってもあるのとないのとでは大違いでしょう。

## テスター氏をエンジニアにする

人手はいくらあっても困ることはないので、テスター氏が工数を食えるよう（エンジニアになれるよう）教育も行っていました。

テスター氏はエンジニア未経験だったので、<b>Gitとは何か</b>の概念から始まり、環境構築についてやプログラミングの概念・[MVC](https://ja.wikipedia.org/wiki/Model_View_Controller)の概念について解説したり、読んでおいてほしい本や記事を伝えていきました。

だいたいこのように未経験者へ教える場合に紹介するものは似通っていて、このようなものが多いです。

### コードを書く

サンプルコードは普段我々が書いているものが大量にあるので、見方を説明するぐらいであとは自力で追ってもらいます。

あとはこれらの本や記事を読んでもらいます。もちろん<b>業務時間中に</b>。勉強するのも仕事のうちです。


**リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)**
https://www.amazon.co.jp/dp/4873115655

**プログラマが知るべき97のこと**
https://www.amazon.co.jp/dp/4873114799

具体的な技術の内容というよりは、考え方とか前提となる発想について、どういう姿勢で臨めば良いのかという意味合いが大きいです。


### MySQL

**PHP+MySQLを使ったスケーラブルなソーシャルゲーム開発**
https://www.slideshare.net/infinite_loop/phpmysql-26254437

**漢(オトコ)のコンピュータ道: MySQLのEXPLAINを徹底解説!!**
http://nippondanji.blogspot.com/2009/03/mysqlexplain.html


### システム監視

監視にはcactiが使われていたのでこれを紹介

**これだけ見れば大丈夫！ーMySQLパフォーマンス監視のツボ（クエリ編）**
https://www.infiniteloop.co.jp/blog/2012/03/mysql-tuning-cacti-query/



## タスクのアサインで心がけたこと

未経験者へは管理画面周りの改修タスクをアサインするのが通例なのですが、

1. 最初に表示のみの画面を作ってもらう
2. 慣れてきたら1の画面で更新ができるような画面を作ってもらう
3. お客さんからの簡単な依頼を担当してもらう（実装内容の相談や対応完了通知等）
4. 期限のあるタスクを担当するようにする
5. コードを書くことに慣れてきたらある程度設計の必要なものを担当してもらう

という課程でアサインをしていきました。

なお、**最初のうちは納期に追われることのないタスクが良い**でしょう。工数のことを意識するのは慣れてきてからで全く問題ないです。

教育と言っても上役のできることはそこまで多くなく、計画的にタスクをアサインしていったり、質問に答えたり、解説をしたり、設計の相談に乗ったりといったことぐらいです。結局は本人のやる気次第なところがあるので、<b>魚（答え）自体を与えるのではなく魚の釣り方（答えの求め方）を教える</b>心持ちが良いです。

運用チームは開発ペースが比較的早くないので、このように長期的なアサインをすることができ、未経験者を育てるのに向いているかもしれません。

テスター氏をエンジニアにすることで、

* チーム全員が実装できるようになったので、QAテストを持ち回りで行うようになった
 * 業務を流動的に行うことができるようになった
* (元)テスター氏の給料を上げることができた
* エンジニアリソースを増やすことができた

という恩恵を得ることができました。


# まとめ：運用フェーズチームでできること

業務改善については、自社サービス開発の場合にできることと受託開発の場合にできることに差があるとは思いますが、望むマインドはあまり変わらないと思います。

また、開発フェーズのチームに比べて「一人あたりのパフォーマンス」を求められることが少なく、未経験者の教育をしやすいのも運用フェーズチームの特徴でしょう。

工数（チームの人数）や座組、状況によってアプローチは変わっていきますが、

* どうサービスを安定させながら通常開発を行っていくか
* 運用のエビデンスを残していくこと
* どう業務改善をしていくか
* どう教育をしていくか

ということをだいたい考えていくのが仕事になるでしょう。

[次回は開発フェーズでの考え方について書いていきたいと思います。](https://qiita.com/tunacook/items/3942dbe55988d9e96412)