次の方法で共有



February 2016

Volume 31 Number 2

Cutting Edge - UXDD によるアーキテクチャの副産物

Dino Esposito | February 2016

Dino Esposito何年もコラムを書いていると、大半のソフトウェアが行っている効率的な方法を 1 つか 2 つ会得して、読者に推薦できればそれだけで満足です。ソフトウェア マーケティングの宣伝文句にだまされてはいけません。ソフトウェアは絶えず改善されていますが、世の中の大半の企業にとってソフトウェアはビジネスの中核ではありません。つまり、企業にとっては、同じソフトウェアを何年間も使い続けられる方がありがたいということです。Tiobe.com (英語) の指標によれば、2014 年の夏の時点でも、使用されているプログラム言語のトップ 10 に依然として Visual Basic 6 が入っていました。ただし、その 1 年半後には、かなりランクを落としていましたが。このことは、ソフトウェアの完全な作り直しをできる限り後回しにしようとする、企業の声なき声を裏付けているように思えます。実際問題として、こうした企業は、今でもビジネスを遂行しているソフトウェア テクノロジに関して、最低でも 5 年分のバックログを抱えています。しかし、こうしたバックログを抱えたシステムでもいざ更新するとなると、アーキテクトは最新鋭のソフトウェアを探すことになります。

ソフトウェア アーキテクチャの現状

ソフトウェア アーキテクチャについて、最近騒がれているキーワードは 2 つです。1 つは「CQRS」 (Command and Query Responsibility Segregation、コマンド クエリ責務分離)、もう 1 つが「Polyglot Persistence」です。CQRS については、最近の Cutting Edge シリーズで取り上げました。足がかりとしては、MSDN マガジン 2015年 6 月号の「一般的なアプリケーション向けの CQRS」(msdn.com/magazine/mt147237) をご覧ください。CQRS はアーキテクチャに関するガイドラインで、システムの状態を読み取って報告するコードと、システムの状態を変更するコードとを分離することを推奨しています。Polyglot Persistence は新しい実践手法で、同じデータ アクセス層のコンテキストで複数の保存テクノロジを使用することです。「Polyglot Persistence」という表現は、ソーシャル ネットワークが毎日管理しなければならない膨大な量のデータを扱うために、ソーシャル ネットワークが採用している複雑な技術ソリューションを 2 つの単語にまとめたものです。Polyglot Persistence の本質は、扱っているデータの種類や量にとって、理想的だと考えられる保存テクノロジを使用することにすぎません。

CQRS と Polyglot Persistence は、非常に大きなメリットやメリットになり得る可能性を秘めています。しかし、Visual Basic 6、Windows フォーム、Web フォームの大規模コード ベースに埋もれている複雑なビジネス アプリケーションのコンテキストにこの 2 つがどのように関わるかを理解するのはおそらく困難です。ただし、現実には関わりが存在し、それを見過ごすと、長期間運用しているプロジェクトや企業にとっては、不利に働く可能性があります。同時に、ソフトウェア アーキテクチャは、非常な忍耐を要するものであってはなりません。CQRS はすばらしいもののように思えますが、これを自身のシナリオに合わせるには、正しく全体像を見通せる必要があります。

そこで、UXDD の観点からソフトウェア アーキテクチャを考えてみます。すると、CQRS にも Polyglot Persistence にも適したアーキテクチャが簡単に見つかります。

タスクベースの設計

UXDD ワークフローの形態は、あらゆる規模の企業が既に採用しており、個人的には、10 人以下の少人数チームでも、数十億ドル規模の企業でも好まれているように思います。この形態を採用している UX チームの中には、社内外を問わず、エンドー ユーザーの協力を得て、画面の細部を作りこんでいるチームもあります。UX チームは PDF ファイルや HTML ファイルの形式でカラフルな資料いくつか作成して、開発チームに提供します。問題は、開発チームがバックエンド スタック全体の設計と構築を完了するまでその資料をほとんど見ようとしないことです。プレゼンテーション レベルで行われる実際のタスクを、ほとんどまたはまったく考慮しないでバックエンドの設計が行われることがあまりにも多すぎます。アーキテクトは、ビジネスロジックのタスクに取り組み、実装の最適化や一般化を行う方法については念入りに時間をかけます。一般に、データのプレゼンテーションやナビゲーションのボトルネックや次善策を十分検討することはありません。開発の終盤になってアプリケーションの実際のユーザー エクスペリエンスが理想的とはいえないことがわかっても、通常、費用対効果の高い方法で変更を実装するのはほぼ手遅れです (図 1 参照)。

ソフトウェア システムのボトムアップ設計とトップダウン設計の比較
図 1 ソフトウェア システムのボトムアップ設計とトップダウン設計の比較

現実に向き合いましょう。リレーショナル モデルは、間違いなくデータ ストレージとしては有効ですが、ソフトウェア アーキテクチャに関しては誤解があります。少なくとも、このモデルが登場してから 20 年が経ち、深刻な誤解を生み始めています。1990 年代半ばの Java 空間では、既にリレーショナル データ モデルと概念データ モデルとの間のミスマッチが問題になり、O/RM ツールによる実験へとつながりました。現在マネージャーになっている世代のソフトウェア アーキテクトは、信頼できるデータベース基盤がすべてだと教えられて成長してきました。信頼できるデータベースが、信頼できるソフトウェアの基礎となることは間違いありません。問題は、ドメインとアプリケーション ロジックの複雑さと量です。ただし、このようなロジックの一部をストアド プロシージャに追加して実行するようになるまでは、それほど大きな問題ではありませんでした。その上、駆け出しのソフトウェア アーキテクトは、古典的な 3 層アーキテクチャ (プレゼンテーション、ビジネス、データ) を目指し、その後、ドメイン駆動設計 (DDD) の階層アーキテクチャ (プレゼンテーション、アプリケーション、ドメイン、インフラストラクチャ) へと進みます。階層の数がどうであっても、設計は事実上ボトムアップです。

ボトムアップ設計が問題なく機能するには、少なくとも以下の 2 つの条件のいずれかが満たされる必要があります。

  1. 理想的な UI がリレーション モデルに非常に密接に関係している
  2. ユーザーが口出しせず、受動的である

ある優れた新しいテクノロジやフレームワークを宣伝するチュートリアルを読むと、ソフトウェア設計は正確な科学のように思えます。しかし、無菌の研究室から現実世界に飛び出すと、ソフトウェア設計は、恐怖、疑惑、疑念が渦巻く場所になります。そこは、「場合による」という 1 つのルールしか存在しない、あいまいな場所です。

UXDD では、情報の理想的なアーキテクチャおよびユーザーとシステムの理想的な対話について、ある程度明確なエビデンス (ワイヤーフレーム) が得られるまでは、本格的な開発を始めないよう提案しています。プレゼンテーション層のワイヤーフレームから始めるトップダウン設計では、ユーザーのニーズに真正面から向き合います。「頼んだものと違う」という辛らつな苦情を耳にする恐れは大幅に下がります。ワイヤーフレームが間違っていると評価されたとき、それは決して好みの問題ではなく、ビジネス上の問題である可能性が高いことを忘れないようにします。ワイヤーフレームへのフィードバックに目をつぶると、最終的なシステムに意図的なバグが生まれる可能性がありります。

最近のアーキテクチャの障害となる不一致をまとめたのが図 2 です。理想的なプレゼンテーション層を表すワイヤーフレームがあり、理解したとおりにビジネス ロジックを実装するコードがあります。残念なことに、この 2 つは必ずと言ってよいほど一致しません。ソフトウェア プロジェクトが、特に予算的に見て、ほぼ期待はずれだとすれば、原因はアーキテクチャの障害となる不一致にはないと自信をもって言えるでしょうか。

アーキテクチャの障害となる不一致
図 2 アーキテクチャの障害となる不一致

アーキテクチャの障害となる不一致への対処

控えめに言っても、ドメイン ロジックの全体をカバーする包括的なドメイン モデルは、やがてまったく意味がなくなります。ドメイン モデルという考え方、および DDD の全体的アプローチは、ソフトウェアの中心にある複雑さに取り組むことに他なりませんが、それも 10 年以上前のことです。それ以来多くのことが変わり、DDD の核となる一部の要素 (具体的には、戦略的設計の概念とツール) がこれまでに増して重要になりますが、個別に結び付くコンテキストの読み書きの側面すべてを網羅するオブジェクト指向ドメイン モデルを構築するのは難しく、非現実的です。

同時に、包括的なドメイン モデルという考え方は、ソフトウェアをボトムアップで見ていくのと同じです。ユーザーが希望することを理解し、モデルを念入りに作り、そのモデルをコーディングしてから、いくつか UI を加えることになります。奇妙に思われるかもしれませんが、成功するソフトウェアとは、どこか魔法のようなブラック ボックス (MBB) を土台に、使いやすく効率的な UX を重ねたものです。

ワイヤーフレームからエンジニアリング作業を始めると、実際に MBB でサポートすべき内容が正確にわかります。さらに、MBB がその機能を果たす限り、ユーザーが正式に求めているものにかなり近いシステムになります。そこには開発者の想定が入り込む余地はほとんどなく、ユーザーとの対話の大半はプロジェクトの初期フェーズにグループ化されます。変更は簡単で、UX テストに合格すれば、残りの大部分は実装の細部に関するものだけです。

UXDD では、タスクとイベントを重視します。トップダウン設計では、クリックや選択のようなユーザーの操作が出発点です。各ユーザー操作を、アプリケーション層のエントリ ポイントに結び付けます。たとえば、ASP.NET MVC では、すべてのコントローラー メソッド (プレゼンテーション層) はアプリケーション層のクラス内のエントリ ポイントに結び付けられます (図 3 参照)。

図 3 CQRS コントローラー

public class SomeController
{  
  public ActionResult SomeQueryTask(InputModel input)
  {
    var service = new QueryStack.SomeService();
    var model = service.GetActionViewModel(input);
    return View(model);
  }
  public ActionResult SomeCommandTask(InputModel input)
  {
    var service = new CommandStack.SomeService();
    service.GetActionViewModel(input);
    RedirectToAction(...);
  }
}

2 つの SomeService クラスはアプリケーション層のセクションで、SomeController クラスによって表されるプレゼンテーション層の一部から可視になります。この 2 つの SomeService クラスは、プレゼンテーションと同じ物理プロジェクトやアセンブリに含めることも、異なるアセンブリやプロジェクトに配置することもできます。このようなことからアーキテクチャ的には、アプリケーション層とプレゼンテーション層は連携することになります。つまり、(Web アプリ、モバイル Web アプリ、モバイル アプリ向けに) 複数のプレゼンテーション層が必要なときは、複数のアプリケーション層を用意してもかまいません。ただし、ロジックの再利用は難しくなります。

アプリケーション層では、承認された UI を使ってユーザーがトリガーできるタスクごとに、エントリ ポイント メソッドを用意します。受け取ったワイヤーフレームを忠実に再現すれば、各画面の流れが明確にわかります。間違えようがありません。効率が悪くなったり、速度が遅くなることはあるかもしれませんが、間違うことはありません。

アプリケーション層は、プレゼンテーション層とデータ転送オブジェクトを交換し、タスクに必要なすべてのワークフローを編成します。これを行うため、通常、アプリケーション層はなんらかの永続ストアとの間でデータを読み書きし、外部 Web サービスにアクセスして、計算を実行します。これは単なるドメイン ロジックで、ドメイン ロジックはユース ケースに応じて変わることはありません。Web またはモバイル プレゼンテーションのどちらから要求された場合でも、ビジネス ドメインのタスクは同じように動作し、すべて再利用可能です。ビジネス ロジックの考え方は、アプリケーション ロジックとドメイン ロジックという明確なセグメントに分離されます。アプリケーション ロジックは、プレゼンテーションの具体的なユース ケースを実装します。ドメイン ロジックは、プレゼンテーションやユース ケースに応じて変わらない部分です。

ドメイン ロジックは、Transaction Script や Table Module など、さまざまなパターンに従って設計することができます。このような設計では、ビジネス ルールは、使用するクラスに挿入される異物です。通常、ビジネス ルールは、操作の実現可能性についての応答を得るために呼び出す機能を形成します。DDD の本質だと誤解されることが多い Domain Model パターンは 1 つのパターンにすぎません。このパターンでは、実際のエンティティのように動作するクラスを作成後、ビジネス ルールを組み込み、クラスが提供するメソッドにアプリケーションを隠ぺいすることを提案しています。ドメイン ロジックを設計する方法に正解や間違いはありません。純粋に姿勢や効果の問題です。

タスクベースの設計では、操作がシステムの状態を変更するかどうか、またはシステムの状態を報告するかどうかが即座にわかります。CQRS 設計を使用すると、コマンドとクエリが自然に分離されます。コマンドとクエリを別のスタックに置くことで、これらを個別に作成および最適化する明確なメリットが得られます。そのため、問題が再発する恐れがなくなり、スケーラビリティが単純化される可能性もあります。CQRS は、UXDD のコンテキストと自然に調和します。

最後に保存

トップからボトムへと設計を進めていくと、最後は保存に行き着きます。早とちりしないでください。すべてのアプリケーションには、効率的に保存され、効率的にクエリされるデータが必要です。保存を最後に考えるのは、保存を軽視するということではありません。ユーザー指向の対話型システムでの保存の設計は、特に UX やドメイン ロジックなどの側面を明確にした後にのみ重要になります。このため、使用するデータベース テクノロジに制約はありません。さらに、CQRS 設計を採用すると、コマンド用の層やクエリ用の層など複数の保存層を簡単に用意して、必要に応じて異なるストレージ テクノロジやストレージ パラダイムに基づいて各層を個別に管理することもできます。たとえば、ある時点の分析結果を UI に報告する必要性があれば、イベントソーシング フレームワークを導入し、イベントに応じて更新や関連操作を追跡することもできます。その結果、システム内で起きていることをすべてログに記録し、自作のビジネス インテリジェンス分析の出発点としても利用できます。同時に、既存のデータをすばやくユーザーに提供する必要がある場合は、プレゼンテーションのニーズに合うデータのプロジェクションとイベント ストアとを同期した状態に保つだけです。この場合のデータのプロジェクションとは、一連の操作後に生成される状態のことです。これは、一連の銀行取引 (イベント) の後、銀行口座の残高 (プロジェクション) を把握するような場面と同じです。コマンドのスタックは、リレーショナル テーブル、NoSQL、イベント ストア、またはそれらの組み合わせに基づきますが、クエリのスタックは、プレーンな SQL Server ビューで単純に構成されるのがほとんどです。

このようなことを総じて Polyglot Persistence と呼びます。

まとめ

開発者が好むかどうかにかかわらず、ユーザーは直接のエクスペリエンスから直感的にシステムを判断します。現在、ソフトウェア プロジェクトの出費を抑える重要な要素は、ユーザーが望むものを迅速かつ正確に作成する能力です。正確に行うことだけでなく、正しい方法で行うことも重要です。UXDD では、できるだけ早い時期に作成するシステムの出力を早期に把握します。その結果、システム導入後にユーザーの不満を解決する回数が減ります。さらに、トップダウン設計を採用することにより、設計のエクスペリエンスは、効果的なソフトウェアをビルドできることが実証済みの CQRS や Polyglot Persistence など、その評判を大きく上回る最新のパターンへと自然に導かれていきます。


Dino Esposito は『Microsoft .NET: Architecting Applications for the Enterprise』(Microsoft Press、2014年) および『Modern Web Applications』(Microsoft Press、2016年) の共著者です。JetBrains の Microsoft .NET Framework および Android プラットフォームのテクニカル エバンジェリストでもあります。世界各国で開催される業界のイベントで頻繁に講演しており、software2cents.wordpress.com (英語) や Twitter (@despos、英語) でソフトウェアに関するビジョンを紹介しています。

この記事のレビューに協力してくれた技術スタッフの Jon Arne Saeteras に心より感謝いたします。