小さなアーキテクチャ







ソフトウェアアーキテクトになりたい:







これは開発者にとって良い目標です。







チームを管理し、データベース、フレームワーク、Webサービスなどについて重要な決定を下したいと思っています。







うん それでは、ソフトウェアアーキテクトになりたくありません。







もちろん欲しい! 私はすべての重要な決定を下す人になりたいです。







これは良いことですが、重要なソリューションをリストしませんでした。 特別な役割を果たさないソリューションをリストしました。







つまり? データベースは重要な決定ではありませんか? どれくらいのお金を彼らに使っているか知っていますか?







おそらく多すぎる。 いいえ、データベースは最も重要な決定事項の1つではありません。







どうやってそれを言うことができますか? データベースはシステムの中心にあります! すべてのデータはそこで収集され、ソート、インデックス付け、およびアクセスされます。 それがなければ、システムはありません!







データベースは単なるI / Oデバイスです。 たまたま、並べ替え、クエリ、レポートのためのいくつかの便利なツールを提供していますが、これらはすべてシステムアーキテクチャのフレームワーク内の補助的な側面です。







補助? これはクレイジーです。







はい、補助的。 システムのビジネスルールは、これらのツールの一部を使用する場合があります。 しかし、それらはビジネスルールにとって不可欠ではありません。 必要に応じて、これらのツールを他のツールに置き換えることができますが、ビジネスルールは変わりません。







はい、しかし、元のデータベースのツールを使用するため、すべてのコードを書き直す必要があります。







まあ、それはあなたの問題です。







どういう意味?







問題は、ビジネスルールがデータベースツールに依存していると考えることです。 そうではありません。 いずれにしても、優れたアーキテクチャを開発したかどうかに依存するべきではありません。







これはクレイジーです。 使用する必要があるツールを使用しないビジネスルールを作成するにはどうすればよいですか?







データベースツールを使用しないとは言いませんでした。 彼らに頼るべきではないと言った。 ビジネスルールは、使用している特定のデータベースを知る必要はありません。







ツールが何であるかを知らずにビジネスルールでツールを使用する方法







依存関係を逆にする必要があります。 データベースはビジネスルールに依存します。 ビジネスルールをベースから独立させます。







あなたはいくつかのゴミを言います。







それどころか。 私はソフトウェアアーキテクチャの言語を話します。 これが依存関係の反転の原理です。 低レベルの側面は、高レベルの側面に依存する必要があります。







もっとゴミ! 高レベルの側面(私が理解しているように、ビジネスルールについて話している)は、低レベルの側面(私が理解しているように、データベースを意味します)を引き起こします。 したがって、呼び出し側が呼び出されたモジュールに依存するのと同じように、高レベルのモジュールは低レベルのモジュールに依存します。 誰もがそれを知っています!







実行時には、これは事実です。 しかし、コンパイル時には、依存関係を逆にする必要があります。 高レベルのソースコードは低レベルのソースコードに言及すべきではありません。







よくやった! 言及せずに何かを呼び出すことはできません。







もちろんできます。 これがオブジェクト指向の本質です。







関連するオブジェクトへのデータと機能の組み合わせにおける、現実世界のモデリングにおけるオブジェクト指向の本質。 コードを直感的なアーキテクチャに整理する。







あなたは教えられましたか?







誰もがそれを知っています。 明らかに、これは本当です。







疑いはありません。 疑いはありません。 それでも、オブジェクト指向の原則を使用すると、実際に何かを言及せずに呼び出すことができます。







OK どうやって?







オブジェクト指向設計では、オブジェクトが互いにメッセージを送信することを知っていますか?







はい もちろん。







メッセージの送信者が受信者のタイプを知らないことを知っていますか?







言語に依存します。 Javaでは、送信者は少なくとも基本的な受信者タイプを知っています。 Rubyでは、送信者は少なくとも受信者が送信されたメッセージを処理できることを知っています。







はい ただし、どちらの場合も、送信者は特定のタイプの受信者を認識しません。







うん。 わかった はい







したがって、受信者のタイプに言及せずに、送信者が受信者で機能を開始する理由になる場合があります。







うん。 そうだね。 わかった。 ただし、送信者は依然として受信者に依存しています。







実行時に、はい。 しかし、コンパイル時ではありません。 送信者のソースコードは言及されておらず、受信者のソースコードに依存しません。 受信者のソースコードは、送信者のソースコードに依存します。







いや 送信者は、メッセージの送信先のクラスに依然として依存しています。







おそらく例が必要です。 Javaで記述します。 最初の送信者パッケージ:







package sender; public class Sender { private Receiver receiver; public Sender(Receiver r) { receiver = r; } public void doSomething() { receiver.receiveThis(); } public interface Receiver { void receiveThis(); } }
      
      





これで、パッケージが受信者になります。







 package receiver; import sender.Sender; public class SpecificReceiver implements Sender.Receiver { public void receiveThis() { //do something interesting. } }
      
      





受信者は送信者に依存していることに注意してください。 SpecificReceiverはSenderに依存していることにも注意してください。 そして、送信者は受信者について何も知りません。







はい、しかしこれは不正行為です。 受信側インターフェースを送信側クラスに挿入しました。







今、あなたは理解し始めます。







何がわかりますか?







もちろん、アーキテクチャの原則。 送信者は、受信者が実装する必要があるインターフェイスを所有しています。







これが、ネストされたクラスを使用する必要があることを意味する場合、...







ネストされたクラスは、物事を成し遂げるための1つの方法にすぎません。 他にもあります。







OK それからデータベース? これから始めました。







別のコードを見てみましょう。 最初のビジネスルールは次のとおりです。







 package businessRules; import entities.Something; public class BusinessRule { private BusinessRuleGateway gateway; public BusinessRule(BusinessRuleGateway gateway) { this.gateway = gateway; } public void execute(String id) { gateway.startTransaction(); Something thing = gateway.getSomething(id); thing.makeChanges(); gateway.saveSomething(thing); gateway.endTransaction(); } }
      
      





このビジネスルールは特別なことは何もしません。







これは単なる例です。 ほとんどの場合、さまざまなルールを実装するこのようなクラスが多数あります。







OK、このGateway



は何ですか?







ビジネスルールが使用するすべてのデータアクセス方法を提供します。 その実装は次のとおりです。







 package businessRules; import entities.Something; public interface BusinessRuleGateway { Something getSomething(String id); void startTransaction(); void saveSomething(Something thing); void endTransaction(); }
      
      





これはbusinessRulesパッケージではないことに注意してください。







うん、わかった。 そして、 Something



クラスとはSomething



ですか?







単純なビジネスオブジェクトを表します。 エンティティと呼ばれるパッケージに入れます。







 package entities; public class Something { public void makeChanges() { //... } }
      
      





そして最後に、BusinessRuleGatewayの実装があります。 このクラスはデータベース自体について知っています:







 package database; import businessRules.BusinessRuleGateway; import entities.Something; public class MySqlBusinessRuleGateway implements BusinessRuleGateway { public Something getSomething(String id) { // use MySQL to get a thing. } public void startTransaction() { // start MySQL transaction } public void saveSomething(Something thing) { // save thing in MySQL } public void endTransaction() { // end MySql transaction } }
      
      





繰り返しますが、ビジネスルールは実行時にデータベースを呼び出しますが、コンパイル時にはデータベースパッケージを呼び出します。 それは言及し、businessRulesパッケージに依存しています。







わかりました、わかりました。 ポリモーフィズムを使用して、データベースの実装をビジネスルールから隠すだけです。 ただし、ビジネスルールにすべてのデータベースツールへのアクセスを提供するインターフェイスが必要です。







いいえ、まったくありません。 すべてのデータベースツールでビジネスルールを提供しようとはしていません。 それどころか、私たちのビジネスルールは、必要なものだけのインターフェイスを作成します。 これらのインターフェイスを実装すると、適切なツールが既に呼び出される場合があります。







ええ、しかし、ビジネスルールにこれらのツールがすべて必要な場合は、それらすべてをgateway



インターフェイスに配置する必要があります。







あなたはまだ理解していないようです。







何がわかりませんか すべてが非常に明確であるように思えます。







各ビジネスルールは、データへのアクセスに必要な方法についてのみインターフェイスを定義します。







やめて なに?







これは、インターフェイス共有原則と呼ばれます。 各ビジネスルールクラスは、データベースエンジンの一部のみを使用します。 したがって、各ビジネスルールは、これらのメカニズムにのみアクセスできるインターフェイスを提供します。







しかし、これは、他のデータベースクラスを呼び出すために、多数のインターフェイスと多数の小さな実装クラスを処理する必要があることを意味します。







いいね 今、あなたは理解し始めていることがわかります。







しかし、これは混乱と時間の無駄です! これはなぜですか?







すべてを清潔に保ち、時間を節約します。







みなさん! これは、コードのための単なるコードの束です。







それどころか、これらの重要なアーキテクチャ上の決定により、無関係な決定を延期することができます。







どういう意味?







ソフトウェアアーキテクトになりたいと思って始めたことを覚えていますか? すべての最も重要な決定を行いたいですか?







はい、それが私が欲しいものです。







これらのソリューションには、データベース、Webサーバー、およびフレームワークがありました。







ええ、あなたはこれらは重要な決定ではないと言った。 あなたは彼らが特別な役割を果たさないと言った。







そうだね。 プレイしないでください。 ソフトウェアアーキテクトが行う重要な決定により、データベース、Webサーバー、およびフレームワークに関する決定を下すことができなくなります。







しかし、これらの決定を最初に行う必要があります!







いいえ、必要ありません。 実際、これらの決定を可能にする必要があるのは、開発サイクルのかなり後の段階(より多くの情報がある場合)です。







Griefは、データベースを時期尚早に選択し、フラットファイル構造で十分であることに気付くアーキテクトです。







Griefはアーキテクトであり、Webサーバーを時期尚早に選択してから、チームが単純なソケットインターフェイスを必要としていたことを認識しています。







Woeは、アーキテクトがフレームワークを時期尚早に課しているチームであり、そのフレームワークが必要のない機会を提供し、共存できない制限を追加することを認識しています。







祝福されたのは、チームが十分な情報を持って決定を下すまで、これらすべての決定を先送りにする方法を提供した建築家のチームです。







Blessedは、リソースを集中的に使用するI / Oデバイスとフレームワークからアーキテクトが非常によく分離されているため、チームが迅速で簡単なテスト環境を作成できるチームです。







建築家が本当に重要なことを心配し、重要ではないものを先送りにするチームは幸いです。







ナンセンス。 何も分かりません







まあ、多分あなたは10年で理解するでしょう...あなたがマネージャーにならなければ。








All Articles