W C++ często używam obiektów w stylu RAII, aby uczynić kod bardziej niezawodnym i przydzielać je na stos, aby kod był bardziej wydajny (i aby uniknąć bad_alloc).Stack przydzielonych obiektów RAII vs zasada DI
Ale tworzenie obiektu konkretnej klasy na stosie narusza zasadę inwersji zależności (DI) i zapobiega przedśmiekaniu tego obiektu.
Rozważmy następujący kod:
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();
}
mogę przetestować IBar::process
, ale także chcą przetestować Some::foo
, bez tworzenia prawdziwego obiektu Connection.
Z pewnością mogę użyć fabryki, ale znacznie skomplikuje to kod i wprowadzi alokację sterty.
Ponadto, nie lubię dodawać metody Connection::open
, wolę konstruować całkowicie zainicjalizowane i w pełni funkcjonalne obiekty.
chciałbym zrobić Connection
typ parametrem szablonu dla Some
(lub foo
jeśli wyodrębnić je jako wolnej funkcji), ale nie jestem pewien, że jest to właściwa droga (szablony wyglądają jak czarna magia dla wielu ludzi, więc ja preferuje użycie dynamicznego polimorfizmu)
Szablony nie powinny być czarną magią dla mniej lub bardziej kompetentnego programisty C++, nie widzę powodu, aby ich unikać.Nie uważam też, że alokacja sterty jest * taka * droga (to oczywiście zależy od oprogramowania, które piszesz), więc nie widzę powodu, aby tego unikać (w przypadku użycia inteligentnych wskaźników). –
@Alex B: jest pewien powód, aby ich unikać, chociaż zgadzam się, że to nie dlatego, że są "czarną magią". Dzieje się tak, ponieważ jeśli wszystko zostanie wstrzyknięte za pomocą parametrów szablonu, wszystko, co napiszesz, jest szablonem, twoja biblioteka jest tylko nagłówkowa i może stać się dość kłopotliwa pod względem kompilacji lub dystrybucji. Chociaż, przypuszczam, że z ostrożnością można by przetestować bibliotekę tylko nagłówkową, następnie zbuduj z niej jednostkę, która zawiera tylko instancje wymagane przez aplikację. –
RAII i DI świetnie ze sobą współpracują, więc tytuł jest mylący, Twoim problemem jest alokacja stosów kontra DI. –