Aikido

Por qué debería utilizar una clase por archivo: mejora la organización del código y la navegación

Legibilidad

Regla

Un clase por expediente.
Varias clases en clases en a único archivo archivo hacer código
organización poco clara y más difícil de navegar.

Idiomas compatibles: 45+

Introducción

La inclusión de varias clases en un único archivo dificulta la localización de clases concretas al navegar por un código base. Los desarrolladores que buscan UsuarioRepositorio no lo encontrará rápidamente si está enterrado en un archivo llamado base de datos.js junto a otras cinco clases. Esto viola el principio de menor sorpresa y ralentiza el desarrollo, ya que los miembros del equipo pierden tiempo buscando definiciones de clases.

Por qué es importante

Mantenimiento del código: Múltiples clases por archivo crean límites poco claros entre responsabilidades. Cuando es necesario modificar una clase, los desarrolladores deben abrir un archivo que contiene clases no relacionadas, lo que aumenta la carga cognitiva y el riesgo de modificar accidentalmente código incorrecto.

Navegación y visibilidad: Los IDE y los editores de texto tienen dificultades para proporcionar una "definición de destino" precisa cuando varias clases comparten un archivo. Los desarrolladores pierden tiempo buscando dentro de los archivos en lugar de ir directamente a la clase que necesitan. Esto se agrava en grandes bases de código con cientos de clases.

Conflictos de control de versiones: Cuando varias clases comparten un archivo, los cambios realizados en clases diferentes por desarrolladores distintos crean conflictos de fusión. Los archivos separados permiten un desarrollo paralelo sin sobrecarga de coordinación, ya que cada desarrollador trabaja en su propio archivo.

Ejemplos de códigos

❌ No 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 };

Por qué está mal: Tres clases de repositorio no relacionadas en un archivo llamado base de datos.js. Búsqueda de Depósito de pedidos requiere saber que está en base de datos.js en lugar de OrderRepository.js. Los cambios en los archivos afectan a varias clases, lo que crea conflictos de fusión innecesarios.

✅ Conforme:

// 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;

Por qué es importante: Cada clase en su propio archivo hace que la navegación sea predecible. Los IDEs pueden saltar directamente a OrderRepository.js al buscar la clase. Los cambios en un repositorio no afectan a los demás, lo que elimina conflictos de fusión innecesarios.

Conclusión

Nombra los archivos según la clase que contienen para una navegación predecible. Esta convención se aplica a grandes bases de código en las que es importante encontrar rápidamente clases específicas. Los archivos adicionales valen la pena por la claridad organizativa que proporcionan.

Preguntas frecuentes

¿Tiene alguna pregunta?

¿Y las clases con ayudantes o las clases particulares?

Las clases ayudantes pequeñas utilizadas sólo por una clase padre pueden permanecer en el mismo archivo si son realmente detalles de implementación. Sin embargo, si se reutilizan o crecen más de 20-30 líneas, extráigalas. Las clases privadas que sólo existen para dar soporte a una clase pública son excepciones razonables.

¿Se aplica esto a las interfaces y tipos de TypeScript?

Los tipos e interfaces utilizados por una clase pueden estar en el mismo fichero. Sin embargo, los tipos compartidos que se utilizan en varios archivos deben estar en sus propios archivos de definición de tipos. La clave está en si la definición se utiliza sólo en ese archivo o se necesita en otro lugar.

¿Qué ocurre con lenguajes como Python, con múltiples clases en la práctica habitual?

Las convenciones de Python difieren, pero el principio se sigue aplicando: agrupa clases relacionadas si forman un módulo cohesivo, pero evita mezclar clases no relacionadas. Un models.py con User y UserProfile tiene sentido. Un utils.py con veinte clases no relacionadas no lo tiene.

¿Cómo organizo las clases relacionadas, como las clases padre e hijo?

Ponlos en archivos separados dentro del mismo directorio. Para Animal y Perro, usa animals/Animal.js y animals/Dog.js. La estructura del directorio muestra las relaciones manteniendo una clase por archivo. Esto se adapta mejor que agrupar clases relacionadas en un solo archivo.

¿Y si al extraer las clases se crean muchos archivos pequeños?

Muchos archivos pequeños son preferibles a pocos archivos grandes. Los IDE modernos manejan miles de archivos de forma eficiente. La navegación por el sistema de archivos es más rápida que la búsqueda dentro de archivos grandes. La claridad de saber exactamente dónde vive cada clase pesa más que la percepción de "demasiados archivos".

Asegúrese gratis

Proteja el código, la nube y el tiempo de ejecución en un sistema central.
Encuentre y corrija vulnerabilidades de forma rápida y automática.

No requiere tarjeta de crédito | Escanea resultados en 32segs.