Return to site

🧱🛠 MINIMAL CONSTRUCTOR & FACTORY METHODS: WRITE OBJECTS THAT MAKE SENSE

November 2, 2025

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