언제 '새'키워드를 사용해야합니까?


15

Misko Hevery가 제공 한 단위 테스팅에 대한 Google Tech Talk 프레젠테이션을 보고 new비즈니스 로직 코드에서 키워드를 사용하지 말라고 말했습니다 .

프로그램을 작성했는데 new여기저기서 키워드 를 사용 했지만 데이터를 보유한 객체를 인스턴스화하는 데 주로 사용되었습니다 (즉, 함수 나 메소드가 없었습니다).

프로그램에 새 키워드를 사용할 때 문제가 발생했는지 궁금합니다. 그리고 우리는 그 '규칙'을 어디에서 깨뜨릴 수 있습니까?


2
프로그래밍 언어와 관련된 태그를 추가 할 수 있습니까? 새로운 언어는 많은 언어 (C ++, Java, Ruby)로 존재하며 의미가 다릅니다.
사키 스크

답변:


16

이것은 단단하고 빠른 규칙보다 더 많은 지침입니다.

프로덕션 코드에서 "new"를 사용하면 클래스를 공동 작업자와 연결합니다. 누군가가 다른 공동 작업자 (예 : 단위 테스트를위한 일종의 모의 공동 작업자)를 사용하려는 경우 공동 작업자가 비즈니스 논리에서 만들어지기 때문에 그렇게 할 수 없습니다.

물론 누군가는 이러한 새로운 객체를 생성해야하지만 이것은 스프링과 같은 의존성 주입 프레임 워크 또는 생성자를 통해 주입 된 비즈니스 로직 클래스를 인스턴스화하는 클래스 중 하나에 두는 것이 가장 좋습니다.

물론, 당신은 이것을 너무 멀리 가져갈 수 있습니다. 새로운 ArrayList를 반환하려면, 아마도 이것은 불변의 List가 될 것입니다.

스스로 물어봐야 할 주요 질문은 "이 유형의 객체를 생성하는이 코드의 주된 책임입니까, 아니면 다른 곳으로 합리적으로 이동할 수있는 구현 세부 사항입니까?"입니다.


1
만약 당신이 불변 목록이되기를 원한다면, Collections.unmodifiableList또는 무언가 를 사용해야합니다 . 그러나 나는 당신이 무슨 뜻인지 안다 :)
MatrixFrog

그렇습니다, 그러나 당신은 어떻게 든 원래의리스트를 만들어서 수정 불가능한 것으로 변환 할 필요가 있습니다.
Bill Michell

5

이 질문의 요점은 끝입니다. 프로그램에 새 키워드를 사용할 때 뭔가 잘못했는지 궁금합니다. 그리고 우리는 그 '규칙'을 어디에서 깨뜨릴 수 있습니까?

코드에 대한 효과적인 단위 테스트를 작성할 수 있다면 아무런 문제가 없습니다. 의 사용이 경우 new단위 테스트 코드에가 어렵거나 불가능했다, 당신은 재 평가 새로운 사용을해야합니다. 이 분석을 다른 클래스와의 상호 작용으로 확장 할 수 있지만 견고한 단위 테스트를 작성하는 능력은 종종 충분한 프록시입니다.


5

요컨대, "new"를 사용할 때마다이 코드가 포함 된 클래스를 작성중인 객체에 단단히 연결합니다. 이러한 객체 중 하나를 인스턴스화하려면 인스턴스화를 수행하는 클래스가 인스턴스화되는 구체적인 클래스에 대해 알아야합니다. 따라서 "신규"를 사용할 때 인스턴스화를 배치하는 클래스가 해당 지식이 상주하기에 "좋은"장소인지 여부를 고려해야합니다. 인스턴스화되는 객체가 변경되었습니다.

다른 구체적인 클래스에 대한 지식이있는 엄격한 결합은 항상 피해야하는 것은 아닙니다. 어떤 수준에서는 무언가 다른 곳에서 객체의 사본을 제공하여 다른 모든 객체가 객체를 처리하더라도이 객체를 만드는 방법을 알아야합니다. 그러나 작성중인 클래스가 변경 될 때 해당 클래스의 구체적인 구현에 대해 알고있는 클래스는 해당 클래스의 변경 사항을 올바르게 처리하도록 업데이트되어야합니다.

항상 물어봐야 할 질문은 "이 클래스가 다른 클래스를 만드는 방법을 알고 있으면 앱을 유지할 때 책임이 되는가?"입니다. 두 가지 주요 설계 방법 (SOLID 및 GRASP)은 일반적으로 미묘하게 다른 이유로 "예"라고 대답합니다. 그러나 그것들은 방법론 일 뿐이며, 둘 다 고유 한 프로그램에 대한 지식을 바탕으로 공식화되지 않았다는 극단적 인 한계가 있습니다. 따라서, 그들은주의 측면에서만 오류를 범할 수 있으며, 단단한 결합 지점은이 지점의 한쪽 또는 양쪽을 변경하는 것과 관련하여 문제를 야기 할 것이라고 가정합니다. 세 가지를 알고 최종 결정을 내려야합니다. 이론적 인 모범 사례 (모든 것이 변경 될 수 있기 때문에 모든 것을 느슨하게 결합하는 것); 이론적 모범 사례를 구현하는 비용 (한 유형의 변경을 완화하면서 다른 유형을 방해하는 몇 가지 새로운 추상화 계층을 포함 할 수 있음) 그리고 당신이 기대하고있는 변화의 유형이 필요할 것이라는 실제 가능성.

몇 가지 일반적인 지침 :

  • 컴파일 된 코드 라이브러리간에 긴밀한 연결을 피하십시오. DLL (또는 EXE와 해당 DLL) 간의 인터페이스는 긴밀한 결합으로 인해 단점이되는 주요 위치입니다. DLL X의 클래스 A를 변경하고 기본 EXE의 클래스 B가 클래스 A에 대해 알고 있으면 두 바이너리를 모두 다시 컴파일하고 해제해야합니다. 단일 바이너리 내에서 변경을 위해 전체 바이너리를 다시 빌드해야하므로 일반적으로보다 밀접한 결합이 더 허용됩니다. 때로는 여러 이진 파일을 다시 작성해야하는 것은 불가피하지만, 특히 모바일 앱 배포와 같이 대역폭이 중요한 상황 (예 : 업그레이드에서 새 DLL을 푸시하는 것이 훨씬 저렴함)의 경우 코드를 구조화하여 코드를 피해야합니다. 전체 프로그램을 추진하는 것보다).

  • 프로그램의 주요 "로직 센터"사이에 긴밀한 연결을 피하십시오. 잘 구성된 프로그램은 가로 및 세로 조각으로 구성되어 있다고 생각할 수 있습니다. 수평 슬라이스는 UI, 컨트롤러, 도메인, DAO, 데이터와 같은 전통적인 애플리케이션 계층 일 수 있습니다. 수직 슬라이스는 개별 창이나보기 또는 개별 "사용자 스토리"(일부 기본 유형의 새 레코드 작성과 같은)에 대해 정의 될 수 있습니다. 잘 구성된 시스템에서 위, 아래, 왼쪽 또는 오른쪽으로 전화를 걸 때는 일반적으로 해당 통화를 추상화해야합니다. 예를 들어, 유효성 검사에서 데이터를 검색해야하는 경우 DB에 직접 액세스 할 수 없어야하지만이를 수행하는 방법을 알고있는 실제 개체가 지원하는 데이터 검색을위한 인터페이스를 호출해야합니다. 일부 UI 컨트롤이 다른 창과 관련된 고급 논리를 수행해야하는 경우 이벤트 및 / 또는 콜백을 통해이 로직의 트리거링을 추상화해야합니다. 결과적으로 수행 할 작업을 알 필요가 없으므로이를 제어하는 ​​컨트롤을 변경하지 않고도 수행 할 작업을 변경할 수 있습니다.

  • 어쨌든, 변경이 얼마나 쉽고 어려울 지, 그리고 그러한 변경이 얼마나 될지 고려하십시오. 작성중인 오브젝트가 한 곳에서만 사용되며 변경을 예측하지 않으면 일반적으로 타이트한 커플 링이 더 허용되며이 상황에서는 커플 링을 느슨하게하는 것보다 우수 할 수 있습니다. 느슨한 결합에는 추상화 구현이 필요합니다.이 계층은 종속성 구현이 변경되어야 할 때 종속 개체로의 변경을 방지하는 추가 계층입니다. 그러나 인터페이스 자체를 변경해야하는 경우 (새 메소드 호출 추가 또는 기존 메소드 호출에 매개 변수 추가) 인터페이스는 실제로 변경에 필요한 작업량을 증가시킵니다. 설계에 영향을 미치는 다양한 유형의 변화 가능성을 평가해야합니다.


3

데이터 만 보유하는 개체 또는 DTO (데이터 전송 개체)는 아무 문제없이 하루 종일 만들 수 있습니다. 피해야 할 곳 new은 작업을 수행하는 클래스에서 소비하는 클래스가 대신 인터페이스 에 대해 프로그래밍 하여 해당 논리를 호출하고 소비 할 수는 있지만 실제로 논리를 포함하는 클래스의 인스턴스를 생성 할 책임은 없다는 것입니다. . 클래스를 포함하는 동작 수행 또는 논리는 종속성입니다. Misko의 대화는 이러한 의존성을 주입하고 다른 엔티티가 실제로이를 작성하도록 책임을지게하는 데 중점을두고 있습니다.


2

다른 사람들은 이미이 점을 언급했지만 개념을 이해하기 쉽기 때문에 Uncle Bob 's (Bob Martin) Clean Code에서 인용하고 싶었습니다.

"건축을 사용에서 분리하는 강력한 메커니즘은 의존성 주입 ( IoC)을 의존성 관리에 적용하는 의존성 주입 (DI) 입니다. 제어반전은 목적에서 전용 인 다른 물체로 2 차 책임을 옮겨서 단일 책임 원칙 . 의존성 관리의 맥락에서, 객체는 의존성 자체를 인스턴스화에 대한 책임을지지해야한다. 대신함으로써 제어 반전, 또 다른 "권위"메커니즘이 책임을 통과해야합니다. 설치가 세계적인 관심사이기 때문에,이 권위있는 메커니즘은 일반적으로 "주요"루틴이거나 특수 목적 컨테이너입니다. "

이 규칙을 따르는 것이 항상 좋은 생각 이라고 생각합니다 . 다른 사람들은 더 중요한 IMO-> 클래스를 종속성 (협력자)과 분리시킵니다. 두 번째 이유는 클래스가 작고 간결하며 이해하기 쉽고 다른 상황에서도 재사용하기 때문입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.