Skillshub java-coding-standards
Java coding standards for Spring Boot services: naming, immutability, Optional usage, streams, exceptions, generics, and project layout.
install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/affaan-m/everything-claude-code/java-coding-standards" ~/.claude/skills/comeonoliver-skillshub-java-coding-standards && rm -rf "$T"
manifest:
skills/affaan-m/everything-claude-code/java-coding-standards/SKILL.mdsource content
Java Coding Standards
Standards for readable, maintainable Java (17+) code in Spring Boot services.
When to Activate
- Writing or reviewing Java code in Spring Boot projects
- Enforcing naming, immutability, or exception handling conventions
- Working with records, sealed classes, or pattern matching (Java 17+)
- Reviewing use of Optional, streams, or generics
- Structuring packages and project layout
Core Principles
- Prefer clarity over cleverness
- Immutable by default; minimize shared mutable state
- Fail fast with meaningful exceptions
- Consistent naming and package structure
Naming
// ✅ Classes/Records: PascalCase public class MarketService {} public record Money(BigDecimal amount, Currency currency) {} // ✅ Methods/fields: camelCase private final MarketRepository marketRepository; public Market findBySlug(String slug) {} // ✅ Constants: UPPER_SNAKE_CASE private static final int MAX_PAGE_SIZE = 100;
Immutability
// ✅ Favor records and final fields public record MarketDto(Long id, String name, MarketStatus status) {} public class Market { private final Long id; private final String name; // getters only, no setters }
Optional Usage
// ✅ Return Optional from find* methods Optional<Market> market = marketRepository.findBySlug(slug); // ✅ Map/flatMap instead of get() return market .map(MarketResponse::from) .orElseThrow(() -> new EntityNotFoundException("Market not found"));
Streams Best Practices
// ✅ Use streams for transformations, keep pipelines short List<String> names = markets.stream() .map(Market::name) .filter(Objects::nonNull) .toList(); // ❌ Avoid complex nested streams; prefer loops for clarity
Exceptions
- Use unchecked exceptions for domain errors; wrap technical exceptions with context
- Create domain-specific exceptions (e.g.,
)MarketNotFoundException - Avoid broad
unless rethrowing/logging centrallycatch (Exception ex)
throw new MarketNotFoundException(slug);
Generics and Type Safety
- Avoid raw types; declare generic parameters
- Prefer bounded generics for reusable utilities
public <T extends Identifiable> Map<Long, T> indexById(Collection<T> items) { ... }
Project Structure (Maven/Gradle)
src/main/java/com/example/app/ config/ controller/ service/ repository/ domain/ dto/ util/ src/main/resources/ application.yml src/test/java/... (mirrors main)
Formatting and Style
- Use 2 or 4 spaces consistently (project standard)
- One public top-level type per file
- Keep methods short and focused; extract helpers
- Order members: constants, fields, constructors, public methods, protected, private
Code Smells to Avoid
- Long parameter lists → use DTO/builders
- Deep nesting → early returns
- Magic numbers → named constants
- Static mutable state → prefer dependency injection
- Silent catch blocks → log and act or rethrow
Logging
private static final Logger log = LoggerFactory.getLogger(MarketService.class); log.info("fetch_market slug={}", slug); log.error("failed_fetch_market slug={}", slug, ex);
Null Handling
- Accept
only when unavoidable; otherwise use@Nullable@NonNull - Use Bean Validation (
,@NotNull
) on inputs@NotBlank
Testing Expectations
- JUnit 5 + AssertJ for fluent assertions
- Mockito for mocking; avoid partial mocks where possible
- Favor deterministic tests; no hidden sleeps
Remember: Keep code intentional, typed, and observable. Optimize for maintainability over micro-optimizations unless proven necessary.