3

C#으로 작성된 웹 API 응용 프로그램이 있습니다. 나는 솔리드 (SOLID) 원칙을 고수하는 디자인을 보장하려고 노력 중이다. 이와 같이 Unity를 사용하여 내 컨트롤러에 의존성을 주입합니다. 그러나 나는 컨트롤러 자체에서 컨트롤러에 의해 수행되는 액션을 얻길 원하기 때문에 기본적으로 다른 (종종 정적 인) 객체의 메소드를 호출한다. 예를 들어 :종속성 삽입/솔리드 걱정

나는 객체가 작업을 수행하는 데 사용 여부를 통해 약간의 불안을 경험하고 무엇
public class MyController : ApiController 
{ 
    private readonly ISomeCrossCuttingInterface _instance; 
    private readonly ILog _log; 

    public MyController(ISomeCrossCuttingInterface someInterface, ILog log) 
    { 
     _instance = someInterface; 
     _log = log; 
    } 

    [HttpPost] 
    [ActionName("MyAction")] 
    public RequestResponse MyAction(MyActionData actionData) 
    { 
     try 
     { 
      return MyActionUser(actionData); 
     } 
     catch (Exception ex) 
     { 
      _log.Error("MyAction error", ex); 
     } 
     return ...; 
    } 

    private RequestResponse MyActionUser(MyActionData actionData) 
    { 
     var responseObj = StaticClass.SomeMethod(_instance, actionData); 
     var responseObj2 = StaticClass2.SomeMethod(_instance, responseObj2); 
     return CreateMyActionResponse(responseObj2); 
    } 

    private RequestResponse CreateMyActionResponse(...) 
    { 
     ... 
    } 
} 

. (위의 예 StaticClass 및 StaticClass2)가 실제로 주입해야한다. 현재 그들은 그렇지 않습니다. 주입 된 개체는 로깅이나 데이터 액세스와 같은 교차 절단 문제와 관련되거나 둘 이상의 컨트롤러에서 사용되는 개체입니다. 그렇다면 작업을 수행하는 객체를 주입하지 않는 이유는 무엇입니까? 나는이 '내부'객체가 하나의 컨트롤러와 관련된 특정 작업을 수행하는 데에만 사용된다고 생각합니다. 즉, 컨트롤러 기능은 본질적으로 하나의 책임을 지닌 객체로 나뉘어져 있습니다. 각 컨트롤러에는 컨트롤러가 수행해야하는 작업을 수행하는 고유 한 객체 세트가 있습니다. 그러나 이것은 나쁜 설계입니까? 모든 사물을 관계없이 주입해야합니까? 모든 입력 정말 감사합니다.

답변

5

SOLID 원칙을 사용하면 코드를 유지 관리하기 쉽고 테스트 가능하며 유연하게 만들 수 있습니다. 이러한 원칙 중 일부를 사용하는 경우에는 사용하지 않는 것보다 낫습니다.

어떻게 든 정적 클래스를 변경하려는 경우 발생할 수있는 일에 대해 생각해보십시오. 변경으로 인해 컨트롤러 중 하나가 손상되지 않는다고 확신 할 수 있습니까?당신은 당신의 정적 클래스에 대한 단위 테스트와 당신의 컨트롤러에 대한 단위 테스트를 가질 수 있지만, 그것들이 함께 작동 하는지를 확인하기 위해서는 통합 테스트가 필요합니다. 정적 클래스를 주입하는 경우 메서드가 호출되었는지 확인하기위한 단위 테스트를 쉽게 수행하고 올바른 결과를 반환 할 수 있습니다.

또한 컨트롤러가이 논리를 수행하는 것을 원하지는 않습니다. 친절하고 편하게해야하므로 모든 것을 서비스에 넣고 서비스가 저장소를 호출하고 논리를 처리하도록합니다. 그런 다음 서비스를 컨트롤러에 삽입하십시오.

+0

감사합니다. 이것은 더 나은 접근 방법처럼 들리지만, 현재 코드는 올바르게 냄새를 맡지 않습니다 (!). 이 서비스는 다음과 같이 유니티 구성에서 설정해야합니다 : container.RegisterType (). 이것은 통일성이이 종속성을 위해 만들 유형을 알 수있게합니다. 내가 알아야 할 것은 LoginService의 의존성을 어떻게 전달하는지입니다. – fhevol

+0

대신 인터페이스를 구현하는 클래스에 대한 어셈블리 집합을 검사하는'container.RegisterTypes'를 사용하면 더 쉽게 만들 수 있습니다. 규칙을 사용하면 'ILoginService'를 구현하는 LoginService가 있으면 주입을 통해 자동으로 해결되는 유형을 사용할 수 있습니다. http://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx – demoncodemonkey

1

음.

저장소를 조롱하고 싶을 것 같습니다. 유사한 방식으로 StaticClass에 다른 동작을 삽입 할 수도 있습니다. 그러나 행동이 고쳐지면 그대로 유지하십시오.

모든 것을 주사 할 수 있다면 코드 팽창으로 이어질 것입니다. 따라서 제 충고는 SOLID 발음을 통제하기 위해 대조를 사용하는 것이 아니라 실제 시험 시나리오를 다루기 위해 사용하는 것입니다.

+0

감사합니다. 클라우드 (아마도 AWS)에서 실행될 응용 프로그램을위한 것이므로 실제로 저장소를 조롱하고 있습니다. 처음에 모든 것을 함께 모으기 위해 저는 저장소를 조롱했습니다. – fhevol

4

주입해서는 안되는 유일한 것은 안정적이며 타사 라이브러리는 변경되지 않으며 테스트 가능성, 유지 보수성, 병렬 개발, 확장 성 또는 후기 바인딩이 필요하지 않음을 알 수 있습니다.

StaticClass에 실제로 로직이 포함되어있는 경우 의 일부로 메소드를 포함하지 않는 이유는 무엇입니까? 그렇지 않으면 다른 레벨 (다른 관심사)에서 다른 작업을 수행해야합니다.

당신은 이미 선반에이 훌륭한 자료를 가지고있을 것이라고 확신하지만, 여기에 링크를 넣어 보겠습니다 : Dependency Injection in .NET (Mark Seemann).

내 개인적인 경험을 통해 : 실제로 작은 응용 프로그램을 만들고 재미있게 만들었 으면 좋겠다. 끝내면 밖으로 던져 버릴거야. 재미있게 놀아 라. Dependency Injection을 여기 저기에 사용하여 단위 테스트를 작성하여 그것이 어떤 느낌인지 그리고 어떻게 처리되는지 확인하십시오. 완벽하면 만들 수 없습니다. 예를 들어, 콘솔과 WPF/WinForms 응용 프로그램간에 쉽게 변경할 수 있습니까? 무엇을 바꾸어야합니까? 두 응용 프로그램간에 모듈을 얼마나 쉽게 교환 할 수 있습니까? 다른 구현을 작성하십시오. 어쩌면 당신은 당신의 콘솔에 당신의 로그를 원할 것입니다, 어쩌면 당신은 GUI, txt 또는 xml 파일에 그것들을 원할 것입니다. 코드를 변경하는 것이 얼마나 쉬운가요? 느슨하게 결합 된 코드가 전체 요점이며 Dependency Injection 패턴이 여기에서 도움이됩니다.

+0

귀하의 조언에 감사드립니다. 정적 클래스의 사용법을 설명하기 위해 정적 클래스를 사용하여 로그인을 검증하는 LoginController (저장소에서 데이터를 가져 와서 암호를 확인)와 세션을 생성하는 두 번째 정적 클래스 (저장소로도 저장 됨)를 사용합니다. 이 응용 프로그램은 REST를 사용합니다). – fhevol

+0

귀하의 의견에 감사 드리며 디자인을 수정했습니다. 책 추천 주셔서 감사합니다. 많은 감사를드립니다. – fhevol

관련 문제