Skip to content

Code OrganizationΒΆ

This guide covers best practices for organizing code structure, file layout, and project architecture across different programming languages.

🎯 Core Organization Principles¢

Single Responsibility PrincipleΒΆ

Each file, class, and module should have one clear responsibility.

Good ExampleΒΆ

# user_service.py - Only handles user business logic
class UserService:
    def create_user(self, user_data):
        # User creation logic only
        pass

    def update_user(self, user_id, user_data):
        # User update logic only
        pass

# user_repository.py - Only handles data access
class UserRepository:
    def save(self, user):
        # Database operations only
        pass

    def find_by_id(self, user_id):
        # Database queries only
        pass

Bad ExampleΒΆ

# user_manager.py - Multiple responsibilities
class UserManager:
    def create_user(self, user_data):
        # User creation logic
        pass

    def save_to_database(self, user):
        # Database logic (wrong place)
        pass

    def send_email(self, user):
        # Email logic (wrong place)
        pass

    def validate_input(self, data):
        # Validation logic (wrong place)
        pass

Dependency DirectionΒΆ

Dependencies should point inward, from high-level to low-level modules.

Application Layer (High Level)
    ↓ depends on
Business Logic Layer
    ↓ depends on
Data Access Layer (Low Level)

πŸ“ Directory Structure Best PracticesΒΆ

Standard Project LayoutΒΆ

project_name/
β”œβ”€β”€ src/                    # Source code
β”‚   β”œβ”€β”€ main/              # Production code
β”‚   β”‚   β”œβ”€β”€ java/         # Java source files
β”‚   β”‚   β”œβ”€β”€ python/       # Python source files
β”‚   β”‚   └── resources/     # Configuration files
β”‚   └── test/              # Test code
β”‚       β”œβ”€β”€ java/         # Test source files
β”‚       └── python/        # Test source files
β”œβ”€β”€ docs/                  # Documentation
β”œβ”€β”€ config/                # Configuration files
β”œβ”€β”€ scripts/               # Build and deployment scripts
β”œβ”€β”€ tests/                 # Integration tests
β”œβ”€β”€ build/                 # Build output
└── README.md              # Project documentation

Language-Specific StructuresΒΆ

Java Maven StructureΒΆ

my-java-project/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main/
β”‚   β”‚   β”œβ”€β”€ java/
β”‚   β”‚   β”‚   └── com/
β”‚   β”‚   β”‚       └── mycompany/
β”‚   β”‚   β”‚           β”œβ”€β”€ controller/
β”‚   β”‚   β”‚           β”œβ”€β”€ service/
β”‚   β”‚   β”‚           β”œβ”€β”€ repository/
β”‚   β”‚   β”‚           └── model/
β”‚   β”‚   └── resources/
β”‚   β”‚       β”œβ”€β”€ application.properties
β”‚   β”‚       └── logback.xml
β”‚   └── test/
β”‚       └── java/
β”‚           └── com/
β”‚               └── mycompany/
β”‚                   β”œβ”€β”€ controller/
β”‚                   β”œβ”€β”€ service/
β”‚                   └── repository/
β”œβ”€β”€ pom.xml
└── README.md

Python Package StructureΒΆ

my-python-project/
β”œβ”€β”€ my_package/
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   β”œβ”€β”€ user.py
β”‚   β”‚   └── product.py
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   β”œβ”€β”€ user_service.py
β”‚   β”‚   └── product_service.py
β”‚   β”œβ”€β”€ repositories/
β”‚   β”‚   β”œβ”€β”€ __init__.py
β”‚   β”‚   β”œβ”€β”€ user_repository.py
β”‚   β”‚   └── product_repository.py
β”‚   └── utils/
β”‚       β”œβ”€β”€ __init__.py
β”‚       β”œβ”€β”€ validators.py
β”‚       └── helpers.py
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ test_models/
β”‚   β”œβ”€β”€ test_services/
β”‚   └── test_repositories/
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ setup.py
└── README.md

C Project StructureΒΆ

my-c-project/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main.c
β”‚   β”œβ”€β”€ user/
β”‚   β”‚   β”œβ”€β”€ user.h
β”‚   β”‚   └── user.c
β”‚   β”œβ”€β”€ product/
β”‚   β”‚   β”œβ”€β”€ product.h
β”‚   β”‚   └── product.c
β”‚   └── utils/
β”‚       β”œβ”€β”€ utils.h
β”‚       └── utils.c
β”œβ”€β”€ include/
β”‚   β”œβ”€β”€ common.h
β”‚   └── config.h
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ test_user.c
β”‚   └── test_product.c
β”œβ”€β”€ build/
β”œβ”€β”€ Makefile
└── README.md

πŸ—οΈ Architectural PatternsΒΆ

Layered ArchitectureΒΆ

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           Presentation Layer          β”‚  (Controllers, UI)
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚            Business Layer            β”‚  (Services, Logic)
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚           Data Access Layer          β”‚  (Repositories, DAOs)
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚            Database Layer            β”‚  (Database, Files)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Java ImplementationΒΆ

// Controller Layer
@RestController
@RequestMapping("/api/users")
public class UserController {
    private UserService userService;

    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        User user = userService.findById(id);
        return ResponseEntity.ok(user);
    }
}

// Service Layer
@Service
public class UserService {
    private UserRepository userRepository;

    public User findById(Long id) {
        return userRepository.findById(id)
            .orElseThrow(() -> new UserNotFoundException(id));
    }
}

// Repository Layer
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findById(Long id);
}

Modular ArchitectureΒΆ

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   User      β”‚  β”‚  Product    β”‚  β”‚  Order      β”‚
β”‚   Module    β”‚  β”‚  Module     β”‚  β”‚  Module     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚                β”‚                β”‚
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚   Common    β”‚
              β”‚   Module    β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Python ImplementationΒΆ

# user/module.py
from ..common.database import DatabaseConnection
from ..common.validators import validate_email

class UserModule:
    def __init__(self):
        self.db = DatabaseConnection()

    def create_user(self, user_data):
        if validate_email(user_data['email']):
            return self.db.insert('users', user_data)
        raise ValueError("Invalid email")

# product/module.py
from ..common.database import DatabaseConnection

class ProductModule:
    def __init__(self):
        self.db = DatabaseConnection()

    def create_product(self, product_data):
        return self.db.insert('products', product_data)

# common/database.py
class DatabaseConnection:
    def __init__(self):
        self.connection = self._create_connection()

    def insert(self, table, data):
        # Database insertion logic
        pass

πŸ“‹ File Organization RulesΒΆ

Naming ConventionsΒΆ

## File Naming Standards

### General Rules
- Use descriptive, meaningful names
- Be consistent across the project
- Use language-specific conventions
- Avoid abbreviations unless widely understood

### Language-Specific Conventions
- **Java**: PascalCase for classes (UserService.java)
- **Python**: snake_case for modules (user_service.py)
- **C**: snake_case for files (user_service.c)
- **Oracle**: snake_case for packages (user_management.pks)

File Size GuidelinesΒΆ

## File Size Recommendations

### Maximum File Sizes
- **Classes**: 300-500 lines maximum
- **Functions**: 50-100 lines maximum
- **Modules**: 1000 lines maximum
- **Configuration files**: As needed

### When to Split Files
- Single file exceeds 500 lines
- Multiple distinct responsibilities
- Different abstraction levels
- Different feature areas

πŸ”§ Code Organization TechniquesΒΆ

Package/Module OrganizationΒΆ

// Good: Organized by feature
com.company.app
β”œβ”€β”€ user/
β”‚   β”œβ”€β”€ UserController.java
β”‚   β”œβ”€β”€ UserService.java
β”‚   β”œβ”€β”€ UserRepository.java
β”‚   └── User.java
β”œβ”€β”€ product/
β”‚   β”œβ”€β”€ ProductController.java
β”‚   β”œβ”€β”€ ProductService.java
β”‚   β”œβ”€β”€ ProductRepository.java
β”‚   └── Product.java
└── common/
    β”œβ”€β”€ BaseController.java
    β”œβ”€β”€ BaseService.java
    └── BaseEntity.java

// Bad: Organized by type
com.company.app
β”œβ”€β”€ controller/
β”‚   β”œβ”€β”€ UserController.java
β”‚   β”œβ”€β”€ ProductController.java
β”‚   └── OrderController.java
β”œβ”€β”€ service/
β”‚   β”œβ”€β”€ UserService.java
β”‚   β”œβ”€β”€ ProductService.java
β”‚   └── OrderService.java
└── repository/
    β”œβ”€β”€ UserRepository.java
    β”œβ”€β”€ ProductRepository.java
    └── OrderRepository.java

Dependency InjectionΒΆ

# Good: Dependency injection
class UserService:
    def __init__(self, user_repository: UserRepository, email_service: EmailService):
        self.user_repository = user_repository
        self.email_service = email_service

    def create_user(self, user_data):
        user = self.user_repository.save(user_data)
        self.email_service.send_welcome_email(user.email)
        return user

# Bad: Hard dependencies
class UserService:
    def __init__(self):
        self.user_repository = UserRepository()  # Hard dependency
        self.email_service = EmailService()     # Hard dependency

    def create_user(self, user_data):
        user = self.user_repository.save(user_data)
        self.email_service.send_welcome_email(user.email)
        return user

Configuration ManagementΒΆ

# config/application.yml
app:
  name: "My Application"
  version: "1.0.0"

database:
  url: "jdbc:postgresql://localhost:5432/mydb"
  username: "user"
  password: "password"

logging:
  level: "INFO"
  file: "logs/application.log"
// Configuration class
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppConfig {
    private String name;
    private String version;

    // getters and setters
}

@Service
public class ApplicationService {
    private final AppConfig config;

    public ApplicationService(AppConfig config) {
        this.config = config;
    }

    public String getAppInfo() {
        return config.getName() + " v" + config.getVersion();
    }
}

πŸ“š Documentation OrganizationΒΆ

Code DocumentationΒΆ

/**
 * Service for managing user operations.
 * 
 * <p>This service provides methods for creating, updating, and retrieving users.
 * It handles business logic and coordinates with the repository layer.</p>
 *
 * @author John Doe
 * @version 1.0
 * @since 1.0
 */
@Service
public class UserService {

    /**
     * Creates a new user.
     *
     * @param userDto the user data transfer object
     * @return the created user
     * @throws IllegalArgumentException if user data is invalid
     * @throws EmailAlreadyExistsException if email already exists
     */
    public User createUser(UserDto userDto) {
        // Implementation
    }
}

README StructureΒΆ

# Project Name

## Description
Brief description of the project purpose and functionality.

## Quick Start
Instructions for getting the project running quickly.

## Project Structure
Overview of the project organization and key directories.

## Configuration
How to configure the project for different environments.

## API Documentation
Link to API documentation or key endpoints.

## Contributing
Guidelines for contributing to the project.

## License
Project license information.

πŸ”„ Refactoring OrganizationΒΆ

Signs of Poor OrganizationΒΆ

  • Large files with multiple responsibilities
  • Deep nesting and complex hierarchies
  • Circular dependencies
  • Duplicated code across modules
  • Difficult to locate specific functionality

Refactoring StepsΒΆ

  1. Identify Problems: Use code analysis tools and reviews
  2. Plan Changes: Create refactoring plan with minimal risk
  3. Extract Modules: Break large files into smaller modules
  4. Reorganize Dependencies: Fix dependency direction issues
  5. Update Tests: Ensure all tests pass after refactoring
  6. Document Changes: Update documentation and README files

πŸ”— Language-Specific OrganizationΒΆ