When designing real-world applications, I’ve found that simplicity is more than elegance—it’s strategic. Simple code is easier to secure, easier to maintain, and more scalable in the long run.
Edsger W. Dijkstra, a renowned computer scientist, famously said: “Simplicity is prerequisite for reliability”.
The KISS principle (“Keep It Simple, Stupid”) is a widely embraced design heuristic in software development, emphasizing the value of simplicity and clarity to enhance security and prevent complexity creep.
Albert Einstein said: “Everything should be made as simple as possible, but no simpler”.
In this post, I’ll share one small pattern I use to improve code maintainability by pushing logic into the object classes where it truly belongs. We’ll explore this through a fun example involving cabins, lodges, and group assignments.
The Problem: Logic Sprawl in Client Classes
Imagine you’re writing software to assign groups to buildings—maybe for a summer retreat or a convention. You might start with two classes: Lodge and Cabin. A common approach is to centralize the logic in a separate client class like GroupAssigner, which decides which building to instantiate.
Here’s some simplified pseudocode for that:
Class GroupAssigner
if Group.groupSize > 12:
Instantiate Lodge
else:
Instantiate Cabin
This works fine at first. But as more building types and rules are added, this logic becomes bloated and hard to maintain. Every time a new rule comes along—or a new building—you must dig into this central logic and update it.
The Pattern: Push Appropriateness Logic into Classes
Instead of piling logic into GroupAssigner, I prefer to let each building class define when it is appropriate for a given group. This means introducing a static method called IsAppropriateFor(Group) into each building class.
Here’s how it looks:
Class Lodge
public static IsAppropriateFor(Group):
return Group.groupSize > 12
Class Cabin
public static IsAppropriateFor(Group):
return Group.groupSize <= 12
Then, your GroupAssigner becomes much cleaner and easier to reason about:
Class GroupAssigner
if Lodge.IsAppropriateFor(Group):
Instantiate Lodge
if Cabin.IsAppropriateFor(Group):
Instantiate Cabin
Why This Matters
This approach has several advantages:
- Encapsulation: The logic describing when a building is appropriate lives inside the building class itself.
- Maintainability: If the rules change for a specific building, you only need to update that building class.
- Clarity: You can scan each building class to understand when it applies—without tracing through a giant
if-elseblock. - Efficiency: Because
IsAppropriateForis a static method, you can call it without instantiating the object—saving resources when instantiation is expensive.
When to Use This
This works best when:
- Each class’s appropriateness is independent of the others.
- You want to evaluate many classes for eligibility.
- You want to avoid expensive object creation just to test eligibility.
⚠️ Note: If class appropriateness depends on other options (e.g., “Use X unless Y is available”), you may still need some coordinating logic in the client class. But that logic will be much simpler if each class clearly states its own rules.
A Fun Example
Let’s apply this with a bit of whimsy. Suppose we’re assigning unique venues to different kinds of groups:
Class CozyCabinInTheUintas
public static IsAppropriateFor(Group):
return Group.IsMyFamily
Class HugeLodgeInParkCity
public static IsAppropriateFor(Group):
return Group.IsAllThoseReadingThisPost
Class DareDevilEventCenter
public static IsAppropriateFor(Group):
return Group.IsCoupleWantingToRideAFlyingBedOver12Trucks
Now the assignment logic becomes fun, clean, and expressive:
Class GroupAssigner
public ScheduleAndReserveEvents:
if CozyCabinInTheUintas.IsAppropriateFor(Group):
Instantiate CozyCabinInTheUintas(Date of Summer Vacation)
if HugeLodgeInParkCity.IsAppropriateFor(Group):
Instantiate HugeLodgeInParkCity(Date of Coding Convention)
if DareDevilEventCenter.IsAppropriateFor(Group):
Instantiate DareDevilEventCenter(Date of Coworker’s Surprise Marriage Proposal)
Final Thoughts
This design isn’t a framework or formal pattern—it’s a mindset: keep logic where it naturally belongs. The class that “knows” when it applies should own that decision logic.
Every time you refactor in this direction, you push your system toward greater clarity, cohesion, and adaptability—and that’s a win for future-you and every developer who comes after.


