Practical Considerations, Trade-offs, and Variations in Clean Architecture

Learning Objectives: By the end of this lesson, you will be able to:

  • Recognize when and how to pragmatically apply Clean Architecture
  • Compare Clean Architecture with Onion and Hexagonal Architectures
  • Identify common pitfalls and make informed trade-offs in real-world projects

1. Welcome and Introduction (5 minutes)

Icebreaker Activity

Have you ever worked on a project where the architecture felt like “too much” for the problem? Or, have you ever regretted not having enough structure as the project grew? Share your experience.

Lesson Overview

  • Duration: 90 minutes
  • Prerequisites: Understanding of Clean Architecture and its layers
  • Materials Needed: Java development environment, pen and paper for sketching project structures

2. Learning Objectives and Session Outline (5 minutes)

What We’ll Cover Today:

  1. When to apply Clean Architecture strictly vs. pragmatically
  2. Boilerplate and complexity: how much is too much?
  3. Variations: Onion Architecture, Hexagonal Architecture (Ports & Adapters)
  4. Common pitfalls and how to avoid them
  5. Mini-project: Sketching a simple app using Clean Architecture
  6. Review and next steps

Success Criteria:

By the end of this session, you should be able to make informed decisions about applying Clean Architecture and recognize its variations and trade-offs.

3. Foundation Knowledge (15-20 minutes)

Core Concepts

When to Apply Clean Architecture

  • Clean Architecture is a guideline, not a strict rulebook
  • For small projects, a lighter approach may be more productive
  • For large, long-lived, or complex projects, the structure pays off

Real-World Analogy: Building a shed vs. a skyscraper: You don’t need the same level of engineering for both, but you still need a solid foundation.

Why This Matters: Over-engineering can slow you down, but under-engineering can lead to pain as the project grows.

Boilerplate and Complexity

  • Clean Architecture introduces more classes, interfaces, and layers
  • This can feel like “boilerplate” in small projects
  • The key is to balance structure with simplicity

Variations: Onion and Hexagonal Architectures

  • Onion Architecture: Similar concentric circles, with core domain at the center
  • Hexagonal Architecture (Ports & Adapters): Focuses on ports (interfaces) and adapters (implementations), often visualized as a hexagon
  • All share the goal of decoupling core logic from external details

Key Terminology

  • Boilerplate: Repetitive code required by a framework or pattern
  • Onion Architecture: A layered architecture with the domain model at the center
  • Hexagonal Architecture: An architecture that emphasizes ports and adapters for flexibility

4. Detailed Explanation and Examples (25-30 minutes)

Understanding Trade-offs and Variations

When to Bend the Rules

  • For prototypes or very small apps, you might combine layers or skip some abstractions
  • As the project grows, refactor toward more structure
  • Always keep business logic decoupled from frameworks and data sources

Comparing Architectures

Aspect Clean Architecture Onion Architecture Hexagonal Architecture
Visual Metaphor Circles Onion (layers) Hexagon (ports/adapters)
Core Principle Inward dependencies Domain at center Ports & adapters
Focus Decoupling, testability Domain purity Flexibility, testability

Example: Simple Note-Taking App Structure

// ...existing code...
// Entities: Note, User
// Use Cases: CreateNote, ListNotes
// Repositories: NoteRepository
// Controllers: NoteController
// Presenters: NotePresenter
// Frameworks: Spring Boot, JDBC, etc.

Explanation:

  • For a small app, you might combine controllers and presenters, or use in-memory repositories
  • For a larger app, separate each layer for flexibility

Common Pitfalls

  1. Pitfall: Leaking framework or database code into core logic Solution: Always use interfaces and keep dependencies pointing inward
  2. Pitfall: Anemic domain models (entities with no business logic) Solution: Place business rules in entities, not just data
  3. Pitfall: Over-abstraction for small projects Solution: Start simple, refactor as needed

5. Live Coding Demonstration (20-25 minutes)

Example 1: Minimal Clean Architecture for a URL Shortener

// Entity
public class ShortUrl {
    private String code;
    private String originalUrl;
    // ...constructor, getters, business rules...
}

// Use Case
public class CreateShortUrlUseCase {
    private ShortUrlRepository repository;
    public CreateShortUrlUseCase(ShortUrlRepository repository) {
        this.repository = repository;
    }
    public void execute(String code, String url) {
        ShortUrl shortUrl = new ShortUrl(code, url);
        repository.save(shortUrl);
    }
}

// Repository Interface
public interface ShortUrlRepository {
    void save(ShortUrl shortUrl);
    ShortUrl findByCode(String code);
}

// In-memory Adapter
public class InMemoryShortUrlRepository implements ShortUrlRepository {
    // ...implementation...
}

Key Points:

  • Minimal layers, but still decoupled
  • Easy to swap repository implementation later

Example 2: Onion vs. Hexagonal in Java

// Onion: Domain at center, interfaces around
// Hexagonal: Ports (interfaces) and adapters (implementations)
// Both can be implemented with Java interfaces and classes

Debugging Demonstration

Show a common error:

// Common mistake: Entity with framework annotation
// @Entity
public class Note {
    // ...
}

// Corrected: No framework code in entity
public class Note {
    // ...
}

6. Hands-On Practice (30-40 minutes)

Exercise 1: Basic Practice (10 minutes)

Objective: Sketch a simple app using Clean Architecture

Instructions:

  1. Choose a simple app (e.g., note-taking, to-do list)
  2. Identify entities, use cases, repositories, and adapters
  3. Draw the structure (circles, onion, or hexagon)

Starter Code: N/A (diagramming exercise)

Solution: A labeled diagram showing layers and dependencies

Exercise 2: Intermediate Challenge (15 minutes)

Objective: Compare Clean, Onion, and Hexagonal Architectures

Requirements:

  • List similarities and differences
  • Discuss when you might choose one over the others

Hints:

  • Focus on dependency direction, testability, and flexibility

Exercise 3: Creative Application (15 minutes)

Objective: Refactor a small project to introduce Clean Architecture principles

Challenge: Take an existing or sample project and identify where you can introduce layers, interfaces, and decoupling. Document your changes and reasoning.

Extension Ideas:

  • Try both minimal and full implementations
  • Reflect on the impact on testability and maintainability

7. Common Pitfalls and Troubleshooting (10 minutes)

Frequent Mistakes

  1. Problem: Over-engineering for small projects Cause: Applying all layers and abstractions from the start Solution: Start simple, refactor as needed

  2. Problem: Not refactoring as the project grows Cause: Leaving code in a “prototype” state Solution: Add structure as complexity increases

Debugging Tips

  • Regularly review dependencies and imports
  • Refactor to introduce interfaces and layers as needed
  • Use diagrams to visualize structure

8. Best Practices and Professional Tips (5 minutes)

Industry Standards

  • Apply Clean Architecture pragmatically
  • Use variations (Onion, Hexagonal) as appropriate
  • Focus on decoupling, testability, and maintainability

Next Steps in Your Learning Journey

  • Try implementing a small project with Clean Architecture
  • Read about Domain-Driven Design (DDD)
  • Explore open-source projects using these patterns

9. Summary and Review (5 minutes)

Key Takeaways

  1. Clean Architecture is a guideline, not a strict rulebook
  2. Variations like Onion and Hexagonal share similar goals
  3. Balance structure and simplicity for your project’s needs

Quick Review Questions

  1. When should you apply Clean Architecture strictly vs. pragmatically?
  2. What are the main differences between Clean, Onion, and Hexagonal Architectures?
  3. How can you avoid over-engineering in small projects?

For Instructors

Teaching Tips

  • Use real-world project examples to discuss trade-offs
  • Encourage students to reflect on their own projects
  • Review diagrams and refactoring exercises for understanding

Assessment Ideas

  • Ask students to sketch and explain a project structure
  • Review written comparisons of architecture patterns
  • Peer review of refactoring plans

Adaptation Notes

  • For beginners, provide more scaffolding and sample diagrams
  • For advanced students, challenge them to refactor a real project
  • Adjust timing based on class experience and engagement