ソフトウェアの設計とアーキテクチャを学ぶ方法-ロードマップ

この記事は、私の最新のプロジェクトであるsolidbook.io-TypeScriptを使用したソフトウェア設計とアーキテクチャのハンドブックで私が書いていることの要約です。この投稿が気に入ったらチェックしてください。

Facebookがかつて誰かのコンピューター上の空のテキストファイルであったという事実を考えるのは私には夢中です。

笑。

昨年、私はソフトウェアの設計とアーキテクチャ、ドメイン駆動設計に熱心に取り組み、それについて本を書いてきました。少し時間を取って、コミュニティと共有できる便利なものにまとめてみたかったのです。 。

これが、ソフトウェアの設計とアーキテクチャを学ぶ方法のロードマップです。

スタックマップの2つのアーティファクトに分解しました。

スタック

ネットワークのOSIモデルと同様に、各層は前の層の基盤の上に構築されます。

スタック

地図

スタックは、すべてがどのように連携するかについての全体像を見るのに適していると思いますが、マップはもう少し詳細であり(そして、Web開発者のロードマップに触発されて)、結果として、より便利だと思います。

こちらが下です!リポジトリをフォークするには、私の詳細な記事を読んで高解像度でダウンロードするには、ここをクリックしてください。

ソフトウェア設計とアーキテクチャのロードマップ

ステージ1:クリーンコード

長持ちするソフトウェアを作成するための最初のステップは、クリーンなコードを作成する方法を見つけることです

クリーンコードは、理解と変更が容易なコードです。低レベルでは、これは次のようないくつかの設計上の選択に現れます。

  • 一貫している
  • コメントを書くよりも意味のある変数、メソッド、クラス名を好む
  • コードがインデントされ、適切な間隔で配置されていることを確認します
  • すべてのテストを実行できることを確認する
  • 副作用のない純粋関数を書く
  • nullを渡さない

クリーンなコードを書くことは非常に重要です。

ジェンガのゲームのように考えてください。

プロジェクトの構造を長期にわたって安定させるために、インデント、小さなクラスとメソッド、意味のある名前などは、長期的には大きな成果を上げます。

クリーンなコードの書き方を学ぶのに最適なリソースは、ボブおじさんの本「クリーンコード」です。

ステージ2:プログラミングパラダイム

保守が容易な読み取り可能なコードを作成しているので、3つの主要なプログラミングパラダイムと、それらがコードの作成方法にどのように影響するかを実際に理解することをお勧めします。

ボブおじさんの本「CleanArchitecture」で、彼は次の事実に注意を向けています。

  • オブジェクト指向プログラミングは、ポリモーフィズムとプラグインを使用してアーキテクチャの境界を越える方法を定義するのに最適なツールです。
  • 関数型プログラミングは、データをアプリケーションの境界にプッシュするために使用するツールです。
  • 構造化プログラミングは、アルゴリズムを作成するために使用するツールです。

これは、効果的なソフトウェアが3つのプログラミングパラダイムスタイルすべてを異なる時間にハイブリッドで使用することを意味します。

コードを書くために厳密に機能的または厳密にオブジェクト指向のアプローチを取ることもできます、それぞれが優れている点を理解することで、デザインの品質が向上します。

あなたが持っているのがハンマーだけなら、すべてが釘のように見えます。

リソース

関数型プログラミングについては、以下を確認してください。

  • フリスビー教授の関数型プログラミングの最も適切なガイド
  • ドメインモデリングが機能する

ステージ3:オブジェクト指向プログラミング

各パラダイムがどのように機能し、パラダイム内でコードを構造化するように促すかを知ることは重要ですが、アーキテクチャに関しては、オブジェクト指向プログラミングがその仕事のための明確なツールです

オブジェクト指向プログラミングにより、プラグインアーキテクチャを作成し、プロジェクトに柔軟性を組み込むことができるだけでなく、OOPには、リッチドメインモデルの作成に役立つOOPの4つの原則(カプセル化、継承、ポリモーフィズム、および抽象化)が付属しています。

オブジェクト指向プログラミングを学ぶほとんどの開発者は、この部分に到達することはありません。問題のあるドメインのソフトウェア実装を作成する方法を学び、それを階層化されたWebアプリの中央に配置します。

関数型プログラミングは、このシナリオのすべての目的を達成するための手段のように思えますが、モデル駆動型設計とドメイン駆動型設計に精通して、オブジェクトモデラーがビジネス全体をカプセル化する方法の全体像を理解することをお勧めします。ゼロ依存ドメインモデル。

なぜそれが大したことなのですか?

ビジネスのメンタルモデルを作成できれば、そのビジネスのソフトウェア実装を作成できるので、それは巨大です。

ステージ4:設計原則

この時点で、オブジェクト指向プログラミングは、リッチドメインモデルをカプセル化し、3番目のタイプの「ハードソフトウェアの問題」である複雑なドメインを解決するのに非常に役立つことを理解しています。

しかし、OOPはいくつかの設計上の課題をもたらす可能性があります。

いつコンポジションを使うべきですか?

いつ継承を使用する必要がありますか?

抽象クラスはいつ使用する必要がありますか?

設計原則は、レールガードとして使用する、非常に確立され、戦闘でテストされたオブジェクト指向のベストプラクティスです。

よく理解しておく必要のある一般的な設計原則の例を次に示します。

  • 継承をめぐる構成
  • 変化するものをカプセル化する
  • コンクリーションではなく、抽象化に対するプログラム
  • ハリウッドの原則:「私たちに電話しないでください、私たちはあなたに電話します」
  • SOLIDの原則、特に単一責任の原則
  • DRY(繰り返さないでください)
  • YAGNI(あなたはそれを必要としない)

ただし、必ず自分で結論を出してください。他の誰かがあなたがすべきだと言っていることだけに従わないでください。それがあなたにとって理にかなっていることを確認してください。

ステージ5:デザインパターン

ソフトウェアのほぼすべての問題は、すでに分類され、解決されています。これらのパターンを実際にはデザインパターンと呼びます。

デザインパターンには、作成構造動作の3つのカテゴリがあります

創造的

作成パターンは、オブジェクトの作成方法を制御するパターンです。

作成パターンの例は次のとおりです。

  • クラスの単一のインスタンスのみが存在できるようにするためのシングルトンパターン
  • クラスのいくつかのファミリのインスタンスを作成するためのAbstractFactoryパターン
  • 既存のインスタンスから複製されたインスタンスから開始するためのプロトタイプパターン

構造

構造パターンは、コンポーネント間の関係を定義する方法を単純化するパターンです。

構造設計パターンの例は次のとおりです。

  • 通常は連携できないクラスを連携させるためのインターフェースを作成するためのアダプタパターン
  • ブリッジパターンは、分割実際階層に属しているクラスのセットへの1つまたは複数の、あるべきであるクラスを、実装を可能にするために互いに独立して開発されます。
  • オブジェクトに責任を動的に追加するためのデコレータパターン

行動

行動パターンは、オブジェクト間のエレガントなコミュニケーションを促進するための一般的なパターンです。

行動パターンの例は次のとおりです。

  • アルゴリズムの正確なステップをサブクラスに延期するためのテンプレートパターン
  • クラス間で許可される正確な通信チャネルを定義するためのメディエーターパターン
  • Observerパターン興味のあるものを購読するクラスを可能にし、変更が発生したときに通知されるため、。

デザインパターンの批判

デザインパターンは素晴らしく、すべてですが、デザインがさらに複雑になる場合があります。YAGNIを覚えて、デザインをできるだけシンプルに保つことが重要です。デザインパターンは、本当に必要であると確信できる場合にのみ使用してください。いつになるかわかります。

これらの各パターンが何であるか、いつ使用するか、いつ使用する必要がないかを知っていれば、より大規模なシステムを設計する方法を理解し始めることができます。

その背後にある理由は、アーキテクチャパターンが高レベルにスケールアップされたデザインパターンであり、デザインパターンが低レベルの実装(クラスや関数に近い)であるためです。

リソース

リファクタリングの第一人者-デザインパターン

ステージ6:アーキテクチャの原則

今、私たちはクラスレベルを超えてより高いレベルの思考をしています。

高レベルと低レベルのコンポーネント間の関係を整理および構築するために行う決定が、プロジェクトの保守性、柔軟性、およびテスト可能性に大きな影響を与えることを理解しました。

できるだけ少ない労力で新しい機能や要件に対応できるようにするために、コードベースに必要な柔軟性を組み込むのに役立つ基本原則を学びます。

これが私がすぐに学ぶことをお勧めするものです:

  • コンポーネントの設計原則:コンポーネントの編成方法、それらの依存関係、それらを結合するタイミング、および誤って依存関係サイクルを作成し、不安定なコンポーネントに依存することの影響については、安定した抽象化の原則、安定した依存関係の原則、および非周期的な依存関係の原則。
  • ポリシーと詳細。アプリケーションのルールを実装の詳細から分離する方法を理解します。
  • 境界、およびアプリケーションの機能が属するサブドメインを識別する方法。

ボブおじさんはこれらの原則の多くを発見して最初に文書化したので、これについて学ぶための最良のリソースは再び「クリーンアーキテクチャ」です。

ステージ7:建築様式

アーキテクチャは重要なものについてです。

それは、システムが成功するために必要なものを特定し、要件に最適なアーキテクチャを選択することによって成功の確率を積み上げることです。

たとえば、ビジネスロジックが非常に複雑なシステムでは、階層化アーキテクチャを使用してその複雑さをカプセル化することでメリットが得られます。

Uberのようなシステムは、一度に多くのリアルタイムイベントを処理し、ドライバーの場所を更新できる必要があるため、パブリッシュ/サブスクライブスタイルのアーキテクチャが最も効果的である可能性があります。

建築様式は高レベルの設計パターンであるため、建築様式の3つのカテゴリはデザインパターンの3つのカテゴリに類似していることに注意することが重要であるため、ここで繰り返します

構造

さまざまなレベルのコンポーネントと幅広い機能を備えたプロジェクトは、構造アーキテクチャを採用することでメリットが得られるか、問題が発生します。

次にいくつかの例を示します。

  • コンポーネントベースのアーキテクチャは、システム内の個々のコンポーネント間の関心の分離を強調しています。ちょっとグーグルを考えてください。企業内にあるアプリケーション(Googleドキュメント、Googleドライブ、Googleマップなど)の数を検討してください。多くの機能を備えたプラットフォームの場合、コンポーネントベースのアーキテクチャは、懸念事項を疎結合の独立したコンポーネントに分割します。これは水平方向の分離です。
  • モノリシックとは、アプリケーションが単一のプラットフォームまたはプログラムに結合され、完全にデプロイされることを意味します。注:アプリケーションを適切に分離し、すべてを1つのピースとしてデプロイすれば、コンポーネントベースのモノリシックアーキテクチャを実現できます
  • 階層化アーキテクチャは、ソフトウェアをインフラストラクチャ、アプリケーション、およびドメインの各層に分割することにより、懸念事項を垂直に分離します。

クリーンなアーキテクチャ

階層化アーキテクチャを使用して、アプリケーションの懸念を垂直に削減する例。これを行う方法の詳細については、こちらをお読みください。

メッセージング

プロジェクトによっては、メッセージングがシステムの成功にとって非常に重要なコンポーネントになる場合があります。このようなプロジェクトの場合、メッセージベースのアーキテクチャは、関数型プログラミングの原則とオブザーバーパターンのような動作設計パターンの上に構築されます。

メッセージベースのアーキテクチャスタイルの例を次に示します。

  • イベント駆動型アーキテクチャは、状態に対するすべての重要な変更をイベントとして表示します。たとえば、ビニール取引アプリ内では、両当事者が取引に同意すると、オファーの状態が「保留中」から「承認済み」に変わる場合があります。
  • パブリッシュ/サブスクライブアーキテクチャは、オブザーバーデザインパターンの上に構築され、システム自体、エンドユーザー/クライアント、およびその他のシステムとコンポーネント間の主要な通信方法になります。

分散

分散アーキテクチャとは、システムのコンポーネントが個別に展開され、ネットワークプロトコルを介して通信することによって動作することを意味します。分散システムは、スループットのスケーリング、チームのスケーリング、および他のコンポーネントへの(潜在的にコストのかかるタスクまたは)責任の委任に非常に効果的です。

分散アーキテクチャスタイルのいくつかの例は次のとおりです。

  • クライアントサーバーアーキテクチャ。最も一般的なアーキテクチャの1つであり、実行する作業をクライアント(プレゼンテーション)とサーバー(ビジネスロジック)の間で分割します。
  • ピアツーピアアーキテクチャは、アプリケーション層のタスクを同等の特権を持つ参加者間で分散し、ピアツーピアネットワークを形成します。

ステージ8:アーキテクチャパターン

アーキテクチャパターンは、これらのアーキテクチャスタイルの1つを実際に実装する方法をより戦術的に詳細に説明します

次に、アーキテクチャパターンとそれらが継承するスタイルの例をいくつか示します。

  • ドメイン駆動設計は、非常に複雑な問題のあるドメインに対するソフトウェア開発へのアプローチです。DDDを最も成功させるには、データベース、Webサーバー、キャッシュなど、アプリケーションを実際に実行するインフラストラクチャの詳細からドメインモデルの懸念を分離するために、階層化アーキテクチャを実装する必要があります。
  • Model-View Controllerは、おそらくユーザーインターフェイスベースのアプリケーションを開発するための最もよく知られているアーキテクチャパターンです。これは、アプリをモデル、ビュー、コントローラーの3つのコンポーネントに分割することで機能します。MVCは、最初に始めたときに非常に便利であり、他のアーキテクチャに便乗するのに役立ちますが、MVCでは多くのビジネスロジックの問題に十分ではないことに気付く時期があります。
  • イベントソーシングは、トランザクションのみを保存し、状態は保存しない機能的なアプローチです。状態が必要になった場合は、最初からすべてのトランザクションを適用できます。

ステージ9:エンタープライズパターン

選択するアーキテクチャパターンには、多くの構成概念と専門用語が導入されており、慣れ親しんで、使用する価値があるかどうかを判断できます。

私たちの多くが知っている例をとると、MVCでは、ビューはすべてのプレゼンテーション層コードを保持し、コントローラービューからのコマンドとクエリをモデルによって処理され、コントローラーによって返される要求に変換します。

モデル(M)のどこでこれらのことを処理しますか?:

  • 検証ロジック
  • 不変ルール
  • ドメインイベント
  • ユースケース
  • 複雑なクエリ
  • およびビジネスロジック

SequelizeやTypeORMなどのORM(オブジェクトリレーショナルマッパー)をモデルとして使用するだけの場合、重要な要素はすべて、どこに移動するかを解釈する必要があり、その間の不特定のレイヤーに配置されます(リッチなはずです)。 )モデルコントローラー

mvc-2

solidbook.ioの「3.1-スリム(ロジックレス)モデル」から引用。

MVCを超えた旅の中でこれまでに学んだことがあるとすれば、それはすべての構造があるということです。

MVCが対処できないもののそれぞれについて、それらを解決するための他のエンタープライズパターンが存在します。例えば:

  • エンティティは、アイデンティティを持つモデルを記述します。
  • 値オブジェクトはIDを持たないモデルであり、検証ロジックをカプセル化するために使用できます。
  • ドメインイベントは、発生している関連するビジネスイベントを示すイベントであり、他のコンポーネントからサブスクライブできます。

選択したアーキテクチャスタイルに応じて、そのパターンを最大限に実装するために学習できる他のエンタープライズパターンがたくさんあります。

統合パターン

アプリケーションが起動して実行されると、ユーザーが増えるにつれて、パフォーマンスの問題が発生する可能性があります。API呼び出しに時間がかかる場合や、サーバーがリクエストで過負荷になるなどしてクラッシュする場合があります。これらの問題を解決するために、パフォーマンスを向上させるためのメッセージキューキャッシュなどの統合について読むことができます。

これはおそらく最も難しいものです:スケーリング、監査、パフォーマンス

規模に応じたシステムの設計は、非常に困難な場合があります。アーキテクチャ内の各コンポーネントの制限を深く理解し、アーキテクチャへのストレスを軽減し、トラフィックの多い状況で引き続き要求に対応するためのアクションプランが必要です。

また、アプリケーションで何が起こっているかを監査する必要もあります。大企業は、潜在的なセキュリティ問題を特定し、ユーザーがアプリケーションをどのように使用しているかを理解し、これまでに発生したすべてのログを記録するために、監査を実行できる必要があります。

これは実装が難しい場合がありますが、一般的なアーキテクチャはイベントベースに見え、イベントストーミング、DDD、CQRS(コマンドクエリ応答の分離)、イベントソーシングなどの幅広いソフトウェアおよびシステム設計の概念、原則、および実践に基づいて構築されます。 。

それがお役に立てば幸いです。

何か提案や質問があれば教えてください。

乾杯!

GitHubでフォークします

ソフトウェアの設計とアーキテクチャに関する本を読む

記事を読む

khalilstemmler.com-大規模なアプリケーション向けの高度なTypeScriptとNode.jsのベストプラクティスと、柔軟で保守しやすいソフトウェアの作成方法を教えています。