Organizing Code Structure
1. Designing Package Structure
| Strategy | Pros | Cons |
| By layer | Familiar, simple | Cross-cuts feature changes |
| By feature | Cohesive, scales | Learning curve |
| Hexagonal | Clear boundaries | Initial complexity |
com.acme.order/
domain/ Order, OrderStatus, OrderRepository (port)
application/ PlaceOrderService
adapters/in/ OrderController
adapters/out/ JpaOrderRepository (adapter)
2. Implementing Layered Architecture
| Layer | Depends On | Knows About |
| Presentation | Application | HTTP, JSON |
| Application | Domain | Use cases |
| Domain | Nothing | Business rules |
| Infrastructure | Domain (impl) | DB, MQ, HTTP clients |
Warning: Domain must never import infrastructure or framework types.
3. Implementing Module Boundaries
| Tool | Mechanism |
| Java Modules | module-info.java exports |
| Maven/Gradle modules | Compile-time isolation |
| ArchUnit | Runtime architecture tests |
| Package-private | Hide implementation classes |
4. Organizing Code by Features
Example: Feature packages
com.acme/
user/ User, UserService, UserController, UserRepository
order/ Order, OrderService, OrderController, OrderRepository
shared/ cross-cutting utilities
| Benefit | Detail |
| Locality | One feature, one place |
| Delete | Remove a feature = remove a folder |
5. Organizing Code by Layers
Example: Layer packages
com.acme/
controller/ UserController, OrderController
service/ UserService, OrderService
repository/ UserRepository, OrderRepository
domain/ User, Order
6. Implementing Constants Management
| Approach | When |
| Per-class constants | Used only locally |
final class Constants | Cross-cutting values |
| Enum | Closed set with behavior |
| Properties file | Externally configurable |
7. Implementing Exception Hierarchy
RuntimeException
└── AppException (base, has errorCode)
├── DomainException
│ ├── ValidationException
│ └── BusinessRuleException
├── NotFoundException
└── IntegrationException
├── DownstreamUnavailableException
└── DownstreamTimeoutException
| Rule | Detail |
| Unchecked by default | Easier propagation |
| Carry context | error code, correlation ID |
| No catch-and-swallow | Always wrap or rethrow |
8. Implementing Utility Packages
| Package | Contents |
util | Generic helpers (avoid dumping ground) |
support | Framework-specific helpers |
common | Shared types across features |
Warning: A growing util package signals missing abstractions — promote to feature packages.
9. Implementing Code Documentation
| Audience | Doc Type |
| Public API users | Javadoc with @param, @return, @throws |
| Maintainers | Why comments, not what |
| Architects | ADRs (architecture decision records) |
| Newcomers | README per module |
10. Implementing File Organization
| Rule | Detail |
| One public class per file | Java requirement |
| File name = class name | Required |
| Member order | static fields → instance fields → constructors → public → private |
| Imports | No wildcard, grouped (java, javax, third-party, project) |
11. Designing Namespace Structure
| Convention | Detail |
| Reverse domain | Globally unique |
| No cycles | Enforce with build/ArchUnit |
| Stable depth | Avoid 6+ nesting levels |
12. Implementing Module Dependencies
| Rule | Enforcement |
| Acyclic | Build will fail or use ArchUnit |
| Inner depends on outer? No | Domain → no infra |
| Stable abstractions | Stable modules expose interfaces |
| Versioned | SemVer for shared modules |