流れで、いよいよオブジェクト指向に対する懐疑心が無視できないレベルに達した2017年冬。Documentationhttp://www.infoq.com/articles/practices-lean-documentationドキュメンテーションをうまく機能させるのは本当に難しい。チームの開発は、同じフロアにいるマーケティングチームからの要求に従って行われている。ミーティングなどで要件のヒアリングを行い、それを簡単なタスクの箇条書きに落とし込む。PDCAサイクルを一週間(場合によっては二週間)ごとに行うイテレーション開発を採用しているので、全ての要件を一度に明らかにせず、次のイテレーションのタスクが埋まる程度にヒアリングを行う。ミーティングではイテレーションの成果を踏まえて次の要件やタスクを考えるので、想定外の事象が発生しても早い段階で軌道修正を行える(ここに落とし穴があったのだが、これはまた後日)。いわゆるアジャイル的な開発である。進捗は可視化されていて、軌道修正もしやすく、見当違いなものを作ってしまうリスクも抑えられるので、なかなか効果的な開発方法に思えるが一つ大きな問題があった。それは、きちんとしたドキュメントを残すタイミングがなく、ほとんど全てが現物主義になってしまうことだ。そもそもアジャイルという手法に現物主義の傾向があるとも言える。動くソフトウェアとクリーンなコードが何よりも現状を雄弁に語るという考え方だ。それはある程度小規模な開発であれば当てはまるかもしれないが、一年以上に渡って開発し続ける複雑なシステムではなかなか難しい状況になる。動くソフトウェアがあったとしても全貌を把握することは難しくなるし、全てのコードをクリーンに保つことも現実的には難しい。ある日、こういうことがあった。開発がスタートしてから一年半が経過し、システムの機能も大分増えてきた頃だ。ような仕様だったと思うんですけど。開発者「え、そうでしたっけ。聞いたように記憶してるんですが。」マーケティング担当者「うーん、それは困るな。お客さんになんと説明すればよいのか。」もの凄くありがちな光景である。イテレーションごとに現物を確認していても、同じ機能を何度も修正している間に、マーケティング担当者の想定と現物がズレてきてしまったのだ。その後もシステムはどんどん複雑化することが予想されたので、たまチームとしても何か対策を打たざるを得なくなった。仕様書を書こうということになったのだが、常に変化し続けるシステムの仕様書を維持管理することの難しさは重々承知している。そこで、どのようにドキュメントを管理したよいかを入念に検討して以下の指針を作った。Documentation」に書かれている指針と大体同じである。Documentationで紹介されている「良いドキュメンテーションのためのルール」は以下の通り:素早く書けて更新出来るようにする。現状を反映してない情報は、まったく情報が存在しないことより有害である。簡単に正しい回答を得られること。必要な情報が見つけづらければ誰もそれを利用しなくなる。ドキュメンテーションが対話を置き換えるわけではない。変更容易性はかなり重要な要件で、これを考えるとWordやExcelなどで仕様書を管理することの問題がよく分かると思う。プロジェクトメンバー全員で情報を共有しつつ、かつ変更も容易に行えるとなると、データベース的な仕組みがどうしても必要になる。昨今の開発プロジェクトだとWikiで仕様を管理することも多いのではないかと思う。Wikiでも、まだ変更容易性に若干の不満があり、ステータス管理やフィードバックなどの扱いに難がある。Issues)を試してみることにした。仕様を独立した小さな単位に分割してチケットとして管理すれば、その単位でステータスを管理したり、フィードバックをチケットのコメントとして行えるようになる。変更についても、そのチケット自体を修正したり、破棄したり、また新しく作ったりと、より柔軟に行える。どのような機能が修正されたかも把握しやすい。Earth(グーグルアースのように構造化せよ)」というプラクティスが紹介されている。全体像から詳細に向かって徐々にズームインしていく仕組みがあれば、情報が格段に見つけやすくなるというわけだ。チームでは、細かい単位であるチケットだけだと全体像が見えないので、Wikiページに概要とチケットへのインデックスを作った。数ヶ月後、苦労して作ったドキュメントは誰にも読まれなくなっていた。読まれないので更新もされない。ドキュメントは徐々に現実からズレていく。ドキュメントの利用者とその目的を特定せよ」)?マーケティング担当者曰く「GitHubを見ることが習慣化していないというのと、同じフロアにいるので、つい直接尋ねてしまう。」ドキュメンテーションを成功させるために、最も重要でかつ最低限必要なことは「(継続的に)読まれること」である。このことは文書そのものをどう書くかということよりも遥かに重要である。文書が適切に書かれるから読まれるのではなくて、読まれるから適切な形に変わっていく。読まれなければその文書は死んだも同然である。ドキュメンテーションというのは固定化されたものではない。コミュニケーションの記録である。口頭の対話は記録されないが、ドキュメンテーションという対話は記録され、かつ構造化される。効率は落ちるが、その記録が残ることの価値はかなり大きい。ここで重要なのは、「読まれること」は「読ませること」ではないということだ。「GitHubを見ることが習慣化していない」という人に対して「じゃあ、習慣化して下さい」と言うのは間違っている。ドキュメンテーションを行うものは、その文書を読んでもらうためのあらゆる努力をしなければならない。それには、Web上にブログを開設して読者を集めることと同様の難しさがある。Example」も、手法としては素晴らしいと思う。Criteria)も分かりやすく書きやすい。実際に、たまチームの一つのプロジェクトでは英語話者と日本語話者が効率的にコミュニケーションするためにこのフォーマットを採用している。これでも「読まれること」とは、全く別次元の話なのだ。ビジネスパーソンとエンジニアは、そもそも異なる言語で会話をしている。アジャイルコミュニティではドキュメントの限界を理解しつつも、テストプログラムに通じる形式的な文書を、いかにビジネスパーソンに読ませる(書かせる)かということに苦心してきた。代表されるように、うまく行っているとは言えないように見える。ビジネスパーソンとエンジニア、両者の想定があまりに違うのである。書いたものを読んでもらうというのは、人を動かすということである。内容が正しくとも、ストーリーなき文章を長々と読めるわけがないというわけだ。アジャイル開発で要件の単位となる「ユーザーストーリー」は、形式的表現に慣れているエンジニアからビジネスパーソンに歩み寄った結果として生み出されたものだ。ドキュメンテーションとはコミュニケーションであり、その質にはコミュニケーション能力がそのまま反映される。プログラミングそのものよりも難しいと言っても過言ではないように思える。現場のエンジニアがMicroservicesアーキテクチャを評価するときは、どうしてもその実用性や現実性、例えばプロセス間通信の多用によるオーバーヘッドなどが問題にされがちである。そのコンセプトをつぶさに見ていくと、これは単にアーキテクチャだけの問題ではなく、ソフトウェア開発はどうあるべきかという、ある種の思想を提示していることに気がつく。開発の現場には「エンジニアとは外から持ち込まれた問題に解を与える者だ」という強い思い込みがあることが多い。これはプログラミングに対する誤解を含んでいるだけでなく、一つのシステムを長く育てるというケースにおいては、持続可能なモデルではない。Methodology」の中で「ソフトウエア開発は、全てが「デザイン」である」と指摘したのはもう大分昔のことだが、この考え方が開発の現場においてどれだけ浸透しているだろうか。ソフトウエア開発は、本質的に、問題に対する解法の実装だけでなく、問題自体の検証と再設定を含むサイクルを繰り返す作業で、プログラミングというのはそのための強力な武器である。設定された問題を解決するためだけにプログラミングが存在し、そしてその問題設定を開発から切り離せると考えるのは、ソフトウエア開発に対する大きな誤解である。Microservicesで提案されているのは、一つのサービスだけでなく、それを開発する開発者(あるいはチーム)も、できるだけ完結した存在になることが望ましいということである。チームが自律的に連携して、全体として大きなシステムを実現するという、オブジェクト指向が理想としていたようなモデルである。理想主義的になり過ぎるのも良くないが、このような考え方のルーツの一つにオブジェクト指向があり、それが考え方としてはデザインパターンやアジャイル開発などにつながり、プロダクトとしてはインターネットやiPhoneなどにつながっていることを考えると、実用性や現実性はともかく、その思想の重要性に注目しておく必要はあるだろう。水平型から垂直型へたまチームで管理しているGitHubリポジトリの数もどんどん増えてきて、今ではデプロイ可能なサービスだけでも20個ぐらい、リポジトリの総数は30を超えた。管理は、これまで一人のインフラ担当者が頑張って面倒を見てきた。このままサービスの数が増えていくと、インフラ部分がボトルネックになって効率が大きく損なわれることが目に見えている。管理方法を変えよう、というのが前回の話であった。この方針変更をたまチームでは「水平型から垂直型への移行」と呼んでいる。まで面倒を見なければならなかった。これを垂直型に移行すると以下のようになる。アウトプットするようにビルドプロセスを変更する。インフラの共通部分は最小限に抑えて、チームメンバー全員で共同管理出来るようにする。水平型も垂直型も、それぞれ一長一短でありトレードオフがある。インフラの共通部分を厚くすれば、同じような構成のサーバーを一括で変更したり、多くのProvisioningコードを再利用出来る一方、共通部分と各アプリケーション開発者間で生じるコミュニケーションコストは馬鹿にならない。高度に訓練されたチームであれば、メンバーの誰もが共通部分(インフラ)とアプリケーションを行ったり来たりしながら自在に開発出来るのかもしれない。残念ながら我々たまチームはそこまでのレベルには達していないので、共通管理する部分を出来るだけ薄くして、後はアプリケーション開発者の裁量に任せてみることにした。この考え方はソフトウェアのモジュール(あるいはオブジェクト)の考え方に似ている。モジュールは外部との責任を明確にする一方、内部構造については隠蔽しておくのが望ましいとされる(責任を果たす限り内部の詳細を問題にしない)。これはモジュール間のコミュニケーションコストを最小限にして、大量のモジュールが柔軟に連携出来るようにするための考え方であり、これをそのままサービス開発に応用するとすれば、アプリケーション開発者は、そのアプリケーションが外部に果たす役割を明確にする限り、他の開発者はその内部のことを(とりあえずは)気にしなくて済む。サービスの数が増えていくのと同時に、技術の進歩に伴って、サービスの粒度が小さくなってきている。Microservice化すると、一つのリポジトリを複数の人間が管理するよりも、一人の人間が複数のリポジトリを管理するケースの方が増えてくる。その意味でも、コミュニケーションコストを抑える方法を考えておかなければならない。個々のサービス開発者に課せられる責任は、オープンソースプロジェクトの開発に要求されることに似ている。そのプロジェクトを誰かに使って欲しければ、それが外部に提供する価値について、そしてその利用方法について、第三者が分かる形で説明する必要がある。ここで何を説明するべきかという最小限のラインを考えることが垂直型の勘所ではないかと思う。中で言及しているように、コンウェイの法則によれば、ある組織が開発するソフトウェアのアーキテクチャはその組織の構造をそっくりそのまま反映した形になる。垂直統合チーム型組織になる。述べたように、いずれも一長一短があるため、どちらが良いとは一概には言えない。チームではたまチーム独自の事情があって、今回は垂直型への移行を試みることになった。この移行によって開発のやり方やアウトプットがどう変わったかはこのブログで逐一レポートする予定である。最後に一つだけ垂直型への期待を述べるとすれば、現代は専門領域の境界がめまぐるしく変化する時代である。一つの専門領域に留まっていたら、あっという間に時代遅れになることも珍しく無い。能力が求められるのではないだろうか。Infrastructureを導入する現在たまチームでは、以下のような自動化を実現している。S3上へのパッケージのリリースから、アプリケーションサーバー上へのデプロイまで自動で行われる。この環境でかれこれ二年ぐらい運用してきたが、自動デプロイは便利だと思いつつ、いくつかの問題点が明らかになってきた。デプロイの際に更新されるのはアプリケーションだけなので、サーバー上のミドルウェアの更新をいつやるか、どうやって安全にやるかを考えるのはなかなか悩ましかった。Chefを経由するより、まずはサーバーを直接直してしまおうという誘惑が常にある(突然のセキュリティアップデートが必要になった場合など)。EC2のインスタンスがリタイアするときにあたふたしてしまう。Chefのコードを書く人がインフラ担当者に限られてしまい、アプリケーション開発者側から手出し出来なくなる。簡単とは言えないChefにも問題があると思われ。ProvisioningコードがCI上に乗っかってない。新たなトレンドなどを鑑みて、インフラの大幅刷新を行うことにした。以下が、目下移行中、新インフラの概要図である。大きく変わるのはアプリケーション開発者が担当するビルドの部分。以下、重要なポイントごとに検討してみる。生成まで面倒を見るようにする。現状のビルドプロセス:新ビルドプロセス:この統合によって、Provisioningの大部分がアプリケーション側に移動することになる。各アプリケーションの開発者が担当することによって、誰もがアプリケーションコードを扱う感覚でProvisioningコードを扱えるようになることを狙いたい。向いているのではないかという判断である。Integration今までCI上で実施されていたのはアプリのビルドまでだった。新しい仕組みでは、サーバーのビルド(AMIの作成)までをCI上で回す。これによって、以下のようなメリットが得られる。Infrastructure新インフラのアプリケーションサーバーは、原則として、一度起動した後にsshなどでログインしてその状態を変更しないようにする。Imageを作り直し、古いサーバーを破棄して新しいサーバーに入れ替える。Infrastructure」と呼ぶ。やりやすくなるなど、数多くのメリットがある。生成するプロセスと、そのArtifactを利用してOrchestration(サーバーの構成管理)を行うプロセスを分離する。前者は個々のアプリケーション開発者が担当し、後者はチーム全体で共同管理することになる。pushしたらアプリケーションの更新まで行われるという、現状実現できている自動化を再現するのが難しくなる。新インフラで得られるメリットに比べたら些細なことだと言えるかもしれないが、今後の課題ということでここに記録しておく。されていないという問題があるため、CircleCIに移行することにした。実現しているのは、状態(セッション)を持たないアプリケーションに限られ、かつデプロイ作業の多くは手動で行っている(ELBの操作など)。保存するようにし、アプリケーションサーバーをステートレスにする。Testで動作確認し、ELB配下で新旧の切り替えを行う。Terraformによって、サーバーの設定・構成がコード化されると共に、管理コンソールで操作する必要がなくなるため、ヒューマンエラーの予防になる。Blog.投稿先:キャンセル。