Aikido

Porque deve utilizar uma classe por ficheiro: melhorar a organização e a navegação do código

Legibilidade

Regra

Uma classe por ficheiro.
Várias classes em a único ficheiro criar código
organização pouco clara e mais difícil de navegar.

Idiomas suportados: 45+

Introdução

Colocar várias classes num único ficheiro dificulta a localização de classes específicas quando se navega numa base de código. Os desenvolvedores que procuram por Repositório de utilizadores não o encontrará rapidamente se estiver enterrado num ficheiro chamado base de dados.js juntamente com outras cinco classes. Isto viola o princípio da menor surpresa e atrasa o desenvolvimento, uma vez que os membros da equipa perdem tempo à procura de definições de classes.

Porque é importante

Manutenção do código: A existência de várias classes por ficheiro cria limites pouco claros entre as responsabilidades. Quando uma classe precisa de ser modificada, os programadores têm de abrir um ficheiro que contém classes não relacionadas, aumentando a carga cognitiva e o risco de modificar acidentalmente o código errado.

Navegação e capacidade de descoberta: Os IDE e os editores de texto têm dificuldade em fornecer uma definição exacta de "ir para" quando várias classes partilham um ficheiro. Os programadores perdem tempo a procurar nos ficheiros em vez de irem diretamente para a classe de que necessitam. Isso se agrava em grandes bases de código com centenas de classes.

Conflitos de controlo de versões: Quando várias classes partilham um ficheiro, as alterações a diferentes classes por diferentes programadores criam conflitos de fusão. Os ficheiros separados permitem o desenvolvimento paralelo sem sobrecarga de coordenação, uma vez que cada programador trabalha no seu próprio ficheiro.

Exemplos de código

Não conforme:

// database.js
class UserRepository {
    async findById(id) {
        return db.users.findOne({ id });
    }
}

class OrderRepository {
    async findByUser(userId) {
        return db.orders.find({ userId });
    }
}

class ProductRepository {
    async findInStock() {
        return db.products.find({ stock: { $gt: 0 } });
    }
}

module.exports = { UserRepository, OrderRepository, ProductRepository };

Porque é que é errado: Três classes de repositório não relacionadas num ficheiro chamado base de dados.js. Procurar por Repositório de encomendas requer saber que está em base de dados.js em vez de OrderRepository.js. As alterações de ficheiros afectam várias classes, criando conflitos de fusão desnecessários.

Conformidade:

// UserRepository.js
class UserRepository {
    async findById(id) {
        return db.users.findOne({ id });
    }
}
module.exports = UserRepository;

// OrderRepository.js
class OrderRepository {
    async findByUser(userId) {
        return db.orders.find({ userId });
    }
}
module.exports = OrderRepository;

// ProductRepository.js
class ProductRepository {
    async findInStock() {
        return db.products.find({ stock: { $gt: 0 } });
    }
}
module.exports = ProductRepository;

Porque é que isto é importante: Cada classe no seu próprio ficheiro torna a navegação previsível. Os IDEs podem saltar diretamente para OrderRepository.js ao procurar a classe. As alterações a um repositório não afectam os outros, eliminando conflitos de fusão desnecessários.

Conclusão

Dê aos ficheiros o nome da classe que contêm para uma navegação previsível. Esta convenção pode ser usada em grandes bases de código, onde é importante encontrar classes específicas rapidamente. Os ficheiros extra valem a pena pela clareza organizacional que proporcionam.

FAQs

Tem perguntas?

E quanto a pequenas aulas de apoio ou aulas particulares?

As pequenas classes auxiliares utilizadas apenas por uma classe-mãe podem permanecer no mesmo ficheiro se forem verdadeiramente detalhes de implementação. No entanto, se as classes auxiliares forem reutilizadas ou ultrapassarem as 20-30 linhas, extraia-as. As classes privadas que existem apenas para suportar uma classe pública são excepções razoáveis.

Isto aplica-se a interfaces e tipos TypeScript?

Os tipos e interfaces utilizados por uma classe podem estar no mesmo ficheiro. No entanto, os tipos partilhados utilizados em vários ficheiros devem estar nos seus próprios ficheiros de definição de tipos. A chave é se a definição é utilizada apenas por esse ficheiro ou se é necessária noutro ficheiro.

O que dizer de linguagens como Python com múltiplas classes na prática padrão?

As convenções Python diferem, mas o princípio continua a aplicar-se: agrupe classes relacionadas se estas formarem um módulo coeso, mas evite misturar classes não relacionadas. Um models.py com User e UserProfile faz sentido. Um utils.py com vinte classes não relacionadas não faz.

Como é que organizo as classes relacionadas, como as classes pai e filho?

Coloque-os em ficheiros separados dentro do mesmo diretório. Para Animal e Cão, utilize animals/Animal.js e animals/Dog.js. A estrutura de diretórios mostra as relações, mantendo uma classe por ficheiro. Isto é melhor do que agrupar classes relacionadas num único ficheiro.

E se a extração de classes criar muitos ficheiros pequenos?

Muitos ficheiros pequenos são preferíveis a poucos ficheiros grandes. Os IDEs modernos lidam com milhares de ficheiros de forma eficiente. A navegação no sistema de arquivos é mais rápida do que a pesquisa em arquivos grandes. A clareza de saber exatamente onde cada classe vive supera a perceção de "muitos arquivos".

Obter segurança gratuitamente

Proteja seu código, nuvem e tempo de execução em um sistema central.
Encontre e corrija vulnerabilidades rapidamente de forma automática.

Não é necessário cartão de crédito | Resultados do scan em 32secs.