Dividir em arquivos - quanto dividir?

9

Se eu disser que tenho uma estrutura hierárquica de entidades, em vez de um modelo de componente. Algo como:
(Sim, isso é feito)

Arma-> Arma-> Arma Automática-> MP44
Ou, mais um exemplo clássico:
Entidade-> MovableEntity-> Inimigo-> WalkingEnemy

Até que ponto você dividiria os arquivos de origem / cabeçalho para facilitar a leitura e a organização? É melhor usar algo como Entity.cpp, MovableEntity.cpp, Enemy.cpp, etc., ou seria melhor uma abordagem como Entity.cpp [contendo Entity and MovableEntity] e Enemy.cpp [contendo Enemy e WalkingEnemy]? (Ou de uma maneira mais independente do idioma, um arquivo Inimigo e um arquivo de Entidade versus um arquivo para cada classe?)
Além disso, isso afetaria algo além de legibilidade e organização?

O Pato Comunista
fonte
11
Nitpicky, mas não acho que language-agnosticseja uma tag apropriada, pois depende muito do idioma que você está usando quanto aos efeitos colaterais.
Tetrad
Bom ponto, acho que posso repetir.
The Duck Comunista

Respostas:

12

Isso é inteiramente uma questão de preferência. No entanto, eu pessoalmente acredito que é melhor errar ao lado de mais arquivos. Java requer uma classe por arquivo , com o nome do arquivo igual ao nome da classe, por exemplo; eles fazem isso por política para aplicar essas boas práticas (embora você possa ter subclasses que basicamente contornam isso).

Além disso, os sistemas de controle de origem são muito bons em mesclar alterações em um arquivo, mas é menos complicado se você estiver trabalhando apenas em arquivos totalmente separados. Você também pode ver com mais facilidade quem mudou qual classe. Digamos que outro desenvolvedor faça uma alteração no arquivo AllEntities.h; você não tem idéia exatamente de qual entidade (ou entidades) ele mudou até você abrir o arquivo e observar a saída do diff.

É ótimo agrupar pequenas estruturas e enumerações relacionadas à classe no arquivo de uma classe . Se você tem um enum usado apenas por uma única classe, por que dividi-lo em seu próprio arquivo? Apenas junte-os. Mas se for usado por outra classe (ou seja, outro membro da classe é do tipo dessa enumeração), é quando é hora de fornecer seu próprio arquivo.

Ricket
fonte
Acordado. A complexidade de seus tipos definitivamente deve ser um fator. Se o seu idioma suportar classes parciais (ou se as implementações de membros puderem ser organizadas de maneira semelhante ao C ++), eu recomendaria dividir tipos particularmente complexos em vários arquivos. Por exemplo, se houver uma interface (grande) que sua classe precise implementar, mas o código for genérico e pouco relevante para o resto, você poderá dividi-lo em um arquivo / classe parcial separados. Para tipos de enumeração, acho que você poderia colocar todas as enumerações para um determinado espaço para nome em um único arquivo.
Mike Strobel
11
Agrupar suas enumerações não significa que alterar um único valor causaria uma recompilação de cada arquivo que usa uma enumeração nesse espaço de nome?
The Duck comunista
Bem, isso realmente depende do idioma, mas sim, certamente poderia ter esse efeito. Não é realmente um problema para mim, pois desenvolvo principalmente em C # (sem compilação arquivo a arquivo), mas pode ser problemático em C ++ e em outras linguagens. Como sempre, há fatores específicos do idioma a serem considerados e esse seria um deles :).
quer
2

Muitos idiomas fora do C / C ++ impõem restrições aos arquivos. Ricket mencionou 'uma classe por arquivo' do Java; Python usa arquivos como namespaces; outras línguas frequentemente copiam o espírito delas.

Se você estiver usando C ou C ++, arquivos mais incluídos geralmente significam tempos de compilação mais longos por arquivo; por outro lado, menos significa mais para recompilar ao fazer pequenas alterações. Como as enumerações não podem ser declaradas a frente em C, você deve sempre colocá-las em arquivos de cabeçalho contendo apenas outras enumerações, para sanidade da dependência.

Caso contrário, o "um arquivo por classe" do Java é razoável, mas há muito tempo o Java suporta classes internas - como um contêiner e uma classe interna de seu iterador. Da mesma forma, em qualquer outro idioma, você provavelmente desejará um registro / estrutura / classe / tipo / interface / blorb dominante por cabeçalho, mas poderá decidir incluir também auxiliares ou contêineres relacionados.

(Você não precisa usar um modelo de componente, mas se tiver uma hierarquia de classes profunda e específica como essa, se odiará mais tarde.)


fonte
Eu estava usando a hierarquia como exemplo; Eu senti que isso enfatizava o que eu queria dizer melhor. No código real, estou me esforçando para obter componentes.
The Duck Comunista