Internal Organization
Standard ordering inside a class: (1) public static constants, (2) private static variables, (3) private instance variables, (4) public methods, (5) private helpers called by each public method, placed immediately after it. This creates a top-down read: public contract first, implementation details below.
Random order — private detail first
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)
Standard order — public contract on top
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)
The Single Responsibility Principle
A class should have one reason to change. Not one method — one responsibility. Ask: "If I describe this class in one sentence, does it need the word and?" If yes, split it. A UserManager that handles authentication, profile updates, email notifications, and audit logging has four reasons to change. Split it into four focused classes.
God Class — does everything user-related
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): ...
Four focused classes, one reason each to change
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): ...
Cohesion and Change
High cohesion means every method uses most of the class's instance variables. When you notice a group of methods only uses a subset of instance variables, that's a class hiding inside your class — extract it. Classes should be open for extension, closed for modification: new behavior = new class, not editing existing code.
Low cohesion — two classes hiding in one
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
High cohesion — extract the hidden class
class DataFetcher:
source = null
data = []
function fetch(): ...
function filter(predicate): ...
class PdfRenderer:
font = "Arial"
margin = 20
function render(data): ...
Code Challenge
Identify and Split the God Class — use the 'and' test. If you need 'and' to describe the class, split it.
Key takeaway
If you need 'and' to describe your class, it has more than one responsibility. Split it until each class has a single reason to exist.