建築に近い推論または単一の紛争の結果

1つのすばらしい普通の木曜日に、いくつかのアーキテクチャ上の決定について1つの開発チームに意見の相違が現れました。その実装は上からの命令によって承認され、合理的な論争の中で生まれませんでした。 しばらくして、すでに新しいプロジェクトで同様の紛争が再び発生しました。 議論はより熱くなり、状況を明確にして啓発を達成するために、外部の大国も関与しました。 後者は達成されなかったが、それでも同じ強い意志の決定により、存在の発展のための選択肢の一つが採用された。 しかし、議論の参加者の1人である賢明なKaaは、未解決の紛争をチームに残さないことを決定しました-将来の紛争、チームの分裂、およびその他の虐殺の理由。

このドキュメントでは、2つのアプローチの長所と短所、コンセンサスに到達し、宇宙の平和と正義を支配することを説明するように求められました。

以下では、これを行うために私の知的能力を最大限に試し(したがって、非常に単純な単語やフレーズを使用します) 由緒ある大衆の血まみれの肉屋を裁判所に持ち込みます。





ニルヴァーナ達成する深byへと導く強い意志のある道



データ処理を扱う一連のサービスがあり、リポジトリを使用してデータを保存します。 なぜなら リポジトリは多くの場合ソースが遅いため、一部のサービスはセッションやキャッシュなどの一時リポジトリを使用します。 そして以来 サービスはWebアプリケーションからだけでなく使用されるため、これらの一時ストレージを直接使用することはできません(たとえば、コンソールアプリケーションにはセッションがまったくありません)。したがって、サービスもそれらと連携します。 (つまり、私たちのアーキテクチャでサービスが何であるかの明確な概念はなく、その最高の目的は示されていません。実際、このアプローチでは、サービスは何かをするクラスです)







図1最初のアプローチのクラス階層

このすべての幸福の実現例は、 Git Hubからダウンロードできます。



私がここで好きではないもの:



第一に、私は権限の委任に関する明確な合意の欠如が嫌いです。サービスとその他の両方ですが、彼らは全く異なることに従事しています。 1つはデータ処理に従事し、もう1つは一時ストレージに従事しています。



次に、SessionDataServiceBaseクラス、つまりT Getメソッド(文字列キー、Func getData)が好きではありません。このメソッドは、セッションだけでなくデータ処理も処理します。 ISessionDataServiceという名前で(実際に当初考えられていたとおり)、それはSessionのラッパーであり、最大値はデフォルト値を返すことであると想定されています。 このオブジェクトの開発の歴史に目を向けると、最初はT Getメソッド(文字列キー、Func getData)(またはその類似物)がインターフェースに記述されていませんでした。 このインターフェースの実装を使用する各クラスで実装されました(一方で、私の意見では、これは正しいです)。 このアプローチにはマイナスがありました-これはコードの再現性です。 これは、サービスの1つでセッションの使用を追加することに決めたときに気づきました。 簡単な調査の後、大量の重複コードが発見されました。より正確には、この重複はすべてのサービスにありました。 これは、宇宙の知覚の私の整合性を侵害し、それと調和して生きることを許しませんでした。 データの追加作業をセッションサービスに委任するのは間違っているように思われましたが、この不協和音を魂から取り除くために、それを何らかの基本クラスに入れることが決定されました(真実への2番目のパスの説明の詳細)。



私たちの神、バイナリコードである神聖によって私に明らかにされた第三の問題は鍵です。 彼らは「森の中にあるもの、fireのためにあるもの」のスタイルで値を割り当てられました(私は認めることを恐れず、一度に私には罪がありました)。 また、void Clearメソッド(文字列[] sessionKeyPrefix)により、完全に予期しない結果が生じる場合がありました。 他の問題もありましたが、それらについては触れませんが、これらの問題を解決することは有能な継承をもたらしました。



4番目の問題はテストです。 意図的な決定をこの構造に変換した後、フードの下でT Get(文字列キー、Func getData)を使用するメソッドのすべてのユニットテストが失敗しました。 私たちのユニットテストの第一人者の助けを借りても、私はすぐにそれらを軽くたたくことはできませんでした。



そして今、利益について-私たちはそれらについて何も言うことができません、つまり、私は敬意と完璧さに満ちた第2の道であり、屈辱と退屈をバイパスして、コードがバイナリコードに直接変換される最も完璧なnに至りますCILへの変換プロセス。



すべての本当に素晴らしいもののように、同時代の人々に笑される道



このアプローチは、主に契約と制限に基づいています。 サービスは、受信したデータを処理し、この処理の結果をリポジトリを介して使用する永続的なリポジトリに保存するクラスであり、リポジトリは1つのみであり、サービスはデータの保存方法について何も知らないと想定されています。 彼は、データベース、ファイル、インターネット上のサードパーティのサービスなどを気にしません。

良い方法では、何らかの種類の基本クラスまたはインターフェイスを作成するのが正しいでしょう。これは、このクラスがストレージとエンドユーザー間のデータの処理と送信を担当することを示します。 しかし、残念ながら、これはまだ行われていません。最初のアプローチで見たように、サービスと呼ばれるクラス(HttpContextBasedSessionDataService)がありますが、リポジトリはなく、データは処理されません。 したがって、サービスの基本エンティティがまだあると想定します。これはIServiceインターフェイスです



HttpContextBasedSessionDataServiceと同様のクラスについて説明します。 リポジトリは、まず低速のデータソースであり、これは常にボトルネックであるため、可能な限り使用されるべきではないという事実のために現れました。 したがって、いくつかのデータを手元に保存することは悪くありません。ここでは、新しい種類のクラスが表示され、データを処理せず、リポジトリを持たず、一時ストレージへのアクセスのみを提供します。 原則として、サービスよりもリポジトリに近く、アプリケーション、キャッシュ、セッションなどの一時ストレージのリポジトリにのみ近いです。 ベースエンティティにIShorttermStoreという名前を付け、そのようなクラスの名前にServiceという単語が記載されていないと仮定します。



ここで、これらの計算に基づいてクラス階層を構築して、以前の実装の欠点を排除し、基本サービスクラスの一時ストレージを操作するための機能、つまりキーと遅延初期化ロジックを操作する機能の一部を取り出してみましょう。

そして、この概念に従って構築されたクラス図を見てみましょう。







図2 2番目のアプローチのクラス階層

このすべての幸福の実現例は、 Git Hubからダウンロードできます。



これは、私の意見では、最初のアプローチが罪を犯すという欠点を取り除きます。 単体テストは追加のMobなしで機能します。

今、想像上の欠陥について。

討論者の議論を思い出すと、クラスがセッションに加えてキャッシュも使用したい場合、問題が発生するという欠点があります。 しかし、実際、これには問題はありません。そのような必要性が生じた場合、SOLID、特にこの略語(インターフェイス分離の原則)の文字Iについて考える価値があり、「刺繍とタイプライティング」も可能なモンスターを作成しないでください。

記憶は選択的であり、明るいことと良いことだけを覚えており、批判をまったく覚えていないため、欠点については何も言えません。 鍛冶屋に私を叩きつけてくれとお願いします。



Mikhailichenko Aleksey、Software .Net Developer、Tech Lead



All Articles