타성 의존 주입이 좋은 생각인가요?
6365 단어 cprogrammingnet
간단한 소개
Dependency Injection에 대해 말했을 때 인터패시브를 실현하는 클래스는 구조 함수에서 인터패시브를 실현해야 하고 인터패시브의 실현은 인터패시브를 실현해야 한다면 순환 의존 오류가 발생할 수 있다.그러나 지연 에이전트를 제공함으로써 이 문제를 해결할 수 있고 자원의 조기 분배 문제와 다른 유사한 문제를 해결할 수 있다.이론적으로 이것은 매우 무섭다.그러나 실천 과정에서 사람들은 이런 상황을 자주 만난다.이 글은 왜 이런 상황이 발생했는지, 그리고 실천과 이론의 차이점을 밝히려고 한다.
문제 정의
인터페이스를 정의하는 것부터 시작합시다.위키백과에서 이것shared boundary between components이라고 한다.주입에 의존하는 상하문에서, 당신은 자주 듣습니다. Single Responsibility Principle 이것은 하나의 종류 (하나의 인터페이스로 확장) 를 한 가지 일만 할 수 있도록 규정하고 있습니다.그러나 이런 상황에서도 Facade, Bridge, Decorator, Proxy, Adapter 소프트웨어 모드의 실현은 에이전트, 통합, 분리 등 다른 구성 요소의 기능만 할 수 있다. 아무리 복잡하든지.또 다른 극단에 이르면 우리는 모든 가능한 방법에 인터페이스를 만들어 순환 의존의 수요를 없애고 필요하지 않은 코드를 불러올 수 있다.그 다음은 인간이 코드를 쓰는 것이다.응용 프로그램의 물리적 위치를 제공할 수 있는 서비스가 필요할 때, Ilocation 서비스라고 부른다. 두 곳 사이의 거리를 계산하고 싶을 때, 같은 서비스를 사용할 것이다. 왜냐하면 그것은 위치에 관한 것이기 때문이다. 그렇지?ILocationProvider 서비스와 ILocationDistance Calculator를 보유한 것은 지나친 느낌이다.위치에 관한 하나의 기능이 이미 실현되었는지 확인하고 모든 Ilocation을 겪었다고 상상해 보세요.인터페이스를 만들고 코드를 작성할 때 새 인터페이스를 만들어야 하며, 이름이 정확한지, 필요한지 밤새도록 생각해야 한다. invalidate their cache
다시 말하면, 상하문에 따라 인터페이스는 분리된 구성 요소와 같이 임의로 복잡한 모든 것이 될 수 있다.그것들은 다른 구성 요소에 필요한 방법과 다른 구성 요소가 필요한 방법을 포함할 수 있다.이런 인터페이스가 더 많으면 실행 흐름에 문제가 없어도 실례화 단계에서 순환 의존이 나타날 수 있다.어리석은 예를 들자.
우리는 포지셔닝 서비스와 시간 서비스가 있다.하나의 처리 공간의 점, 다른 처리 시간의 점.만약 우리가 누군가가 운동한 모든 역사를 가지고 있다면.제공된 시간(GetLocation)에 따라 위치를 얻거나 제공된 위치(GetTime)에 따라 시간을 얻을 수 있습니다.현재 사용자의 입력은 텍스트이기 때문에 Location Service와 Time Service가 텍스트를 실제 공간과 시간으로 변환해야 합니다. 따라서 GetLocation은 ITime Service를 사용하고 GetTime은 ILocation Service를 사용합니다.프로그램을 시작하면 순환 의존 오류가 발생합니다.바보 같다고 했잖아.어쨌든, 모든 서비스를 ITime Parser와 ITI 관리자, 또는 다른 것으로 나눌 수 있으며, IText Parser라는 새로운 인터페이스를 만들 수 있으며, 재구성 해결 방안이 많다.하지만 재구성된 사치가 없다면 왜 무슨 일을 하겠는가?물론 GetLocation을 호출하면 해석 시간만 있으면 GetTime이 호출되지 않고, 반대로도 마찬가지입니다.
솔루션?
의존 관계를 사용해야만 진정으로 그것을 얻을 수 있는 가능한 해결 방안당신이 제공한 것은 필요한 인터페이스의 실제 실현이 아니라 타성 에이전트입니다.다음은 일반적인 LazyProxy 구현의 예입니다.
public class LazyProxy<TInterface>:Lazy<TInterface>
{
public LazyProxy(IServiceProvider serviceProvider) : base(() => serviceProvider.GetService<TInterface>()) { }
}
문제가 해결되었어요, 맞아요?Location Service는 하나LazyProxy<ITimeService>
를 요청하고 GetLocation은 _lazyTimeService.Value.ParseTime(input)
를 실행합니다. 이것은 처음으로 하나의 Time Service를 실례화합니다. 이것은 하나LazyProxy<ILocationService>
를 요청하고 GetTime에서 사용합니다_lazyLocationService.Value.ParseLocation(input)
. 이것은 Location Service의 기존 실례를 가져옵니다Singleton.이 두 서비스 중 어느 것이든 다른 의존 항목이 많이 필요하다고 상상해 보세요.이른바'a'leaky abstraction다.실제 서비스를 사용하기 전에, 실례화와 캐시 서비스 (모든 의존항) 의 복잡성을 숨깁니다.그리고 실제 똥이 실제 팬들에게 맞을 때 실수를 할 수도 있다.나는 '허점이 백출하다' 라는 단어가 상술한 습어에서 기원될 수 있다고 믿는다.징그러워, 그렇지?바로 이런 추상이 그 배후의 복잡성을 누설했다.
네가 이렇게 해서는 안 되는 원인은 매우 많다.통과합시다.
비평하다
가장 뚜렷한 것은 네가 더 잘할 수 있다는 것이다.위의 간단하면서도 인위적인 예에서 디자인은 결함이 있다. 왜냐하면 모든 서비스는 매우 독립된 두 가지 일을 하고 있기 때문이다. 그것이 바로 파라미터를 바탕으로 값을 제공하고 텍스트를 해석하는 입력이기 때문이다.만약 해석이 응용 프로그램의 필수 기능이라면 왜 두 서비스가 모두 사용하는 ITextParser 인터페이스를 설계하지 않습니까?만약 당신의 경우, 때로는 하나의 클래스를 실례화하여 하나의 함수를 사용하고, 때로는 다른 그룹의 함수를 사용한다면, 아마도 당신은 그것을 두 부분으로 나누어야 할 것이다.그러나 현실 생활에서 코드를 완전히 제어할 수 없을 수도 있고, 코드를 재구성할 자원이 없을 수도 있다.귀신이 곡할 노릇이군, 너는 깊이 빠졌을지도 몰라spaghetti code!붕괴될까 봐 코드를 접촉하는 것을 허락하지 않는 카드 회사에서 일한 적이 있습니까?
다음 문제는 가능한 버그에 대한 검출을 코드가 실행하는 특정한 지점으로 미루는 것입니다.일관성 없는 복제 오류Heisenbug를 생성합니다.IMomentum Service를 함께 사용하는 경우 얼마나 적합합니까?개발자들은 Heisenbug를 좋아한다. 왜냐하면 그것을 해결하는 시간에 큰 차이가 있을 수 있기 때문에, 그들은 자신이 작성한 코드를 실제로 사용하도록 강요당할 것이다.Oh, the humanity! 그러나 초기에 발견된 유일한 문제는 관계도에서의 순환에 의존하는 것이다. 이것은 디자인 문제와 같다.그것을 사용하려고 시도할 때 실행 중인 오류가 발생합니다.
이런 모델이 해결할 또 다른 문제는 본래 존재하지 말아야 한다.분명히 구조 함수should only construct는 외부 자원의 사용을 다른 메커니즘으로 처리하도록 한다.그러나 여기에는 장애가 하나 있다. 만약 당신이 구조 함수에 대한 요구를 받아들였다면, 당신은 이미 누설된 추상을 사용했을 것이다.마찬가지로 구조 함수를 변경할 수 없습니다.
하지만 이런 모델의 작업 방식을 고려해 보자.그것은 언제든지 요청 클래스의 실례화가 이루어질 수 있다는 사실에 기반을 두고 있다.service locator 메커니즘이 존재하는 사실은 GetService 방법의 지연 실례화이다.사실상 이런 타성 주입 모델 자체가 서비스 제공자 모델constructor dependency injection의 추상적이다.GetLocation 메서드에서
var timeService = _serviceProvider.GetService<ITimeService>()
를 실행할 수도 있고 완전히 동일한 작업을 수행할 수도 있습니다.그래서 이것은 네가 이렇게 해서는 안 되는 또 다른 원인이다. 바로 혼합 은유이다.하지만 헤헤!만약 네가 여기까지 읽는다면, 너는 내가 그 바보들을 한데 섞는 것을 좋아한다는 것을 알게 될 것이다.결론
어쨌든, 만약 당신이 다른 유사한 재구성 방법이 있다면, 나는 이 해결 방안을 추천할 수 없다.그러나 중요한 고비에 효과가 있을 수도 있다.너의 생각을 나에게 알려줘!
그나저나 이 문제도 Stack Overflow에서 토론한 적이 있는데, 여기에 재미있는 답안이 있다.
Reference
이 문제에 관하여(타성 의존 주입이 좋은 생각인가요?), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/costinmanda/is-lazy-dependency-injection-a-good-idea-c3p텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)