16 Essential Coding Habits Every Developer Should Master
This article presents sixteen practical coding habits—from self‑testing and parameter validation to thread‑pool usage and cache consistency—that help developers avoid common bugs, improve reliability, and write cleaner, production‑ready code across backend systems.
1. Self‑test after modifying code
Always run a quick test after changing code, even if you only altered a variable or a single configuration line, to catch regressions early.
2. Validate method parameters
Check inputs for nullability, length, and format before processing; unvalidated parameters often cause simple bugs such as database insertion errors.
3. Consider interface compatibility when updating old APIs
When extending an existing public interface, preserve backward compatibility (e.g., add new parameters while keeping old ones functional).
// old interface
void oldService(A, B) {
// compatible with new interface, pass null for C
newService(A, B, null);
}
// new interface (cannot remove old one immediately)
void newService(A, B, C);4. Add clear comments for complex logic
When business logic is intricate, write explicit comments to aid future maintenance.
5. Close IO streams after use
Never leave file or network streams open; use finally blocks or try‑with‑resources to release resources promptly.
FileInputStream fdIn = null;
try {
fdIn = new FileInputStream(new File("/jay.txt"));
} catch (FileNotFoundException e) {
log.error(e);
} catch (IOException e) {
log.error(e);
} finally {
try {
if (fdIn != null) {
fdIn.close();
}
} catch (IOException e) {
log.error(e);
}
}Since JDK 7, prefer try‑with‑resources:
try (FileInputStream inputStream = new FileInputStream(new File("jay.txt"))) {
// use resources
} catch (FileNotFoundException e) {
log.error(e);
} catch (IOException e) {
log.error(e);
}6. Guard against runtime errors (array bounds, division by zero, null pointers)
Check collections size before accessing elements and validate inputs to prevent common exceptions.
// risky code
String name = list.get(1).getName(); // may cause IndexOutOfBoundsExceptionSafe version:
if (CollectionsUtil.isNotEmpty(list) && list.size() > 1) {
String name = list.get(1).getName();
}7. Batch remote/database calls instead of looping individual requests
Network and IO operations are expensive; prefer a single batch query over many per‑iteration calls.
// good
remoteBatchQuery(param); // bad
for (int i = 0; i < n; i++) {
remoteSingleQuery(param);
}8. Think about concurrency consistency when code runs in multiple threads
Operations that are not atomic (e.g., check‑then‑update) can cause race conditions; use atomic DB updates or proper locking.
// unsafe
if (isAvailable(ticketId)) {
// add cash
deleteTicketById(ticketId);
}Safe version using atomic delete:
if (deleteAvailableTicketById(ticketId) == 1) {
// add cash
} else {
return "No available ticket";
}9. Null‑check objects before accessing their properties
Never assume an object is non‑null; guard with an if‑statement to avoid NullPointerException.
if (object != null) {
String name = object.getName();
}10. Use appropriate thread pools and consider isolation
Thread pools reduce creation overhead, improve response time, and enable resource reuse; allocate separate pools for critical business flows.
11. Run SQL statements in the database and examine the execution plan
Before deploying, execute your queries and use EXPLAIN to verify index usage and performance.
EXPLAIN SELECT * FROM user WHERE userid = 10086 OR age = 18;12. Handle exceptions, timeouts, and retries when calling third‑party APIs
Set connection timeouts, decide retry policies, and for sensitive services add signature verification and encryption.
13. Ensure API idempotency
Design APIs so that repeated identical requests have the same effect, using techniques such as unique indexes, tokens, or distributed locks.
14. Consider linear safety of collections in high‑concurrency scenarios
Non‑thread‑safe structures like HashMap can cause dead loops; prefer ConcurrentHashMap or other safe collections.
15. Account for master‑slave replication lag
When reading after a write, be aware that the slave may not have caught up; critical paths may need to read from the master.
16. Keep cache and DB consistency; guard against cache penetration, avalanche, and breakdown
Cache improves latency but requires strategies to stay consistent with the database and to prevent massive cache misses from overwhelming the DB.
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.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
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.
