C++에서는 종종 RAII 스타일의 객체를 사용하여 코드의 안정성을 높이고 스택에 할당하여 코드를 더 효율적으로 만들었습니다 (bad_alloc을 방지했습니다).스택에 RAII 객체와 DI 원칙이 할당 됨
그러나 스택에 콘크리트 클래스의 객체를 생성하면 종속성 반전 (DI) 원칙을 위반하고이 객체를 조롱하는 것을 방지합니다.
다음 코드 고려 : 나는 IBar::process
을 테스트 할 수 있습니다
struct IInputStream
{
virtual vector<BYTE> read(size_t n) = 0;
};
class Connection : public IInputStream
{
public:
Connection(string address);
virtual vector<BYTE> read(size_t n) override;
};
struct IBar
{
virtual void process(IInputStream& stream) = 0;
};
void Some::foo(string address, IBar& bar)
{
onBeforeConnectionCreated();
{
Connection conn(address);
onConnectionCreated();
bar.process(conn);
}
onConnectionClosed();
}
, 그러나 나는 또한 실제 연결 객체를 생성하지 않고, Some::foo
을 테스트 할 수 있습니다.
확실히 팩토리를 사용할 수 있지만 코드가 복잡해지고 힙 할당이 도입됩니다.
또한, Connection::open
메서드를 추가하고 싶지 않습니다. 완전히 초기화되고 완전한 기능을 갖는 개체를 만드는 것이 좋습니다.
나는 Some
에 대한 Connection
타입 템플릿 매개 변수를 만들 (또는 foo
을위한 경우에하는 무료 기능으로 추출),하지만 난 그게 올바른 방법 (템플릿을 많은 사람들에게 마술처럼, 그래서 있다는 모르겠어요 것 동적 다형성 사용을 선호)
템플릿이 더 많거나 적을 유능한 C++ 프로그래머에게는 검은 마법이되어서는 안됩니다. 나는 그것을 피할 이유가 없습니다.또한 나는 힙 할당이 비싸다는 것을 생각하지 않는다. (스마트 포인터와 함께 사용되는 경우) 이것을 피할 이유가 없다. –
@Alex B : "블랙 마술"이 아니기 때문에 일종의 피할 수있는 이유가 있습니다. 모든 것이 템플릿 매개 변수를 통해 주입되면 작성한 모든 내용이 템플릿이고 라이브러리가 헤더 전용이며 컴파일 또는 배포 측면에서 상당히 복잡 할 수 있기 때문입니다. 주의 할 것은 헤더 전용 라이브러리를 단위 테스트 할 수 있다고 가정하고 응용 프로그램에 필요한 인스턴스화 만 포함하는 TU를 작성하십시오. –
RAII와 DI가 함께 작동하므로 제목이 잘못 표시됩니다. 문제는 Stack Allocation 대 DI입니다. –