🔸 TLDR
▪️ Tactical DDD helps you write domain code where rules live with data 🧠
▪️ Use Value Objects to prevent invalid states 💎
▪️ Use Aggregates to define consistency boundaries 🔒
▪️ Keep services focused (domain vs application vs infrastructure) 🎛️
▪️ Repositories are for aggregate roots, not every table 📚
🔸 CONTEXT
DDD isn’t a “framework”. Tactical DDD is a set of code-level building blocks to keep your domain model coherent, testable, and hard to misuse 🧠✅ It’s especially useful when business rules get messy (pricing, billing, workflow, compliance, etc.).
🔸 STRUCTURE
▪️ Domain layer: the business rules (your “truth”) 🧾
▪️ Application layer: orchestrates use cases (commands, transactions) 🎛️
▪️ Infrastructure layer: DB, messaging, HTTP, external APIs 🔌
▪️ UI/API layer: controllers, DTOs, serialization 🌐
▪️ Aim: dependencies point inward → domain doesn’t know frameworks 🧅
🔸 OBJECTIVES
▪️ Put rules near the data they protect 🛡️
▪️ Make invalid states unrepresentable 🚫
▪️ Reduce “god services” and anemic models 🧟♂️
▪️ Improve readability: business code that reads like the business 📖
▪️ Enable safe evolution: refactors without breaking everything 🔧
🔸 ENTITIES & VALUE OBJECTS
▪️ Entity = has identity across time (e.g., OrderId) 🆔
▪️ Value Object = defined by its values (e.g., Money, Email) 💎
▪️ Entity pitfalls ⚠️
▪️ Public setters → invariants get bypassed 😬
▪️ Equality by all fields → bugs with persistence / identity 🤯
▪️ “Entity everywhere” → unnecessary complexity 🧨
▪️ Builders & DSL (to enforce valid creation) 🧱
▪️ Use factory methods for common valid states:
Order.open(customerId)
▪️ Use a builder when many optional fields exist
▪️ Use a test DSL to express scenarios clearly:
anOrder().withItem("SKU-1").paid().build() ✅
▪️ Value Object rules 💡
▪️ Immutable ✅
▪️ Validated at creation ✅
▪️ Equality by value ✅
▪️ Examples: Money, Quantity, VatRate, Address, TimeWindow 🧾
🔸 AGGREGATES & AGGREGATE ROOTS
▪️ Aggregate = cluster of objects that must stay consistent together 🔒
▪️ Aggregate Root = the only entry point from the outside 🚪
▪️ Why it matters: invariants are enforced in one place ✅
▪️ Practical rules 🧭
▪️ Keep aggregates small (performance + clarity) 🪶
▪️ Reference other aggregates by ID, not by object graph 🔗
▪️ One transaction = one aggregate consistency boundary 🧾
▪️ Example idea:
Order is root; OrderLine is internal; Product is another aggregate (refer by ProductId) 📦
🔸 SERVICES & THEIR ROLES
Not everything belongs inside entities/value objects — services have legit jobs 👇
▪️ Domain Service 🧠
▪️ Business operation that doesn’t “fit” naturally in one entity
▪️ Stateless, expresses domain language
▪️ Example: pricing policy, risk calculation, matching rules 💰
▪️ Application Service 🎛️
▪️ Orchestrates use cases: load aggregate → call domain behavior → save → publish events
▪️ Talks DTOs / commands, handles transactions
▪️ Should NOT contain business rules (otherwise it becomes a “god service”) 🚫
▪️ Infrastructure Service 🔌
▪️ Technical details: sending emails, HTTP calls, database adapters
▪️ Hidden behind interfaces so the domain stays pure 🧼
🔸 IMPLEMENTING REPOSITORIES
▪️ Repository = collection-like abstraction for aggregates 📚
▪️ Repositories typically exist per aggregate root (not for every entity) 🎯
▪️ Common shape:
▪️ findById(id)
▪️ save(aggregate)
▪️ optionally findBy(...) //when it supports a true use case
▪️ Tips ✅
▪️ Return domain types, not persistence models 🧠
▪️ Avoid leaking ORM concerns into the domain 🚫
▪️ Prefer queries that match business language (e.g., findOpenOrdersFor(customerId)) 🔎
🔸 STRATEGIC DDD VS TACTICAL DDD
▪️ Strategic DDD
= “Where are the boundaries?” 🗺️
▪️ Split the system into Bounded Contexts
▪️ Align teams on a Ubiquitous Language ▪️
Define how contexts integrate (context map) 🔗
▪️ Tactical DDD
= “How do we model it in code?” 🛠️
▪️ Implement the model inside a context with:
▪️ Entities / Value Objects 🆔💎
▪️ Aggregates / Roots 🔒
▪️ Services + Repositories 🧠📚
▪️ Shortcut 🧠
▪️ Strategic: map the domain
▪️ Tactical: code the domain
🔸 TAKEAWAYS
▪️ Start small: create 2–3 Value Objects and enforce validation ✅
▪️ Make aggregates tiny and explicit about invariants 🔒
▪️ If business rules are in application services → you’re drifting to anemic DDD 🚨
▪️ Design APIs that make the “right way” the easiest way 🛠️
▪️ Tactical DDD is about maintainability, not ceremony ✨
#DDD #DomainDrivenDesign #TacticalDDD #SoftwareArchitecture #CleanCode #Backend #Java #SpringBoot #Microservices #DesignPatterns #SoftwareEngineering #Refactoring
Go further with Java certification:
Java👇
Spring👇
SpringBook👇
JavaBook👇