45 Tips for Writing Clean, Beautiful Code
This article presents 45 practical coding tips—from naming conventions and formatting to exception handling, thread safety, and design patterns—illustrated with Java examples and real‑world scenarios, helping developers produce readable, maintainable, and robust code.
Maintaining code left by a departed teammate can be painful due to long methods, excessive if‑else chains, and unclear intent; the root cause is often poor coding standards. This guide compiles 45 concrete tips covering naming, formatting, comments, refactoring, and best‑practice patterns to write clean, beautiful code.
1. Naming Conventions
Use descriptive, readable names. Replace ambiguous variables like int i = 0; with int count = 0;, and prefer meaningful English identifiers such as private String idCardNo; and private String phone;.
2. Code Formatting
Adopt consistent spacing, brace alignment, and line breaks. Modern IDEs can auto‑format to improve readability.
3. Writing Good Comments
According to Clean Code , comments should fill gaps where code cannot express intent, explain why a piece exists, document parameters and return values, warn about constraints, and use // TODO for unfinished work.
4. Extract Try‑Catch Logic
Move the core logic out of a long try‑catch block into a separate method, as shown in the Eureka service‑shutdown example, to keep the main flow clear.
5. Keep Methods Short
Long methods (e.g., 2000+ lines) are hard to understand; refactor them using patterns like Strategy to improve modularity.
6. Remove Duplicate Code
Extract repeated logic into utility classes or a common superclass to enhance extensibility.
7. Use Early Returns
Replace deep nested if chains with early return statements to flatten logic and improve readability.
8. Simplify Complex Conditions
Break complicated boolean expressions into well‑named variables before the if statement.
9. Elegant Parameter Validation
Leverage Bean Validation annotations like @NotBlank on DTO fields and apply @Valid at the controller level.
10. Unified Return Structure
Standardize API responses (e.g., {"code":0,"message":"成功","data":"..."}) to simplify client handling.
11. Centralized Exception Handling
Use Spring’s global exception mechanism to avoid repetitive try‑catch blocks.
12. Avoid Passing Null
Mark nullable parameters with @Nullable and non‑null with @NonNull to prevent NPEs.
13. Avoid Returning Null
Prefer Optional<T> over null and annotate return types accordingly.
14. Logging Guidelines
Make logs searchable with clear keywords, include stack traces for errors, use appropriate log levels, and avoid logging overly large payloads.
15. Consistent Library Usage
Standardize on a single JSON library (e.g., Fastjson or Gson) to reduce dependency churn.
16. Prefer Utility Classes
Use helper methods (e.g., CollectionUtils.isEmpty()) instead of manual checks.
17. Don’t Reinvent the Wheel
Replace custom date formatting with proven libraries like Hutool to avoid thread‑unsafe SimpleDateFormat.
18. Single‑Responsibility Principle
Design classes and methods to perform one function, exemplified by Nacos’s HttpAgent handling only HTTP request construction.
19. Prefer Composition Over Inheritance
Use member variables for reuse (composition) rather than extending classes, which reduces coupling and improves flexibility.
20. Apply Design Patterns Wisely
Use patterns such as Strategy for pluggable message notifications, defining a MessageNotifier interface and concrete implementations for SMS and app notifications.
21. Avoid Overusing Patterns
Don’t apply patterns where simple conditional logic suffices, as shown with a straightforward if check for printing a person.
22. Program to Interfaces
Depend on abstractions (e.g., FileStorage) rather than concrete implementations to enable easy swapping of storage providers.
23. Refactor Legacy Code Regularly
When business requirements evolve, refactor existing code (e.g., introduce a strategy interface for notifications) to keep the codebase adaptable.
24. Null Checks
Guard against NPEs caused by null returns, auto‑unboxing, or RPC responses; use Optional where appropriate.
25. Override toString() in POJOs
Facilitate debugging and logging by providing meaningful string representations.
26. Replace Magic Numbers with Constants
Define immutable constants for repeated literal values (e.g.,
private static final String GUANG_DONG_PROVINCE = "广东省";).
27. Release Resources in finally
Ensure locks or I/O streams are released in a finally block, as demonstrated by CopyOnWriteArrayList ’s add implementation.
28. Use Thread Pools
Replace manual thread creation with a pool to reduce resource consumption, improve response time, and simplify management.
29. Name Threads
Assign meaningful names to threads to aid log analysis and troubleshooting.
30. Use volatile for Visibility
In RocketMQ’s consumer loop, volatile guarantees that a stop flag set by one thread becomes visible to the polling thread.
31. Consider Thread‑Safety
When multiple threads may update shared state (e.g., token cache), employ double‑check locking or synchronized structures to avoid race conditions.
32. Use Asynchrony Cautiously
Be aware of transaction boundaries, CPU load, and error handling when introducing async processing.
33. Minimize Lock Scope
Lock only the critical section to reduce contention, as illustrated by optimizing CopyOnWriteArrayList ’s addAll method.
34. Define Enums for Type Distinction
Use enums to represent distinct business types instead of raw integers for clarity.
35. Set Timeouts on Remote Calls
Prevent threads from hanging indefinitely by configuring timeouts for RPC or third‑party API requests.
36. Pre‑size Collections
Specify initial capacities for ArrayList and HashMap to avoid costly resizing and copying.
37. Avoid BeanUtils for Property Copying
Prefer compile‑time mappers like MapStruct over reflection‑based BeanUtils for better performance.
38. Use StringBuilder for Concatenation
Manually build strings with StringBuilder to avoid repeated temporary objects created by the + operator.
39. Specify Rollback Exceptions
Annotate @Transactional with rollbackFor to include checked exceptions in rollback logic.
40. Beware of Self‑Invocation with Proxies
Calling a @Transactional method from within the same class bypasses the proxy, rendering the transaction ineffective; inject the proxied bean instead.
41. Select Only Needed Fields
Query specific columns to reduce network traffic and enable index‑only scans.
42. Avoid Database Calls Inside Loops
Batch fetch data and map results to avoid N+1 query problems.
43. Prefer Business Logic Over Multi‑Table Joins
Implement joins in application code when database joins are inefficient or prohibited.
44. Install Code Inspection Plugins
Use tools like Alibaba’s code‑style plugin to receive real‑time feedback on violations.
45. Communicate With Teammates
Regularly discuss design decisions and project context to avoid pitfalls and improve code quality.
References: Clean Code , Alibaba Java Development Manual , and a linked article on writing frustrating code.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Shepherd Advanced Notes
Dedicated to sharing advanced Java technical insights, daily work snippets, and the power of persistent effort.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
