REST論文からアーキテクチャを進化させる方法論を学ぶ

こちらは[DMM.com Advent Calendar 2018](https://qiita.com/advent-calendar/2018/dmm) 11日目の記事です。

## はじめに

弊社は20年間成長し続けるサービスを持っている一方、技術の負債も十分に溜まりました。この現状に対して、弊社が改善策を取り込んでいます。
アーキテクチャをどううまく進化させて行くのか考えているうちに、偶然に有名な論文のことを思い出しました。

> Fielding, Roy Thomas. Architectural Styles and the Design of Network-based Software Architectures. Doctoral dissertation, University of California, Irvine, 2000.
> <https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm>

十年前に「RESTful」流行始まった時に、論文全体に興味がほぼなかったので、 **CHAPTER 5** の結論の部分を鵜呑みに読んで、色々「RESTful」的なWEBサービス構築を行っていましたが。10年後の今に論文全体をもう一度細かく読んだら...

> なるほど！
> アーキテクチャを進化させる方法論があるんだ

と感じられます。
なので、論文の内容を紹介させていただきます。
(すべての内容の紹介ではなく、論文の論理構成、既存システムのアーキテクチャの理解と更新に関する理論の概要をご紹介いたします。)

## 論文の経緯

1990年 www が発明されて以来、物凄く発展されて来ました。

<img src="https://qiita-image-store.s3.amazonaws.com/0/54714/dd49b352-2e20-3ad1-d3b9-e584911f74af.png"  width=70%>

_(データ : NetCraft and Internet Live Stats (elaboration of data by Matthew Gray of MIT and Hobbes' Internet Timeline and Pingdom))_

その10年間Webのアーキテクチャーを定義する標準も徐々に変更されていきました。論文の作者の [Roy Thomas Fieldingさん](http://roy.gbiv.com/) が、1993年から積極的にWWWのプロジェクトを参加していて、ソフトウェアの開発や下記の標準の定義等の仕事をしました。その時に、どうやって新しい機能を、既に大規模にデプロイされているアーキテクチャにうまく導入し、混乱や悪い影響を発生させないのか、作者の課題でした。

-   HTTP/1.0
    -   1996年 RFC 1945
-   HTTP/1.1
    -   1997年 RFC 2068 / RFC 2145
    -   1999年 RFC 2616
-   URI
    -   1995年 RFC 1808
    -   1998年 RFC 2396
    -   2005年 RFC 3986

2000年のこの論文は、作者がその当時webアーキテクチャを改善・進化させる考え方のまとめです。

## 論文の構成

<img src="https://docs.google.com/drawings/d/e/2PACX-1vTTD_wZDIDsVRRluV92ePql1AYwO4cu0O2gvFoXuBjQefzVPuQi0QJowFNqKqp1r-R5NUMsNhQlJZij/pub?w=960&h=720"  width=70%>

## 論文の貢献

-   ① **アーキテクチャスタイル** でソフトウェアアーキテクチャを理解するためのフレームワークを定義しました。
    -   ソフトウェアアーキテクチャを記述するための **一貫性のある用語集** も含まれています。
-   ② **ネットワークベースアプリケーション** の **アーキテクチャスタイル分類方法論** 。
    -   あるアーキテクチャスタイルがシステムに適用されると、このスタイルの制約で色々 **アーキテクチャプロパティ** が生まれるので、これで色々スタイルを確認して分類しました。
-   ③ アーキテクチャスタイルの **REST** を記述しました。
-   ④ モダンなWorld Wide Webのアーキテクチャの設計とデプロイにおける REST アーキテクチャスタイルの **適用** と **評価** 。

`③` と `④` はよく知られていますが、 `①` と `②` は方法論として、重視されなかったようです。
本文は `①` と `②` を中心に、既存システムのアーキテクチャをどう進化させるかと学びます。

## 論文の使い方

論文が長いので、アーキテクチャ設計の目的によって、その論文の一部のみをよく読んでもいいと思います。

### WEBサービスを構築したい方

-   第5章： Representational State Transfer (REST)

### 既存アーキテクチャを進化させる方法論を学びたい方

-   第1章の全部（基本概念）
-   2.2 設計の評価 (スタイルでアーキテクチャの評価の方法論)
-   4.3 アプローチ (応用例)

### 既存アーキテクチャを進化させる方法論を応用したい方

-   上の基礎知識 (つまり 1 / 2.2 / 4.3 )
-   深く応用するための参考素材として:
-   2.3 (ネットワークベースベースアプリケーションアーキテクチャの) 重要なプロパティ
-   第3章 ネットワークベースベースアプリケーションのアーキテクチャスタイル
    -   スタイルリスト <https://www.ics.uci.edu/~fielding/pubs/dissertation/net_arch_styles.htm#tab_3_6>

第5章以降の内容（REST）、ネット上に資料が多いのです。
本文はアーキテクチャを進化させる方法論を学びたいため、主に第1章〜第4章の一部内容を話します。

## ソフトウェアアーキテクチャの基本

第1章の内容:概念の弁別や用語の定義等、特に、アーキテクチャ要素を定義する上で、大事なプロパティとスタイルの概念を記述しました。

まず私の理解:それぞれの概念の [関係図](https://gist.github.com/dulao5/c4d9dd33b727f08077feed9b6bc48cb9#file-1-architectural-define-dot) です：

<img src="https://user-images.githubusercontent.com/689799/49709493-ff570180-fc77-11e8-9f83-6c6748c7400a.png"  width=90%>

### ソフトウェアのアーキテクチャの定義

-   ソフトウェアアーキテクチャとは、システムのある実行段階に、Run-time要素の抽象化であります（Run-time
    Abstraction ）
-   システムにたくさん抽象階層、たくさん実行段階が持っているかもしれないので、それぞれの抽象階層の実行段階はアーキテクチャが存在します。
-   「抽象化」の方法は下記アーキテクチャ要素・プロパティの紹介が終わったら話します。

### アーキテクチャの要素(Elements)



> A software architecture is defined by a configuration of architectural elements--components, connectors, and data--constrained in their relationships in order to achieve a desired set of architectural properties.

ソフトウェアアーキテクチャは、アーキテクチャ要素（構成要素、コネクタ、及ぶデータ）の構成によって定義されます。それらの関係が制約されるので、望ましいアーキテクチャプロパティのセット（設計意図）を実現します。

#### コンポネント / Component

> A component is an abstract unit of software instructions and internal state that provides a transformation of data via its interface.

コンポーネントはソフトウェア命令と内部状態の抽象的なユニットです。インタフェース経由でデータの変換を提供します。
コンポネントの定義は、他のコンポネントに提供するインタフェースとサービスで定義すべきです。（インタフェース後ろの内部実装と関係ありません）

##### 私の理解

データを処理する機能＋パブリックインタフェースを持っています。

#### コネクタ / Connector

> A connector is an abstract mechanism that mediates communication, coordination, or cooperation among components.

コネクタは、コンポーネント間の通信、調整、または連携を仲介する抽象的な仕組みです。
コンポネントとの違い：コネクタは、このコンポネントインタフェースから、他のコンポネントインタフェースまで、データを転送しますが、データを変更しません。

* 例：
    -   shared representations (わからない)
    -   remote procedure calls (RPC)
    -   message-passing protocols (メッセージパッシング)
    -   data streams (データストリーム)

#### データ / Data

> A datum is an element of information that is transferred from a component, or received by a component, via a connector.
> 


データは、コネクタ経由でコンポーネントから転送される、またはコンポーネントによって受け取られる情報の要素です。

* 例：
    -   byte-sequences
    -   messages
    -   marshalled parameters
    -   serialized objects

##### 私の理解

コンポネント間のコネクタ経由の情報のみ「データ」であり、作者は（アーキテクチャの視点から見ると）「コンポネント内部の情報は `データ` ではない」と言っていますが、「ファイル」は内部の情報ではなく「転送」であるって言いました。
（ネットワークベースアプリケーションのアーキテクチャ見ると、 `ファイル名` はファイルシステムのインタフェースのパラメータであり、ファイル中身は転送された結果です。アーキテクチャの視点でデータを見るのは大事なことです）

### アーキテクチャの構成 / Configuration

> A configuration is the structure of architectural relationships among components, connectors, and data during a period of system run-time.

構成とは、システム実行時のコンポーネント、コネクタ、およびデータ間のアーキテクチャ上の関係の構成です。

#### 私の理解

つまりアーキテクチャ図によく表現されている全体構成のことです。

### アーキテクチャのプロパティ / Properties

> The set of architectural properties of a software architecture includes all properties that derive from the selection and arrangement of components, connectors, and data within the system.

システム内のコンポーネント、コネクター、およびデータを選択と配列すると、プロパティのセットが得られます。

> The goal of architectural design is to create an architecture with a set of architectural properties that form a superset of the system requirements.

アーキテクチャ設計の目標は、アーキテクチャプロパティセットを持つアーキテクチャを作成して、そのプロパティセットはシステム要件のスーパーセットである（つまりシステムの要件を満足する）ことです。

### アーキテクチャのスタイル / Style

> An architectural style is a coordinated set of architectural constraints that restricts the roles/features of architectural elements and the allowed relationships among those elements within any architecture that conforms to that style.

アーキテクチャスタイルは、協調しているアーキテクチャ制約セットであります。アーキテクチャ要素の役割/機能を制限し、そのスタイルに適合するアーキテクチャ内の要素間の許容される関係を制限しています。

#### 私の理解

本論文の目的は「アーキテクチャを理解するためのフレームワーク」を発見するので、色々システムのアーキテクチャをハイレベルで比べたり、評価したり、分類したり、共通特徴を定義したりをします。
アーキテクチャ要素はアーキテクチャの基本ユニットであり、細かすぎます。
アーキテクチャの構成はそれぞれシステムの全体像で、異なるシステムのアーキテクチャを比べられないのです。
アーキテクチャのプロパティはそれぞれのシステムのアーキテクチャの設計成果物であり、それでも異なるシステムを比べられないのです。
その理由で、作者が「アーキテクチャのスタイル」というハイレベルの概念を定義して、それを使ってアーキテクチャを比べたり、評価したり、分類したり、共通特徴を定義したりをすることができます。

-   なので概念階層的には
    -   細かい要素→全体構成\|制約→制約セット→スタイル

> New architectures can be defined as instances of specific styles \[38\]. Since architectural styles may address different aspects of software architecture, a given architecture may be composed of multiple styles. Likewise, a hybrid style can be formed by combining multiple basic styles into a single coordinated style.

-   具体的なアーキテクチャ→instance\_of→アーキテクチャスタイル
    -   システムがたくさん側面があるので、 具体的なアーキテクチャ `→instance_of→` 複数アーキテクチャスタイル
-   basic styles `*→1` single coordinated style / hybrid
    style
-   なので概念階層的には
    -   細かい要素 → システムの側面の制約 → 制約セット → 基本スタイル `*→1` 一つの協調スタイル

## アーキテクチャの設計の評価（第2.2章）

既に完成した実行しているシステムの「アーキテクチャのRun-timeの特徴を評価するのができます」が、我々は「アーキテクチャ案を実装する前に、アーキテクチャ設計を評価する仕組み」がもっと欲しいです。でも、「客観的にアーキテクチャの設計を評価することは難しい」ので、「システムの制約の裏の設計理論根拠を検査して、制約から得たプロパティセットと設計目的を比べる」必要があります。

<img src="https://user-images.githubusercontent.com/689799/49740203-15e07580-fcd7-11e8-92c4-516ce978e90b.png" width=60%>

*キーポイントは「制約/constraints」を「特定/identity」することです*

まだ覚えていますか？第1章にスタイルの定義:

> アーキテクチャスタイル `＝` 協調しているアーキテクチャ制約セット

なので「スタイル」は「制約セット」に名称付ける便利に引用できるものですね。作者が第3章で、よく使われてるネットワークベースアプリケーションのアーキテクチャスタイルを洗い出して、用意しておきましたので、「制約セット」を議論する時に「スタイル名」だけを言うと便利になります。

なので

> アーキテクチャの設計の決定 `＝` 何かしらのスタイルを応用することと一緒です

逆に

> 制約を特定したら `⇒` 設計者がその当時に導入したスタイルがわかります

それで、アーキテクチャを評価する具体的な方法がありました：

-   評価したいアーキテクチャの制約を特定します。
-   システムの色々側面の制約セットが、対する複数のスタイルを求めます。
    -   スタイルの解空間を派生ツリー(derivation tree)にします。
    -   一番最初は、このツリーが root note だけで、「NULLスタイル」であります
    -   制約Aを特定して、設計者がその当時に導入したスタイルを推論して、派生ツリーに入れます
    -   制約Bも特定して、対するスタイルも派生ツリーに入れます
    -   最後に、派生ツリー（つまりできたハイブリッドスタイル）を確認します
        -   第3章の経験を活用して
        -   スタイル　→　プロパティにします
        -   プロパティで、全体的にアーキテクチャを評価します

特に、 `(協調している)制約セット` や `(その制約から得た)プロパティセット` や `(該当制約に対する名称の)スタイル` 3つの概念よく論文の後半で転換されるので、その３つ概念の関係図を簡潔にまとめます：


<img src="https://user-images.githubusercontent.com/689799/49742757-86d65c00-fcdc-11e8-8338-3e5b7d39e2e4.png" width=50%>

### 派生ツリー(derivation tree) の例
<img src="https://user-images.githubusercontent.com/689799/49741190-35789d80-fcd9-11e8-8a4e-17bffa8d2d1e.png" width=50%>

## Webアーキテクチャの設計：問題と洞察 ☛ アプローチ（第4.3章）

作者が HTTP/1.0 ・ HTTP/1.1を設計する当時、WEB初期(HTTP/0.9以前)のアーキテクチャの記述や設計理論が足りませんでした。
作者のアプローチは３つのSTEPです：

### ① 初期のWEBアーキテクチャの制約を特定する

第1章の通りに、「制約→スタイル→アーキテクチャプロパティ」の経路で、プロパティから見ると、理論根拠が **見えるようになります。** 

> 仮説I：WWWアーキテクチャの背後にある設計の理論根拠は、Webアーキテクチャ内の要素に適用される制約セットからなるアーキテクチャスタイルで記述できます。

### ② インターネット規模の分散型ハイパーメディアシステムに期待されるアーキテクチャプロパティを特定する

つまり要件分析です。
新しい要件に対するアーキテクチャプロパティの洗い出して、第2章の通りに、派生ツリーに新しいベーススタイルを入れることができます。

> 仮説II：現代のWebアーキテクチャの望ましい特性をよりよく反映する新しいハイブリッドスタイルを導き出すために、WWWアーキテクチャスタイルに制約を加えることができます。

### ③ STEP②で得た新しいアーキテクチャスタイルを指導方針として、Webアーキテクチャの拡張・変更提案を評価することができます。

第2章の評価方法で、提案を新しいスタイルの制約と比べて、コンフリクトがあるかどうか見えます。
コンフリクトがあると、該当提案が一つ・複数のWebの原則と違反することがわかります。

> 仮説III：Webアーキテクチャを変更するための提案を、新しいWWWアーキテクチャスタイルで評価し、展開前のコンフリクトを分析することができます。

## まとめ

10年前に論文の結論だけを読んだこと、損でした。もちろんこの論文の第5章のみ読んでRESTを学ぶことはいいですが、この論文のアーキテクチャの理論も非常にいいと思いますので、アーキテクチャに興味あるかた、ぜひ読んでください。
アーキテクチャ様々な定義がありますが、この論文の論理構成は非常いいと思います。一貫性のある用語の定義、既存システムのアーキテクチャの分析方法、アーキテクチャの拡張・変更案に対する実装前の評価方法、「既存アーキテクチャを進化させる方法論」として、弊社に参考になれると思います。
今後、方法論を応用するため、また読みたいと思います。