例のように、密結合を避けられない場合があります。しかし、それはあなたがそれを受け入れる必要があるという意味でもありません。代わりに、乱雑さをカプセル化し、日常生活から切り離して隔離します。
たとえば、現在のフォーム認証ユーザーが必要な場合、にアクセスする以外に選択肢はありませんHttpContext.Current.Request.User.Identity.Name
。ただし、どこに電話をかけるかは選択できます。
HttpContext.Current
問題の解決策です。結果を使用する場所から直接呼び出す場合、同じ場所で問題と解決策を宣言しています。「現在のHTTPコンテキストからのものとして揺るぎなく宣言されている現在のユーザー名が必要です。」これは両方の定義を混乱させ、同じ問題に対する異なる解決策を可能にしません。
私たちが欠けているのは、私たちが解決しようとしている問題の明確な表現です。この例では、次のようになります。
現在のリクエストを行ったユーザーを特定します
HttpContext.Current
、またはユーザー名を使用しているという事実は、主要な問題定義の一部ではありません。これは、現在のユーザーを必要とするコードを複雑にするためだけに役立つ実装の詳細です。
インターフェイスを介して、現在のユーザーを取得する意図を表すことができます。実装の詳細はありません。
public interface IUserContext
{
User GetUser();
}
HttpContext.Current
直接呼び出したクラスは、代わりにこのインターフェースを使用して、コンテナーによって注入され、DIの良さを維持できます。IUserContext
また、パブリックAPIからは見えない依存関係を持つよりも、クラスがコンストラクターでを受け入れることの方がはるかに意図を明らかにします。
実装は、静的呼び出しを単一の場所に埋め込んで、オブジェクトに害を及ぼすことができなくなります。
public class FormsUserContext : IUserContext
{
private readonly IUserRepository _userRepository;
public FormsUserContext(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public User GetUser()
{
return _userRepository.GetByUserName(HttpContext.Current.Request.User.Identity.Name);
}
}