TLDR 💡
Keep your constructor minimal: only assign the required fields.
For anything non-trivial, use named factory methods.
🔸 WHAT IS A "MINIMAL CONSTRUCTOR"?
▪️ A minimal constructor is a constructor that only sets the mandatory fields of the object.
▪️ It doesn’t start business logic, network calls, lookups, etc.
▪️ It doesn’t mutate global state or call other services.
Everything else should go into static factory methods (for example: fromJson(...), forUser(...), withDefaults(...)) or a builder. 🧼
The job of new MyClass(...) should be: “store arguments into fields”. Nothing more.
🔸 WHY THIS MAKES THE OBJECT LIFECYCLE CLEARER
▪️ When the constructor only sets fields, it's obvious which data is required for the object to exist ✅
▪️ You immediately know what is initialized at creation time vs what is computed later
▪️ You avoid "mystery side effects" happening during new (DB calls, I/O, heavy validation...)
This clarity gives you a simpler mental model of the instance lifecycle. 🧠
🔸 INSTANTIATION VS USAGE: KEEP THEM SEPARATE
If the object is doing real work in the constructor, you're mixing 2 phases:
1️⃣"Create me" 🐣
2️⃣"Start doing business" 🚀
That's dangerous because you can't hold an instance in a safe, uninitialized-but-valid state.
Good design = creation is one step, usage is another step:
▪️ First you build the object
▪️ Then you call methods on it to perform behavior
This separation makes code predictable and composable.
🔸 FACTORY METHODS EXPLAIN INTENT
Constructors have no name. You can't tell why you're building the object.
Factory methods are named. That gives context:
Order order = Order.express(userId, cart);
Order order = Order.standard(userId, cart);
Order order = Order.fromJson(payload);
Much better than:
Order order = new Order(userId, cart, true, false, null);
Why this matters:
▪️ The name documents the scenario 🏷
▪️ You can enforce invariants per scenario
▪️ You can choose caching, pooling, defaults, validation... without leaking complexity to callers
Your API becomes self-explanatory.
🔸 IT'S EASIER TO TEST 🧪
Minimal constructors = deterministic tests:
▪️ You can new MyClass(...) in unit tests without spinning up the world 🌍
▪️ No hidden DB calls / HTTP calls in new
▪️ You can inject fakes/mocks in a factory method that prepares the object for a specific test scenario
Example for tests:
UserSession session = UserSession.testSession("vincent"); // factory just for tests
Clean. Focused. Stable.
🔸 TAKEAWAYS 🚀
▪️ Keep constructors boring: just assign required fields
▪️ Push complex setup into factory methods with meaningful names
▪️ Make object creation explicit and side-effect free
▪️ Separate "I exist" from "I work"
▪️ Your future self (and your teammates) will thank you 🙏
#cleanCode #java #oop #craftmanship #testing
Certify: http://bit.ly/javaOCP