Uncle Bob's Clean Architecture Principles in the AI Era

Introduction

Robert C. Martin's Clean Architecture principles have guided software development for years. As AI becomes more integrated into our development process, these principles take on new significance and require adaptation.

The Dependency Rule Revisited

Uncle Bob's fundamental rule states that dependencies should point inward, toward higher-level policies. With AI, this rule becomes even more critical as we need to ensure AI tools don't create unwanted dependencies.

Clean Architecture with AI

1. Entities Layer

The innermost layer contains enterprise business rules. AI should never modify these core entities.


// Core business entity - AI should not modify this
class User {
  constructor(id, name, email) {
    this.id = id;
    this.name = name;
    this.email = email;
  }

  isValidEmail() {
    const emailRegex = /^[^s@]+@[^s@]+.[^s@]+$/;
    return emailRegex.test(this.email);
  }

  // Business rules - immutable by AI
  canAccessFeature(feature) {
    return this.subscriptionLevel >= feature.requiredLevel;
  }
}
            

2. Use Cases Layer

AI can help implement use cases, but the business logic should remain human-defined.


class CreateUserUseCase {
  constructor(userRepository, emailValidator) {
    this.userRepository = userRepository;
    this.emailValidator = emailValidator;
  }

  async execute(userData) {
    // Business logic - human-defined
    if (!this.emailValidator.isValid(userData.email)) {
      throw new Error('Invalid email format');
    }

    const existingUser = await this.userRepository.findByEmail(userData.email);
    if (existingUser) {
      throw new Error('User already exists');
    }

    const user = new User(
      this.generateId(),
      userData.name,
      userData.email
    );

    return await this.userRepository.save(user);
  }

  private generateId() {
    return crypto.randomUUID();
  }
}
            

3. Interface Adapters Layer

AI can generate adapters and controllers, but the interfaces should be human-designed.


class UserController {
  constructor(createUserUseCase) {
    this.createUserUseCase = createUserUseCase;
  }

  async createUser(req, res) {
    try {
      const user = await this.createUserUseCase.execute(req.body);
      res.status(201).json(user);
    } catch (error) {
      res.status(400).json({ error: error.message });
    }
  }
}

// AI can generate this implementation
class UserRepositoryImpl {
  async save(user) {
    // Database implementation
    return await db.users.insert(user);
  }

  async findByEmail(email) {
    return await db.users.findOne({ email });
  }
}
            

AI-Safe Architecture Patterns

1. Interface Segregation

Define clear, small interfaces that AI can implement without breaking the architecture.


// Good: Small, focused interface
interface EmailValidator {
  isValid(email: string): boolean;
}

// Bad: Large interface that's hard to implement correctly
interface UserService {
  createUser(data: any): Promise;
  updateUser(id: string, data: any): Promise;
  deleteUser(id: string): Promise;
  getUser(id: string): Promise;
  listUsers(): Promise;
  // ... many more methods
}
            

2. Dependency Inversion

Use dependency injection to make AI-generated components easily replaceable.


class UserService {
  constructor(
    private userRepository: UserRepository,
    private emailValidator: EmailValidator,
    private logger: Logger
  ) {}

  async createUser(userData: CreateUserRequest): Promise {
    this.logger.info('Creating user', { email: userData.email });
    
    if (!this.emailValidator.isValid(userData.email)) {
      throw new ValidationError('Invalid email format');
    }

    const user = new User(userData);
    return await this.userRepository.save(user);
  }
}
            

AI Integration Guidelines

  • Keep Core Business Logic Human-Written: AI should not modify entities or core business rules
  • Use AI for Implementation Details: Let AI handle database queries, API calls, and utility functions
  • Maintain Clear Boundaries: Define interfaces that AI can implement without breaking architecture
  • Review AI-Generated Code: Always review AI output for architectural compliance

Bibliography

  • Martin, R. C. (2017). "Clean Architecture: A Craftsman's Guide to Software Structure and Design"
  • Martin, R. C. (2009). "Clean Code: A Handbook of Agile Software Craftsmanship"
  • Martin, R. C. (2011). "The Clean Coder: A Code of Conduct for Professional Programmers"
  • Evans, E. (2003). "Domain-Driven Design: Tackling Complexity in the Heart of Software"

Conclusion

Clean Architecture principles remain fundamental in the AI era. By following these guidelines, we can leverage AI's capabilities while maintaining software quality and architectural integrity.

Subscribe to AI.TDD - The New Paradigm of Software Development

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe