この投稿は2017年9月27日15:32にSummerによって最終編集されました。
この記事はQ&Aを模した短編小説で、著者はユーモラスな文体で建築家の仕事を簡潔に分析しています。「私はソフトウェアアーキテクトになりたい」と。 これは若いソフトウェア開発者にとって素晴らしい選択肢です。 チームを率いて、データベースやフレームワーク、ウェブサーバーなどに関する重要な意思決定をしたいと思っています。 ああ、それならソフトウェアアーキテクトになりたくないんですね。 もちろん、重要な決定を下す側になりたかった。 それは構いませんが、重要な決定はリストに含めていません。それらは無関係な決定です。 どういう意味ですか。 データベースは重要な決定ではないと言っているのですか?私たちがどれだけ使っているか知っていますか? もしかしたらコストがかかりすぎるのかもしれません。 しかし、データベースは重要な決定の一つではありません。 どうしてそんなことが言えるんですか。 データベースはシステムの中核であり、すべてのデータは体系化され、分類され、インデックス化され、アクセスされます。 データベースがなければ、システムも存在しません。 データベースは単なる輸入輸出デバイスであり、分類、クエリ、情報報告のための有用なツールを提供しますが、これらはシステムアーキテクチャの補助的な機能に過ぎません。 助けは? これはひどい。 そう、補助的なものだ。 システムのビジネスルールはこれらのツールの一部を活用できるかもしれませんが、それらのツールは対応するビジネスルールに本質的に組み込まれているわけではありません。 必要に応じて、既存のものを別の道具に置き換えることも可能です。 そしてビジネスルールは変わりません。 そうですが、これらのツールは元のデータベースで使われていたため、再コーディングしなければなりませんでした。 それが君の問題だ。 どういう意味ですか。 あなたの問題は、ビジネスルールがデータベースツールに依存していると思っていることですが、実際はそうではありません。 少なくとも、良いアーキテクチャが提供されるまでは、こうはならないはずです。 本当におかしいです。 それらのツールを使わないビジネスルールはどうやって作成するのでしょうか? データベースツールを使わないとは言いませんが、依存しているわけではありません。 ビジネスルールはどのデータベースを使っているかを知る必要はありません。 では、どのツールを使うべきか分からないまま、どうやってビジネスルールを手に入れるのでしょうか? 依存関係を逆転させ、データベースがビジネスルールに依存しるようにします。 ビジネスルールがデータベースに依存していないことを確認してください。 そんな馬鹿なことを言っている。 むしろ、私はソフトウェアアーキテクチャの言語を使っています。 これが依存逆の原理であり、低レベル標準は高水準標準に依存すべきです。 そんなことない! 高レベルの基準(ビジネスルールを参照する場合)、低レベルの基準を呼び出す(データベースを参照する場合)。 したがって、高レベル基準は、発信者が呼びかけた相手に依存しているという原理に従い、低レベルの基準に依存します。 みんな知ってるよ! これは実行時には当てはまります。 しかしコンパイル時に求めているのは依存関係の反転です。 高レベルガイドラインのソースコードには、低レベルのガイドラインのソースコードが記載されてはなりません。 お願いだから! どうして電話をかけるのに言わずにできるの? もちろん問題ありません。 それがオブジェクト指向の意味です。 オブジェクト指向とは、実際のモデルを作成し、データ、機能性、そして一貫したオブジェクトを組み合わせることを指します。 コードを直感的な構造に整理することについてです。 そう言われてるの? ご存知の通り、これは明白な真実です。 はい、そうですが、オブジェクト指向ガイドラインを使う場合は、言及しなくても呼び出すことは可能です。 どうやってやるんだ? オブジェクト指向設計では、オブジェクト同士がメッセージを送り合います。 もちろん、その通りです。 送信者がメッセージを送るとき、受信者の種類を知らない。 使われる言葉によります。 Javaでは、送信者は少なくとも受信機の基本型を知っています。 Rubyでは、送信者は少なくとも受信側が受信したメッセージを処理できることを知っています。 そうです。 いずれにせよ、送信者は受信機の具体的なタイプを知りません。 そうだね、まあ、そうだよ。 したがって、送信者は特定の受信機の種類を明記せずに、機能を実行できる受信機を設計できます。 そうだ、そうだ。 分かりました。 しかし、送信者は受信者に依存します。 これは実行時には当てはまります。 しかし、コンパイルすると異なります。 送信者のソースコードは受信者のソースコードに言及したり依存したりしません。 実際、受信側のソースコードは送信側のソースコードに依存しています。 そんな筈はありません! 送信者は送るクラスに依存します。 おそらくソースコードから少しでも分かりやすくなるでしょう。 以下の段落はジャワ語で書かれています。 まずは送信者についてです: 荷物送信者; パブリッククラス Sender { private Receiver receiver; 公開送信者(受信者r){ 受信者 = r; } public void doSomething () { receiver.receiveThis (); } パブリックインターフェース Receiver { void receiveThis (); } }こちらが受信者です: パッケージ受信機; インポート送信者。 送信者; public class SpecificReceiver は Sender.Receiver { public void receiveThis () { //do something interesting を行います。 } }注:受信機は送信者に依存し、SpecificReceiverは送信者に依存し、送信者には受信機関連の情報はありません。 はい、でも嘘をついていますよね。受信機のインターフェースを送信者クラスに入れていますよね。 君は少しずつ理解し始めている。 何を知っている? もちろん、それは建築の原理です。 送信側は受信側が実装しなければならないインターフェースを持っています。 もしそれがネストクラスを使わなければならないことを意味するなら、...... ネストクラスは目的を達成する手段の一つに過ぎず、他にも方法はあります。 ちょっと待って。 これがデータベースと何の関係があるのでしょうか? データベースについて話し始めました。 コードをもう少し見てみましょう。 まずはシンプルなビジネスルールです: パッケージ businessRules; インポートエンティティ。 何か; パブリッククラス BusinessRule { private BusinessRuleGateway gateway; public BusinessRule (BusinessRuleGateway gateway) { this.gateway = gateway; } public void execute (String id) { gateway.startTransaction (); 何か thing = gateway.getSomething (id); thing.makeChanges(); gateway.saveSomething(物); gateway.endTransaction (); } }ビジネスルールはあまり重みを持ちません。 これは一例に過ぎません。 多くの異なるビジネスルールを実装するこのようなクラスは他にも存在する可能性があります。 では、ゲートウェイとは具体的に何でしょうか? ビジネスルールを通じてすべてのデータアクセス方法を提供します。 以下のように実装します: パッケージ businessRules; インポートエンティティ。 何か; public interface BusinessRuleGateway { Something getSomething (String id); void startTransaction (); void saveSomething(何かのもの); 無効終了トランザクション(); }注:これはbusinessRulesに掲載されています。 では、何かクラスとは何ですか? これは単純なビジネスオブジェクトを表しています。 私はそれをエンティティに分けました。 パッケージエンティティ; public class 何か { public void makeChanges () { //... } }最終的にBusinessRuleGatewayの実装では、このクラスは実際のデータベースを知っています: パッケージデータベース; import businessRules.BusinessRuleGateway; インポートエンティティ。 何か; public class MySqlBusinessRuleGateway は BusinessRuleGateway { public Something getSomething (String id) { // MySQL を使って get a thing. } public void startTransaction () { // start MySql transaction } public void saveSomething(何か) { // MySQL で save thing} public void endTransaction () { // end MySqlトランザクション } }さらに、ビジネスルールは実行時にデータベースを呼び出すことに注意してください。 しかし、コンパイル時にはデータベースがbusinessRulesに依存しています。 なるほど、わかった気がします。 多型を使って、データベースがビジネスルールから実装されていることを隠しているだけです。 しかし、ビジネスルールにすべてのデータベースツールを提供するインターフェースは依然として必要です。 いいえ、全く違います。 ビジネスルールにデータベースツールを提供しようとはしていません。 代わりに、必要なインターフェースを作成するためにビジネスルールを使っています。 これらのインターフェースを実装することで、適切なツールを呼び出すことができます。 はい、しかしすべてのビジネスルールですべてのツールを使う必要があるなら、そのツールをゲートウェイインターフェースに置くだけで十分です。 ああ、まだわかってないと思うよ。 何がわかるって? これはすでに明らかです。 各ビジネスルールは、必要なデータアクセスツールに対して1つのインターフェースのみを定義しています。 ちょっと待って、どう思う? これがインターフェース分離原則です。 各ビジネスルールクラスはデータベースの特定の機能のみを使用します。 したがって、各ビジネスルールが提供するインターフェースは対応する施設のみにアクセスできます。 しかし、そのため多くのインターフェースや、他のデータベースクラスを呼び出す小さな実装クラスが存在します。 よし、だんだん理解してきたな。 しかし、それはあまりにも散らかりすぎて時間の無駄です。 なぜこんなことをするのか? これは整理されていて時間の節約にもなります。 さあ、コードのためにたくさんコードを作れよ。 むしろ、重要なアーキテクチャ上の決定によって無関係な決定が遅れることもあります。 それはどういう意味ですか。 最初にソフトウェアアーキテクトになりたいと言っていたのを覚えていますよね? 本当に重要な決断はすべて自分で下したいのです。 はい、私もそう思いました。 データベース、ウェブサーバー、フレームワークについての意思決定をしたいですよね? そう、あなたはそれが重要ではないと言いますね。 ただの無関係な内容です。 そうです。 それです。 ソフトウェアアーキテクトが下す重要な決定は、データベース、ウェブサーバー、フレームワークに関する意思決定を可能にします。 でも、まずは自分でどれを決める必要がある! いいえ、うまくいきません。 実際、これらは開発サイクルの後半、情報がより豊富になったときに決定することができます。 アーキテクトがフレームワークを事前に特定したものの、必要な性能を提供できなかったり、耐え難い制約を導入した場合は大変なことです。 建築家が決定を延期することを決めたときだけ、情報が十分に揃ったときに決定を下します。 遅くリソースを大量に消費するIOデバイスやフレームワークを使わないチームは、アーキテクトの裁量で高速で軽量なテスト環境を作成できます。 本当に重要なことに関心を持ち、そうでない者を遅らせるのはその設計者だけであり、そのようなチームは幸運な存在です。 そんなことないよ、全然わからないよ。 この記事をよく見てください。さもなければ、さらに10年待たなければわかりません。
|