Code Smells
Code smells are recurring indicators of design or implementation problems that may warrant refactoring. They are warning signs rather than proof that code is incorrect.
A code smell is a recognizable pattern in source code that suggests the design may be harder to understand, maintain, test, or change than necessary. Common examples include duplicated logic, overly long methods, large classes, excessive coupling, and unclear names.
A smell is different from a bug. A bug means the program behaves incorrectly for some input or situation, while a smell indicates a potential quality or design problem. Smelly code can work correctly today but still increase the cost and risk of future changes.
For a Java backend engineer, smells often appear around object responsibilities, dependencies, error handling, and repeated business logic. For example, a service class that performs validation, database access, external API calls, and formatting may have too many responsibilities and become difficult to test independently.
Refactoring is the usual response, but not every smell needs immediate fixing. The appropriate action depends on context, change frequency, risk, and the cost of introducing a different design. The goal is to improve maintainability without adding unnecessary abstraction.
Key points
- Code smells are warning signs, not necessarily defects.
- Common smells include duplication, long methods, large classes, and excessive coupling.
- A smell can exist even when the program produces correct results.
- Refactoring can address smells while preserving externally observable behavior.
- Prioritize smells that make frequent or risky changes harder.
Interview questions
What is a code smell?
A code smell is a pattern in code that suggests a design or maintainability problem. It does not necessarily mean the code is wrong or will fail. Examples include duplicated code, very long methods, and classes with too many responsibilities. Developers inspect the context and may refactor the code if the smell creates meaningful maintenance risk.
What are some common code smells you look for in Java code?
I would look for duplicated logic, methods that are too long, classes with too many responsibilities, unclear names, and excessive coupling between classes. I would also look for deeply nested conditionals and methods that require many parameters. These patterns can make code harder to understand, test, and change. I would consider the surrounding context before deciding whether a refactoring is worthwhile.
Is duplicated code always a code smell?
Duplication is often a smell, but identical-looking code does not always belong behind one abstraction. Two pieces of code may currently look similar while representing different business concepts that are likely to evolve independently. Forcing them into a shared abstraction can create unwanted coupling. I would examine why the duplication exists and whether changing one copy should logically require changing the other.
How would you refactor a class that has too many responsibilities?
First, I would identify the distinct responsibilities and the dependencies associated with each one. I would then consider extracting cohesive behavior into separate classes with clear interfaces. In a Java backend, this might separate persistence, validation, external integration, and domain logic where those responsibilities are genuinely independent. I would use tests to verify behavior while making the changes incrementally.
Why can code smells become expensive in a backend system?
Smells can increase the effort and risk associated with future changes. For example, duplicated business rules can drift apart, while excessive coupling can cause a small change to affect unrelated components. Poorly separated responsibilities can also make unit tests slower or more complicated because tests require many dependencies. The cost is therefore often cumulative: the code may work correctly, but each subsequent change becomes harder to reason about and validate.