General Coding Practices
- Follow Standard Naming Conventions
- Classes: Use PascalCase (e.g.,
User
,OrderService
). - Methods: Use camelCase (e.g.,
getUserName
,processOrder
). - Variables: Use camelCase (e.g.,
userName
,orderList
). - Constants: Use uppercase with underscores (e.g.,
MAX_USERS
,DEFAULT_TIMEOUT
).
- Classes: Use PascalCase (e.g.,
- Comment Your Code
- Use Javadoc comments for public methods and classes.
- Add inline comments to explain complex logic.
- Avoid Magic Numbers
- Use constants instead of hardcoding values.
// Good Example
public static final int MAX_USERS = 100;
if (currentUserCount > MAX_USERS) {
// handle error
}
// Bad Example
if (currentUserCount > 100) {
// handle error
}
Function and Method Size
Keep functions and methods small. A function should do one thing and do it well. Avoid long parameter lists.
// Good Example
public User getUserById(int userId) {
// Retrieve user by ID
}
// Bad Example
public User getUser(int userId, boolean includeAddress, boolean includeOrders) {
// Retrieve user with multiple options
}
Error Handling
Use exceptions instead of error codes. Handle exceptions at the appropriate level of abstraction.
try {
// code that may throw an exception
} catch (Exception e) {
logger.error("An error occurred", e);
throw new CustomException("Error processing request", e);
}
Code Formatting
Use consistent code formatting rules. Configure your IDE to use the same formatting rules (e.g., 4 spaces for indentation).
Specific Practices
- Immutable Objects
- Prefer immutability for value types.
// Good Example
public final class User {
private final String name;
private final int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// getters
}
// Bad Example
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
// getters and setters
}
- Prefer Composition over Inheritance
- Use composition to extend class functionality instead of inheritance when appropriate.
// Good Example
public class Printer {
private final PrinterDriver driver;
public Printer(PrinterDriver driver) {
this.driver = driver;
}
public void print(String document) {
driver.print(document);
}
}
// Bad Example
public class Printer extends PrinterDriver {
public void print(String document) {
super.print(document);
}
}
- Consistent Error Messages
- Use consistent and meaningful error messages.
// Good Example
if (user == null) {
throw new IllegalArgumentException("User must not be null");
}
// Bad Example
if (user == null) {
throw new IllegalArgumentException("Error: user");
}
- Use Descriptive Names
- Use names that describe the purpose of the variable, method, or class.
// Good Example
public class UserManager {
private List activeUsers;
public void addUser(User user) {
activeUsers.add(user);
}
}
// Bad Example
public class UM {
private List list;
public void add(User u) {
list.add(u);
}
}
Development Process for Java Team
Version Control
Git Workflow
- Main Branches
main
: Contains production-ready code.develop
: Contains the latest development changes.
- Supporting Branches
feature/*
: Used for developing new features.release/*
: Used for preparing a new production release.hotfix/*
: Used for quick fixes to production code.
Example Branching Strategy
# Create a new feature branch from develop
git checkout -b feature/feature-name develop
# Merge feature branch into develop after completion
git checkout develop
git merge feature/feature-name
# Create a new release branch from develop
git checkout -b release/release-version develop
# Merge release branch into main after release preparation
git checkout main
git merge release/release-version
# Create a new hotfix branch from main
git checkout -b hotfix/hotfix-name main
# Merge hotfix branch into main and develop after fixing
git checkout main
git merge hotfix/hotfix-name
git checkout develop
git merge hotfix/hotfix-name
Continuous Integration
Setting Up CI/CD
- Choose a CI/CD Tool
- Use tools like Jenkins, GitHub Actions, GitLab CI, or CircleCI.
- Automate Builds and Tests
- Set up automated builds and tests to run on every commit.
Pipeline Example (GitHub Actions)
name: Java CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Build with Gradle
run: ./gradlew build
- name: Run tests
run: ./gradlew test
Code Reviews
Pull Request Workflow
- Create a Pull Request
- Push your branch to the remote repository.
- Open a pull request (PR) from your branch to the target branch (
develop
ormain
).
- Review the PR
- Assign reviewers to the PR.
- Reviewers provide feedback and request changes if necessary.
- Merge the PR
- Once the PR is approved and all checks pass, merge the PR into the target branch.
Example PR Description
### Summary
- Added user authentication feature using JWT.
- Updated user model and database schema.
- Added tests for authentication endpoints.
### Changes
- New endpoints: /login, /signup
- Updated User model: added password field
- Added authentication middleware
### Testing
- Unit tests: 100% coverage for new features
- Manual testing: verified login and signup functionality
### Issues
- Closes #123: User authentication
Documentation
Code Documentation
- Use Javadoc for Public APIs
- Document all public classes and methods using Javadoc.
- Inline Comments
- Add inline comments to explain complex logic or algorithms.
Example Javadoc
/**
* Service for managing user accounts.
*/
public class UserService {
/**
* Registers a new user.
*
* @param user The user to register.
* @return The registered user.
* @throws UserAlreadyExistsException if the user already exists.
*/
public User registerUser(User user) throws UserAlreadyExistsException {
// implementation
}
}
Testing
Unit Testing
- Use JUnit for Unit Tests
- Write unit tests for all public methods.
Example Unit Test
public class UserServiceTest {
@Test
public void testRegisterUser() {
UserService userService = new UserService();
User user = new User("testuser", "password");
User registeredUser = userService.registerUser(user);
assertNotNull(registeredUser);
assertEquals("testuser", registeredUser.getUsername());
}
}
Integration Testing
- Use Spring Boot Test for Integration Tests
- Write integration tests to verify the interaction between components.
Example Integration Test
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserControllerIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testSignup() throws Exception {
String userJson = "{"username": "testuser", "password": "password"}";
mockMvc.perform(post("/signup")
.contentType(MediaType.APPLICATION_JSON)
.content(userJson))
.andExpect(status().isOk())
.andExpect(jsonPath("$.username").value("testuser"));
}
}
Code Review Security Checklist for Java Team
Authentication and Authorization
- Ensure all endpoints require authentication.
// Example @RestController public class UserController { @GetMapping("/users") @PreAuthorize("hasRole('USER')") public List
getAllUsers() { return userService.getAllUsers(); } } - Verify that roles and permissions are correctly enforced.
// Example @PreAuthorize("hasRole('ADMIN')") public void deleteUser(Long userId) { userRepository.deleteById(userId); }
Input Validation
- Ensure all user inputs are validated to prevent SQL injection, XSS, and other injection attacks.
// Example public class User { @NotNull @Size(min = 2, max = 30) private String name; @Email private String email; }
Error Handling
- Do not expose stack traces or internal error messages to users.
// Example @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity
handleException(Exception ex) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An unexpected error occurred"); } }
Logging
- Ensure sensitive information is not logged.
// Example logger.info("User logged in with username: {}", username);
- Log authentication attempts and failures.
// Example logger.warn("Failed login attempt for username: {}", username);
Session Management
- Ensure sessions are invalidated on logout.
// Example @RequestMapping("/logout") public String logout(HttpServletRequest request) { request.getSession().invalidate(); return "redirect:/login?logout"; }
Data Protection
- Ensure sensitive data is encrypted at rest and in transit.
// Example // Use HTTPS for secure communication http.requiresChannel() .anyRequest() .requiresSecure();
// Example @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
Dependency Management
- Ensure all dependencies are up to date and free from known vulnerabilities.
// Example // Use tools like OWASP Dependency Check for vulnerability scanning
API Security
- Ensure APIs are protected against common attacks like CSRF and CORS.
// Example @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() // Use CSRF protection as appropriate .cors().and() // Configure CORS settings .authorizeRequests() .anyRequest().authenticated(); } }
Code Quality
- Review code for potential security issues, such as hardcoded credentials or insecure configurations.
// Example // Avoid hardcoding credentials private static final String DB_PASSWORD = System.getenv("DB_PASSWORD");
API and REST Security Guidelines for Java Team
Authentication
Use OAuth2 or JWT for authentication to ensure secure access to APIs.
// Example of configuring JWT authentication in Spring Boot
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()));
}
}
Authorization
Implement role-based access control (RBAC) to manage permissions and access levels for different users.
// Example of role-based access control in Spring Boot
@RestController
@RequestMapping("/api/admin")
@PreAuthorize("hasRole('ADMIN')")
public class AdminController {
@GetMapping("/users")
public List getAllUsers() {
return userService.getAllUsers();
}
}
Data Validation
Validate all incoming data to prevent SQL injection and other attacks. Use frameworks like Hibernate Validator for validation.
// Example of data validation in a Spring Boot application
@RestController
public class UserController {
@PostMapping("/users")
public ResponseEntity createUser(@Valid @RequestBody User user) {
// handle user creation
}
}
Error Handling
Use proper HTTP status codes for error responses and handle exceptions gracefully.
// Example of a global exception handler in Spring Boot
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity handleUserNotFound(UserNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage());
}
@ExceptionHandler(Exception.class)
public ResponseEntity handleException(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An unexpected error occurred");
}
}
Logging
Log all access and error events for monitoring and auditing purposes. Use a logging framework like SLF4J with Logback.
// Example of logging in a Spring Boot application
@RestController
public class LoggingController {
private static final Logger logger = LoggerFactory.getLogger(LoggingController.class);
@GetMapping("/example")
public ResponseEntity example() {
logger.info("Example endpoint accessed");
return ResponseEntity.ok("Example");
}
}
Rate Limiting
Implement rate limiting to prevent abuse of the API. Use tools like Bucket4j or libraries provided by API gateways.
// Example of rate limiting using Spring Boot and Bucket4j
@RestController
public class RateLimitingController {
private final Refill refill = Refill.greedy(10, Duration.ofMinutes(1));
private final Bandwidth limit = Bandwidth.classic(10, refill);
private final Bucket bucket = Bucket4j.builder().addLimit(limit).build();
@GetMapping("/limited")
public ResponseEntity limitedEndpoint() {
if (bucket.tryConsume(1)) {
return ResponseEntity.ok("Request allowed");
} else {
return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body("Too many requests");
}
}
}
SQL Guidelines for Java Team
General Guidelines
- Use Clear and Consistent Naming Conventions
- Tables: Use singular nouns (e.g.,
user
,order
,product
). - Columns: Use lowercase letters and underscores to separate words (e.g.,
first_name
,order_date
). - Primary keys: Prefer using
id
as the primary key for all tables.
- Tables: Use singular nouns (e.g.,
- Avoid Using Reserved Words
- Always check for SQL reserved words before naming tables or columns.
- Use Proper Indexing
- Index columns that are frequently used in
WHERE
,JOIN
,ORDER BY
, andGROUP BY
clauses to improve performance.
- Index columns that are frequently used in
- Normalize Data
- Use normalization to eliminate redundant data and ensure data integrity.
- Use Transactions
- Wrap related SQL statements in transactions to ensure data consistency.
- Comment Your Code
- Add comments to complex queries to explain their purpose.
Writing SQL Queries
SELECT Statements
Retrieve specific columns instead of using SELECT *
to improve performance.
-- Good Example
SELECT first_name, last_name, email FROM user WHERE active = 1;
-- Bad Example
SELECT * FROM user WHERE active = 1;
JOINs
Use explicit JOIN
syntax for better readability.
-- Good Example
SELECT u.first_name, u.last_name, o.order_date
FROM user u
JOIN order o ON u.id = o.user_id
WHERE o.order_date > '2023-01-01';
-- Bad Example
SELECT u.first_name, u.last_name, o.order_date
FROM user u, order o
WHERE u.id = o.user_id
AND o.order_date > '2023-01-01';
Subqueries
Use subqueries when needed but avoid using them in SELECT
clauses as they can be inefficient.
-- Good Example
SELECT first_name, last_name
FROM user
WHERE id IN (SELECT user_id FROM order WHERE order_date > '2023-01-01');
-- Bad Example
SELECT first_name, last_name, (SELECT order_date FROM order WHERE user.id = order.user_id AND order_date > '2023-01-01')
FROM user;
Handling NULL Values
Use IS NULL
or IS NOT NULL
to handle NULL
values explicitly.
-- Good Example
SELECT first_name, last_name
FROM user
WHERE middle_name IS NULL;
-- Bad Example
SELECT first_name, last_name
FROM user
WHERE middle_name = NULL;
Inserting Data
Always specify the columns when inserting data to avoid issues with schema changes.
-- Good Example
INSERT INTO user (first_name, last_name, email) VALUES ('John', 'Doe', 'john.doe@example.com');
-- Bad Example
INSERT INTO user VALUES ('John', 'Doe', 'john.doe@example.com');
Updating Data
Be careful with UPDATE
statements to avoid unintentional changes. Use WHERE
clause to specify rows to be updated.
-- Good Example
UPDATE user SET email = 'new.email@example.com' WHERE id = 1;
-- Bad Example
UPDATE user SET email = 'new.email@example.com';
Deleting Data
Use DELETE
statements with WHERE
clause to avoid deleting all rows.
-- Good Example
DELETE FROM user WHERE id = 1;
-- Bad Example
DELETE FROM user;
Performance Tips
- Limit the Use of Cursors
- Use set-based operations instead of cursors for better performance.
- Avoid Heavy Use of Triggers
- Triggers can negatively impact performance and complicate debugging.
- Optimize Queries
- Use
EXPLAIN
orEXPLAIN ANALYZE
to understand query execution plans and optimize accordingly.
- Use
- Batch Processing
- Use batch processing for bulk inserts or updates to reduce the number of database round trips.
Best Practices
- Consistent Error Handling
- Use consistent error handling strategies in both SQL and Java code.
- Security
- Use parameterized queries or prepared statements to prevent SQL injection attacks.
- Code Reviews
- Regularly review SQL code during code reviews to maintain quality and performance standards.
- Documentation
- Maintain up-to-date documentation for database schemas and SQL queries used in the application.
Examples
Example 1: Simple Select with Join
SELECT u.first_name, u.last_name, o.order_date
FROM user u
JOIN order o ON u.id = o.user_id
WHERE o.order_date > '2023-01-01';
Example 2: Insert with Specified Columns
INSERT INTO user (first_name, last_name, email)
VALUES ('Jane', 'Smith', 'jane.smith@example.com');
Example 3: Update with Where Clause
UPDATE user
SET email = 'jane.newemail@example.com'
WHERE id = 2;
Example 4: Delete with Where Clause
DELETE FROM user
WHERE id = 2;
Bitbucket Administration for Java Team
Setting Up a Repository
- Create a new repository in Bitbucket.
- Set up repository settings:
- Configure access control.
- Set up branch permissions.
Example Branching Strategy
# Create a new feature branch from develop
git checkout -b feature/feature-name develop
# Merge feature branch into develop after completion
git checkout develop
git merge feature/feature-name
# Create a new release branch from develop
git checkout -b release/release-version develop
# Merge release branch into main after release preparation
git checkout main
git merge release/release-version
# Create a new hotfix branch from main
git checkout -b hotfix/hotfix-name main
# Merge hotfix branch into main and develop after fixing
git checkout main
git merge hotfix/hotfix-name
git checkout develop
git merge hotfix/hotfix-name
Repository Access
- Navigate to the repository.
- Click on Settings > User and group access.
- Click Add users and groups.
- Enter the username or group name.
- Set the access level (Read, Write, Admin).
- Click Add.
Branch Permissions
- Navigate to the repository.
- Click on Settings > Branch permissions.
- Click Add a branch permission.
- Set the branch or pattern (e.g.,
main
,develop
). - Choose the restrictions (e.g., require pull request approvals).
- Click Save.
Commit Message Guidelines
Write clear, concise commit messages. Use imperative mood in the subject line (e.g., "Add feature", "Fix bug").
// Example Commit Message
feat: Add user authentication
- Implement login and signup endpoints
- Add JWT token generation and validation
- Update database schema for user accounts
Closes #123
Pull Request Process
Creating a Pull Request
- Push your branch to Bitbucket.
- Navigate to the repository.
- Click on Pull requests > Create pull request.
- Fill in the PR details:
- Title: Short summary of the changes.
- Description: Detailed explanation of the changes.
- Select reviewers.
- Click Create pull request.
Reviewing a Pull Request
- Navigate to the PR.
- Review the changes:
- Files changed: View the diff of the changes.
- Commits: View the commits included in the PR.
- Add comments or suggestions.
- Approve the PR if the changes are satisfactory.
- Merge the PR once approved.
Examples
Example 1: Creating a Repository
# Log in to Bitbucket
# Navigate to Repositories > Create repository
# Fill in repository details
# Click Create repository
Example 2: Creating a Feature Branch
git checkout -b feature/add-authentication develop
Example 3: Adding a User to a Repository
- Navigate to the repository.
- Click on Settings > User and group access.
- Click Add users and groups.
- Enter the username.
- Set the access level (Read, Write, Admin).
- Click Add.
ArtefactRegistry Naming Convention for Java Team
General Guidelines
- Use Clear and Descriptive Names
- Names should clearly convey the purpose of the artefact.
- Include Version Numbers
- Use semantic versioning (e.g., 1.0.0, 2.1.0).
- Use Lowercase Letters
- Use lowercase letters and hyphens to separate words.
Examples
Example 1: Library Artefact
com.example.library:library-name:1.0.0
Example 2: Project Artefact
com.example.project:project-name:2.1.0
Example 3: Service Artefact
com.example.service:service-name:3.0.0