πŸš€ Mastering Java Coding Best Practices: A Beginner's Guide to Writing Clean and Scalable Code

Lalit SharmaLalit Sharma
6 min read

By Dev Lalit – June 2025


🧭 Introduction

When starting out with Java programming, it's easy to focus only on making the code "work." However, working code is not enough in the real world. In enterprise-grade software, your code must also be clean, structured, maintainable, and scalable. This guide aims to help you achieve that using industry-level Java coding standards derived from:

  1. Java: The Complete Reference by Herbert Schildt – a globally recommended resource for Java learners

  2. Effective Java by Joshua Bloch – used in many IIT Computer Science curriculam

  3. IIT Madras' NPTEL Java Programming Course by Prof. Debasis Samanta – A structured beginner-to-advanced course .


🧱 1. Project Structure: The Backbone of Every Application

Why it matters:

A clean project structure helps organize your code in a way that makes it easy to understand, extend, and debug.

πŸ”Ή 1. Project Structure (Modular, Layered Architecture)
Structure your project by layers:
πŸ“ projectname
β”œβ”€β”€ πŸ“ src
β”‚ β”œβ”€β”€ πŸ“ main
β”‚ β”‚ β”œβ”€β”€ πŸ“ java
β”‚ β”‚ β”‚ └── πŸ“ com.companyname.projectname
β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ controller β†’ REST controllers (Handle API Requests )
β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ service β†’ Business logic
β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ repository β†’ JPA repositories
β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ model β†’ Entities (JPA)
β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ dto β†’ Data Transfer Objects
β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ mapper β†’ MapStruct or custom mappers
β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ config β†’ Spring configs (e.g., SecurityConfig)
β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ exception β†’ Custom exceptions & handlers
β”‚ β”‚ β”‚ β”œβ”€β”€ πŸ“ util β†’ Utility/helper classes
β”‚ β”‚ β”‚ └── πŸ“ security β†’ Authentication & authorization
β”‚ β”‚ └── πŸ“ resources
β”‚ β”‚ β”œβ”€β”€ πŸ“„ application.yml β†’ Main config file
β”‚ β”‚ β”œβ”€β”€ πŸ“ static β†’ Static assets (JS, CSS, etc.)
β”‚ β”‚ β”œβ”€β”€ πŸ“ templates β†’ Thymeleaf/FreeMarker templates
β”‚ β”‚ β”œβ”€β”€ πŸ“ i18n β†’ Localization files
β”‚ β”‚ └── πŸ“ log β†’ Log file storage (if configured
β”‚ β”‚ to write here)
β”‚ └── πŸ“ test
β”‚ └── πŸ“ java
β”‚ └── πŸ“ com.companyname.projectname
β”‚ β”œβ”€β”€ πŸ“ controller
β”‚ β”œβ”€β”€ πŸ“ service
β”‚ └── ... (tests matching main structure)
β”œβ”€β”€ πŸ“ target β†’ Compiled classes and build artifacts
β”‚ (generated)
β”œβ”€β”€ πŸ“„ pom.xml β†’ Maven build configuration
β”œβ”€β”€ πŸ“„ .gitignore β†’ Git ignored files list
└── πŸ“„ README.md β†’ Project overview & instructions

Interconnection:

  • Controller calls Service, which uses Repository.

  • DTOs move data between layers without exposing Entities.

  • Config and Exception ensure the application behaves predictably.


πŸ“› 2. Naming Conventions: Say Goodbye to Confusion

Why it matters:

Proper naming helps you and others understand what your code does just by looking at it.

Best Practices:

  • Packages: com.company.project.module (lowercase, dot-separated)

  • Classes: PascalCase β†’ UserServiceImpl

  • Methods/Variables: camelCase β†’ getUserById(), userName

  • Constants: UPPER_SNAKE_CASE β†’ ROLE_ADMIN

Example:

public class UserServiceImpl implements UserService {
    public UserDto getUserById(Long userId) { ... }
}

🧾 3. Code Formatting: Make It Human-Readable

Key Rules:

  • Indentation: Use 4 spaces instead of tabs for consistent spacing.

  • Line length: Keep lines under 120 characters to improve readability, especially on smaller screens.

  • Braces: Always use {} even for single-line if, for, or while statements to avoid bugs.

  • ⭐Avoid wildcard imports: Write explicit imports (βœ… import java.util.List;) instead of (❌ import java.util.*;) to prevent namespace conflicts and improve clarity.

Why it matters:

Readable code = maintainable code. When code is neatly structured and follows consistent patterns, it's easier for others (and your future self) to understand and debug it. Use tools like IntelliJ IDEA's default formatter or Google Java Style to automatically enforce these rules.

Examples:

❌ Bad Practice:

import java.util.*; // not clear what classes are used
if (isActive) doSomething(); // lacks braces, risky in future edits

βœ… Good Practice:

import java.util.List; // clear and specific

if (isActive) {
    doSomething(); // safer, avoids accidental logic errors
}

Even a single missing brace can introduce hard-to-catch bugs. Stick to clean, consistent formatting to write safer, more professional Java code.


πŸ”„ 4. Use DTOs Instead of Entities

Why it matters:

Entities are tied to your database structure. Never expose them directly in APIs. Use DTOs to control what data is shared.

Example:

// Entity
public class User { Long id; String username; }

// DTO
public class UserResponseDto { Long id; String username; }

πŸ›‘οΈ 5. Exception Handling: Write Predictable Code

Best Practices:

  • Create custom exceptions for specific errors

  • Use @ControllerAdvice for global handling

Example:

@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException { ... }

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<String> handle(UserNotFoundException ex) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
    }
}

πŸ” 6. Security: Handle Data Responsibly

Do’s:

  • Use @Valid to validate incoming data

  • Encrypt passwords using BCryptPasswordEncoder

  • Avoid logging sensitive data

  • Use UUIDs instead of numeric IDs in public APIs


πŸ—‚οΈ 7. Logging: Stop Using System.out.println()

Use SLF4J and Lombok’s @Slf4j:

@Slf4j
public class UserService {
    log.info("User created: id={}, username={}", id, username);
}

πŸ“¦ 8. Use Lombok with Caution

Use for DTOs:

@Value
@Builder
public class UserResponseDto {
    Long id;
    String username;
}

Avoid in JPA Entities:

Using @Data on JPA entities can lead to problems (e.g., infinite recursion, poor Hibernate compatibility).


πŸ§ͺ 9. Testing: Build Confidence in Your Code

  • Use @WebMvcTest for controller tests

  • Use Mockito or @MockBean for service layer

  • Use H2 or Testcontainers for integration tests


πŸ“š 10. Document Your APIs

Use Swagger/OpenAPI:

@Operation(summary = "Get all users")
@ApiResponse(responseCode = "200", description = "Success")

Swagger UI helps you test and document your APIs visually.


  • Static Analysis: SonarLint, PMD, SpotBugs

  • Formatting & Checks: Checkstyle

  • Integrated into IDEs or CI pipelines


🧠 Key Takeaways for Beginners

PracticeWhy It’s Important
Proper Project StructureOrganizes code cleanly
Naming ConventionsMakes code readable & understandable
DTO over EntityEnsures security & abstraction
Custom ExceptionsPredictable, maintainable error handling
Lombok Usage (Selective)Reduces boilerplate, but with caution
API ValidationAvoids garbage data from reaching logic
Logging via SLF4JHelps in debugging, tracing issues
TestingBuilds confidence in changes
API Docs via SwaggerImproves collaboration & clarity

🎯 Final Words by Dev Lalit

Clean code is not just for senior developers. If you're a beginner, it's your superpower in disguise. Adopt these habits from Day 1 and you'll not only write code that works β€” you'll write code that lasts.

If you found this helpful, consider following me for more beginner-to-pro-level Java insights!


Happy Coding πŸ‘¨β€πŸ’» – Dev Lalit

1
Subscribe to my newsletter

Read articles from Lalit Sharma directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Lalit Sharma
Lalit Sharma