En C++ a menudo utilizo objetos estilo RAII para hacer el código más confiable y asignarlos en la pila para hacer que el código sea más eficiente (y para evitar bad_alloc).Pila de objetos RAII asignados frente al principio DI
Pero la creación de un objeto de clase concreta en la pila viola el principio de inversión de dependencia (DI) y evita la burla de este objeto.
Considere el siguiente código:
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();
}
puedo probar IBar::process
, pero también quiero probar Some::foo
, sin crear objeto de conexión real.
Seguramente puedo usar una fábrica, pero complicará significativamente el código e introducirá la asignación de montones.
Además, no me gusta agregar el método Connection::open
, prefiero construir objetos completamente inicializados y completamente funcionales.
me gustaría hacer Connection
tipo de un parámetro de plantilla para Some
(o para foo
si extraerlo como una función gratuita), pero no estoy seguro de que es la manera correcta (plantillas se ven como una magia negro para muchas personas, por lo que Prefiere usar polimorfismo dinámico)
Las plantillas no deben ser magia negra para el programador de C++ más o menos competente, no veo ninguna razón para evitarlas.Además, no creo que la asignación de heap sea * que * costosa (esto, por supuesto, depende del software que escriba), así que tampoco veo motivos para evitarla (cuando se usa con punteros inteligentes). –
@Alex B: hay una razón para evitarlos, aunque estoy de acuerdo en que no es porque sean "magia negra". Es porque si todo se inyecta a través de parámetros de plantilla, entonces todo lo que escribes es una plantilla, tu biblioteca es solo de encabezado y puede ser bastante engorrosa en términos de compilación o distribución. Aunque, supongo que con cuidado podría probar la biblioteca de encabezado único, luego compilar una TU que solo contenga las instancias que necesita la aplicación. –
RAII y DI funcionan muy bien juntos, por lo que el título es engañoso, su problema es la asignación de pila vs DI. –