Understanding Object-Oriented Principles

1. Understanding Encapsulation

AspectMechanismJava Modifier
Data hidingRestrict direct field accessprivate
Controlled accessGetter/setter methodspublic
Package-privateSame package only(default)
Subclass accessInheritance hierarchyprotected
Invariant guardValidation in settersthrow on invalid

Example: Encapsulated balance

public final class Account {
    private long balanceCents;
    public long getBalanceCents() { return balanceCents; }
    public void deposit(long cents) {
        if (cents <= 0) throw new IllegalArgumentException("positive only");
        this.balanceCents += cents;
    }
}

2. Understanding Abstraction

TypeConstructUse Case
ProceduralMethod extractionHide algorithm steps
DataADTs, classesHide representation
BehavioralInterfacesHide implementation
PolymorphicAbstract classesPartial implementation

Example: Payment abstraction

public interface PaymentGateway {
    PaymentResult charge(Money amount, Card card);
}
// Callers depend only on the contract, not Stripe/PayPal details.

3. Understanding Inheritance

TypeJava SyntaxNotes
Single classclass B extends AOne superclass only
Multiple interfaceclass B implements X, YNo diamond problem
Sealedsealed class S permits A, B Java 17+Closed hierarchy
Finalfinal class FCannot subclass
Warning: Prefer composition; deep inheritance creates fragile base class problems.

4. Understanding Polymorphism

FormMechanismResolution
Subtype (dynamic)Method overrideRuntime dispatch
ParametricGenerics <T>Compile-time
Ad-hocMethod overloadingCompile-time signature
CoercionImplicit conversionsType promotion

Example: Subtype polymorphism

List<Shape> shapes = List.of(new Circle(2), new Square(3));
double total = shapes.stream().mapToDouble(Shape::area).sum();

5. Understanding Composition over Inheritance

ConcernInheritanceComposition
CouplingTight (parent internals)Loose (interface only)
FlexibilityFixed at compile timeSwap at runtime
Reuse"Is-a""Has-a"
TestabilityHarder (mock parent)Inject mock collaborator

Example: Compose, don't extend

// BAD: class CachingUserService extends UserService { ... }
// GOOD:
public class CachingUserService implements UserService {
    private final UserService delegate;
    private final Cache<Long, User> cache;
    public User find(long id) {
        return cache.get(id, delegate::find);
    }
}

6. Understanding Coupling and Cohesion

MetricGoalIndicator
CouplingLowFew external dependencies, abstract types
CohesionHighMethods operate on same fields/concept
Afferent (Ca)TrackedHow many depend on this
Efferent (Ce)LowHow many this depends on
Instability IStable for coreCe / (Ca + Ce)

7. Understanding Information Hiding

HideTechnique
ImplementationProgram against interfaces
Internal stateprivate + immutability
ConstructionStatic factories, builders
Module internalsJava module exports selectively

8. Understanding Separation of Concerns

LayerResponsibility
ControllerHTTP I/O, validation
ServiceBusiness workflow, transactions
DomainBusiness rules, invariants
RepositoryPersistence
InfrastructureExternal systems (HTTP, MQ)

9. Understanding Law of Demeter

RuleAllowed Calls
"Talk to friends"Self, parameters, fields, created objects
ForbiddenChained a.getB().getC().doX()

Example: Tell, don't ask

// BAD: order.getCustomer().getAddress().getStreet()
// GOOD:
order.shipTo(label);  // order knows how to expose what's needed

10. Understanding DRY Principle

AspectFix
Duplicate logicExtract method/class
Duplicate constantsCentralize in constants class
Duplicate knowledgeSingle source of truth
Warning: Avoid premature DRY — coincidental duplication should not be merged.

11. Understanding YAGNI Principle

SymptomAction
"Maybe we'll need..."Don't build it
Speculative interfaceInline until 2nd caller
Unused config knobRemove

12. Understanding KISS Principle

Sign of complexitySimplification
Deep nestingGuard clauses, early return
Long methodsExtract method
Clever one-linerReadable multi-line
Generic everywhereConcrete until needed