ニート(図コンテクスト知識アタッチメント)のテキスト読み取りチャネル・アーキテクチャ

免責事項:この記事はブロガーオリジナル記事ですが、許可ブロガーなく再生してはなりません。https://blog.csdn.net/yunqiinsight/article/details/91492546

、永遠の急速な発展のWorldプログラム、マスター今日のスキルは来年時代遅れかもしれないが、時代を超えた何かがあり、これらをマスターし、あなたがプログラムの海で迷子にないであろう、アーキテクチャは、このような考えであります事のようなもの。

この記事では「道路のクリーンアーキテクチャ、」研究ノート、ソフトウェアシステムの値からの記事、アーキテクチャ値と目標の仕事を認識し、アーキテクチャ、指導思想(設計原理)、部品のサイズと分割方法の基本設計を理解するために、コストを削減するため、右建築意思決定や建築デザインを作るための部品の設計、方法およびデカップリングの選択のコンポーネントの境界の様々なコンポーネント間の通信の方式間の依存関係、著者の独自の解釈を与えられました。

Alibabaのミドルウェア、マイクロチャネル公共番号ダイアログボックス「フレームワーク」を送信し、知識のコンテキスト図「道路のクリーンアーキテクチャ」を得ることができます。

ソフトウェアシステムの値

アーキテクチャは、そのアーキテクチャの価値を理解するために、我々は最初のソフトウェアシステムの値をクリアする必要があり、ソフトウェア・システムの一部です。ソフトウェアシステムの値は、2つの側面、値および構造値の振る舞いを持っています。

行動値は、需要の実現、および保護の可用性(機能的バグ、パフォーマンス、安定性)を含め、ソフトウェアのコアバリューです。これは、ビジネス初勝利を支援することは、当社のエンジニアの主要な責任であり、私たちの作業内容のほぼ90%を占めました。値のアーキテクチャは、当社のソフトウェア(ソフトウェア)が柔らかくすることですので、ビジネスには、値の明確な、安定したフレームワークは無視することができますが、非常に重要なの事業は、多くの場合、明確な、急速な発展はありませんが、その後、建築場合(ソフト)。これは、2つの方法で理解することができます。

  • 要件が変更されると、ソフトウェアの変更は簡単で、便利なことする必要がありました。
  • 実施形態を変更して表示さの難しさ(範囲)の幾何学的変化にかかわらず、特定の形状(形状)の変更。

我々は行動の値にのみ焦点を当てた場合、それはアーキテクチャの値を気にしない、何が起こるのだろうか?これは、反復バージョンとともに、本の中で例真の記録である、コードの増加の行あたりのコストを変更するには、対応する、エンジニアのチームの規模が拡大し続けますが、コードの行の合計数が安定し、生産効率のエンジニアを減らします。それが追いついていないこと、収益がお金を失い始めるかどうボスの観点から、それは、会社のコストの急速な成長です。

可視値アーキテクチャの重要性は、我々は良い作品と建築的価値の値との関係を処理する方法を確認するために緊急かつ重要な次の有名なマトリックスから始まります。

次のように重要な緊急行列は、作業の順序は次のとおりです。1.重要と>重要2.ない3.>緊急重要ではないが、緊急の重要な4>緊急ではありません。需要の振る舞いの値は通常、PDで作られて実現し、より緊急のが、常に、特に重要ではありません。仕事内容インフラ値、上げ定型発達の学生が重要であるが、基本的には非常に緊急ではないが、短期的、あまりにも行いません。死にません。値が2アーキテクチャ(重要緊急ではないが)下落したので、物事の価値の挙動は、1と3(重要かつ緊急、緊急しかし重要ではありません)落ちます。我々は我々の仕事の枠組みの中で1と3つの別々のインサートと一緒に混合取る必要があり、コードをノックダウンする前に、学生を開発しています。
 

第二に、ターゲット・アーキテクチャの仕事

以前の値のアーキテクチャを説明し、建築的価値は、その全ライフサイクルサポートソフトウェアシステム、理解しやすいシステムの一部を詳細にターゲット・アーキテクチャは、システムの構築および保守要件を満たすために少なくとも人件費を使用するために、分かりやすく、された作品であります展開する、変更しやすく、維持しやすい、使いやすいです。優れたアーキテクチャのあらゆる側面のライフサイクルのために別の追求を持っています:

  • 開発段階では:;不必要なコラボレーションを避けるために、異なるコンポーネントの責任異なるチーム足場の複雑なコンポーネントの多くを使用しないでください。
  • 展開フェーズ:スクリプトと構成ファイルの山の展開に依存しないでください。より多くの重質成分の展開を、作品自体の展開は無価値である一方で、部品点数を削減するために、可能な限りほとんどありません。
  • フェーズを操作する:異なるアーキテクチャは、さまざまな要件に応じて口座に一定の長さを取るために、開示したアーキテクチャは、システム動作中に役割を果たすべきである:実体はクラスに、開発者の実施形態、機能、動作の設定にアクセスできるようにすることですと、または機能モジュールの形で明確に名前の目立つ位置は、対応する機能について説明占めます。
  • 保守フェーズ:クエストは、コストとリスクを削減します。クエストコストがどこでどのように最善の問題を解決するために、既存のソフトウェアシステムの仕事をタップし、新しい機能を識別したりすることです。リスクは、変更を行ったときに、それが新たな問題に由来することができるです。
     

第三に、プログラミングパラダイム

実際には、いわゆるフレームワークは、制限源は通信手段が、上限コンパレータを制限する、制限依存配置場所に制限することです。プログラミングのパラダイムは、それが私たちの制御フローとデータフローを制限し、最も基本的な制限である:構造化プログラミングがコントロールの直接転送を制限し、オブジェクト指向プログラミングは、制御の間接的な移転を制限し、関数型プログラミングは、割り当てを制限し、私はあなたが見ると信じてここで、我々は無知な力に目を向ける必要があり、Shajiao、コントロールの上のShajiao間接転写の制御の直接転送、精巧後ろに、心配しないでください。

最近3つのプログラミングパラダイムでも、半世紀のための新しいプログラミングパラダイムを半世紀の歴史を持っていない、未来はないかもしれません。制限、制御の転送を制限すると、データの割り当てを制限するプログラミングパラダイムを意味するので、他にも広がりを欠いています。興味深いことに、提案されたこれらの3つのプログラミングパラダイムの時系列は、前から後ろに、すべての人の直感に反するかもしれです:関数プログラミング(1936)、オブジェクト指向プログラミング(1966)、構造化プログラミング(1968 )。

1.構造化プログラミング

構造化プログラミングは、シーケンシャル構造、分岐構造、これら三つのプログラム構造の任意の環状構造を証明して使用するように構成され、後藤の使用を制限することができます。構造化プログラミングの遵守は、エンジニアがいる限り、これらは余分なコードが識別され、自分自身を証明するように、使用可能な構造を証明している一連のコードの一部で、その推論プログラムを証明するために数学のようにすることができ、それを推測することができるよう、プログラム全体の右セックス。

コントロールの直接転送するための上述の構造化プログラミングは、実際には、goto文を制限し、制限されていました。コントロールの直接転送とは何ですか?関数呼び出しや後藤声明で、コードは他のコードを実行するために、オリジナルのプロセスでターンを継続しないと、あなたはどのようなコードの実行を指摘しました。なぜ、goto文を制限しますか?goto文のいくつかの用途は、モジュールになりますので、再帰的に小さく、証明可能な単位に分割することはできません。主要な問題の分割コア値の使用は、プログラミング構造分解です。

実際には、構造化プログラミングの遵守は、エンジニアはプログラムが数学者自身の権利のようなものであることを証明することができない、唯一の物理学者として、彼のプログラムは一時的に(バグを発見していない)改ざんされていないと述べました。数式や物理学の方程式の最大の違いは、数式を証明することができ、物理的な式がある限り、現在の実験データの改ざんがそれを取らなかったとして、我々はそれが正しいと信じて、証明することはできません。プログラムは同じで、すべてのテストケースに合格した、我々はこのプログラムが正しいことを信じて、問題を見つけられませんでした。

2.オブジェクト指向プログラミング

関心のある唯一の多型アーキテクチャの観点から、カプセル化、継承、および多型を含むオブジェクト指向プログラミング、。ましょ米国も依存反転であるコンポーネント間通信機能を呼び出し、によって多型より便利で安全な方法(ように制御依存とは逆の流れ方向)に基づい。

非オブジェクト指向プログラミング言語では、どのように我々は、相互のデカップリングを達成するためにコンポーネント間の関数呼び出し?答えは、関数ポインタです。Cで書かれたオペレーティング・システムのような、以下の構造がIOデバイスドライバのみがそれ自身の実装に関数ポインタを参照する必要がある特定のIOデバイスを切り離すように定義されます。

struct FILE {
    void (*open)(char* name, int mode);
    void (*close)();
    int (*read)();
    void (*write)(char);
    void (*seek)(long index, int mode);
}

この関数ポインタを通じて、コンポーネント間の通信は非常に脆弱であり、技術者は、契約の初期化関数ポインタに厳密に従ったものでなければならない方法、および厳密に限り、人は契約に準拠していないとして、これらのポインタを呼び出すための合意に基づいて、プログラム全体を追跡し、排除することが極めて困難と生成されます。バグ。したがって、インターフェースを介して、オブジェクト指向プログラミング関数ポインタの使用を制限 - 実施抽象クラス - 継承多型の代替方法を。

制御の間接的な転送のために上述のオブジェクト指向プログラミングは、実際には、関数ポインタの使用を制限する、制限されています。コントロールの間接転写とは何ですか?コードは、元のプロセスは、他のコードを実行する代わりに続け、とではありませんが、あなたが知らない何のコードの特定の実装、あなただけのチューニング関数ポインタまたはインターフェイス。

3.関数型プログラミング

関数型プログラミングはありませんだけで、ここでのアーキテクチャの観点から、その副作用を懸念し、様々な特性の多くの定義であり、状態を変更しないでください。関数型プログラミング、独立性を維持する機能は、つまり、すべての機能は、特に外部変数の値を変更しないで、新しい価値、ない他の行為を返します。プログラミングの割り当て前述の機能が制限されていた、それはこの機能を指します。

建築の分野では、すべての競争上の問題、デッドロック、同時実行の問題は、変数変数によって引き起こされます。十分なメモリと計算がある場合、アプリケーションは、上述の問題のいくつかを回避するために、唯一頭トランザクション・レコードで計算関数型プログラミング全く不変の状態を使用してイベント追跡可能な方法を使用することができます。現在のところ変数変数ソフトウェアは非現実的であることを確認するいかなるシステムはありませんが、我々は、アセンブリの状態を変更することなく、プログラミング機能を使用して、修正することなく部分と部分の状態を変更する必要があることにより、別個のコンポーネントに分けることができますそしてシステムの安定性と効率を向上させます。

要約すると、プログラムが改ざんできる論理ブロックから確立することができない何の構造化プログラミングは、セルの境界を越えないオブジェクト指向プログラミングは、非常に面倒で危険なプロセス、関数型言語とすることがない可能性がないように、より効率的で安定したアセンブリ。いいえプログラミングパラダイムは、アーキテクチャ設計は問題外になることはありません。
 

第四に、設計原理

そして、プログラミングパラダイムは、より密接なアーキテクチャと設計原則との関係に比べ、原理はデータや関数をクラスに編成されている方法で私たちを案内しますアーキテクチャ設計の指導思想であり、コンポーネントやプログラムに一緒にリンクする方法についての授業。リバース、アーキテクチャの主な仕事は、メソッドのコンポーネントを分離、解体方法で私たちを導く方向の大きさ、相互依存の部品を分解し部品、設計原理に分解ソフトウェアです。

設計原理の多くがありますが、私たちは、アーキテクチャの設計原理は、コードのクラスやレベルで、OCP(オープンクローズドの原則)です導かれた、次のとおりです。SRP(シングル責任の原則)、LSP(リヒター置換原則)、ISP(インタフェース分掌の原則) 、DIP(依存性逆転原理)成分のレベルである:REP(リユース、均等論を放出する)、 - CRP(CO多重化原理)のCCP(クロージャの一般的原理)、処理コンポーネントの依存関係三の原則。全く依存リング原理、安定し、着実な抽象的な原則の原則に頼っていません。

1.OCP(開閉原理)

うまく設計されたソフトウェアが拡大すると、変化に抵抗するために簡単なはずです。これが私たちのアーキテクチャ設計の基本理念である、他の原則は、このサービスの原則です。

2.SRP(シングル責任の原則)

すべてのソフトウェア・モジュールは、1および修正する唯一の理由を持っている必要があり、「修正の原因は、」システムの利用者または所有者を意味し、あるものを翻訳し、すべてのモジュールは、ユーザの値に対してのみ責任があります。コンポーネントを分割する方法を、私たちを導く原則。

例えば、CTO兼COOは、彼らが現在の統計的手法は、我々はその後、COOは、時間の統計情報を作業週末は2倍されると言われ、コードセットを再利用し、同じことがこれに応じて要件を変更することが求められ、統計職員の勤務時間を持っていますコードは、CTOはsqualling来るする必要があります。もちろん、これは非常に単純な例であり、実際のプロジェクトクエストの多大な費用がかかる体の値、より多くのサービスを提供し、リスクを修正するためのコードがたくさんあります。

また、コードが複数の所有者を持っているとき、それはあなたのコードのマージの競合で問題が発生します。

3.LSP(リヒター置換原理)

ときに、同じインタフェースの異なる実装と互換性、システムの動作は変化しないままであるべきです。基本理念は、その実装へのインタフェースです。

あなたは、彼らの行動は確かに本当に必ずしも、そう一貫して、同じインターフェイスを実現するために、非常に混乱しなければなりません。面積=幅*高さ、setWとSETHを呼び出す際のインタフェース長方形、正方形の実装は、正方形は、実際にその辺の長さを設定し、同じことを行うように:私たちは、長方形のシステムの動作があるという仮説を立てました。次に、長方形形状の単位テストが合格の下、同じインタフェースを達成するために、正方形では動作しませんが、システムの挙動が変更され、これはLSPの違反の古典的なケースです。

Rectangle r = ...
r.setW(5);
r.setH(2);
assert(r.area() == 10);

4.ISP(インタフェース偏析原理)

この方法は、不要な、コンポーネントやクラスに依存しません。私たちのインターフェイスデザインを基本原則。

我々はインターフェイスに依存しているが、実際には、我々はすでにこれらのメソッドが変更されたときにメソッドやクラス、またはクラスに依存する必要はありません、方法の一部のみを使用する場合、それはクラスを再コンパイル、または私たちがする再組み立てを引き起こすために私たちの原因になります展開は、これらは不要です。だから私たちはより良い小さなポートを定義していたが、使用方法が出てリッピング。

5.DIP(依存性逆転原理)

フロー制御の方向と逆方向に永遠に依存して国境を越えて設定します。私たちの相互依存設計コンポーネントの方向を導く原則。

依存関係逆転の原則動作原理は、あなたが方向依存コンポーネント間で変更したいときどちら側のポイントに応じて、コンポーネント間通信の抽象クラスインターフェース、境界のどちら側のインターフェイス、する必要がありますが、非常に強いです。

6.REP(リユース、均等論を公開)

ソフトウェア再利用の最小サイズは、その解放の最小サイズに等しくなければなりません。単刀直入に言えば、それはコンポーネントにポンプ配置するコードの一部を再利用することです。私たちのサイズの部品分割の基本理念。

7.CCP(共通閉鎖原則)

同じ目的のためにも、種類を変更し、それが同じアセンブリ内に配置されるべきです。CCPの原理は、SRPの原理は、コンポーネント・レベルに記載されています。私たちのサイズの部品分割の基本理念。

ほとんどのアプリケーションで、複数のコンポーネント、開発者にまたがっている場合、同じ理由で、同じコンポーネントで最高に起因するコードの変更の再利用性よりもはるかに大きな保守の重要性については、提出され、展開コストが上昇します。

8.CRP(共同多重化の原則)

コンポーネントを強制しないでください、それに依存する必要はありません。CRPの原理は、ISP主成分レベルに記載されています。私たちのサイズの部品分割の基本理念。

私は、あなたが経験のこの種を持っていることを確認統合された成分Aが、コンポーネント部品B、Cに依存しています でも、成分Bならば、Cは、あなたは完全に使用するだけでなく、それらを統合しなければならなかったことはできません。あなたが唯一の成分Aが追加の依存関係をもたらす要素で容量、追加容量の一部を使用するためです。あなたは一般的な再利用の原則に従っている場合、あなたが使用したい部分だけを残して、スプリットを配置する必要があります。

3つの原則REP、CCP、互いに、REPとCCPがボンディングされている原則とCRP競争関係の間に、彼らは大きな要素となり、CRPの原理は、それは部品が小さくなり排他原理です。REP、CCPを遵守し、CRPを無視し、あまり使わなかったコンポーネントとクラスに依存し、これらのコンポーネントやクラスの変更は、独自のコンポーネントあまりにも多くの不必要なリリースにつながることができ、REP、CRPを遵守し、CCP無視コンポーネントが細かすぎ分割、および変更の需要はn個の成分を変更する必要がありますので、コストをもたらすことは膨大です。

良い建築家がこのようなプロジェクトの初期段階のように、エリア内の三角形の緊張の上の位置に、研究開発チームの現在の状態のために最も適したを見つけることができるはず、CCPは、プロジェクトの開発と、REPよりも重要である、最も適した場所は絶えず調整する必要があります。

9.ませ原理は、リングを依存していません

健康は有向非巡回グラフ(DAG)でなければなりません依存、相互に依存するコンポーネントは、実際には、あなたは、一緒にパブリッシュ一緒にユニットテストをしたい大きなコンポーネントを構成しています。私たちは、DIPの原則に依存することにより、リングの反転を離乳させることができます。

10.依存安定化の原則

リライアンスは、より安定した方向を指している必要があります。

ここでの安定性は、それが変更のコストのコンポーネントを参照することで、直接的な関連性(どのくらいの頻度安定性の変化と需要より関連)のその頻繁な変更。最も直接的な方法は、多くを変更するコンポーネントを困難にしているようにように、このようなコードサイズの量など、多くのコンポーネントの変更コンポーネントのコストに影響を与える要因、複雑さ、明快さとは、最も重要な要因は、その構成要素の数に依存している、があります他のコンポーネントは、それに依存します!

アセンブリの安定性の定量的尺度である:不安定(I)=(依存+の数に依存する数)に依存する/の数。地元の安定性の原則に違反して依存していた場合は、解決策は、DIPによって信頼を逆にすることです。

11.抽象的原則を安定させます

抽象コンポーネントの程度は、その安定性と一致しなければなりません。コンポーネントは、インターフェースコンポーネントの特定の実装に依存するので、それはその拡張性の安定性に影響を与えないように、別の成分として、通常、抽象的安定インタフェース、抽象クラスを変更するには困難な高次高次アーキテクチャ設計戦略を防ぐために。

组件抽象化程度的定量化描述是:抽象程度(A)= 组件中抽象类和接口的数量 / 组件中类的数量。

将不稳定性(I)作为横轴,抽象程度(A)作为纵轴,那么最稳定、只包含抽象类和接口的组件应该位于左上角(0,1),最不稳定、只包含具体实现类,没有任何接口的组件应该位于右下角(1,0),他们连线就是主序列线,位于线上的组件,他们的稳定性和抽象程度相匹配,是设计良好的组件。位于(0,0)周围区域的组件,它们是非常稳定(注意这里的稳定指的是变更成本)并且非常具体的组件,因为他们的抽象程度低,决定了他们经常改动的命运,但是又有许多其他组件依赖他们,改起来非常痛苦,所以这个区域叫做痛苦区。右上角区域的组件,没有其他组件依赖他们,他们自身的抽象程度又很高,很有可能是陈年的老代码,所以这个区域叫做无用区。

另外,可以用点距离主序列线的距离 Z 来表示组件是否遵循稳定抽象原则,Z 越大表示组件越违背稳定依赖原则。
 

五、架构工作的基本方针

了解了编程范式和设计原则,接下来我们看看如何应用他们拆分组件、处理组件依赖和组件边界。架构工作有两个方针:

尽可能长时间地保留尽可能多的可选项。这里的可选项指的是无关紧要的细节设计,比如具体选用哪个存储方式、哪种数据库,或者采用哪种 Web 框架。业务代码要和这些可选项解耦,数据库或者框架应该做到像插件一样切换,业务层对这个切换的过程应该做到完全无感。

低层次解耦方式能解决的,不要用高层次解耦方式。组件之间的解耦方式后边细讲,这里强调的是边界处理越完善,开发和部署成本越高。所以不完全边界能解决的,不要用完全边界,低层次解耦能解决的,不要用高层次解耦。
 

六、组件的拆分

首先要给组件下个定义:组件是一组描述如何将输入转化为输出的策略语句的集合,在同一个组件中,策略的变更原因、时间、层次相同。

从定义就可以看出,组件拆分需要在两个维度进行:按层次拆分、按变更原因拆分。

这里的变更原因就是业务用例,按变更原因进行组件拆分的例子是:订单组件、聊天组件。按层次拆分,可以拆为:业务实体、用例、接口适配器、框架与驱动程序。

  • 业务实体:关键业务数据和业务逻辑的集合,与界面无关、与存储无关、与框架无关,只有业务逻辑。
  • 用例:特定场景下的业务逻辑,可以理解为 输入 + 业务实体 + 输出 = 用例。
  • 接口适配器:包含整个整个MVC,以及对存储、设备、界面等的接口声明和使用。

一条策略距离系统的输入、输出越远,它的层次越高,所以业务实体是最高的层,框架与驱动程序是最低的层。
 

七、组件依赖处理

前面拆好了组件分好了层,依赖就很好处理了:依赖关系与数据流控制流脱钩,而与组件所在层次挂钩,始终从低层次指向高层次,如下图。越具体的策略处在的层级越低,越插件化。切换数据库是框架驱动层的事情,接口适配器完全无感知,切换展示器是接口适配器层面的事情,用例完全无感知,而切换用例也不会影响到业务实体。

八、组件边界处理

一个完整的组件边界包括哪些内容?首先跨越组件边界进行通信的两个类都要抽象为接口,另外需要声明专用的输入数据模型、声明专用的返回数据模型,想一想每次进行通信时都要进行的数据模型转换,就能理解维护一个组件边界的成本有多高。

除非必要,我们应该尽量使用不完全边界来降低维护组件边界的成本。不完全边界有三种方式:

  • 省掉最后一步:声明好接口,做好分割后,仍然放在一个组件中,等到时机成熟时再拆出来独立编译部署。
  • 单向边界:正常的边际至少有两个接口,分别抽象调用方和被调用方。这里只定义一个接口,高层次组件用接口调用低层次组件,而低层次组件直接引用高层次组件的类。
  • 门户模式:控制权的间接转移不用接口和实现去做,而是用门户类去做,用这种方式连接口都不用声明了。

除了完全边界和不完全边界的区分,边界的解耦方式也可以分为3个层次:

  • 源码层次:做了接口、类依赖上的解耦,但是放在同一个组件中,通常放在不同的路径下。和不完全边界的省略最后一步一样。
  • 部署层次:拆分为可以独立部署的不同组件,比如 iOS 的静态库、动态库,真正运行时处于同一台物理机器上,组件之间通常通过函数调用通讯。
  • 服务层次:运行在不同的机器上,通过 url 、网络数据包等方式进行通讯。

从上到下,(开发、部署)成本依次升高,如果低层次的解耦已经满足需要,不要进行高层次的解耦。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

おすすめ

転載: blog.csdn.net/yunqiinsight/article/details/91492546