seri::diary

プログラミングのこととかポエムとか

リードエンジニアを3ヶ月やって得た開発マネジメントに関する教訓

ここ3ヶ月ぐらい同じRails案件でリードエンジニアとして仕事をしています。 何気にマネジメント的なことをやるのが初めてだったので色々と戸惑うことがありましたが、だいぶ慣れてきて知見が溜まってきたので、自分のしごとの振り返りも兼ねてまとめておきます。

リードエンジニアのお仕事とは

会社やチームによって全くと言っていいぐらい異なると思いますが、私の場合は以下の様なことをしてきました。

開発スタート時

要件確認

  • 仕様書を読んで全体像やどこから着手するかなどを考える

Railsアプリのベース部分の実装

  • rails new
  • DB周りの設定
  • 初期モデルクラスをDB定義に基づいて作成
  • factoryも使いそうなものについてのみ作成
  • rspecrails_config等諸々の設定
  • ローカル環境動作用のseedsを整備
  • 使いたいGemを追加
  • 共通で使うCoffeeScriptのライブラリを思いつく限り実装
  • CoffeeScriptの実装方針が人によってブレるとイヤだったので早い段階でサンプルになるような実装を入れた

情報共有

  • 開発環境構築に必要な情報をgithubwikiやREADME.mdに記載
  • 連携する外部APIなどを事前に検証し、問題がある場合は関係者に確認して解決して対応方法をwikiに記載

開発中

コア機能の実装

  • ひと通りのControllerとviewを実装してひと通り画面が動くように。細かい調整は個別にissue立ててメンバーに割り振り
  • 要件がふわっとしててクライアントに確認が必要な機能や重たい機能の実装

issue量産

  • 各機能ごとに親issueを切り、それに紐づく子issueを作って管理した。

例: 「A機能」が親issueで「Aデータ登録」「Aデータ編集及び削除」「Aデータ一覧」「Aデータ詳細画面」「AデータValidation」が子issueといった具合

その時description内で #100みたいに親issueのIDを参照させておくと、親issueの一覧に子issueのリストが表示される格好になるので進捗管理に便利である。

  • タスクはなるべく親機能ごとに割り振ったがデッドロックになってしまう所もあってやりながら調整した。

他のメンバーのレビュー

  • Railsのレベルはバラバラだったので、Rails経験が浅いメンバーには「何故こうしないといけないのか?」と細かく説明するコメントをつけるよう心がけた
  • 要件自体があまりしっかり決まっていなかったので、かならずローカル環境で動作させて、動作自体に違和感がないかまで含めてチェックした
  • specが落ちていたらまずspecが通るように直してもらってからレビューした
  • Turbolinksの動作原理を理解していないメンバーが数人いたようなので参考資料を読んでもらうよう頼んだりもした

クライアントとのコミュニケーション

  • 要件で不明確な部分の質問
  • 工数的に厳しい場合の代替案の提案
  • 問い合わせ対応

インフラ作業

  • サーバに入れるのが自分だけだったので追加でimageMagickをインストールしないといけないとか、ステージング環境のログを見るとかは全部自分でやっていた

得た教訓

開発方針を統一できるように最初の段階でサンプルになるような完璧な画面を作ってしまうべき

specをどの程度の粒度で書くか、とかConcernに何を載せるか、といった「決め事」が統一出来ずに開発後半では画面によって大分差が出てしまった。

大体のメンバーは自分が実装した所を手本に進めてくれていたが、それも完璧ではなかったので(例えばValidationは後で実装する、とか書いてたらそれまで真似してvalidation処理抜けの画面が量産されて死ねた)、やはり最初に完璧な手本となる画面を実装してしまうべきだった。

特にRailsだと、この機能はControllerにベタ書きか、それともconcernに切り出すか、みたいな判断基準が人によってかなり差がある。

放っておくとfat controllerになったり機能が重複しまくってたりということがいとも簡単に起きて後で泣きを見る羽目になるので、なるべくそういう事故を防ぐためにも最初にサンプルとなる実装をリーダークラスの人間が実装してしまうべきだと考える。

issueを細かく切りすぎず、ある程度大きいまとまりでどばっと渡してしまうべき

これは完全に失敗だったなと思ったのだが、とある機能の画面で以下のようにissueを分けて、それぞれ別の担当者に振ったことがある

  • A入力画面の細々した修正
  • A入力確認画面の細々した修正
  • A入力プレビュー画面の細々した修正
  • A入力最終確認画面の細々した修正
  • A登録画面の細々した修正

そしたら本来共通で実装すべきユーティリティ系のクラスをそれぞれが別々に実装したり、前後の画面で辻褄が合わなくなって自分が全部調整する羽目になったりと、あとで整合性を取るのに凄く労力を要してしまった。

他にあまりタスクが無い時期だったのと、ベースとなる部分は全て自分が実装し終わっていたので大丈夫かと思っていたが、完全に判断ミスだった。

画面の前後でちょっとずつ実装スタイルが違うよりはA機能全体で統一性が取れていた方がレビューもラクだしコードの変な重複が発生する可能性も低い。

実際、開発後半はある程度デカい機能をまるっと投げて、PRのdescriptionでtaskをチェックボックス付きリストにしてもらってそれを一個ずつ消化してもらうスタイルに変えた。上記の例で言えば「A機能の登録・編集・削除全部」みたいな粒度である。そしたら開発効率も品質もかなり上がったように思う。

開発の進め方は最初にきちんとルール化しておくべき

PR駆動の開発の仕方が理解できていないメンバーがいたりして、まぁそんな初歩的なことを教えるのも失礼だし、慣れれば勝手に他の人に合わせてくれるだろと思ったら、数週間経っても全くPRも作らないしcommitも適当だしみたいなスタイルで開発を進め始めたメンバーがいた。

さすがに一人だけ足並みそろえていないのはまずいので、口酸っぱく「作業が終わったらPRを出してください」とか「commitはもっと細かく入れてください」とか「間違ったcommitが入っていないかチェックしてからPRを出してください」とか言い続けて改善してもらったのだが、これが普段の業務において意外なほど大変だった。

少しイライラもしていたのだが、見かねたマネージャーに「長年やってきた人のスタイルはそう簡単に変わりません」と窘められることもあった。確かにその通りだし、自分もたまたまPR駆動で開発するのに慣れているから出来ているだけということもあるだろう。

そんな訳で、今後は開発スタート時にその辺の教育コストを削減できるように、Githubの使い方やらPR駆動のスタイルなどをまとめたドキュメントを作っておいて、それを最初に参照してもらった上でスタートできるようにしようとしている。

具体的には以下のような感じでまとめていく予定である。

丁寧にレビューすれば人は育つ(と思った)ので時間かけてでも丁寧にレビューすべき

何度もレビューの指摘→修正のやり取りをしないといけないケースもあって、そういう時はさすがに「もうめんどいから俺で巻き取るか」といった感情が芽生えてきやすい。この案件もそういう時が何度もあった。

でも、それをやって自分一人で全部巻き取っていたら開発はスケールしないし、費用対効果も悪い。なのでなるべく「一度指摘したことは2回目以降はちゃんとやってもらいたい」と思い、レビュー時に指摘する時も

「これだとXXのケースで動かないので○○としてください」

だけで終わるのではなく、

「これだとXXのケースで動かないので○○としてください。なぜなら△△で□□でほげほげで。。」

みたいな感じで、なるべく理由もセットで指摘するようにした。

そうすれば似たような場面でも応用効かせてくれるかという期待を込めていたのだが、実際一ヶ月も一緒に開発していると段々と効果が現れたのか、同じ指摘は段々と2回しなくても勝手にちゃんとやってくれていたりというケースが増えてきた。

もちろん変わらない人もいたが、一部のメンバーはちゃんと一度指摘したことを守ってくれるようになったので、レビューする側としてはかなり楽になってきた。

ただ、これらの指摘事項は当然自分自身が実践するべきで、多少めんどくさいからと自分が手を抜いていたら「アイツ他人には厳しくて自分は甘えてんじゃん」ということで効果は半減していたように思う。そういうこともあって、なるべく他人に厳しくする分自分のコードにも厳しい目で実装してきたつもりだが、これは自分自身のトレーニングにもなって良かったと思う。

レビューばかりすると自分の担当分が進まない

PRでレビューを依頼されるとすぐに対応して次のタスクを振りたくなるものだが(少なくとも私は)、レビューばかりしていて本業が進まない、という典型的なパターンに自分もハマりかけた。

これに対する解決策としては以下の様なことで対応してきた

  1. すぐにレビューしなくてもやることがすぐ枯渇しないように常に大量にタスクを積んでおく
  2. 本当にすぐ見ないといけないレビューでなければ後に回す
  3. 自分の1日の作業時間においてレビューに割く時間と作業に割く時間を決めておき、それを守る

一番のリスクは「自分がレビューしないことでそのメンバーのタスクが進まない」というロック状態を作り出してしまうことだが、それを回避する方法としては1が意外と有効だった。

レビューする時間を短縮するというのは品質に関わるので避けた方がよく、どちらかと言えば期限を決めてタスクをどかどかと積んで「上から順番にやっていって~」という風に任せてしまった方がラクだと感じた。

この方法を行うリスクとしては、知らないうちに進捗が悪くなっているとか、間違った設計で実装を進めてしまっているということがあるが、なるべくはやくWIP PRを出してもらうことで大体解決していた。