docker runでエラー 'No such file or directory'
さくらのDocker入門
Dockerの理解を深めるために、さくらのDocker入門を見ながら実際に手を動かしていきました。すると、早速理解できていないことに気づきました。
1 | docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:5.7 |
この部分です。docker runの--linkオプションの意味を理解していなかったので、手元にあるDocker実践ガイドで--linkオプションの説明を探しました。
linkオプションについて
mw0001というコンテナの起動で--link mariadb0001:db0001オプションを利用しており、その説明は以下のようになっていました。
- これから起動するコンテナ
mw0001は、稼働中のコンテナmariadb0001とリンクを張る - コンテナ
mw0001において、mariadb0001コンテナの環境変数を取得することができる db0001はエイリアス名であるmw0001が取得できるmariadb0001コンテナの環境変数名には、エイリアス名を大文字にした文字列が付与される
ということなので、エイリアス名を大文字にしたDB0001をprefixとした環境変数として、mariadb0001コンテナの環境変数を取得できるのだろうことはわかりました。
上記の説明の次のページになんのためにlinkオプションを利用するのかが記載されていました。
Column linkとは
Dockerにおけるlinkは、単一のDocker環境内で稼働する複数のコンテナ間において、コンテナの環境変数を他のコンテナで利用する機能です。
コンテナは、起動するたびにIPアドレスなどが変わるため、コンテナ間で通信を行う際に、環境変数に定義されたIPアドレスやポート番号を環境変数に定義し、その環境変数を別のコンテナで利用できるようにします。
なるほど、そういう目的なのですね。実際に試してみます。
コンテナmariadb0001の作成
まず、MariaDBのコンテナを作成します。本にしたがって行いますので、ベースイメージはcentos:7.5.1804となります。
yumリポジトリの追加
MariaDBの最新版を導入するため、リポジトリファイルを用意し、yum.mariadb.orgで提供されるリポジトリを使えるようにします。
1 | [mariadb] |
書籍のbaseurlはアクセスできなかったので修正しました。
Dockerfileの作成
Dockerfileは書籍のものを記載(したつもりでした)。
1 | FROM centos:7.5.1804 |
Dockerfileに記載のENTRYPOINTのシェルを準備したり、MariaDBの設定ファイルの準備も行いました。
イメージのビルド
では早速imageをbuildします。Dockerfileがあるディレクトリに移動し、以下のコマンドを実行します。
1 | $ docker image build -f Dockerfile -t centos:mariadb0001 . |
ということで、無事ビルドできました。
コンテナの起動
ビルドしたイメージからコンテナを起動します。
1 | $ docker run -d -e DBNAME=testdb -e MARIADBUSER=root -e MARIADBPASSWORD=mysqlPassword -v /var/lib/mysql:/var/lib/mysql:rw --name mariadb0001 centos:mariadb0001 |
起動したコンテナのIDが返ってきました。
無事起動できていると思いきや
1 | $ docker ps -a |
Exited…止まってしまっています…
起動しない原因の調査
まずはログをみてみます。
1 | $ docker logs 1ad8c112f237 |
DockerfileでCOPYしているはずのファイルがないと言われています。そんなはずはないと思って、なんどか再ビルドしたりしてみましたが全く変化がありません。
検索して出てくる結果は、docker image buildのタイミングでNo such file or directoryエラーが出るというものばかりで、docker container runのタイミングでエラーになるケースは見当たりません。
エラーの原因
もう一度Dockerfileをよくみてみました。すると、書籍はファイルパスがダブルクォートで括られていましたが、自分のDockerfileはシングルクォートになっていました。
もしやと思ってダブルクォートに変更後、再ビルド→起動してみると、無事起動しました!
1 | $ docker ps -a |
ダブルクォートで記載しないといけない点に関しては公式ドキュメントにも記載がありました。
こちらの下の方に注釈があり、その中で記載されています。
1 | exec 形式は JSON 配列として解釈されます。 |
なるほど、JSONなのですね、JSONでは文字列を括るのはダブルクォートでないとエラーになってしまいます。そういうことなのですね。
まとめ
Dockerfileでのexec形式([]で引数を取るパターン)では、文字列をダブルクォートで括るということを忘れないようにします。
次回はちゃんとlinkのテストを行いたいと思います。
その他
この調査でよく使ったコマンド
docker container prune
止まっているコンテナを一括削除docker ps -a
全てのコンテナの一覧表示docker logs <コンテナID>
コンテナのログを出力する。エラーが起こった時には真っ先に確認するdocker image rm <イメージ名>
指定したイメージを削除する
単数形/複数形の変換がおかしいときの外部キー制約がエラーになる場合の対処法
外部キー制約の設定ができない
テーブルを作成するためにmigrationファイルを作成しdb:migrateしたら思いもよらないエラーが発生したので対処法を調査しました。
エラー内容
既存のテーブル(document_bases)があり、そのテーブルのidを外部キーに持つテーブル(document_views)を作成します。
migrationファイルを準備します
1 | class CreateDocumentView < ActiveRecord::Migration |
db:migrateします。すると以下のようなエラーが表示されました。
1 | ActiveRecord::StatementInvalid: Mysql2::Error: Key column 'document_basis_id' doesn't exist in table: ALTER TABLE `document_views` ADD CONSTRAINT `document_base_id_on_document_views` FOREIGN KEY (`document_basis_id`) REFERENCES `document_bases` (`id`) |
原因調査
最初なぜエラーになるのか全くわからなかったのですが、よく見るとKey column 'document_basis_id'となっていて、存在するカラムdocument_base_idと異なっています。
調べてみるとbasesはbaseの複数形でもあり、basisの複数形でもあるようです。basesから単数形に戻すときにbaseではなくbasisを選択されてしまっているようです。
対応方法
t.referencesのオプションであるforeign_keyでなんとか指定できないかと思い、add_foreign_keyのオプションを調べてみました。
https://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/add_foreign_key
するとoptionsの説明の最初に答えが書いてありました。
1 | :column |
Defaults to to_table.singularize + "_id"と書かれているので、singularizeメソッドを試してみました。
1 | [1] pry(main)> 'bases'.singularize |
ということでforeign_keyのオプションにcolumn: :document_base_idを指定することで無事migrateできました。
修正済migrationファイル
1 | class CreateDocumentView < ActiveRecord::Migration |
まとめ
Railsの単数形/複数形変換で存在しないカラム名/テーブル名に変換されてしまった場合は明示的に名前を指定するようにする。
APIドキュメントをちゃんと読むようにする。
AmazonLinux2のDocker Imageにnginxをインストールする
ベースイメージの選択
最終目標として、AWS ECS(以下ECS)でRailsアプリケーションを動作させたいと思っています。ECSで利用するイメージのベースはなにがよいかわかっていないので、とりあえずAmazonLinux2を利用します。一旦テストのためにローカルでDockerfileを作成してみます。
AmazonLinux2のイメージはdockerhubにありました。
https://hub.docker.com/_/amazonlinux
tagはlatestや2とすれば大丈夫のようです。
nginxのインストール
Dockerfileを記述していきます
1 | FROM amazonlinux:latest |
docker image buildを実行します
1 | $ docker image build -f Dockerfile -t al2_nginx:latest . |
nginxのパッケージがないようなので調べてみると、 amazon-linux-extras install nginx1.12でインストールが可能とのこと。Dockerfileを編集します。
1 | FROM amazonlinux:latest |
そして、再度ビルドします
1 | $ docker image build -f Dockerfile -t al2_nginx:latest . |
依存関係によって82ものパッケージがインストールされますが、無事nginxはインストールできたようです。
ただ気になるメッセージがありました。
1 | NOTE: The livepatch extra is in public preview, not meant for production use |
livepatch extraというのは本番用ではないということと、nginx1.12のサポートがすでにを終わっているということでした。
nginxのバージョン変更
nginxのバージョンをあげるにはどういう風に指定すればいいのかを調べてみると、以下のページが見つかりました。
https://dev.classmethod.jp/articles/al2-nginx1-new-extras-topic/
記事に書いてある内容ですと、nginx1と指定するとよさそうです。
再度Dockerfileを更新します。
1 | FROM amazonlinux:latest |
再度buildします。
1 | $ docker image build -f Dockerfile -t al2_nginx:latest . |
今度は1.16.1がインストールできました(2020年6月現在)
まとめ
- AmazonLinux2のDockerImageはDockerhubから取得できる。
- AmazonLinux2にnginxをインストールする場合は、amazon-linux-extrasコマンドを利用する
- トピックをnginx1とすることで1系の最新バージョンがインストールできる
- extrasリポジトリで配布されるパッケージは、トピック変更が発生するため、定期的なOSパッチ更新などのタイミングで利用中のトピックのサポート状況を確認する。Dockerfileのメンテナンスを行う。
次にRubyのインストールとRailsアプリケーションのデプロイを行いたいと思います。
100人のプロが選んだソフトウェア開発の名著 後編
プロが選んだソフトウェア開発の名著 後編
前回の続きです。51以降も読みたい本がたくさんありました。
持っていてもう一度読みたい本
-
ケント・ベックの本。アジャイルの原点とも言えます。今読むと原点に帰って今の状況を俯瞰できるかもしれません。わたしが持っているのは古い方です。
-
ソフトウェア開発のプロジェクトを成功に導くために必要な原理原則が書かれています。
-
偉大なプログラマになるための指針が書かれています。忘れそうになったときに何度も繰り返し読みたい本です。
-
ちょっと手を出しづらいタイトルですが、ミックさんが紹介していて、無駄なページが1ページもないとおっしゃっているので是非読みたいです。この紹介文が書かれた時点で20年前の本ということは、30年前の本ということです。確認したら1991年初版発行でした。こちらもワインバーグさんの本です。
-
最近スプリントがうまく回せていないので、もう一度手法を見直したいです。
-
アジャイルプラクティスと同様、スプリントがうまく回せていないので読みたいです。
-
最近チケット作成など管理系の仕事が多くてうんざりしています。仕事が楽しくできてないので、初心を取り戻すべく読んでみたいと思います。
-
ここで紹介されているのは第1版です。紹介されいている時代は第2版はまだ出てないです。わたしはこの本を読んでcase式についてしっかり理解してからSQLの幅がグッと広がったのを感じました。とても良い本です。いつでも再読したい本です。
-
ActiveRecordなど今あるアーキテクチャパターンはほとんどこの本で説明されています。オブジェクト指向に傾倒しているわたしとしてはマーチン・ファウラーさんの本は読まないわけにはいきません。
持っていないけど読みたい本
-
紹介している前田修吾さんは計算機科学の専門教育を受けずにプログラマになった。そのことで大変な思いをしたので、同じような人にこの本を薦めたいとのこと。自分も物理専攻で計算機科学の専門教育を受けておらずちょっとしたコンプレックスを感じることがあります。というか、情報系の授業を受けていた人たちが羨ましいです。
-
ワインバーグさんの本。紹介してくれている方もワインバーグさんの他の著書も読んでみてはどうか?と言っています。
-
なかなかテストコードを書く習慣がつかない自分を戒めてくれるのではないかと期待しています。
まとめ
後編もボニュームのある本がそろっていました。比較的古い本が多いですが、紹介されてから10年経った今も色褪せてないことは間違いないでしょう。読み終わったら紹介します。
100人のプロが選んだソフトウェア開発の名著
プロが選んだソフトウェア開発の名著
本棚を整理していたら、100人のプロが選んだソフトウェア開発の名著が出てきました。本が好きなので、本を紹介する本は読みたくなってしまいます。2012年出版の本ですが、内容や紹介されている本はプロが選んでいるだけあって、長年読まれている名著ばかりで古い感じはありません。持っていてもう一度読みたい本、持ってないけど読みたい本をリストアップしたいと思います。
持っていてもう一度読みたい本
UNIXネットワークプログラミング〈Vol.1〉ネットワークAPI:ソケットとXTI
2010年くらいに組み込みLinuxの仕事をしているときに読んだ本です。昔を懐かしむとともに、昔は理解できなかったところが今は理解できるかもしれないと思います。
-
こちらも組み込みLinuxの仕事をしているときに読んだ本です。UNIXのシステムコールを理解したいと思います。今読むことで新しい発見があるかもしれません。詳解UNIXプログラミング 第3版で新しい版も出ています。
-
ワインバーグさんの本をいつかまとめて読みたいと思っています。この本では紹介されていないですがライト、ついてますか―問題発見の人間学も読みたいです。
-
こちらはKindle版を購入したのですが、内容を思い出せないので再読します。
-
前職の時に読書会を行って全部読みました。ですが、最近自分がレガシーコードを生産してしまっているのではないかという危機感を感じているので再読します。
-
本書で紹介されているのはこちらですが、最近第二版を買ったので読みたいと思います。サンプルコードで利用している言語がJavaからJavaScriptに変わっていたのは衝撃でした。
-
内容をはっきり思い出せないので再読します。
-
一度内容をしっかりまとめたいので再読します。
-
最近小さな問題に頭を悩まされています。紹介文を読んで、これらの問題解決のために新しいパラダイムを自分に導入したいと思います。
-
この本はサンプルコードがわかりづらくて挫折した記憶があります。自分が理解しているオブジェクト指向をさらに高めるために再読したいです。
-
あのnaoyaさんが紹介しています。最近モチベーションが下がってきているので、サブタイトルにあるような
持続するやる気をいかに引き出すかを知りたいと思います。 -
以前一緒に働いていた同僚から勧められた本です。その当時はちゃんと理解できなかったので再読します。
持っていないけど読みたい本
-
本書で紹介されているのはこちらですが、第二版が出ているので第二版を買おうと思います。紹介してくれている方は数学に対する劣等感があるそうで、数学ガールを読んだけど理解できなかったとのことです。わたしと全く一緒だなと思いました。わたしは大学で物理を専攻していたのですが、数学が理解できずコンプレックスをなくすために数学研究会のサークルに入ったくらいです。数学が好きになれるよう読んでみたいと思います。
-
広範囲な問題解決を行う場合、パッケージ、ライブラリを作ることが良い方法なのかなと思います。そのために読んでみたいと思います。
-
紹介文にあるように、いろんなプログラミング言語に影響を与えた言語の成り立ちを知ることはプログラミング言語を理解する上で有益だと思います。
まとめ
長くなってしまったので、100のうちの50までまとめました。51からの後半はまた後日記載したいと思います。
マイクロサービスにおける単一責任の原則
動機
前回の動機で書いたように、マイクロサービスアーキテクチャには凝集性はマイクロサービスを考える際に重要な概念であり、SRP(単一責任の原則)の定義によって認識が強化されたと記載されていました。その概念はマイクロサービスを設計していく上で重要になりそうなので、しっかりと理解したいと思います。
凝集性とは
凝集性の定義を確認します。意味はわかるのですが言葉にするのは難しいです。ウィキペディアによると、凝集度(ぎょうしゅうど、コヒージョン、cohesion)とは、情報工学においてモジュール内のソースコードが特定の機能を提供すべく如何に協調しているかを表す度合いである。とのことです。
ウィキペディアの高い凝集度に記載の説明、凝集度は、あるコードがどれだけそのクラスの責任分担に集中しているかを示す尺度である。オブジェクト指向プログラミングでは、クラスの凝集度を高めるようにそのクラスの責任範囲を設定することが有益とされている。凝集度の高いシステムでは、コードの読みやすさと再利用の容易さが増し、複雑さが管理可能な程度に抑えられる。がわかりやすいかなと思います。この説明で重要だと思う点はクラスの凝集度を高めるようにそのクラスの責任範囲を設定することが有益という点です。これは責務駆動設計であり、単一責任の原則に従うべきであるということです。責務駆動設計についてはオブジェクトデザインが参考になると思います。この本は10年くらい前、まだオブジェクト指向がしっかり理解できていなかった頃に読んで、とても参考になりました。みなさんもある処理を追加するときに、この処理はどのオブジェクトに行わせるのがよいのかを考えると思います。それが責務駆動設計です。
単一責任の原則について
単一責任の原則について、再度確認したいと思います。
アジャイルソフトウェア開発の奥義によると、
クラスを変更する理由は1つ以上存在してはならない
と記載されています。これだけを見るとどういうことかわかりづらいですし、しかもそんなこと可能なのか?と思ってしまいます。実際には、クラスを変更する理由はただ1つであるように設計するということです。なぜそうすべきなのでしょうか。
単一責任にすべき理由
アジャイルソフトウェア開発の奥義にはいくつか単一責任にすべき理由がかかれていますが、正直あまりわかりやすいものではないと思います。
わたしは、単一責任にすべき理由はただ1つで依存関係を減らすということだと思います。
これは静的言語で特にいえることだと思うのですが、変更したクラスに直接依存しているクラスは再コンパイルが必要です。クラスが複数の責務を持ち、いろんなクラスと依存関係を持っている場合、ある一つの変更で、依存関係を持っているクラス全てを再コンパイルしないといけません。再コンパイルしたプログラムはさらにデプロイを行わなければいけません。
これは静的言語だけではありません。わたしが業務で関わっているRailsでも複数の責務を持つクラスを変更すると、そのクラスに影響する全てのクラスのspecを実行しなければなりません。その数は少ない方が良いです。
変更する理由を1つにするということは、関係のないクラスの再コンパイル、デプロイが発生しないということだと思います。プログラマが知るべき97のことで、ロバート・C・マーティンは、良いシステムデザインとは、システムのコンポーネントがそれぞれ独立してデプロイできるようになっているデザインのことですと言っています。まさにその通りだと思います。
ただ依存関係を持たずに単独で仕事をするクラスはあまりありません。ということは、結局あるクラスを変更すると、依存関係を持っているクラスも再コンパイル、デプロイが発生するのではないか?という指摘があるかもしれません。その場合は依存関係逆転の原則を利用します。わたしがSOLID原則の中で一番好きな原則です。また別の機会で詳しくみていきたいと思います。
マイクロサービスにおける単一責任の原則の応用
では、マイクロサービスの設計において、単一責任の原則はどう考慮していくのが良いでしょうか。
先ほどデプロイの話が出てきました。あるサービスを変更したときに、依存関係を持っているサービスが複数あると、それらを同時にデプロイしなければいけません。それっは不可能ではないかもしれませんが難しいことだと思います。それを防ぐために単一責任の原則を守っていくべきだと思います。
しかしそれでもプログラムと同じような問題は発生します。サービス間のインターフェースなどを変更してしまうと、依存関係を持っているサービスも変更せざるを得ません。それを防ぐためには依存関係逆転の原則をサービス間に適用します。サービスは他のサービスに依存するのではなく、サービス間のインターフェースに依存するようにします。そうすれば、各サービスの変更を行っても他のサービスは変更を行わなずにすみます。
まとめ
単一責任の原則をマイクロサービスの設計にどう活用するかをみてきました。マイクロサービスは以下の二つのことを守れば、他のマイクロサービスの変更の影響を受けずにすむでしょう。
- サービスの凝集度を上げ、責務をはっきりさせる。
- サービス間はサービスに依存するのではなく、サービスのインターフェースに依存するようにする。
マイクロサービスを設計するときには気をつけていきたいと思います。
プログラマが知るべき97のこと 09. 他人よりまず自分を疑う
動機
マイクロサービスアーキテクチャを読んでいて(寄り道するからなかなか進まないですが)、凝集性はマイクロサービスを考える際に重要な概念であり、SRP(単一責任の原則)の定義によって認識が強化されたと記載されていました。
引用がプログラマが知るべき97のことだったので、懐かしいと思いパラパラめくっていたら、全く別のところに目がとまりました。09. 他人よりまず自分を疑うというエッセイです。
他人よりまず自分を疑う
エッセイの内容を要約すると次のような感じです。
- プログラマは自分が書いたプログラムが思い通りに動作しないことがあると、なかなか自分を疑うことをせず、何か他の原因だと思う
- しかし実際はだいたい自分が原因である
- なので、他に原因があることを証明することよりも、自分のコードのバグを見つけることに時間とエネルギーを注いだ方がずっと良い
- 自分の書いたコードを疑い、デバッグに関して一般に「すべき」と言われていることをやる
- 自分のコードを徹底的に調べて、それでもバグが見つからない場合に、他の調査を開始する
なぜこのエッセイが気になったか
少し前、同僚から以下のような指摘を受けました。
「あなたの変更が原因で、バグが発生していました。修正しましたので、レビューお願いします。」
そんなはずはないのに…と思ったのですが、まずは修正してもらったコードをレビューしました。修正は私の変更とは関係ないところがされていて、しかもバグは残ったままのようでした。冷静に、「この修正では、バグはなくなっていないのではないですか?この部分を修正すべきだと思います。」とコメントで伝えました。
コメントの内容は伝わったようで、バグの原因であるコードを修正してくれたのは良いのですが、まだ納得がいかないようで、「あなたが修正する前は、正しく動作していました。」と言ってきます。修正した箇所をしっかり理解していれば、そんなことを言うはずがありません。「本当ですか?」と聞いてみたのですが、「本当です!」と強気な態度を崩しません。
結果的に、修正箇所だけではなく、その周りのコードの説明をすることで理解してもらえました。しかし、なぜこのような無礼なことを言ってくるのでしょうか。相手の精神状態などいろいろ原因はあると思いますが、プログラマ、エンジニアとして足りてないことは確かです。そしてチーム内に無駄な軋轢を生んでいます。
まとめ
他人よりまず自分を疑う
常に自分が間違っているかもしれないと思いながら、自分のコード、作業に細心の注意を払うことでバグをなくすことができます。また、バグをなくす過程で発生する不要な人間関係の悪化を防ぐことができます。そしてなにより、自分の失敗からよりたくさん学ぶことができます。そういった姿勢、マインドがプログラマ、エンジニアの成長する条件だと思います。
AWSの薄い本 IAMのマニアックな話 その3 IAMグループのデザインパターン
前回まで
前回はIAMポリシーとそのデザインパターンについて学びました。
今回はIAMグループのデザインパターンについて理解したいと思います。
IAMグループのデザインパターン
IAMグループのデザインパターンは大きく2つの方法があります。
- 個々のIAMグループには、グループの責務にあったIAMポリシーのみを付与し、IAMユーザーは複数のIAMグループに所属する方法
- 1つのIAMグループに必要な権限を全て付与し、IAMユーザーはそのIAMグループにのみ所属する方法
それぞれのメリット、デメリットをみていきましょう
複数のグループに所属するバターン
ユーザーが複数のグループに所属することを前提とします。
メリット
ポリシーが複数のグループから利用されることがほとんどない(ポリシー:グループ = 1: 1)ので、変更の際の影響範囲がわかりやすくなります。
ポリシーから見ると、グループは1つに特定されるように設計すべきだということです。
また、必須の権限を全ユーザーが所属するグループに付与することで、抜け漏れを防ぐことができます。
デメリット
ユーザーがどのグループに所属しているのか、どのグループに所属すべきなのかの管理が煩雑になりそうが気がしています。本来ポリシーを付与すべきでないユーザーに付与してしまう事故が起こりかねないと思います。
グループ内に複数のポリシー
ユーザーが1つのグループに所属することを前提とします。
メリット
ユーザーは基本的に1つのグループにしか所属しないため、ユーザーから見るとシンプルな構造になります。また、ポリシーも複数のグループから利用されることが前提になるため、自然とシンプルで使いやすいポリシー設計になります。
デメリット
権限を細かくわけたい場合は、そのユーザーのためのグループのような設計になってしまうかもしれません。1ユーザーあたり1グループ作成しないといけなくなる可能性もあり、グループの数が増えて管理が煩雑になるかもしれません。
まとめ
IAMグループのデザインパターンとして、複数グループに所属するパターンと、グループ内に複数ポリシーを配置するパターンの2つを見てきました。
筆者はこの2つの方法に、機能的な優劣はないので、どちらを選択するかは好みの問題であると言っています。しかし、筆者はグループ内に複数ポリシーを配置するデザインパターンを利用することが多いとのことです。特に好みがなければグループ内に複数ポリシーを配置するパターンを利用するのがよいのではないでしょうか。
わたしは、この2つのデザインパターンの違いは責務(権限)をどこに凝縮するかによるのかなと思います。ユーザーが複数のグループに所属するパターンだと、グループが責務の単位となり、グループがそれぞれ疎になると思います。設計としてはこちらの方がきれいかもしれません。グループ内に複数のポリシーをもつパターンだと、ポリシーが疎になります。グループ自体はポリシーを複数持っており重複する部分もあるため、設計はそれほどきれいではないかもしれませんが、ユーザーから見た時にとてもシンプルになると思います。
一旦はグループ内に複数のポリシーを持つパターンで設計を考えてみるという指針にしようと思います。
次回はIAMのセキュリティーについて読んでいきたいと思います。
クリーンアーキテクチャ
動機
前回、ヘキサゴナルアーキテクチャについて調べました。日本語訳で、似たようなアーキテクチャであると紹介されていたクリーンアーキテクチャを知ることでより深くヘキサゴナルアーキテクチャを知ろうと思います。
書籍 Clean Architectureとブログの内容について
原文と日本語訳(はもちろん一緒)と書籍でクリーンアーキテクチャに言及している章をみてみましたが、内容はすべて一緒でした。なので、ここからは書籍の22章をもとに内容を理解していきたいと思います。
クリーンアーキテクチャ
アーキテクチャの特徴
ヘキサゴナルアーキテクチャの紹介のなかで、実践テスト駆動開発で採用したものと記載がありました。この書籍の中では、17章のMainクラスを分解するで、Mainクラスからさまざまな責務を抽出した結果、「ポートとアダプタ」アーキテクチャになったという形で利用されていました。こちらの書籍についてはまた別の機会で詳しくみていきます。
いろんな類似のアーキテクチャがありますが、共通する点は「関心ごとの分離」という目的を持っている点です。外部との依存関係がなくなるため、外部の環境(UI,DBなど)は交換可能になります。

この図はブログでも紹介されています。正直言って、六角形が円になっただけのような気がしなくもないです。層がすこし増えているかなというのと、ビジネスロジックがEnterprise Business RulesとApplication Business Rulesにわけられているところが変わったかなというくらいです。
このアーキテクチャを動作させるもっとも重要なルールは、依存性のルールであると言っています。そのルールは
ソースコードの依存性は、内側(上位レベルの方針)だけにむかっていなければいけない。
ということです。外部に依存してはいけないということです。次にこのアーキテクチャを構成する各要素を書籍を引用して紹介します。
エンティティ
エンティティは最重要ビジネスルールをカプセル化したもの。
ユースケース
ユースケースはアプリケーション固有のビジネスルールが含まれている。ユースケースは、エンティティに入出力するデータの流れを調整し、ユースケースの目標を達成できるように、エンティティに最重要ビジネスルールを使用するように指示を出す。
インターフェースアダブター
インターフェースアダプターはユースケースやエンティティに便利なフォーマットから、データベースやウェブなどの外部エージェントに便利なフォーマットにデータを変換するアダプター。
この層のインターフェースに依存するように実装することで、外部エージェントを交換可能にしているのだと思います。
フレームワークとドライバ
図のもっとも外側の縁は、フレームワークやツールで構成されています。たとえば、データベースやウェブフレームワークなどです。フレームワークとドライバの層には詳細が詰まっています。ウェブも詳細、データベースも詳細。被害が抑えられるようにこれらは外側に置いておきます。
境界を越える
図の右下に、円の境界線をどのように越えるべきかの例が記載されています。コントローラーからプレゼンターへの制御の流れがあるが、ユースケースを経由しています。この際に、依存関係逆転の法則を用いてコントローラー、プレゼンター共通のインターフェースを提供します。
制御の流れは外側から内側であるが、ソースコードの依存関係は内側から外側へ発生します。
まとめ
こうした単純なルールに従うのは、それほど難しいことではなさそうです。ルールを守っていればいずれ多くの苦痛から解放してくれると言っています。
全体のまとめ
クリーンアーキテクチャも関心ごとの分離が目的のアーキテクチャです。外部を交換可能にするためには依存関係を守ること、しっかりと関心ごとを分離することが重要です。ここでもオブジェクト指向の基本原則であるSOLIDが重要になってきます。特にD(依存関係逆転の法則)は重要だと思いました。
マイクロサービスにおけるサービスはオブジェクト指向におけるオブジェクトと同義だと思います。責務を明確にし、インターフェースを正しく定義し利用しやすいマイクロサービスを設計したいものです。