Skip to main content

Backend Style Guide

This section contains the code style guide for the Civitas Core V2 backend code. This guide should be followed at all times and considered during code reviews to maintain a clean, consistent, and readable codebase.

This style guide is not immutable. If some rules do not make sense or can be improved, changes can be made in consultation with the team. This should happen rarely and ideally only at the start of the project (the later a rule is changed, the more code must be adjusted).

The Google Java Style Guide is used as the reference for all coding conventions:
https://google.github.io/styleguide/javaguide.html

The Google Java Format plugin is used to enforce all formatting rules, including indentation, braces, line wrapping, imports, and more. Developers should not manually adjust formatting—always use the plugin.


Naming Conventions

  • Classes & Interfaces: UpperCamelCase
  • Methods & Variables: lowerCamelCase
  • Constants: SCREAMING_SNAKE_CASE
  • Packages: lowercase, separated by dots
  • Acronyms / Initialisms: all uppercase (e.g., URLParser)

Formatting & Indentation

  • Use Google Java Format for all code formatting
  • Opening braces { on the same line
  • Indentation is handled automatically by the plugin
  • Do not manually break lines or adjust spacing

Documentation

  • All public classes must have Javadoc with description
  • Javadoc formatting should follow the Google Java Style

Imports

  • Imports are automatically sorted and grouped by the plugin
  • Avoid wildcard imports (e.g., import java.util.*;)

Constants & Magic Numbers

  • Use named constants instead of magic numbers

double total = price + (price * 0.2);


static final double TAX_RATE = 0.2;
double total = price + (price * TAX_RATE);

Project Structure

The backend follows a layered, exercise-based folder structure to maintain clarity and separation of concerns:

  • Controller: Handles HTTP requests/responses.
  • Service: Contains business logic.
  • Repository: Handles data access/persistence.
  • Model / Entity: Represents domain objects, database entities, or DTOs.

Example folder layout:

src/main/java/com/opsource/
├── controller/
│ └── UserController.java
├── service/
│ └── UserService.java
├── repository/
│ └── UserRepository.java
├── model/
│ ├── User.java
│ └── UserDTO.java

Do / Don’t Examples


// Mixing controllers and services in the same folder
src/main/java/com/opsource/
├── UserController.java
├── UserService.java


// Separate folders by responsibility
src/main/java/com/opsource/controller/UserController.java
src/main/java/com/opsource/service/UserService.java

Notes:

  • Each layer should only interact with the layers directly above or below it. For example, controllers call services, services call repositories.

OpenAPI / API Design

  • All endpoints must have an OpenAPI specification defined from the start
  • The OpenAPI spec is the source of truth for the API
  • Any changes to the API must update the OpenAPI spec immediately
  • Follow RESTful best practices:
    • Use plural nouns for resource names (e.g., /users instead of /user)
    • Use proper HTTP methods (GET, POST, PUT, DELETE)
    • Return standard HTTP status codes
  • Include request and response schemas in the OpenAPI definition
  • Documentation should be automatically generated from the OpenAPI spec

Do / Don’t Examples


// Implementing an endpoint without OpenAPI spec
@PostMapping("/user/create")
public User createUser(User user) { ... }


// Define in OpenAPI first
@PostMapping("/users")
public User createUser(@RequestBody User user) { ... }

Error Handling

  • Throw specific exceptions; avoid generic Exception
  • Prefer try-with-resources for AutoCloseable resources

Testing

  • Test names should describe behavior: method_condition_expectedResult
  • Put each test class in the same package as the class it tests, inside src/test/java, to match the main code structure

Do / Don’t Examples


@Test
public void test1() { ... }


@Test
public void divide_whenDenominatorIsZero_shouldThrowArithmeticException() { ... }

Logging

  • Use a standard logging framework (SLF4J)
  • Avoid System.out.println
  • Use appropriate log levels (DEBUG, INFO, WARN, ERROR) and include context

Do / Don’t Examples


System.out.println("Failed to save user");


logger.error("Failed to save user with id {}", userId, exception);

CI Integration

  • The CI pipeline must enforce:
    • Google Java Format compliance
    • OpenAPI spec validation
  • Developers must run the formatter locally before submitting pull requests