こんにちは! 季節が秋に突入し、次第にスノボ欲が高まってきた吉次です。
前回は勤怠連絡の出欠確認を自動化するという題材で記事を書かせていただきました。今回はもう少し開発の話題に寄せ、チームの開発ルールができるまでの話をしたいと思います。
はじめに
みなさんは、「開発ルール」と聞いて何を思い浮かべますか?
一口に開発ルールといっても、コーディング規約、Gitのブランチングルール、命名規則、開発におけるマインド、社内のローカルルールなどなど、枚挙にいとまがありません。今回の記事ではソース管理、タスク管理、リリースの3つに着目し、どのようにして開発ルールの効率化を図ったかを振り返ります。
ぐるなびにおけるソース管理の遍歴
Gitによるソース管理
ぐるなびにおけるGitの歴史はさほど長くありません。下記はぐるなびソースコード管理の略歴です。
時期 | ツール | 問題点など |
---|---|---|
~2012年7月 | SVN or 管理なし | 複数人での開発や、並行開発時にマージが大変 |
2012年8月~2015年6月 | RhodeCode/Backlog | 協力会社とのリポジトリの共有ができない/やりづらい コードレビューの履歴が残らない 誰が承認したのか明確でない |
2015年6月~ | GitLab | ??? |
私の配属当初(2014年7月)は、リポジトリで管理されていないソースが散見。一部でSVN(Apache Subversion)やGitを利用してはいました。しかし、ソースコード管理の文化が成熟しておらず、使い方も明確に定まっていませんでした。
そんな状況下で立ち上がったのは、開発統括グループという部署です。現在も開発環境改善・品質向上のための取り組みは継続的になされています。GitLabの導入はその取り組みのうちの1つです。
Jenkinsによるデプロイ環境
GitLabが導入されてからほどなくして、デプロイ環境を改善するためにデプロイ用のJenkinsが導入されました。
Jenkinsが導入されるまでの本番リリース作業は下記の手順。
- リリース対象ファイルをまとめる
- ファイルアップロード用サーバの特定のディレクトリに配置
- サーバに入り「リリース準備シェル」を実行して差分等を確認(リリース前日に済ませる)
- サーバに入り「リリースシェル」を実行
リリースに使用する2種類のシェルはバックアップの作成やファイルの配置、切り戻し用のシェル生成などが自動化されていました。しかしながら、2の準備作業は手作業で行うために作業漏れのリスクがあり、ダブルチェックに大きなコストがかかります。そして何より、サーバにログインしてコマンドを叩くことによる精神的負担は大きなものになっていました。
デプロイ用のJenkins導入後は、ボタン1つでデプロイできるようになりました。リリース作業の大部分が自動化されたことによって、準備を含むリリース作業が効率化。精神的な負担も軽減されました。
タスク管理/ソース管理・コードレビュー/リリースの具体的な施策
晴れてGitLabとJenkinsが導入され、ソース管理とデプロイが快適に行える環境を手に入れました。しかしながら、良いツールが「存在するだけ」では何の意味もありません。エンジニアたるもの、ツールを使いこなして現場に最適化するのは至上命題だと思います。
私は、これらのツールを使いチームにとって最適な開発ルールを策定するというミッションを掲げ、業務改善の一環として取り組みました。
開発ルール策定において考えたこと
良い道具が与えられ、いよいよルールを定めていくフェーズに入りました。しかし、闇雲に進んでも良い結果は得られません。立ち止まって落ち着きましょう。何事も始まりが肝心です。
まずは、どのような状態を実現したいのかを考えてみました。
- ソース管理がきっちりできること
- タスク管理が適切に行え、開発がスムーズに進むこと
- 意義がありかつ効率的なコードレビューができること
- システマチックであること
- リリース作業がシンプルであること
開発における三角関係
ひとまず要件が決まりました。つぎに、実現したいことを並べたところ「開発における三角関係」があると気づきました。
登場人物は下記の3人です。
- タスク管理
- ソース管理・コードレビュー
- リリース
これら3人は実はべったりと癒着しています。誰か1人がサボるとあとの2人の足を引っ張ることになります。目的は単にタスク管理を効率化させたり、ソース管理やコードレビューを実践したり、簡単にリリースすることではありません。
真の目的は「開発プロセス全体」を最適化することです。GitLabやJenkinsのような新しく導入されたツールは、個別に見るとたしかに優秀といえます。ですが、それがあれば開発が上手くいくのかという問いに対する答えはずばり「NO」。私たちエンジニアは、よくできた歯車の1つ1つを上手く噛み合わせてチームの成果を最大化しなければなりません。
(暫定的)最適解を導くための3つの手法
上記を踏まえて、開発ルールを策定していくことに。策定するにあたっては「思考するための基準」があります。最初から狙っていたわけではなく、後から冷静に振り返ってわかったことですが、この場を借りてシェアしたいと思います。
- リリースから考える
- 品質とタスク管理から考える
- 効率から考える
それぞれの観点について説明していきます。
1. リリースから考える
「開発プロセス全体の最適化」と豪語していましたが、やはりものには優先順位があります。3人のうち最も責任があるのはリリース。リリース作業で事故を起こさないことが何より重要だと思います。事故を予防するためには、JenkinsのJOBの設定がシンプルであることは大前提となります。そのために必要なのは適切な単位にリポジトリを分割し管理してやることです。
■GitLab移行前の問題点
GitLabに移行する前には、下記のような問題がありました。
- コンテンツごとに1つのリポジトリとして、バッチやWebのソース、さらにはドキュメントが1つのリポジトリに混在していた
- 結果的にコミット履歴が見づらくなってしまっていた
■解決のためのアプローチ
この問題を解決するために、リポジトリはコンテンツ×同系統のサーバ群単位で分割してソースだけ入れるようにしました。
例えば、同じコンテンツでもバッチとWebがあり、Webサーバはxとyの2系統ある場合、下記3つのリポジトリに分割します。JenkinsのJOBは、リポジトリに1対1で紐づく形で別々に作ってやればOKです。
- バッチ用のリポジトリ - バッチ用のデプロイJOB
- Web(x系統)のリポジトリ - Web(x系統)用のデプロイJOB
- Web(y系統)のリポジトリ - Web(y系統)用のデプロイJOB
2. 品質とタスク管理から考える
■GitLab移行前の問題点
品質とタスク管理の面から考えると、GitLab移行前には、以下の問題がありました。
- 変更したソースファイルを表にして、Gitの差分ベースで1つずつ確認してコメント
- 行に対してコメントできない
- 見にくい(スプレッドシートとソースを行き来して疲れる)
- 一度に見る量が多すぎてレビュアーの心が折れる
■解決のためのアプローチ
この問題を解決したのが、GitLabのマージリクエストという機能でした。GUI(Graphical User Interface)で差分を確認し、行単位で指摘をしたり議論を展開できます。
コードレビューはGitLabの機能を利用しました。
タスク管理とリンクするブランチモデルを使ってコードレビューの単位を最適化する
私のチームで運用しているブランチ戦略を階層構造で表したのが上記の図です。開発案件ごとにgit-flowに近いモデルを作るので、私は「n-git-flow」と呼んでいます。
詳細を説明すると長くなってしまうので、紹介するのは要点のみです。 ポイントは下記の通り。
- 開発案件ごとに階層(案件用の親階層)を分割
- 案件用の親階層下にgit-flowでいうところの「develop」ブランチと「feature」階層を作成
- feature階層下のブランチで機能を実装し、案件階層下のdevelopブランチをターゲットとしてマージリクエストを発行
- 全てのマージリクエストが完了し、リリース準備に移る段階で、トップレベルのdevelopブランチにマージ
また、このブランチモデルはチケットによるタスク管理体系ときれいに対応します。
ブランチ | チケット |
---|---|
project-A/develop | 開発案件Aに関するタスクの親チケット |
project-A/feature/配下 | 開発案件Aで実装する各機能単位のチケット |
このブランチモデルとタスク管理によって、マージリクエストの単位が明確化。また、1コンテンツについて複数の開発案件が同時に走る場合でも、案件ごとにブランチが分離されているのでやりやすくなりました。プログラムでいう名前空間のようなイメージです。
コードレビューのガイドラインを作成
繰り返しになりますが、道具はただ使うだけではあまり意味がありません。コードレビューの位置付けを「チームビルディングの一要素であり、良いコードを生み出すチームの文化を作るためのツール」とし、議論・学習・実践のサイクルを回すためのガイドラインを作成。チームに展開しました。
こちらも細かいところまで説明すると長くなってしまうので割愛しますが、これらについてまとめたものが下記となります。
- コードレビューの目的
- コードレビューの方法(いつやるか?だれがやるか?)
- レビュイーの心構え
- レビュアーの心構え
3. 効率から考える
ここまでで説明した2つの観点によるアプローチで枠組みが整いました。あとはいかに無駄を省いて機械的に運用できるようにするかが大切になってきます。
主にGitの運用についてになりますが、命名規則を定めました。
ありそうな失敗談……「どっちでもいい」「なんでもいい」ことに頭を悩ませてしまう
- featureブランチの名前は、機能を表したいがセンスがない/意味が良くわからない名前になってしまう
- タグ名はリリースを表す名前にしたいが、センスがない/意味が良くわからない名前になってしまう
解決のためのアプローチ……システマチックな命名規則をルール化
命名について、悩んだわりに良いものが出てこないのはよくある話です。「どっちでもいい」、「なんでもいい」ことは考えないでも決まるようにしました。
- ブランチ名はチケットのキー名をそのまま使う
- リリースタグは日付にする
featureブランチはチケットのキー名に対応しているため、機能に関する議論や経緯などをすぐに参照できます。
リリースタグはJenkinsによるデプロイ時に画面から指定されるものですが、昇順ソートとしています。新しいものが常に選択肢の先頭にくるようにしておけば、すぐに目的のタグを見つけることができます。オペレーション面にも有用な規則ではないでしょうか。
まとめ
いかがでしたでしょうか。開発のやり方はチームの体制や担当コンテンツの数・特性などによっても大きく左右されます。正解もありません。
さらにいえば、今の私のチームにおいてもこれが100%良いものであると言い切ることはできません。ただ、軸となる考え方自体の応用範囲は広いのではないかと考えています。タスク管理・ソース管理・リリース。三位一体で効率の良い開発を実現させましょう!
お知らせ
ぐるなびでは一緒に働く仲間を募集しています。