けんかすることなくアーキテクチャと実装を共有する方法

新しいシステムの作成は、概念と設計の詳細化、アーキテクチャ設計、実装、テスト、リリースの多段階プロセスです。 アーキテクチャの設計と実装は、開発者が主に関係する段階です。







ほとんどの開発者は、システムまたはその一部がゼロからどのように配置されるかを考えるために、アーキテクチャに従事することを好みます。 システムのアーキテクチャを熟考し、それを実装する人がいる場合、動機付けに問題はありません。プログラマーは、自分のアイデアの実現から満足を得ます。 しかし、あるアーキテクチャを考え、別のアーキテクチャを実装する場合、後者は自然なinりを抱く可能性があります。













このような状況を回避する方法、実装がアーキテクチャの精緻化と同じくらい興味深い場合がある理由、およびそれ以上の場合については、この記事で説明します。







はじめに



よく考え抜かれたアーキテクチャは、 ブレークダウンタスクの基礎として使用できます。十分に分離された各コンポーネントの実装は、別個のサブタスクになります。







たとえば、 パイプとフィルターのスタイルで設計されたリクエスト処理パイプラインがある場合、サブタスクは個々の処理ステップ(各ステップには独自のサブタスクがあります)とすべてのステップを接続する別のサブタスクの実装になります。







よく考えられたアーキテクチャとサブタスクへの分解は、システムの作成方法と人件費の評価を可能にする方法の一般的なアイデアを提供しますが、計画を実行するには十分ではありません。 サブタスクの説明には、コンポーネントが何をすべきかが記載されており、速度とメモリ消費の要件が含まれている場合がありますが、その作成方法に関する包括的な指示はありません。







実際には、指定された要件を満たすコンポーネントを作成するための多くのオプションがあります。 コードの柔軟性、拡張性、サポートの容易さなど、実装方法に大きく依存します。 コードデザインの概念近づきます







コード設計コンセプト



コード設計は、アーキテクチャまたはコード編成と呼ばれることもあれば、単にアーキテクチャと呼ばれることもあります。 コードデザインという用語は、システムアーキテクチャと対比され、それらの間に明確な境界線が引かれているため、用語デザインに準拠しています。 具体的には、例を考えてください。







人気を得ているサイトのバックエンドを開発しているとしましょう。 サーバーの数はすでに数十を超えており、視聴者は増え続けており、サイトでのユーザーの行動に関する分析(訪問ページの人気度、ユーザープロファイルに応じた機能の使用頻度など)を収集することにしました。







メトリックの保存場所、ネットワーク上でのメトリックの転送方法、メトリックストアが利用できない場合の対処方法、バックエンドサービスがメトリックを記録する方法など、多くのアーキテクチャ上および技術上の問題が発生します。 アーキテクチャは、これらの質問に答え、ソリューションのコンポーネントを決定し、それらの要件を設定するだけです。







InfluxDBをストレージとして使用し、UDPを使用してネットワーク経由でメトリックをtelegrafに転送し、ストレージの使用不可を回避するために、複数のサーバー間で複製されたKafkaにメトリックを保存するとします。 すべてのメトリックは、バックエンドサービス-> telegraf-> Kafka-> InfluxDBのように進みます。 メトリックバックエンドを作成するために、UDPを使用してtelegrafでメトリック転送機能を実装するモジュールを作成することにしました。







メトリックを記録するためのモジュールはシステムの独立したコンポーネントであり、その記述は開発者に委任できる独立したサブタスクです。 このサブタスクには、回答が必要な多くのソリューションと質問があります。メトリックは同期的または非同期的に送信されます。 いくつかのバックエンドスレッドの同時アクセスがどのように同期されるか、主なクラス/機能は何か。







これらの質問はソリューションアーキテクチャの説明の範囲外ですが、それらに対する答えは広範囲に影響します。 たとえば、ソリューションの運用中にテクノロジースタックが最適に選択されておらず、Telegrafを代替ソリューションに置き換える必要があることが明らかになった場合、モジュールをクラスに誤って分割すると、モジュール全体を書き換えずにこれを許可できません。 これらの質問への答えはコードデザインのドメインです







コード設計の開発は、システムアーキテクチャの開発とコーディングの間にある独立した設計段階です。 アーキテクチャとコード設計の間に線を引くことにより、すべての詳細を考慮せずにシステムを設計し、限られた時間で人件費を評価できます。 一方、実装の別の段階としてコード設計の開発を強調すると、システムの品質を向上させ、さらなる改善のコストを削減し、サポートを容易にすることができます。







コーディングの前に実装段階でコード設計を検討する必要があるため、実装は興味深いものになります。コード設計の設計作業は、アーキテクチャレベルでシステム全体を設計することと同じくらい興味深いものです。 この考えは、 神話上のマン月にブルックスによって表現されました。







もちろん、アーキテクチャとコード設計の間に線を引くことはそれほど単純ではないかもしれません。この問題を詳しく見てみましょう。







アーキテクチャとコード設計の境界



イデオロギー的には、アーキテクチャとコード設計の設計レベルは異なります。アーキテクチャは、初期段階であり、確実性がほとんどない段階で考え出され、コード設計を通して考えると詳細が追加されます。 したがって、それらは異なる時点で実行されます。アーキテクチャは最初に近づき、サブタスクの実装中のコード設計です。







設計のこれら2つの段階の境界を描くことは、いくつかの要因に依存します。主な要因は次のとおりです。









アーキテクチャ設計とコード設計の間に良い線を引くことができるいくつかの特別なケースがあります。







コンポーネントには厳密なAPIがあります。

たとえば、私の実践では、既存のデーモンが使用するOSリソースをキャプチャ/解放するためのUNIXソケットAPIの上に実装するというタスクがありました。 このタスクは、新しい叙事詩機能のために選択されたアーキテクチャのフレームワークの中で起こりました。 アーキテクチャのフレームワーク内では、APIを記述することはかなり高レベルであり、詳細な設計は実装中に後で行われました。







特定のインターフェースを持つモジュール/クラス

モノリシックシステムの一部の設計を委任する最も簡単な方法は、モジュールまたはクラスを強調表示し、そのインターフェイスとタスクを記述することです。 個別のサブタスクとして割り当てられたモジュールが大きすぎてはいけません。 たとえば、シャードデータベースにアクセスするためのクライアントライブラリは間違いなく別のモジュールですが、このライブラリを実装するタスクは、より詳細な設計なしでは人件費で評価することは困難です。 一方、小さすぎるクラスを実装するタスクは簡単です。 たとえば、サブタスク「特定のパスで特定のフォルダーの存在をチェックする機能を実装する」が発生した場合、アーキテクチャーは非常に詳細に考え抜かれます。







要件が固定された小さなコンポーネント

コンポーネントが十分に小さく、解決する問題が厳密に定義されている場合、実装の人件費を十分な精度で見積もることができ、コンポーネント自体の実装には設計の余地が残されます。 例:クラウンで実行され、特定のパスにある古いファイルとディレクトリを再帰的に削除するプロセス。







アンチパターン



アーキテクチャに対する思考と実装の間の分布が正しくない場合のシナリオがありますが、それらのいくつかについて以下で説明します。







すべてが細部に至るまで設計されています。

詳細なUMLダイアグラムが作成され、各クラスの各メソッドのシグネチャが指定され、個々のメソッドを実装するためのアルゴリズムが説明されています...このような詳細な説明によれば、システムを最速で、実際に実装できます。なぜなら、創造性の余地がないような細部まですべてが計画されているからです。書かれた。 開発者ができるだけ早く彼に言ったことをコーディングすることが目標であれば、はい、できます。







ただし、もう少し深く掘り下げると、この流れでの作業の組織化における多くの欠点が明らかになります。 まず、このような詳細ですべてを設計するには、設計自体に多くの時間を費やす必要があります。 開発者が実装前に通常考えることは、アーキテクトがこのスキームで考え直すことです。すべてのデザインはプロジェクトの開始に近づくため、プロジェクトの期間が長くなる可能性があります。 結局のところ、設計作業をパーツに分割しないと、並列化できません。 第二に、実装中の設計作業の欠如は、開発者のモチベーションを大幅に低下させます。彼らが言うことを正確に行うことは初心者にとって有益ですが、経験豊富な開発者は退屈します。 第三に、このアプローチは一般に出力の品質を低下させる可能性があります。十分に独立したコンポーネントに分割されていないシステムは、維持および拡張がより困難になります。







アーキテクチャは常に1人の開発者が設計し、残りは 煙る 実現するだけ

まず、これが有用な場合にはいくつかのケースに注意する必要があります。 まず、これは初心者が多く、経験豊富なプログラマが1人だけいるチームです。 この場合、新人は十分な品質で仕事をするためのアーキテクチャを設計するのに十分な経験がありませんが、同時に、よく考えられたアーキテクチャを実装することでレベルを上げることができます。 第二に、これらはいくつかのチームが関与する大規模なプロジェクトです。 次に、プロジェクトのアーキテクチャの設計は2つのレベルに分けられます。アーキテクトは全体としてそれを考え、各チームは責任範囲内のコンポーネントのアーキテクチャを考えます。







しかし、かなり経験豊富な専門家で構成される1つのチームを検討してください。 アーキテクチャのタスクが常に最も経験豊富な開発者などの1人だけに割り当てられる場合、他の開発者は自分の能力を完全に明らかにすることはできません。 誰もが適用する一連の技術を持っているため、システムアーキテクチャは一方的です。 異なる開発者が異なるコンポーネント/サブシステムのアーキテクチャを考えた場合、これは経験の交換とチームメンバーの開発を促進します。 あまり経験の浅いチームメンバーでさえ、建築上のタスクを与えられるべきです。これにより、レベルが上がり、プロジェクトへの関与が増します。







おわりに



実装における設計段階の存在は、実装タスクを面白くする主な要因です。 もちろん、他にもあります。新しいテクノロジーの使用、研究タスクですが、原則として、それらはあまり一般的ではありません。 実装タスクが設計を必要とせず、単純なコーディングで構成される場合、これは開発者のモチベーションに大きく影響し、彼らのスキルの使用を許可しません。







実装段階でコード設計を設計することにより、人件費を適切に見積もり、作業をより効率的に並列化し、一般にシステムの品質を向上させることができます。

実装中にコード設計を設計する必要があるため、開発者の目には実装が面白くなります。







間違いを犯す価値はありません。サブタスクの実装から設計作業を除外するのは、常に経験豊富な開発者にのみアーキテクチャタスクを委ねるべきではないのと同じです。








All Articles