Windows Azure Storage Service を用いた在庫管理の設計

http://social.msdn.microsoft.com/Forums/ja-JP/windowsazureja/thread/b76f647b-5e11-446b-92bd-2efdc2e7e362 Azure フォーラム に質問があった在庫管理の設計例を題材にしたWindows Azure Storage Service(主にKVS)による設計例をここで考えていきたい。問題の詳細は上記のリンクを参照してください。 1. 商品在庫管理テーブル 商品コード 商品名 在庫エリアコードAREA01在庫数 在庫エリアコードAREA02在庫数 在庫エリアコードAREA03在庫数 1 液晶テレビ 7 0 0 2 テレビラック 3 0 0 3 7.1chオーディオ 0 0 100 商品在庫管理テーブルを定義します。在庫エリアがこの問題では3箇所になっていますが、より多くの在庫エリアコード(倉庫)があって、商品に必要な属性数との和がAzureテーブルのプロパティ数の上限数(255以内*)に達してしまう場合は、在庫エリアコード毎に商品の在庫管理テーブルを作り、それらから商品毎にまとめた在庫数を管理する集計用の在庫管理テーブルを用意して、注文処理ではその集計用のテーブルを使い在庫を引き当てるようにします。各在庫エリアコードの在庫管理テーブルと集計用の在庫管理テーブルはeventual consistencyで変更を伝搬します。 * http://msdn.microsoft.com/en-us/library/dd179338(v=MSDN.10).aspx 注文処理では、この在庫管理テーブルの商品から在庫量を読み取り、必要な注文数が確保できるかどうかを確認します。必要な注文数が確保できるならば、その注文数を在庫量から減らして在庫管理テーブルを更新します。更新するとき楽観的同時制御(optimistic concurrency)を使い、同一商品の在庫がこの注文処理中に更新があったかどうかをチェックします。もし、同一商品の在庫がこの注文処理中に変更したときは、再度、同一商品の在庫数を読み取り注文数が確保できるかどうかを確認して再処理を試みます。なお、複数の在庫エリアコードのうち、注文数を満たすためにどこの在庫エリアコードを使うかなどのロジックはここでは考えません。 在庫管理テーブルはこのように注文により減算される一方、倉庫における入庫(新規の補填や返品などによる)によって在庫量が増加します(棚卸などでの欠損やその他の理由により倉庫オペレーションで在庫が減ることは例外事項としてここでは考えません)。倉庫オペレーションによる在庫量の増加も同じ在庫管理テーブルに対して注文と同じように更新を行います。更新の際の楽観的同時制御の利用により、入庫処理中に注文があり、在庫数が減産される場合は再度、再処理を試みます。 Webアプリケーションでのカタログの在庫数の表示の変更は、注文での在庫の引当てが成功し在庫管理テーブルの更新された後、また、入庫により在庫管理テーブルの更新が成功した後に表示の変更を行います。 注文および入庫は在庫管理テーブルの非正規化(RDBの第1正規化相当)により、1行に対する更新操作なので操作の実行はACIDトランザクションで保護されます。しかし、ここでの問題は、 (a) ある注文処理中の、別の注文処理、入庫処理の割り込み (b) 入庫処理中に、(複数の)注文処理の割り込み にあります。これを楽観的同時制御で解決しています。 2. 注文テーブル 注文コード 注文日時 会員コード 会員名 商品コード 商品名 注文数量 取引単価 小計 在庫エリアコード…

3

クラウドのアプリケーション開発へのソフトウェアファクトリー適用

マイクロソフト株式会社 萩原正義   Microsoft社は2004年よりソフトウェアファクトリーを次世代のソフトウェア開発基盤技術として推進してきた。2009年以降はWindows Azure Platformを始めとするクラウドが新しいソフトウェアの開発および実行基盤と位置付けられる段階になり、クラウドのアプリケーション開発へのソフトウェアファクトリーの適用の機会が増えると予想される。そこでここでは、ソフトウェアプロダクトラインの構築、特性モデルによる可変性(ソフトウェアの要求変更能力)の提供、ソフトウェア開発プロセスの自動化と効率化、DSLによるモデル駆動型開発、開発資産の管理などソフトウェアファクトリーが取り組む技術を考慮し、クラウドのアプリケーション開発へのソフトウェアファクトリーの適用を解説する。 1 クラウドのアプリケーション開発の基本 1.1 クラウドのアプリケーション開発上の制約 クラウドのアプリケーション開発に特有の制約条件を以下に示す。 (1)非同期通信 部分的な障害に対応するため、同期通信によるトランザクションは参加者のライフタイム同期が全体の稼働を停止させるため許容されない。 (2)常時稼働 常時データ更新の可能性があり、スケーラビリティの観点で書き込みロックをしておくことも不可能なので古いデータの読み取りが前提となる。 (3)CAP(Consistency,Availability,Partition tolerance)定理 可用性とスケーラビリティの確保を前提とするとデータの一貫性が確保できないことを提示する。従来のACID(Atomicity, Consistency, Isolation, Durability)トランザクションとは異なるデータ一貫性の確保が必要となる。その一手法がeventual consistencyと呼ばれるデータの一貫性要求の強さを表現したモデルとその実装法である。 (4) キーバリューストア オンプレミスで主流のRDBに変わり、キーとバリューをセットにしたデータサービスが基本となる。その結果、RDBとは異なるデータ設計、トランザクション実装法、データ管理方法が必要となる。キーバリューストアは行データ毎に異なる物理ノードに配置され、行データ単位でトランザクションを実行するため、スケールアウト設計が基本となる。 1.2 クラウドのアプリケーション開発手順 クラウドのアプリケーション開発(スケールアウト設計)の手順の概要を以下に示す。 (1)スケーラビリティのボトルネックとなるデータ層にキーバリューストアを利用する場合、スケールアウト設計のためにアプリケーションのワークロードパターンからデータアクセス法の最適化(データ非正規化)を決定する。そのため、ワークロードパターンの特定のための機能分割を行う。 (2) (1)と並行して個別アプリケーション機能に依存しないデータアーキテクチャを設計する。具体的にはマスターデータとトランザクションデータを識別し、マスターデータを論理的に一元管理する。トランザクションデータはマスターデータを一方向参照する。 (3)アプリケーションアーキテクチャを設計する。非同期通信、並列処理を前提とした参照アプリケーションアーキテクチャを採用する。必要に応じてマスターデータ分割、その複製をトランザクションデータ側に置き、アプリケーションのワークロードパターンに合わせて非正規化する。キーバリューストアでは行データ単位で異なる物理ノードに配置されるため、非正規化データは水平パーティション化して行データ毎に異なる物理ノードに配置し、物理ノードの並列処理を活用する。データ分割、トランザクション分割によるスケーラビリティの向上を考える一方、分割したデータ間での一貫性の確保のために、eventual consistencyのための実装を追加する。スケーラビリティと一貫性の確保は常にトレードオフの関係にある。 (4)アプリケーションアーキテクチャ上でコンポーネント指向によるアプリケーション開発をする。アプリケーションの要求変更(可変性)に対応してマルチパラダイム設計を行う。マルチパラダイム設計はドメイン毎に設計や実装のためのパラダイムの選択を変えることで、可変性に対して柔軟性を与える設計方法である。たとえば、ロジックの実装、データ構造の振る舞いの変化にはオブジェクト指向、分散バッチ処理の実行には関数型、変更箇所の配置にはコンポーネント指向、機能の提供にはサービス指向というパラダイムの選択と組み合わせを使って設計を進める。 1.3 ユースケースに関連する設計上の問題 クラウドのアプリケーション開発におけるスケールアウト設計では、アプリケーションのデータアクセス方法を決めるユースケースに従ってデータの非正規化、水平パーティション化を行うことが重要である。クラウドのアプリケーション開発ではユースケースが多くの問題に関連づけられている。ここでは、ユースケースに関連する主要な5つの問題を示す。 (a)ユースケースがデータの非正規化,水平パーティション化の物理設計を決定 (b)更新系と参照系にユースケースを分離し,eventual consistencyによるデータ一貫性を実現 (c)1ユースケースはサービスの窓口になるboundaryと,共通性の高いコアモデルのdomain modelの論理レベルの設計モデルに分割 (d)1ユースケースはWebアプリケーションやWebサービスのためのフロントと,ビジネスロジックのためのバックの物理レベルのプログラミングモデルに分割 (e)1ユースケースはクラウド上のトランザクションシステムのフロントと,オンプレミスのトランザクションシステムのバックに配置 (a)(b)はユースケース単位で見た外部仕様での問題である。(c)(d)(e)はユースケースの実装や配置に関する問題で内部仕様での問題である。 2 クラウドのアプリケーション開発へのソフトウェアファクトリーの適用 2.1 ソフトウェアファクトリーの位置づけと現状 クラウドを前提としたソフトウェア開発は大規模、複雑である。クラウドのアプリケーション開発では、DOA(データ中心アプローチ)の分析方法、SOA(サービス指向アーキテクチャ)によるドメインや機能分割、オブジェクト指向分析設計によるオブジェクト指向開発言語を前提とした設計手法、コンポーネント指向による保守や配置、開発プロセス全体を駆動するユースケース駆動などを組み合わせる。たとえば、DOAでデータを分析、定義し、ユースケースを基準にして開発プロセスを駆動する場合や、プロセス分析でビジネスプロセスを分析、定義し、サービスを基準にして開発プロセスを駆動する場合などがある。開発すべき対象、ドメイン、要素技術、実行環境に応じて分析法と開発アプローチを適切に組み合わせてリスクを軽減することが求められる。これに加えて、並列実行や非同期通信の実装のための関数型パラダイム、モデル駆動型開発のためのUML/DSLの抽象化したモデルによる保守とコード生成、可変性に対するドメイン分析とマルチパラダイム設計などを併用する。このように複雑に複合化した技術を用いるクラウドのアプリケーション開発では、技術の複合化にみられる複雑さの問題にとらわれることなく,非同期通信とデータ非一貫性などの根源的な問題を見ていく必要がある。 一方、このような取り組みはもちろんプロジェクトの成功のためには重要ではあるが、ビジネス価値やソフトウェア技術の可能性を十分に高めた革新的なソフトウェアを開発するためには、プロジェクトの駆動や管理、実装やテストをできるだけ効率化し、設計上の意思決定など、より根源的な問題に時間を割くべきであろう。 ソフトウェアファクトリーが目指すソフトウェア開発の工業化は、ソフトウェア開発を完全に自動化するような創造性のない開発を意味していない。むしろその逆であり、繰り返される煩雑な作業を自動化し、創造的なソフトウェアの開発に注力することが目的である。クラウドは技術的な革命であるが故に可能性が高く、他方では複雑な技術課題の克服が命題でもある。ソフトウェアファクトリーのようなソフトウェア開発基盤がまさに求められる開発と実行の環境である。しかし、現状のソフトウェアファクトリーには次の3つの問題が存在する。 (1)ソフトウェアファクトリーは、ソフトウェアプロダクトラインを基本とし、プロダクトラインのアーキテクチャの定義範囲をドメイン分析で決定する。しかし、SOA、クラウドでは広域で時として動的なアプリケーション間連携が前提となるので、アーキテクチャ定義範囲の固定化を要求するドメイン分析は困難な作業となる。ただし現実には、WebやXMLなどが広域アーキテクチャの基盤となっている実績が存在するので不可能なわけではない。 (2)ソフトウェアファクトリーの実現は開発環境やツールの実装には原則として依存しない。ただし、Microsoft社のVisual Studioがその主要な開発環境であることに間違いない。Visual…

0

アジャイル開発とアーキテクチャ

アーキテクチャの基本的な考え方は、機能要求に先行して構築されてることです。 この原則は、EA(Enterprise Architecture)、DOA(データ中心アプローチ)、プロダクトライン開発のアーキテクチャでもほぼ同じ思想を持っています。 一方、アジャイル開発ではTDDなどを使い、要求を定義しその実現を検証しながら開発を進めます。その結果、開発される成果物は必然的に要求との依存性が高くなります。要求との追跡性の重視や、ビジネス価値の追求を重視すれば、その傾向はさらに強くなります。それ自体は悪いことではなく、顧客の満足を考えればいい結果をもたらすでしょう。 リファクタリングを行うことで得られる結果は、インターフェイス定義の明確化(変化する部分と変化しにくい部分の分離)、コンポーネントやクラスやサービスの粒度の適正な決定を行えること、拡張性のためのより良い解を得られることなどです。 アーキテクチャをコンポーネントの関係でとらえるとリファクタリングはこの構造を決める上で有効な手段と感じるでしょう。 ただし、ここでアジャイル開発におけるアーキテクチャの構築で2つの注意点があります。 (1)アーキテクチャは現在の要求だけで構築すべきでない。 (2)コンポーネントの構造だけがアーキテクチャではない。 たとえば、(1)で要求がゴールの達成やそのための戦略に基づいて定義されていたとすれば、アーキテクチャは直接的な要求を満足するだけでなく、ゴールの達成のために構築されるので、より合理性を持ちます。ただ、その場合であっても、EAにあるように、システムのアーキテクチャが存在する以前からビジネスアーキテクチャは先行して存在しており、その一部がシステムアーキテクチャになることを考えると、アーキテクチャはシステムへの要求とは独立する存在と考えたほうが適切といえるでしょう*1。これは、教育システム、法令システムの社会構造が、個別のそれらへの要求を超えて存在しているのと同じ状況です。個別の要求はアーキテクチャに対して変化を及ぼすことはあっても、アーキテクチャは要求とは独立して存在すべきなのです。より分かりやすい例は、開発言語やRDBを大きなアーキテクチャとみなせば、これらの技術が大きくは社会的な要求によって変わったにしても、個別プロジェクトの要求くらいでは変わらないことでも分かるでしょう。 *1 ZachmanもEAはシステムアーキテクチャというより、Enterprise(企業経営、活動)のためのと言っている。 (2)は概念や哲学などの発想を言っています。たとえば、トランザクションモデルでのスナップショット分離レベルのような比較的新しいトランザクションモデルを概念として取り入れることもアーキテクチャの一部です。しかし、こうした技術は、コンポーネントの粒度の決定、インターフェイス定義の明確化とは独立しています。発想できることは、開発プロセスにアジャイルを使うかどうかとは別の次元です。アジャイルを使うことにより、多くの概念の発想ができる可能性が高くなるのであれば、アジャイルはアーキテクチャ構築に有効な手段となるでしょう。 一般には、(1)では要求の裏付けとなるゴールまで考えたアーキテクチャよりは、要求を直接実現するアーキテクチャになりやすく、(2)では、発想の探求よりも要求の実現を第1と考える傾向が強くなるので、この場合には、アジャイル開発におけるアーキテクチャの構築はうまくいかないでしょう。 現実には、アジャイル開発は、既存のフレームワークや開発基盤技術の上で行うのが前提であるので、アーキテクチャの大半はアズイズで与えられていて、その上でロジックの構造だけを考える場合が多いので有効となっているとみられます。MVCやデータアクセスの方法が与えられている場合か、プロジェクトリーダの頭の中に基本的なアーキテクチャのアイディアがアジャイルとは関係のない次元に存在している場合が多いといえます。 さて、皆さんの意見はどうでしょうか?

1

アーキテクチャは暗黙知の1表現

平鍋氏のアーキテクチャとはを読んで私のアーキテクチャに対して感じていることを以下に書きます。 http://blogs.itmedia.co.jp/hiranabe/2008/10/grady-booch-dd7.html Booch氏のアーキテクチャはデザインであるが、すべてのデザインがアーキテクチャであるわけではない、という深い意味を持つ言葉は、アーキテクチャは暗黙知を表現する1形態であって、連続する意思決定から構成されていると、解釈します。暗黙知だから、創発されることもあり、また、パターン化のような形式化に限界があることが説明できます。またすべての意思決定の意図が表現できるものでもないことが分かります。こうした表現形態は形式的にUMLなどのモデルで表現できたとしても、意図を正確に伝えることには限界があります。 では、我々はアーキテクチャをどう扱えばいいのでしょう。僕はできる限り科学に基づくべきだと考えています。そうであるなら、ある程度の合理性と客観性を持つことができるでしょう。アーキテクチャは多くの場合、箱と線による抽象的なモデルで表現されるので、分かりにくく、あいまいだと考えてしまうことも多いのですが、抽象化はあいまいとは違います。抽象化したとしても、厳密な定義は可能です。 いつもはモデルを見せて、アーキテクチャは「はい、これです」みたいなトップダウンのパターンですませてしまい、深い意味を犠牲にしてしまうので、ここではアーキテクチャを科学に基づかせる例を具体的に示しましょう。 例1: .NETのコードアクセスセキュリティのアーキテクチャ コードアクセスセキュリティ(CAS)の詳細な説明はここをご覧ください。 http://www.atmarkit.co.jp/fdotnet/technology/idnfw11_index/index.html アーキテクチャとして、コンポーネントとOOPを採用する前提でコードアクセスセキュリティを提供する機構を考えてみれば、コード実行に信頼性を上げる方法は、物理的に以下の段階でのセキュリティチェックに決まることになります。 (1)コンポーネントのロード時のチェック (2)クラスのロード時のチェック (3)メソッドがJITコンパイル時のチェック (4)メソッドの呼び出し実行時のチェック この段階は、コンポーネントとOOPを組み合わせてソフトウェアを開発するという前提で、ローダーやJITコンパイラのような機構を使うとしても、実行のタイミングとして必然的に現れます。いわば物理法則で決まるタイミングです。そして、それぞれのタイミングでのチェックは、チェックにかかる計算コストをできるだけ減らすという指標をとれば、また、おのずと決まってくるのです。後は、(1)ではコンポーネントのメタデータを記述する宣言、(2)はクラス間の継承関係の制約、(3)はリンク時のチェック、(4)はスタックの呼び出し順に従う制限を考えればいいことになります。   例2: IIS の拡張アーキテクチャ 現在のCPUアーキテクチャは、スレッドの実行予想やキャッシュの有効化を考えるとパイプライン処理が有効となります。IISの拡張性はこのパイプラインを前提としたアーキテクチャです。パイプラインアーキテクチャを採用する場合、パイプラインを構成する各ステージは時間順序の制約から物理法則で決まります。たとえば、ページの実行前には、認証や認可のチェック、キャッシュが利用可能かどうかのチェック、URLのマップ、各種サーバ状態(コンテキスト)の設定などが必要です。こうしたプログラムの実行、リソース間の制約関係、で決まる一貫性の制約を守ることは、誰が考えても必然的な結果を得ることができます。 http://learn.iis.net/page.aspx/496/iis-url-rewriting-and-aspnet-routing/ は、IIS 7.0の画面遷移のアーキテクチャの比較の例です。URLの書き換えによっても、ルーティング制御を持つ機構とマッピングを組み合わせた機構を使ったとしても、それぞれの優劣の比較はありますが、根本的には物理法則に依存していることが分かるでしょう。 アーキテクトの意思決定は非常に多くの技術選択肢の中から最良と思うものを選択します。属人的な決定かもしれませんが、科学の世界に基づくことで、ブレを少なくすることは可能です。 以上のような考慮と意図を具現化したアーキテクチャは、しかし、多くの仮定、前提、制約条件から成り立つ暗黙知の一種であることには変わりません。

0

アーキテクトの審美眼

翔泳社のDBマガジンに連載中の記事のこれまでの一覧です。   No. 1 アーキテクチャとは何か 例えばイベント駆動を考える アーキテクトの悩み アーキテクチャの縦と横の関係 縦横2つに分ける理由と効果 縦と横で表現したアーキテクチャの例 もう一度世の中の動きを見る 今後の連載予定 No. 2 俊敏なアーキテクチャ システムを俯瞰する視点「俊敏さ」 抽象化を支えるボトムアップ 俊敏なアーキテクチャの構築法 ITシステム間の接続 データ品質の確保 ビジネスプロセスの最適化 ビジネスの観測可能性の実現 ビジネスの制御可能性の実現 情報一元化の達成 俊敏さをさらに理解する 成熟度モデル 成熟度モデルの例 典型的なロードマップ 現実との乖離 要求の合意に基づかないシステム開発 ドメイン駆動型開発 おわりに No. 3 概念レベルの分類法から見たアーキテクチャ(前編) ソフトウェア開発の基本は分割と複合化 ソフトウェア開発における分類法 もの/こと分析 「もの」と「こと」の関係を分析する 「もの」「こと」からビジネス状況を分析する 「もの」の見え方の変化をとらえる OOPLの継承による分類とその限界 分類法はスナップショット おわりに No. 4 概念レベルの分類法から見たアーキテクチャ(後編) 概念モデルの位置付けを振り返る 概念モデルからの分析/設計方法 アプローチによる分析方法の違い オブジェクト指向アプローチの分析方法 データ中心アプローチの分析方法 ステレオタイプによる分類 ストリームラインオブジェクトモデリングによる分析/設計 分析の練習…

0

アーキテクチャ設計におけるモジュール化(2)

前回の説明の中でモジュール化という言葉を出しましたが、この定義について誤解を生まないように少し説明を加えましょう。モジュール化とは、モジュールを作るという意味ですが、ここでのモジュールは.NETでのアセンブリー、あるいは、JavaでのJARのように物理的な配布のためのパッケージではありません。これらは、配布、インストール、運用時の構成管理(セキュリティ設定など)、物理レベルの資産のバージョン管理のための単位です。一般的には、機能の単位、保守の単位、再利用の単位、配置の単位に利用されます。これらは、物理的形式(ファイル)ですので、プラットフォームや実装に依存します。 一方、ここでのモジュールは、論理レベルの成果物(モデル)に対する単位をいいます。主に可変性の単位で、内部のモデルはほぼ同一の変更の度合いを持っています。分かりやすく言えば、コードの変更の例で、データベースのスキーマにカラムの追加を行う場合、それを処理するデータアクセスコードやロジック、UIの変更も必要となる場合があります。これらの変更はすべて一貫性を持ってなければならず、テスト検証の上、チェックインされます。変更はアーキテクチャのレイヤーにまたがる複数の箇所で起こり、この範囲を表現するのがここでのモジュールです。 モジュールは適切は配布のためのパッケージに関連づけられます。まずモジュールが定義され、そして配置のためのパッケージ化に対応づけられます。それぞれが別の構成定義、バージョン管理されます。 このモジュールはおわかりのように、アーキテクチャのレイヤー(論理的なコンポーネント)構造とは複雑な関係にあります。両者は依存関係は持っていますが、モジュールからアーキテクチャに対して一方向の依存関係があり、その点では、アーキテクチャを先行的に設計しますし、モジュール化の定義の仕方にアーキテクチャの設計は影響を受けません。 このモジュールはまた別の特徴としてパラメータをとります。パラメータによりモジュールを構成定義可能として可変性を持たせるといってもいいでしょう。実際には、パラメータはアーキテクチャの拡張部分に作用してアーキテクチャの構成を可変にしたりもします。このパラメータの設定をXMLやプログラムで行ってもいいですし、DSLのようなツールを使って行ってもいいです。 さて、こうして作られたモジュールをアーキテクチャを使うことを前提としたプロジェクトで再利用していきます。あるプロジェクトでは、モジュールAとBをそれぞれパラメータ設定して再利用し、別のプロジェクトではモジュールAとCをまた別のパラメータ設定して再利用します。 ここで疑問なのは、こうしたモジュールの再利用が有効となるかどうかという点です。いままでもコンポーネントの再利用があまり有効でなかったのに、モジュールにしたからといって同じように有効とならないのではという疑問です。もっともな疑問でしょう。 モジュールがコンポーネントと異なる点は3つあります。 1つは、要求に対してあらかじめドメイン分析を行い、どのような可変性が必要かを分析してスコープを決めている点です。したがって、ここでもモジュールはこのスコープ内に有効性は限定されます。この限定により、再利用性を高めようとします。 第2として、可変性を持たせることにより再利用を決め打ちにしていないことです。完成したコンポーネントは適用範囲を狭めますが、モジュールは可変性をプログラム可能な領域まで広げることで再利用性を高めようとしています。 第3として、これが一番大切なことですが、モジュールは再利用の状況を見てリファクタリングされるという点です。当初のプロジェクトでモジュールの定義があまり有効でない場合は、その後のプロジェクトでは、モジュール定義を変更して再利用性を高めます。しかし、この場合でもアーキテクチャとの一方向性の依存関係により、アーキテクチャには変更がないようにします。アーキテクチャの保守は別の観点で行うべきだからです。 こうしたモジュールを可変性を表現するフィーチャ(特性)モデルに対応づけます。つまり、要求からフィーチャを構成定義します。フィーチャはモジュールに対応づけられているので、フィーチャの構成定義はつまり実装の構成定義になります。要求は実現されるわけです。 この前提にはアーキテクチャはドメイン分析で作られること、そして、プロジェクトで繰り返し利用される長期の資産であることが求められます。いままでのようなワンオフ開発ではありません。ですので、ワンオフ開発が投資的に有利な場合の話ではありません。 モジュールは要求を構成定義するフィーチャから使われ、適切にリファクタリングされるという前提では、その存在理由から100%の再利用性を持ち得ます。 これがソフトウェアプロダクトラインです。請負型のワンオフ開発をやっている限り再利用性を高めるには限界があることを理解されたでしょうか。ソフトウェアプロダクトラインは請負型をプロダクト(パッケージ)開発型にする手法です。また、そうでないければ、大部分のソフトウェア開発の未来は明るくないと思っています。 要求に時間をかけることは大切ですが、同じくらい設計にも時間をかけるべきでしょう。日本の現状は、要求やプロジェクト管理に行き過ぎていて、設計や開発手法の有効性について見落としているのではないでしょうか。この方面ではまだやることが多くあり、それらの改善はプロジェクト管理よりも生産性に寄与し、品質にも大きく貢献できると思っています。

0

アーキテクチャ設計におけるモジュール化(1)

アーキテクチャはコンポーネントの構造として定義されます。この定義を見て、アーキテクチャはコンポーネントをモジュールにして実装すると思っている人が多いのではないだろうか? しかし、ここで指摘したいのはアーキテクチャの設計、その構造定義と、モジュール化は分離して考えなければいけないことです。たとえば、Webアプリケーションやマイクロソフトのエンタープライズシステムでの参照アーキテクチャ、JavaEEで見られる多層モデルによるアーキテクチャの構造はモジュールではありません。 アーキテクチャのそれぞれの役割に応じて論理的なコンポーネントを定義し、それらが複合構造となっています。UI、UIプロセス、ビジネスロジック、データアクセス、データハンドラ、サービスエージェントなどと呼ばれる論理的なコンポーネントを構造化してアーキテクチャを定義します。このアーキテクチャに対して、保守の単位、品質の確保のための検証の単位、ユーザに対する有効な機能の単位、再利用の単位、などがどうなるかを考えてみましょう。これらが、モジュール化の対象となります。 現在のアーキテクチャはフレームワークは前提としますが、一回毎にカスタム(ワンオフ)開発する請負型の開発が大部分で、UI部品など物理的なコンポーネント、抽象クラス、UIスタイル、コーディングコンベンション、開発プロセスモデルなど、断片的、局所的な再利用に限定されています。つまり、モジュール化の対象として、再利用の単位、ユーザに対する有効な機能の単位を考えるほどの洗練されたレベルになっていません。このことは、アーキテクチャのコンポーネントの構造とモジュール化が分離できていない理由の1つでもある。また、現在の主流のオブジェクト指向が、再利用の単位やユーザに対する有効な機能の単位を分離するには、制約が大きいことももう1つの理由となっています。 たとえば、再利用の単位としてクラスを考える場合、単一責務の原則でクラスを定義したとしても、、非機能要求を含めるとクラスには多くの関心が含まれます。その結果、オブジェクト指向特有のもつれ合いの問題が発生します。このもつれ合いを回避し、再利用性を高めるには、クラスより小さい言語構造、あるいは、モデル要素が必要となるのです。Scala やC++にある”trait”という言語構造はこの問題を改善するために存在します。 ユーザに対する有効な機能の単位としては、Jacobson氏が提唱するユースケーススライスがあります。ユースケーススライスは、クラスだけでなく、既存クラスに挿入するメソッド、属性などをまとめて定義するパッケージです。これはユースケースがクラスに横断的になっており、やはりオブジェクト指向特有の散乱の問題を発生させるからである。 http://www.amazon.co.jp/%E3%83%A6%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%82%B9%E3%81%AB%E3%82%88%E3%82%8B%E3%82%A2%E3%82%B9%E3%83%9A%E3%82%AF%E3%83%88%E6%80%9D%E8%80%83%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA-Object-Oriented-Selection%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-Jacobson/dp/4798108960/ref=pd_bbs_2/250-7397366-0246623?ie=UTF8&s=books&qid=1190189497&sr=8-2 以上から、アーキテクチャの構造からモジュール化を分離できないのは、既存の技術制約が問題となっていることがわかります。 しかし、それ以上にワンオフ開発では、この技術課題を開発プロセスの改善などで補ってきた(*)ことで、本質的な問題の解決を避けてきたともいえます。再利用の問題1つにしても、あまり進んでいないのは、技術的制約にあるのではなく、ワンオフという開発の仕方が再利用を強制していないことによる面が大きいのです。 (*) クラスのリファクタリングで開発フェーズ、リビジョン、ビルドなどで調整する。

0

[補足] ソフトウェアプロダクトラインにアスペクト指向は有効か?

前回の補足です。 アスペクト指向がソフトウェアプロダクトラインに本質的に親和性を持たない理由は、ソフトウェアプロダクトラインのアーキテクチャの拡張点には、拡張点に応じて「異なる」拡張コードを導入しなければいけないからです。一方、アスペクトの定義は、この拡張点をjoin pointで定義する場合、「同一」のadviceのコード定義を導入することになります。これでは、ソフトウェアプロダクトラインのプロダクトに応じた拡張点の拡張コード、プロダクトのバージョンに対する拡張コードの進化がうまく表現できません。 Software Factoriesの教科書には、factoryの実装技術としてアスペクト指向コンポーネントが有望ととられるような記述がありますが、厳密には現在のAOPは適切な実現法とは言えません。Microsoft社がAOPに消極的である理由は優先度の問題もありますが、このあたりに理由があります。 歴史的にみれば、AHEADなどソフトウェアプロダクトラインと親和性を持つFOP(Feature Oriented Programming Language)は、mixinを拡張法に持ちます。mixinの方がアスペクトに比べて、base クラスに対する局所的な拡張性、バージョン管理に対して有効な技術と考えられるからです。また、AHEADは直交する関心を代数学的に扱うことで、特性の複合化の組み合わせ数を減らすためのプラットフォームとなっています。正確にいえば、直交する関心の個数(次元)をN、各関心のとりうる実現法の数をkとすると、O(N**k)がO(N*K)になります。 さて、mixinとアスペクトを組み合わせて相補的にソフトウェアプロダクトラインを構築する方法はないでしょうか? アスペクトが持つpointcut定義を使い、アーキテクチャの拡張点をjoin pointで定義します。次に各join pointではadviceを使わず、間接的にmixinを呼ぶようにします。こうすれば双方の利点を得ることができます。これにより、特性間の依存関係は、特性を含むシナリオをサポートするユースケーススライス、つまり、アスペクト間の依存関係となり、最終的にmixinの依存関係になります。つまり、mixin間の複合化の制約関係になります。 こうしてみると、ソフトウェアプロダクトラインに有効な複数の複合化アーティファクト(設計モデルやパラダイム)を考えていくと、技術が複雑化することがわかります。まして、それらの設計が正しく行われるための分析プロセスなど方法論自体が複雑化します。これをドメインエンジニアリングで行うアーキテクトの技術力いかんにソフトウェアプロダクトラインの成功がかかわるということになります。 私はこうした複雑化した技術は好きではありません。単純化こそ有効な手段と考えています。しかし、企業システムの領域に限っても、ドメインをストレートに表現するドメインモデルは、ビジネス構造をできるだけ忠実に表現しているようでも、そこには多くのビジネスの振る舞い、シナリオが暗黙のうちに仮定されていることは理解しなければなりません。つまり、構造的にみれば、抽象化が可能な比較的単純な表現になっているかもしれませんが、ビジネスルールや要求の検証プロセス、状態遷移などが隠されていて、本質的にはかなり複雑なはずです。ですので、ドメインモデルと使うかどうかによらず、現実世界のシステムはかなり複雑で、それを体系化するソフトウェアプロダクトラインも必然的に複雑さを扱う必要が生じます。その結果、抽象化や単純化のための技術の適切な選択が重要となります。AHEADの代数学的アプローチ、AOPのpointcut言語、mixinの複合化技術、アスペクト指向分析設計など、技術の採用が正しいかどうかの判断を今一度考える必要があります。

0

ソフトウェアプロダクトラインにアスペクト指向は有効か?

ソフトウェアプロダクトラインの開発ではアーキテクチャに適切な拡張性を持たせ、要求に応じてアーキテクチャを再利用しつつ、その拡張性を使い個別の可変性に対応していくことが求められます。 コアのアーキテクチャの開発は、オブジェクト指向を使ったフレームワーク開発に代表されるように、アーキテクチャスタイルを考慮して進められます。拡張性の実現法は、用いるパラダイムに応じて多様な選択肢がありますが、典型的にはコンポーネントの接続を用いた設計がとられます。ここでいうコンポーネントは.NETアセンブリなどの特定プラットフォームの物理レベルのコンポーネントを指すのではなく、UMLのコンポーネントで表現される論理レベルでインターフェイス定義を持つモデルをいいます。このモデルをオブジェクト指向を用いて実現するならば、Open-Closed Principleに従う、複数のクラスで構成される物理的配布単位とみなすことができます。しかし、ソフトウェアプロダクトラインの可変性の観点では、こうした静的タイプだけによる実現法では限界があります。より一般的にはUMLパッケージを用いる方法があります。UMLパッケージは物理的配布単位で得られる変更の一貫性の単位を論理レベルで表現しているとみなせます。トランザクションスコープといってもいいでしょう。これにはクラスのような静的な構造だけでなく、シーケンス図や状態遷移図のような動的な振る舞いを含むことができます。こうして複数のモデルをまとめて1つの一貫性のある変更単位を定義するのがUMLパッケージです。内部にあるモデルが論理レベルの表現であるのなら、UMLパッケージ全体として実装に依存しない定義が可能となります。UMLパッケージはパラメータを取ることができます。たとえば、クラスのフィールド定義、シーケンス図の操作の一部をパラメータ化することができます。こうして、UMLパッケージを定義しておき、その実現法を変更の一貫性を含めて、モデル変換やモデル言語のコード生成に任せることで、可変性への対応をモデルベースで行うことができます。たとえば、UMLパッケージとして最近注目を浴びているのが、Jacobson氏のユースケーススライスです。ユースケーススライスとは、その名前のとおり、ユースケースに関する追跡性のあるモデルです。ユースケースの実現をオブジェクト指向で行うと、クラスに横断的な構造となるので、アスペクト指向を使い横断的な関心としてユースケースを表現します。ただし、AOPとは異なりプログラミング言語の物理レベルではなく、概念、論理レベルを主に対象としたアスペクト指向の表現です。 さて、ソフトウェアプロダクトラインの可変的な特性をユースケースとして表現し、それをユースケーススライスを使ってモデル駆動型で実現しようとする試みは、一見すると非常に有望な手段と一頃は思われていました。しかし、研究が進むにつれて多くの技術制約や問題が明らかになり、現在はあまり有力な手段とは思われていません。私も1年ほど前、こうした検討をかなり進めましたが、実現可能性という点で採用しませんでした。 現在のこの分野の動向は、AOSD Conference 2007の動向などから、2つの方向性を持つと考えています。 1つは、ソフトウェアプロダクトラインの特性と親和性のある形に実現法を変えてアスペクト指向の技術を適用していくこと。たとえば、アスペクトはベースクラス(OO)に対して横断的にコードの挿入やインターセプトを行うために、アスペクトとベースを関係づけるポイントカット言語が1対nの関係を持つ特徴があります。一方、ソフトウェアプロダクトラインでは、1つの可変点に対して要求に応じて複数のバージョンのコンポーネントやパッケージが対応づけられるので、パッケージとベース(可変点)はn対1の関係を持ちます。これは、関係づけにおいて本質的な違いで、アスペクト指向をソフトウェアプロダクトラインへ適用するうえで大きな制約となります。このためアスペクト指向はフィーチャ指向に置き換える必要があります。 もう1つは、モデル駆動型開発に用いるDSL自体にアスペクト指向を入れるというアプローチです。これをDomain Specific Aspect Language(DSAL)といいます。たとえば、トランザクションモデル、例外処理などに特化したDSLの開発での適用が考えられます。こうして汎用DSLに対して、そのDSLを補完するDSALを用意して可変性に対応します。

0

非分散アーキテクチャの原則は正しいか?

一般にスケーラビリティを得るためには、分散させないことがアーキテクチャの原則です。プロセス間通信のマーシャリングコストはインプロセスのローカルコールに対して桁違いのオーバーヘッドになるからです。また、分散トランザクションのロックもこの状況を悪化させます。それにもかかわらず、GoogleやAmazonなど大規模サイトは分散アプローチをとり、スケーラビリティを確保しています。この事実は非分散アーキテクチャの原則を否定しているともいえます。 企業システムや大規模Webアプリケーションを想定する場合、非分散のアーキテクチャの原則は有効でしょうか。分散させない原則は企業システムではなかなか現実的に実行は困難です。性能面だけでなく、管理コスト面で分散システムには不利益がありますが、本当でしょうか?性能面と管理面の2つを考えてみましょう。 性能面分散システムのスケーラビリティを考えるとき、マスターデータをどう扱うかが最も大きな問題と考えます。冗長性を排除した論理的に統合されたデータ定義の原則、”one fact in one place” はシステムが分散か集中化によらず有効な原則です。問題は、論理的に統合されたデータ定義を物理的にどう配置するかです。これには2つの考え方があります。いずれもスケーラビリティの観点から、shared nothingを原則とします。 1つはドメインモデル(論理データモデル)に対してユースケースで決定されるトランザクションスコープを単位としていく考え方。トランザクションスコープが分散しないように、独立したサービス、権限の範囲を単位とした配置とします。たとえば、注文に対して、製品出荷、決済に関する部分は別トランザクションとして切り離します。もう1つはマスターデータのパーティショニングを単位とする考え方です。たとえば、Web 2.0系のアプリケーションではユーザ単位に配置を決定します。この2つの考え方を物理的な配置の設計モデルとします。 性能的に最も重要なのは書き込みの帯域幅です。物理的にマスターデータを統合すると、書き込みに対する一貫性を確保しつつ、読み取りに対してはレプリケーションを使った性能改善ができます。しかし、これは誤ったアーキテクチャです。レプリケーションはバッチ型でそれ自体のオーバーヘッドが大きく、書き込みに対するスケーラビリティの改善となりません。書き込みの帯域幅を上げるには、マスターデータの物理的なパーティショニングを行い、それぞれパーティションを処理するホストに対して書き込み処理を並列に実行することが重要です。また、各ホストが処理すべきデータ量は統合ホストに比べて減るのでキャッシュのヒット率が上がります。ここで、ホストが書き込み処理に対して並列な動作をするためには、ホスト間にまたがるデータ操作ができるだけ減るようなデータ設計をユースケースから考える必要があります。たとえば、あるユーザへの別ユーザのコメントの追加などのデータ処理をどうするかです。これと類似の問題に、特定のパーティションに対する負荷が大きくなり、パーティションの切り直しが必要になる場合の対応があります。この対応ができるだけ少ないという前提での設計を考えるべきです。物理パーティショニングでは、これらが満たされる制約条件があるので、万能というわけではありません。 以上の考慮から、分散トランザクション処理と物理パーティニングは相反する要求であることがわかります。物理的に分割すれば一貫性に対するトランザクション処理が必要となり、分散させないために集約すれば、負荷が集中するからです。この相反では物理パーティショニングを優先します。スケーラビリティに対して、線形的な拡張が期待できるからで、また、安価なサーバハードウェアによる構築、耐障害性の利点があるからです。また、レプリケーションとパーティショニングも相反します。ここでは上記の説明のとおり、パーティショニングをとります。 管理面サーバ集約がもてはやされているように、システムが分散することによる管理コストの上昇があります。しかし、一方では、集約による障害対応のコスト高が伴います。集約によるデータ量の増大もバックアップコストを上げます。分散による管理コストの上昇はあるのですが、物理分割以前にデータの論理的な統合に伴うコスト削減効果が高いので、論理と物理をいっしょに考えるべきではありません。特に現状の企業システムでは、論理的に統合されていない、データのサイロが多数あることによる管理コストの負担が大きいからです。

0