Development Guidelines

 

General Coding Practices

  1. 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).
  2. Comment Your Code
    • Use Javadoc comments for public methods and classes.
    • Add inline comments to explain complex logic.
  3. 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

  1. 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
}
  1. 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);
    }
}
  1. 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");
}
  1. 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

  1. Main Branches
    • main: Contains production-ready code.
    • develop: Contains the latest development changes.
  2. 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

  1. Choose a CI/CD Tool
    • Use tools like Jenkins, GitHub Actions, GitLab CI, or CircleCI.
  2. 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

  1. Create a Pull Request
    • Push your branch to the remote repository.
    • Open a pull request (PR) from your branch to the target branch (develop or main).
  2. Review the PR
    • Assign reviewers to the PR.
    • Reviewers provide feedback and request changes if necessary.
  3. 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

  1. Use Javadoc for Public APIs
    • Document all public classes and methods using Javadoc.
  2. 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

  1. 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

  1. 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

  1. Ensure all endpoints require authentication.
    // Example
    @RestController
    public class UserController {
    
        @GetMapping("/users")
        @PreAuthorize("hasRole('USER')")
        public List getAllUsers() {
            return userService.getAllUsers();
        }
    }	
  2. Verify that roles and permissions are correctly enforced.
    		// Example		@PreAuthorize("hasRole('ADMIN')")		public void deleteUser(Long userId) {		    userRepository.deleteById(userId);		}		

Input Validation

  1. 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

  1. 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

  1. Ensure sensitive information is not logged.
    // Example
    logger.info("User logged in with username: {}", username);
  2. Log authentication attempts and failures.
    // Example
    logger.warn("Failed login attempt for username: {}", username);

Session Management

  1. Ensure sessions are invalidated on logout.
    // Example
    @RequestMapping("/logout")
    public String logout(HttpServletRequest request) {
        request.getSession().invalidate();
        return "redirect:/login?logout";
    }

Data Protection

  1. Ensure sensitive data is encrypted at rest and in transit.
    // Example
    // Use HTTPS for secure communication
    http.requiresChannel()
        .anyRequest()
        .requiresSecure();
    Use strong hashing algorithms for passwords.
    // Example
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

Dependency Management

  1. Ensure all dependencies are up to date and free from known vulnerabilities.
    // Example
    // Use tools like OWASP Dependency Check for vulnerability scanning

API Security

  1. 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

  1. 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

  1. 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.
  2. Avoid Using Reserved Words
    • Always check for SQL reserved words before naming tables or columns.
  3. Use Proper Indexing
    • Index columns that are frequently used in WHERE, JOIN, ORDER BY, and GROUP BY clauses to improve performance.
  4. Normalize Data
    • Use normalization to eliminate redundant data and ensure data integrity.
  5. Use Transactions
    • Wrap related SQL statements in transactions to ensure data consistency.
  6. 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

  1. Limit the Use of Cursors
    • Use set-based operations instead of cursors for better performance.
  2. Avoid Heavy Use of Triggers
    • Triggers can negatively impact performance and complicate debugging.
  3. Optimize Queries
    • Use EXPLAIN or EXPLAIN ANALYZE to understand query execution plans and optimize accordingly.
  4. Batch Processing
    • Use batch processing for bulk inserts or updates to reduce the number of database round trips.

Best Practices

  1. Consistent Error Handling
    • Use consistent error handling strategies in both SQL and Java code.
  2. Security
    • Use parameterized queries or prepared statements to prevent SQL injection attacks.
  3. Code Reviews
    • Regularly review SQL code during code reviews to maintain quality and performance standards.
  4. 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

  1. Create a new repository in Bitbucket.
  2. 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

  1. Navigate to the repository.
  2. Click on Settings > User and group access.
  3. Click Add users and groups.
  4. Enter the username or group name.
  5. Set the access level (Read, Write, Admin).
  6. Click Add.

Branch Permissions

  1. Navigate to the repository.
  2. Click on Settings > Branch permissions.
  3. Click Add a branch permission.
  4. Set the branch or pattern (e.g., main, develop).
  5. Choose the restrictions (e.g., require pull request approvals).
  6. 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

  1. Push your branch to Bitbucket.
  2. Navigate to the repository.
  3. Click on Pull requests > Create pull request.
  4. Fill in the PR details:
    • Title: Short summary of the changes.
    • Description: Detailed explanation of the changes.
  5. Select reviewers.
  6. Click Create pull request.

Reviewing a Pull Request

  1. Navigate to the PR.
  2. Review the changes:
    • Files changed: View the diff of the changes.
    • Commits: View the commits included in the PR.
  3. Add comments or suggestions.
  4. Approve the PR if the changes are satisfactory.
  5. 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

  1. Navigate to the repository.
  2. Click on Settings > User and group access.
  3. Click Add users and groups.
  4. Enter the username.
  5. Set the access level (Read, Write, Admin).
  6. Click Add.

 

 

ArtefactRegistry Naming Convention for Java Team

General Guidelines

  1. Use Clear and Descriptive Names
    • Names should clearly convey the purpose of the artefact.
  2. Include Version Numbers
    • Use semantic versioning (e.g., 1.0.0, 2.1.0).
  3. 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