12 articles in low level design › anti-patterns.
Learn why a class that knows everything and does everything is the hardest to test, extend, and maintain, and how to break it apart using Single Responsibility and Extract Class.
Learn why separating all business logic from domain objects into service classes produces procedural code disguised as OOP, and how a rich domain model fixes it.
Learn why overusing singletons creates hidden global state, makes code untestable, introduces threading hazards, and how dependency injection replaces them cleanly.
Learn why passing raw strings, ints, and booleans for domain concepts creates type-confusion bugs, and how value objects and Java records fix it.
Learn why unnamed numeric constants scattered through code create maintenance nightmares, and how named constants, enums, and configuration eliminate them.
Learn why methods that obsess over another class's data signal misplaced responsibility, and how Move Method refactoring creates cleaner, more cohesive designs.
Learn why subclasses that ignore or override inherited methods signal a broken IS-A relationship, and how interface segregation resolves the LSP violation cleanly.
Learn why methods with many parameters invite argument-order bugs, how to detect the smell, and how parameter objects and builders eliminate it.
Learn why optimizing code before profiling wastes time on the wrong bottlenecks, and how the profile-first methodology finds and fixes actual performance problems.
Learn why deep inheritance hierarchies become brittle and hard to change, and how favoring composition with strategy injection leads to more flexible, testable designs.
Learn why chaining method calls across object boundaries violates the Law of Demeter, creates brittle coupling, and how delegating methods fix the problem cleanly.
Learn why shared mutable state causes race conditions, data corruption, and heisenbugs in concurrent code, and how immutability, actors, and proper synchronization prevent them.