Files
calendar/agents/rules/patterns-factory-pattern.md
Benny JooGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
ab21c7f805 refactor: Cal.diy (#28903)
* feat: Cal.diy — community-driven MIT-licensed fork of Cal.com

This squashed commit contains all Cal.diy changes applied on top of calcom/cal.com main:

- Rebrand Cal.com to Cal.diy across the entire codebase
- Remove Enterprise Edition (EE) features, license checks, and AGPL restrictions
- Switch license from AGPL-3.0 to MIT
- Remove docs/ directory (migrated to Nextra at cal.diy)
- Remove dead code: org tests, EE tips, platform nav, premium username, SAML/SSO, etc.
- Clean up .env.example for self-hosted Cal.diy
- Update Docker image references to calcom/cal.diy
- Update README, CONTRIBUTING.md, and issue templates for Cal.diy community fork
- Add PR welcome bot for Cal.diy contributors
- Fix API v2 breaking changes oasdiff ignore entries
- Replace Blacksmith CI runners with default GitHub Actions

3893 files changed, 20789 insertions(+), 411020 deletions(-)

Co-Authored-By: [email protected] <[email protected]>

* refactor: remove org-specific /organizations/:orgId endpoints from API v2 atoms controllers (#1701)

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix: revert Cal.diy Inc to Cal.com, Inc. in license files, copyright notices, and package metadata (#1702)

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* rip out org related comments in api v2

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-04-15 09:52:36 -03:00

2.9 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
Use Factory Pattern to Push Conditionals to Entry Points HIGH Keeps services focused and prevents complexity accumulation patterns, factory, conditionals, single-responsibility

Use Factory Pattern to Push Conditionals to Entry Points

Impact: HIGH

If statements belong at the entry point, not scattered throughout your services. This is one of the most important architectural principles for maintaining clean, focused code that doesn't spiral into unmaintainable complexity.

The problem with scattered conditionals: A service is written for a clear, specific purpose. Then a new product requirement arrives, and someone adds an if statement. A few years later, that service is littered with conditional checks. The service becomes:

  • Complicated and hard to read
  • Difficult to understand and reason about
  • More susceptible to bugs
  • Violating single responsibility
  • Nearly impossible to test thoroughly

Incorrect (conditionals scattered in service):

class BillingService {
  async processPayment(entityId: number, entityType: string) {
    if (entityType === "organization") {
      // Organization-specific logic
      const org = await this.getOrganization(entityId);
      if (org.billingPlan === "enterprise") {
        // More nested conditionals...
      }
    } else if (entityType === "team") {
      // Team-specific logic
    } else if (entityType === "user") {
      // User-specific logic
    }
  }
}

Correct (Factory pattern with specialized services):

// Factory makes the decision at entry point
class BillingServiceFactory {
  static async createService(entityId: number): Promise<BillingService> {
    const entity = await determineEntityType(entityId);
    
    switch (entity.type) {
      case "organization":
        return new OrganizationBillingService(entity);
      case "team":
        return new TeamBillingService(entity);
      default:
        return new UserBillingService(entity);
    }
  }
}

// Each service handles ONLY its specific logic - no conditionals
class OrganizationBillingService extends BillingService {
  async processPayment() {
    // Only organization logic here - clean and focused
  }
}

class TeamBillingService extends BillingService {
  async processPayment() {
    // Only team logic here - clean and focused
  }
}

Benefits:

  • Services stay focused with one responsibility
  • Changes are isolated to specific service implementations
  • Testing is straightforward - test each service independently
  • New requirements don't pollute existing code

Guidelines:

  • Push conditionals up to controllers, factories, or routing logic
  • Keep services pure and focused on a single responsibility
  • Prefer polymorphism over conditionals
  • Watch for if statement accumulation during code review

Reference: Cal.diy Engineering Blog