Organización de Clases
Las clases deben ser pequeñas, enfocadas y tener una única razón para cambiar.
Organización Interna
Orden estándar dentro de una clase: (1) constantes estáticas públicas, (2) variables estáticas privadas, (3) variables de instancia privadas, (4) métodos públicos, (5) helpers privados llamados por cada método público, colocados inmediatamente después de él. Esto crea una lectura de arriba abajo: contrato público primero, detalles de implementación abajo.
Orden aleatorio — detalle privado primero
class InvoiceService:
function _formatAmount(amount):
return "$" + formatDecimal(amount, 2)
function _calculateTax(subtotal):
return subtotal * 0.08
STANDARD_TAX_RATE = 0.08 // ← buried
function generate(order): // ← hard to find
tax = _calculateTax(order.subtotal)
total = order.subtotal + tax
return "Invoice: " + _formatAmount(total)
Orden estándar — contrato público arriba
class InvoiceService:
STANDARD_TAX_RATE = 0.08 // 1. constants
function generate(order): // 2. public
tax = _calculateTax(order.subtotal)
total = order.subtotal + tax
return "Invoice: " + _formatAmount(total)
function _calculateTax(subtotal): // 3. private helpers
return subtotal * STANDARD_TAX_RATE
function _formatAmount(amount):
return "$" + formatDecimal(amount, 2)
El Principio de Responsabilidad Única
Una clase debe tener una sola razón para cambiar. No un método — una responsabilidad. Pregunta: "Si describo esta clase en una oración, ¿necesita la palabra y?" Si es así, divídela. Un UserManager que maneja autenticación, actualizaciones de perfil, notificaciones por email y logging de auditoría tiene cuatro razones para cambiar. Divídelo en cuatro clases enfocadas.
Clase Dios — hace todo lo relacionado con usuario
class UserManager:
// Authentication
function login(email, password): ...
function logout(sessionId): ...
function resetPassword(email): ...
// Profile
function updateName(userId, name): ...
function uploadAvatar(userId, file): ...
// Notifications
function sendWelcomeEmail(user): ...
function sendPasswordResetEmail(user): ...
// Audit
function logLoginAttempt(email, ok): ...
function logProfileChange(uid, field): ...
Cuatro clases enfocadas, una razón de cambio cada una
class AuthService:
function login(email, password): ...
function logout(sessionId): ...
function resetPassword(email): ...
class UserProfileService:
function updateName(userId, name): ...
function uploadAvatar(userId, file): ...
class UserNotificationService:
function sendWelcome(user): ...
function sendPasswordReset(user): ...
class UserAuditLog:
function recordLogin(email, ok): ...
function recordProfileChange(uid, field): ...
Cohesión y Cambio
Alta cohesión significa que cada método usa la mayoría de las variables de instancia de la clase. Cuando notas que un grupo de métodos solo usa un subconjunto de las variables de instancia, hay una clase escondida dentro de tu clase — extráela. Las clases deben estar abiertas para extensión, cerradas para modificación: nuevo comportamiento = nueva clase, no editar el código existente.
Baja cohesión — dos clases ocultas en una
class ReportGenerator:
data = [] // ─┐ data fields
source = null // ─┘
font = "Arial" // ─┐ formatting fields
margin = 20 // ─┘
function fetchData(): ... // uses data, source
function filterData(): ... // uses data
function setFont(f): ... // uses font
function setMargin(m): ... // uses margin
function renderPdf(): ... // uses font, margin
Alta cohesión — extrae la clase oculta
class DataFetcher:
source = null
data = []
function fetch(): ...
function filter(predicate): ...
class PdfRenderer:
font = "Arial"
margin = 20
function render(data): ...
Desafío de Código
Identifica y Divide la Clase Dios — usa el test del 'y'. Si necesitas 'y' para describirla, divídela.
💡Conclusión clave
Si necesitas 'y' para describir tu clase, tiene más de una responsabilidad. Divídela hasta que cada clase tenga una única razón de existir.
🔧 Algunos ejercicios pueden tener errores. Si algo parece incorrecto, usa el botón Feedback (abajo a la derecha) para reportarlo — nos ayuda a corregirlo rápido.
Pista: Lista cada método de la clase, luego agrúpalos por los datos que operan. Los métodos que solo tocan los mismos campos van juntos. Los grupos que tocan campos *diferentes* te dicen dónde dividir.
✗ Tu versión