POLICY技術指針
序文
この文章は、セプテーニ・オリジナルに所属する企画者・エンジニアの指針となるよう、2016年5月当時の我々の目指すところ/我々が取っている行動の理由/我々が求める姿勢、を文章化したものです。
我々は”高速高品質”を目指す
システム開発は機を逸さないために開発速度が重要です。かといって品質を顧みなさすぎても不幸を生み出します。我々は高速に高品質なシステムを開発できる状態を目指します。
初回リリース最速を目指すことは意味しません。初期に作成する部分は最も下地となる部分であり、土台です。土台が腐ると、その上位レイヤーも腐ります。取り返しも付かないことが多いので丁寧に作成しましょう。
我々は保守性のあるコードを高速に生産する
“品質”と一口に言っても国際規格が存在するくらい複雑ですが、我々は品質の中でも”保守性”を重要視します。
保守性の低いコードを保守しようとすると、開発者の肉体や精神の不健康を招き、酷くなると休職・離職に繋がります。ビジネス面においてもフットワークは悪くなり、徐々に貢献できなくなってくるどころか、障害による損失・運用でカバーの多発によりマイナス影響を与えることも起こりえます。
低い保守性のコードは追記された部分も悪くなりがちなうえ、前例に従うつもりでコピペされることも多いので、いつの間にか増殖します。後から改善することも困難です。早めに対応しましょう。
採用活動にも影響があります。良いコードを書いていればPRになりますが、悪いコードが蔓延していると好んで劣悪な環境に入りたがる人は居ないため、人材の確保が難しくなります。
いずれも会社の存続にも影響する問題であることから、我々はまずは保守性があり、それを保てるコードを高速に生産できる状態を目指します。
具体的に何をするのか
高速高品質を目指すため、効率が良い道具とプロセスを選び、良い状態を作れるよう努力をして、良い状態を作り、それを保ちます。
Scalaを使う理由は気軽に品質を維持するため
我々はScalaを積極的に使用します。
Scalaは表現力に富み、手慣れた状態であれば労力少なく意図する機構を記述することができます。また型がありIDEも発展していることから、リファクタリングを行いやすく品質維持の労力が少ない言語です。
学習コストは小さくありませんが、何ヶ月もかかるものではありません。Javaの資産を活かせる点も実用的です。現時点では意識の高い人材との出会いを増やす効能もあります。
Scalaを利用しない場合
バッチなど、小さなプログラム、もしくは完全な使い捨てなプログラムを作成する場合、Scalaは利用しません。BashなりPythonなりPHPなり、状況に応じて使いやすい物を利用します。
またユーザーに配布する必要がある、といった事情でフットプリントを大きく出来ない場合も利用しません。GoやC#、Excel VBAなどユーザー利便性と開発効率・保守性を天秤にかけて利用言語を選定します。
iOS開発や古いシステムの保守、目的とする環境でScalaが利用できない場合も他の言語を利用します。ただし、目的のライブラリが特定言語の物しかない、といった場合であればマイクロサービス化して分離を試みる、ラッパーを開発する、といった手法を検討する余地があります。
マイクロサービスを導入する場合、試行のしやすさを目的にレンダリング部分だけPHPに担当させるといったことも選択に入ります。
学習コストや人材調達の都合を言い訳にして、普及した言語を選択することは行いません。
なお目的を鑑み、より優れた言語が登場した場合は、それに乗り換えることが推奨されます。
スクラムを採用する理由はプロダクトオーナーがハンドルを握るため
我々はスクラムを積極的に採用します。
開発においてリソースが潤沢であることは希で、殆どの場合、限られたリソースの振り分け判断が重要となります。
スクラムはバックログを通してプロダクトオーナーの意図を表せますし、スプリントとストーリーポイントにより、コストも根拠を持って可視化することができ判断に活かせます。
これ以外にも、顧客意見反映を手続き化・迅速化できる/進捗確認や異常の検出できるタイミングが多い/ベロシティにより完成予想に根拠を持たせられる、といったメリットがあります。
スクラム以外を使う場合
不具合や割り込みが多すぎる場合、スプリントが成り立たないためカンバンを利用します。プロダクトが大きい場合は保守チーム・開発チームといったようにチーム別けをして制度を変える手法も検討できます。
削りようが無い最小要件の物を最速で作るといったように、プロダクトオーナーの意図を入れようが無い場合も、検討会・反省会の時間が無駄であるためカンバンを利用します。この場合、事態が落ち着き次第、速やかにスクラムに移行することが推奨されます。
開発チームの外に予定を説明する場合はガントチャートが便利です。内部管理には利用すべきではありません。目安以上の精度は出しづらく、スケジュールに合わせて実装を曲げる事態を招きます。
DDDを採用するのはチーム全員で要件の芯を捉え続けるため
我々はドメイン駆動設計を積極的に採用します。
ドメイン駆動設計は言葉と実装を一致させることを目指す設計手法です。「エンジニア以外にも翻訳不要で伝えることができる」「設計と実装に対する価値観が共有できる」という特徴があり、チーム全員で要件の芯を捉える助けになることを期待しています。
具体的には、やらねばならないことのコストをプロダクトオーナーが認識しやすくなる/レビューや仕様検討時に、言葉と実装が一致しているか、というチェックを行えるようになる/設計や概念がまずい場合、言葉にすると自然と大仰に成り危険な感じになる、といった効能を期待しています。
なお、”レイヤードアーキテクチャを採用する”ではないため、上記効能を維持出来るアーキテクチャであればどの手法でも構いません。
DDDを採用しない場合・崩す場合
小さなプログラム、もしくは完全な使い捨てのプログラムの場合、DDDは採用しません。
マイクロサービスにおいては、特定サービスの内部だけ採用しない、といった選択もあり得ます。
既存コードへの改修や、フレームワークなど開発環境の仕様が特殊である、など導入に無理が出過ぎる場合も採用しないか、崩すことを検討します。
プロトタイプ作成時にも採用しません。プロトタイプは全てを割り切って高速に具現化することに価値があり、丁寧に設計することは目的と反します。調査が終わったら本番コードに流用せず、必ず破棄してください。
なお、この文章でのプロトタイプとは中身は仮実装だが発注者が実装するものの具体的イメージを掴む助けになり、使い勝手も検証できる程度のもの、を差します。
ユニットテストを書く理由はリファクタリングをし続けるため
我々はユニットテストを書きます。
改修を続けるシステムにおいて、仕様変更に伴い既存コードがベストな設計で無くなる場面が発生します。この際、保守性を維持するためには既存コードも理想と思える設計に書き換える—リファクタリングをする必要が有ります。
テストがあれば”書き換えたが動かしたことが無い”領域が減り、安心度が高まります。テストが無い場合、只の作り直しであるためリスクが大きく既存コードの改修は憚られる場合が発生します。これが積み重なると設計の歪みが大きくなり、保守性の大幅な低下を招きます。
またユニットテストは頻繁に動作確認ができる作業台としての役割も期待します。E2EテストやF5(再読込)駆動開発では全てを結合しなければ動作確認ができませんし、場合分けをカバーしきるのは難しいですが、ユニットテストであればメソッド単位で確認を行うことができます。細かな場合分けにも対応できます。
我々はTDDを標準とはしませんが、その心は参考にし、ある程度小さいまとまりでテストを動かしましょう。テストを書くことで自分の書いたコードの最初の利用者が自分となりましょう。使い勝手の改善や、不具合検出の助けとなります。
テストを書く=遅い、という思い込みを止めよう
テストもコードを書く以上、時間を消費するのは確かですが、作業台として活用をすれば確認効率も高まるので、慣れ次第ではF5駆動開発より素早く開発できるかもしれません。
仕様変更を行ったときの確認項目の削減効果も大きいので、長期的に見て速度を落とさないための手段、と考えても良いでしょう。
カバレッジ100%を目指す、といったテストを書きすぎる方向に陥ると本当に遅くなるので注意しましょう。テストの密度や品質は保守性の維持を念頭に置きつつ、適度に省きましょう。他のテストにより安心できる部分は省くことが推奨されます。テストはよりカバー率の高くなる下位層の方—レイヤードアーキテクチャであればDomain層/Infra層、の方を充実させましょう。
テストを書かない場合
バッチなど小さなプログラム、もしくは完全に使い捨てであることが確定しているプログラム、にはテストを書かなくても十分な場合が多いでしょう。
またプロトタイプに対しても前述の理由でテストは書くべきではありません。
レビューを行うのは意識を保ち続けるため
我々はコードレビューを行います。
一人で綺麗な設計・コードを書き続けるのは難しく、他人の目と意見があってこそ行うことが出来ます。鉄の自制心を持ったメンバーでチームを固めているわけでもなければ、レビュー無しに品質を保ち続けるのは困難でしょう。
レビューを行い続けるため、属人性を高めない
一人開発、もしくはサーバをいじれる人一人・クライアントをいじれる人一人、というようにスキルセットで担当分けをすると相互にレビューをすることが難しくなります。このような属人性を高める体制は避けるべきです。
可能であればサーバ側2名・クライアント2名、もしくはサーバとクライアントを両方扱える者1名を混ぜる体制にしてレビュー品質の確保を組織レベルで心がけましょう。
それでも1名〜2名で始めざるを得ない場合は発生しますが、この状態を長引かせると属人性が高まりすぎてしまい、健全なレビュー体制に戻せなくなります。早めにタスクローテーションを行う、もしくは二人でサーバを作ってから二人でクライアントを作成する、等の工夫で属人性が高まらないよう注意をしましょう。
レビューを行わない場合
よほどの緊急事態でなければ、レビューを行わない理由はありません。
そもそも一人開発である、専門性が高く自分しか見ることが出来ない、等の問題でレビューを行えない場合は有ります。これは組織の問題なので、組織(あるいはチーム)で解決を図ることになります。具体的には単独開発にならないアサインをする・専門家を育てる、といった策になります。
プロダクトオーナーに求めることは采配
プロダクトオーナーには市場で生き残れる製品を作る責任がありますし、チームが生存できる衛生を保つ義務があります。
バックログ=限られたリソースの振り分け、を通して義務の全うを目指すことになりますが、ステークホルダーに引っ張られ、チームが破綻する状況を招いてはいけませんし、チームを大事にしすぎてステークホルダーが満足しない状況を招いてもいけません。
限られたリソースの中で膨大なストーリーをこなすことになります。それぞれのストーリーの目的を把握し、優先度を割り出し取捨選択し、自信と根拠のある選択をチームに示す姿勢が求められます。
とくに技術的負債が残る不完全な工法を選択する、といった危険な選択を行う場合、それを本当に行うべき状況なのかの確認、関係者全員へのリスクの共有と覚悟の取りつけ、残る影響の解消計画の立案、などの行動が求められます。
衛生を保つため、開発メンバーから上がってくる技術的負債の返済やライブラリバージョンアップ等のストーリーも状況を鑑み適切にバックログに盛り込む必要があります。
ステークホルダーから受注をする、というスタイルの場合、ステークホルダーが何をやりたいのかを具体的に想像できているとは限りません。話を分析し、より効率的なストーリーを編み出す手腕も求められます。
スクラムマスターに求める事は円滑
スクラムマスターとはスクラムを円滑に回すための様々な事を行う役割です。
具体的には、各種会議の司会を行う/進捗が不穏であればヘルプを行ったり都合したりする/チームが緩んでいれば発破を掛ける/プロダクトオーナーを教育する/実装時間をより確保できるよう工夫をする/検討会・反省会が長くなりすぎないよう注意する/会議が増えすぎないよう注意する/属人性が高まらないアサインを考える/技術的負債を解消するストーリーの提案/組織的問題があれば上長と相談する、などの行動が求められます。
プロダクトオーナーとは利益が相反するため、兼任はできません。
メンバーに求めることはチームでの達成
スクラムに参加するエンジニアには、チームで達成できるように振る舞うことが求められます。チームがスプリントを達成できるよう自分の分を頑張る(ただし抱えすぎ厳禁)のは当然として、チームを助ける・頼る視点が重要です。
スクラムでは自己組織化を目指します。スクラムルールの原点である"スクラムガイド"では"自己組織化チームは作業を成し遂げるための最善の策を,チーム外部からの指示ではなく,自らが選択する"と記述されています。
チームで進捗の厳しい仲間が居た場合、アドバイス等を行うほか、落ちそうなストーリーがチームにとって重要であれば、自分の分を落としてでも巻き取りに行くことがより良い結果に繋がります。逆に自分の頑張りが及ばす、達成できなさそうであれば早めにチームに助けを求めることがより良い結果に繋がります。
おわりに
この文章に記載されている具体的技術(言語・設計手法等)はすぐに陳腐化すると予想されるため、拘り続ける意味はありません。しかし、この文章に記載されている考え方は時間が経っても大きくは変わらないと思われます。常に心に留め、研鑽を積みましょう。