|
| 1 | +# Java Guidelines — S3Mock |
| 2 | + |
| 3 | +Canonical reference for Java idioms, naming conventions, and code quality standards used across this project. |
| 4 | + |
| 5 | +## Style |
| 6 | + |
| 7 | +Java code follows the **[Google Java Style Guide](https://google.github.io/styleguide/javaguide.html)** enforced by Checkstyle (`etc/checkstyle.xml`). |
| 8 | + |
| 9 | +Key rules: |
| 10 | +- **Indentation**: 2 spaces (no tabs) |
| 11 | +- **Line length**: 120 characters maximum |
| 12 | +- **Braces**: Always use braces for `if`, `for`, `while`, `do` blocks |
| 13 | +- **Imports**: Static imports first, then third-party packages; alphabetical within groups; no wildcard imports |
| 14 | + |
| 15 | +## Modern Java Idioms |
| 16 | + |
| 17 | +### Local Type Inference |
| 18 | +- Use `var` for local variables when the type is clear from context: |
| 19 | + ```java |
| 20 | + var uploadFile = new File(UPLOAD_FILE_NAME); |
| 21 | + var response = s3Client.getObject(...); |
| 22 | + ``` |
| 23 | +- Avoid `var` when the inferred type would be ambiguous or unclear |
| 24 | + |
| 25 | +### Collections |
| 26 | +- `list.size() == 0` / `list.size() > 0` → `list.isEmpty()` / `!list.isEmpty()` |
| 27 | +- Use `List.of(...)`, `Map.of(...)` for immutable collections instead of `Collections.unmodifiableList(...)` |
| 28 | +- Prefer streams over explicit loops for transformations: |
| 29 | + ```java |
| 30 | + buckets.stream().map(Bucket::name).collect(Collectors.toSet()) |
| 31 | + ``` |
| 32 | + |
| 33 | +### Switch Expressions |
| 34 | +- Prefer switch expressions over `if-else` chains with 3+ branches |
| 35 | + |
| 36 | +### Text Blocks |
| 37 | +- Use text blocks for multi-line strings |
| 38 | + |
| 39 | +## Common Anti-Patterns |
| 40 | + |
| 41 | +| Anti-Pattern | Refactor To | |
| 42 | +|---|---| |
| 43 | +| `list.size() == 0` | `list.isEmpty()` | |
| 44 | +| `Collections.emptyList()` | `List.of()` | |
| 45 | +| `Collections.unmodifiableList(new ArrayList<>(...))` | `List.copyOf(...)` | |
| 46 | +| `"" + value` | `String.valueOf(value)` or `String.format(...)` | |
| 47 | +| Empty catch blocks | At minimum, log the exception | |
| 48 | +| Magic numbers/strings | Named constants | |
| 49 | + |
| 50 | +## Naming Conventions |
| 51 | + |
| 52 | +Follows [Google Java Style](https://google.github.io/styleguide/javaguide.html#s5-naming): |
| 53 | +- **Classes/Interfaces/Enums**: `UpperCamelCase` |
| 54 | +- **Methods/Variables**: `lowerCamelCase` |
| 55 | +- **Constants** (`static final`): `UPPER_SNAKE_CASE` |
| 56 | +- **Booleans**: `is-`/`has-`/`should-`/`can-` prefixes |
| 57 | +- **Collections**: plural nouns |
| 58 | +- **Avoid abbreviations**: `bucketMetadata` not `bktMd` |
| 59 | +- **Abbreviations** in type names: at most 4 consecutive uppercase letters (e.g., `KmsKeyRef` not `KMSKeyRef`) |
| 60 | + |
| 61 | +## Test Naming |
| 62 | + |
| 63 | +- **Method names**: Use descriptive verb phrases — `shouldUploadAndDownloadObject`, `defaultBucketsGotCreated` |
| 64 | +- **Avoid**: generic names like `testSomething` or `test1` |
| 65 | +- **Pattern**: Arrange-Act-Assert |
| 66 | + |
| 67 | +## Javadoc |
| 68 | + |
| 69 | +- Use `/** */` for public APIs; `//` inline comments for rationale |
| 70 | +- Comments explain **why**, never **what** — remove comments that restate the code |
| 71 | +- Javadoc tag order: `@param`, `@return`, `@throws`, `@deprecated` |
| 72 | +- Add comments for edge cases, non-obvious S3 semantics, or workarounds |
| 73 | +- Link to AWS API docs or GitHub issues where relevant |
| 74 | +- Single-line Javadoc is allowed: `/** Short description. */` |
0 commit comments