ソフトウェア・アーキテクチャをコードに反映させる

この記事は、Simon Brown氏による、”Mapping software architecture to code”を、ご本人の許可を得て翻訳したものです。*1

This article is translated from ”Mapping software architecture to code” written by Mr. Simon Brown, with his permission.


ソフトウェア・アーキテクチャを開発チームのドメインに取り戻す

私が今、多くのソフトウェア・チームと行っていることの一つは、絵の書き方を教えることだ。私たちの業界では、カンバンやストーリー・ウォールなどを使った可視化をとても上手くやっている。その一方、ソフトウェアの可視化方法を忘れてしまっている。要するに、多くのチームがスピードに挑戦している中で、チーム全体が仕事を進めるための、共通したビジョンの作成に苦戦しており、それが結局はブレーキになっているのだ。そして今日、可視化のためにUMLを使っている人は殆どいない。UMLはただ問題を大きく見せるだけである。私はこれ関する記事を、もうすぐ公開する予定である(公開しだい、リンクをつける予定)。また、私の「Software Architecture for Developers」のebookや、この4月にヨーロッパ(ITARCIASA UKMix-IT)やUS(SATURN)で話した内容でもカバーされている。 このスライド(Agile software architecture sketches – NoUML!)は、数週間前にダブリンで発表したものだ。

この記事で伝えたいこと

この記事で伝えたいことは単純なことだ。もしあなたが作っている巨大なシステムが、いくつもの小さなコンポーネントからなると考えているのならば、それをあなたのコードベースにも反映させること。コードとソフトウェア・アーキテクチャを明確に紐づけるために、(レイヤーや機能というよりむしろ)コンポーネントによって、あなたのコードを組織化すること。もしあなたのソフトウェア・システムの構造を説明するのが難しいのならば、それを変えること。

コンポーネントへの分解

この記事の目的のため、ソフトウェア・システムを可視化すること自体は問題ではなく、あなたが作らなければならない新システムのために、ソフトウェア・アーキテクチャに関するいくつかのアイデアをスケッチしている所だと仮定しよう。”ちょうど良い”ソフトウェア・アーキテクチャに重要なのは、ソフトウェア・システムの重要な要素がどのように整合しているかを理解することである。 私にとってそれは、コンポーネント、サービスまたはモジュールのレベルまで降りていくことを意味する。これが実装の詳細レベルまで理解することではなく、最初のレベルの分解を行うことである、ということを強調するのは意味があるだろう。コンポーネント・ベース開発に関するウィキペディアのページはよいまとめである。コンポーネントとは、基本的にはリスク計算部品や監査ログ部品、レポート生成部品、データ取り込み部品などである。コンポーネントを最も単純に考える方法は、コンポーネントがインターフェースの後ろにある、関連した振る舞いの集合であり、それが1つもしくは複数のクラスによって実装されるものである、ということである。良いコンポーネントは、良いクラスと同じ特徴を多く共有している。高凝集性 、粗結合、明確に定義されている公開インターフェース、カプセル化など。

ソフトウェア・システムをコンポーネントの用語で考えることはいくつもの利点がある。本質的なのは、基幹システムを作り上げる数百・数千の個々のクラスとしてではなく、少数のハイレベルな抽象物として、ソフトウェアを考え、語ることができることである。以下の写真は私たちが行っているトレーニング・クラスで作成された典型的なコンポーネント図である。各グループは、データを取得し、計算を行い、そしてExcelのレポートを出力するような、単純な金融リスク・システムのデザインを行うよう要求される。

このスケッチは、データを取得し、リスク計算を行い、レポートを生成するようなシステムに期待されるような、主要なコンポーネントを含んでいる。これらのコンポーネントは、 システム境界内の振る舞いを分割するフレームワークを提供する。それによって、主なユースケースやユーザーストーリーを追いかけるのがだいぶ容易になるはずだ。これは、ソフトウェア開発を始めるのに本当に良いスタート地点であるし、チームが取り組むための共有ビジョンを作るのに役立つ。しかしまた同時に、とても危険なものでもある。技術的な選択やオプションなしでは、これらの図はある種の”象牙の塔のアーキテクト”が作ったものに見えるだろうし、技術的なバックグラウンドを持つ多くの人には、非常に”概念的”に見えてしまう。

コンポーネントについて語り、クラスを書く

人々は徐々に、ソフトウェアをよりハイレベルな構築ブロックとしてみることの利点を理解してきている。アーキテクチャに関する議論の際に、人々がコンポーネントの用語を使用しているのを耳にするだろう。しかしながら、アーキテクチャがコードベースに反映されることは少ない。あなたのコードベースを見てほしい。その中に、明確にコンポーネントを見ることができるだろうか。それとも、何か異なった構造を反映しているだろうか。 コードベースを開いたとき、それはしばしばコードの組織化による、他の構造を反映しているだろう。Mark Needhamは「コーディング:Packaging by vertical slice」という、コードの組織化における一つのアプローチに関して、素晴らしいポストを書いている。また、Googleで「機能によるパッケージ 対 レイヤーによるパッケージ(package by feature vs package by layer)」で検索すると、同じトピックに関するたくさんの議論を見つけられるだろう。ソフトウェア・システムのアーキテクチャ・ビューとコードのマッピングは、非常に異なっていることが多い。これは、しばしば人々がアーキテクチャの図(もしくはドキュメント)を無視し、「コードこそが唯一の真実さ」という理由になっている。

アーキテクチャ図の自動生成

少し話を変えよう。私は数週間前、ダブリンでChris Chedgeyに会った。彼に会ったことが、このポストに関するインスピレーションを受ける一因となった。ChrisはHeadway Softwareという企業の共同設立者で、Structure101という製品を持っている。見たことが無ければ、ちょっと見てほしい。 カッコイイやつを作っているところだ。ツールの要約をすることで、彼らの製品に対して何らかの正当化をしようとは思っているわけではないが、多くの機能うちの一つが、存在するコードベースの可視化し、理解する機能である。

私がソフトウェア・システムの可視化方法を教える際、様々な抽象レベルの、簡単な非UMLスケッチをたくさん作成する。スケッチとは、コンテキスト図コンテナ図、そしてコンポーネント図のことある。このコンテキスト、コンテナ、コンポーネントのアプローチは、基本的にはただのツリー構造である。システムはコンテナ(Webサーバー、アプリケーション・サーバー、データベースなど)から構成され、それらはさらにコンポーネントから構成される。いくつかの例をFlickrや私の本から見ることができる。

これがただのツリー構造だとするのなら、存在するコードベースからこれらの図を自動生成するのはいたって単純明快なやり方だ。そしておそらく、これができるツールがあるのだろうが、上手くやれるようなツールを見たことがない。Microsoft Visual Studioはレイヤー図などを生成してくれるが、そのようなアーキテクチャに関する図のサポート機能について、べた褒めする人には会ったことが無い。多くのツールがパッケージやクラスの依存関係の図を生成してくれるが、コンポーネントを表そうとはしない。結局、コンポーネントとは何なのだろうか? インターフェースを実装したクラスはコンポーネントなのか?もしあなたが制御の反転(inversion of control)を使用しているのなら、インジェクトされるものは全てコンポーネントなのか?

なぜこのような図の自動生成が扱いにくいのかを説明するいくつもの理由があるが、一度コーディングを開始すると、コンテナ(実行環境や、処理の境界)やコンポーネントに関するセマンティクスは、コードベースを占めるクラスの海の中で失われてしまうからだろう。多くの開発者がIDEの中で、再利用な可能なライブラリや配置可能な単位をあらわすために、システムを多くのプロジェクトに分割する。しかしながら、外部のツールが単純にJARファイルやDLLのブランチに対して動作する場合、このような情報へのアクセスは行われない。本質的に、抽象的な構造要素に関する情報は、コードベースの中では十分に表されないのだ。ほとんどのコードベースで、コンポーネントの定義に関する一連のルールにたどり着けるだろう。しかしながら、おそらくそれらの概念を明確化するほうが簡単だ。 Architecture Description Languageのように、いくつかのやり方は存在するが、私は実際使われているのを見たことはない。

コンポーネントによるパッケージング

コードに話を戻そう。コードベースの組織化は非常に助けになるが、妨げにもなる。レイヤーによるコードベースの組織化は、ソフトウェアの全体構造を見やすくするが、そこにはトレードオフが存在する。例えば、 ユーザーストーリーやフィーチャーを変更するために、あなたが複数のレイヤー(パッケージやネームスペースなど)を徹底的に調査する必要がある場合だ。また、エンタープライズ・システムにおけるレイヤー化の、きわめて一般的なアプローチにより、多くのコードベースが、最終的には気味が悪いほど同じような見た目に落ち着く。マーティンおじさんは、「コードベースは、ビジネス・ドメインについて大声で語るべきだ」と言っている。レイヤーというよりフィーチャーによってコードを組織化することが、それをもたらすだろうが、やはりここにもトレードオフが存在する。 私が経験した他の方法は、コンポーネントによるコードの組織化だ。次のスクリーンショットは、私のtechtribes.jeウェブサイト (ジャージー島のデジタル分野に関するコンテンツ・アグリゲーターやポータル・サイト)における例を表している。このスクリーンショットは、コアのコンポーネントのみを表している:分割されたSpring MVCプロジェクトと、コンポーネントを使用するコントローラーが存在する。

これはフィーチャーによるパッケージングに似ているが、Mark Needhamがブログで述べている”マイクロ・サービス”により似通ったものだ。je.techtribes.componentの個々のサブパッケージは、分割されたコンポーネントと、自身の内部レイヤー、Springの設定を備えている。 可能な限り、内容物は全てパッケージのスコープとなっている。 個々のコンポーネントを、自身のプロジェクト、または個別にバージョン管理するためにソースコードのリポジトリから取得したり、格納したりすることができる。もしあなたが粗結合なコンポーネントからなる分散メッセージング・システムのような、明確に粗結合なものを作っているのなら、このやり方は見慣れたものだろう。しかしながら私は、多くの人々が彼らのシステムをコンポーネントの用語で考えながらも、実際にはいまだによりモノリシックに物事を構築していることをかなり確信している。私は以前、確かに巨大なシステムの部分を同じようなやり方でパッケージしてはいたが、かなりアドホックなやり方であった。正直にいうと、パッケージの中にコードを組織化するのは頭脳をたっぷり使うようなものではない。とくに自由に使えるようなリファクタリング・ツールがある場合には。コンポーネントによるコードの組織化により、明確にコンポーネントのコンセプトを、アーキテクチャからコードベースへ反映させられる。もしあなたのソフトウェア・アーキテクチャの図がビジネス・ドメインについて何かを叫んでいるのなら(そして、そうあるべきだ)、それはコードベースにも反映されるのだ。

ソフトウェアの構造的要素

私たちはここで、je.techtribes.componentのサブパッケージはコンポーネントであるという取り決めを行ったが、メタデータを使用して明示的にコンポーネントを示すのがより簡単である。Javaではアノテーション、.NETではアトリビュートなどを、そのために使用できる。もしソフトウェアの、他の構造的な要素(サービスやレイヤー、コンテナなど)に同じアプローチを使用できれば、ツールベンダーはこのメタデータを使用して、意味のある、そして”単純な”アーキテクチャ図を自動的に生成できるだろう。加えて、クラスというより、コンポーネントにフォーカスした依存図を生成するために、この構造的な情報を使用できるだろう。私は、アノテーションを使うこの方法の実験を始めており、発見したものを保管するためのGithubリポジトリを作成した。

このやり方に対する主な反対意見は、コンポーネントをベースとしたソフトウェアシステムのデザインが、”唯一のやり方”ではない、というものである。 さらに巨大なソフトウェア・システムを考える際の良いアプローチであり、疎結合のアーキテクチャのためのすばらしい足がかりではある。しかし、銀の弾ではない。あなたがどのようにソフトウェアをデザインしようと、この記事がソフトウェア・アーキテクチャと、それをコードに反映させる方法のマッピングについて、あなたが考えるための一助となることを望む。

ソフトウェア・アーキテクチャとコーディングは、しばしば相互排他的な分野と見なされ、そしてアーキテクチャからコードへ、そしてその逆のマッピングはほとんどなかった。効果的に、そして効率的にソフトウェア・アーキテクチャを可視化することは、チームでよいビジョンを共有する手助けとなり、より迅速に前に進むための助けにもなる。アーキテクチャからコードへの単純で明示的なマッピングを持つことは、特に共同で作られたデザインやコード所有を見るときにも役立つ。さらには、ソフトウェア・アーキテクチャを、それが本来属するところの、開発チームのドメインに持って帰ることにも役立つのである。


(翻訳者のコメント)

アーキテクチャとコードをどう関連づけるか、この頃よく考えるテーマでもあったので訳してみました。

ちなみに、文章中で触れられていたNoUMLについては、アジャイルにおけるソフトウェアアーキテクチャ図とNoUMLとして、InfoQで翻訳版が公開されています。

*1:原文公開日:2013年4月8日。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です