enum no cabeçalho causa recompilações excessivas
John Lakos refere-se a esse problema comouma fonte insidiosa de acoplamento em tempo de compilação (Figura 0-3, em sua introdução):
O problema que estou enfrentando é que muitos arquivos são compilados porque existe uma dependência física de uma única enumeração.
Eu tenho um cabeçalho com a definição de enum:
// version.h
enum Version {
v1 = 1,
v2, v3, v4, v5, ... v100
};
e isso é usado por centenas de arquivos. Cada arquivo define uma classe de objetos, que devem ser lidos no disco, usando oread()
função.Version
é usado para determinar a maneira como os dados devem ser lidos.
Toda vez que uma nova classe ou membro da classe é introduzida, uma nova entrada é anexada à enumeração
// typeA.cpp
#include "version.h"
void read (FILE *f, ObjectA *p, Version v)
{
read_float(f, &p->x);
read_float(f, &p->y);
if (v >= v100) {
read_float(f, &p->z); // after v100 ObjectA becomes a 3D
}
}
e
// typeB.cpp
#include "version.h"
void read (FILE *f, ObjectB *p, Version v)
{
read_float (f, &p->mass);
if (v >= v30) {
read_float (f, &p->velocity);
}
if (v >= v50) {
read_color (f, &p->color);
}
}
Agora, como você pode ver, uma vezObjectA
alterações, temos que introduzir uma nova entrada (digamosv100
) aoVersion
. Consequentemente, todostype*.cpp
arquivos serão compilados, mesmo que apenasread()
doObjectA
realmente precisa dov100
entrada.
Como posso inverter a dependência da enum, com alterações mínimas no cliente (ou seja,type*.cpp
), para que apenas os arquivos .c necessários sejam compilados?
Aqui está uma solução possível, em que pensei, mas preciso de uma melhor:
Eu estava pensando em colocar o enum em um arquivo .cpp e exporint
s com os valores dos respectivos membros enum:
//version.cpp
enum eVersion {
ev1 = 1,
ev2, ev3, ev4, ev5, ... ev100
};
const int v1 = ev1;
const int v2 = ev2;
....
const int v100 = ev100; // introduce a new global int for every new entry in the enum
faça um alias para oVersion
digite de alguma forma
//version.h
typedef const int Version;
e introduza apenas os valores constantes que são necessários a cada vez:
// typeA.cpp
#include "version.h"
extern Version v100; ///// *** will be resolved at link time
void read (FILE *f, ObjectA *p, Version v)
{
read_float(f, &p->x);
read_float(f, &p->y);
if (v >= v100) {
read_float(f, &p->z); // after v100 ObjectA becomes a 3D
}
}
mas acho que isso parece uma solução muito ruim, que remonta aos tempos anteriores ao cabeçalho