SCAが目指すものは、コンポーネントという単位で分けられた、様々な粒度のプログラム部品を適切に組み合わせることで巨大なシステムの構築を可能にすることである。また、「コンポーネントを組み合わせる」ことと「コンポーネントを実装する」ことをかなり厳密に区別しており、理論的には、どんな実装技術(Java、C++、BPELなど)で作成されたコンポーネントもSCA仕様に則っていれば問題なく組み合わせることができる。

SCA仕様を理解するには、「コンポーネントを実装する」という低レベルの概念と、「コンポーネントを組み合わせる」という高レベルの概念を分けて考えることが近道となる。ここでは、高レベルの概念を先に説明して、トップダウンのアプローチによりSCA仕様の理解に努めることにしよう(なお、正式な仕様にはここで述べるような高レベル/低レベルといった概念上の区分けはない。あくまで説明のための便宜的なものなので注意してほしい)。抽象的な話が少し長くなってしまうが、まずは我慢して以下の説明に目を通していただきたい。その後にTuscanyを使った実際に動くサンプルをご覧になれば、理解が早いと思う。余裕があれば、サンプルを試した後に再度この説明を読んでいただけると理解が深まるだろう。

SCAの概念

では、図1をご覧いただきたい。

図1: 一般的なSCAアセンブリの構造

この図は、一般的なSCAアセンブリ(assembly)の構造を表しており、SCAの仕様書内で用いられている記法(図形の形、色など)を用いている。SCAアセンブリとは、SCA仕様で定められている、コンポーネントを初めとした構成要素を組み合わせて構築された成果物のことである。SCAをベースとしたアプリケーションを作成するということは、SCAアセンブリを構築することと同義になる。この図を一見すると、SCAアセンブリはコンポーネント以外にも、大小様々な構成要素から成り立っていることがわかる。

以下、この図で使われている構成要素について説明していこう。

ドメイン

ドメインは、複数のコンポジットを内包する最も上位の概念で、単一の組織が持つ業務領域に対応する。主な役割はSCAサービスのカプセル化と名前空間の分離であり、Javaのパッケージなどをイメージするとわかりやすい(あくまでイメージ。ドメインは、Javaのパッケージよりも規模が大きく、カプセル化の機能もさらに強力だ。例えば、あるドメインから別ドメインのサービスを利用するには、Webサービスなど、SCA以外の技術を同時に利用する必要がある)。例えば、銀行というドメインが、金融関係の機能や口座管理の機能を全て内包するといった感覚である。

コンポジット

コンポジットは、ドメイン内の基本的な単位を表す概念であり、複数のコンポーネント、サービス、リファレンス、ワイヤの組み合わせから成る(詳細は後述)。コンポジット同士はリモートサービスとリファレンス(後述)という関連により通信を行える。また、コンポジット自体が別のコンポジットにおけるコンポーネントになることもできる(これは非常に重要な性質である)。それにより細粒度のコンポーネントを包み隠し、それ自体を中粒度のコンポーネントとして扱うことができる。このことが、大小様々な粒度のコンポーネントを維持/管理することを容易にするのである。SCAの中核を成す非常に重要な概念である。

コンポーネント

コンポーネントは、SCAにおける最も基本的な単位で、実際に業務ロジックが記述される部分である。コンポーネントはコンポジット内で結合され、業務の解決を図る。非常に重要な点として、コンポーネントはどのような技術で実装されるかについての制限が全くないということが挙げられる。つまり、1つのコンポーネントを実装するのに、Java、C++、BPEL、他のコンポジット、果てはJavaScriptやSpring Beanなど、様々な実装技術を選ぶことができる。こうした異種コンポーネントを透過的に結合できるのがSCAの最大の強みとなる。

サービス

SCAにおけるサービスとは、コンポーネント、もしくはコンポジットの実装が外部に対して提供する機能のことを言う(図1で言うと、緑の矢尻型の図形)。つまり、コンポーネントAがコンポーネントBの機能を必要としている場合、「コンポーネントAがコンポーネントBを利用する」というのは厳密に言うと誤りで、「コンポーネントAが、コンポーネントBが提供するサービスを利用する」と言うのが正しい(図1におけるコンポジットY内のコンポーネントA、Bの関連を見てほしい)。

とはいえ、それほど難しく考える必要はない。簡単に言えば、コンポーネントはサービスを提供する、サービスは何らかのインタフェース(Javaインタフェースが代表的)の形で提供される、サービスを利用する側はそのインタフェースを介してコンポーネントの機能を呼び出す、というだけのことだ。

サービスにはリモートとローカルの2種類がある。リモートサービスは、WebサービスやJava RMIなどのバインディング技術を用いてリモートマシン上の処理を呼び出すことができるサービスであり、スケーラビリティに優れているが、分散処理ならではの余分な処理が必要になる。ローカルはメモリを共有する同一マシン上の処理を呼び出すサービスであり、サービスの呼び出し自体は高速だが拡張性に劣る。

また、コンポジットがサービスを提供することもできる。そのような形態にしておけば別のコンポジットがそのサービスを利用することも可能になる。コンポジットが提供するサービスを宣言するには、SCDL(後述)によるservice要素の記述が必要で、サービスのインタフェースの指定と、「コンポジット内のどのコンポーネントが実際にそのサービスの機能を提供するか」を指定することになる。また、コンポジットの外部に公開するサービスはリモートサービスでなければならない。

リファレンス

リファレンスは、コンポーネントもしくはコンポジットの実装が他のサービスに依存していることを表す。実装寄りの話になるが、Javaで書かれたコンポーネントがリファレンスを持つ場合、ランタイムによる依存性注入(Dependency Injection)を利用して他のコンポーネントインスタンスを取得し、サービスを利用することができる(Setterインジェクション、フィールドインジェクション、コンストラクタインジェクションが利用可能)。

ワイヤ

ワイヤは、サービスとサービスの間を繋ぐもの、という概念を表す。ワイヤの一方の端にはリファレンスが、もう一方の端にはサービスが来ることになる。