{ "dimension": "architecture", "prefix": "ARCH", "description": "Rules for detecting architecture issues including coupling, layering, and design patterns", "rules": [ { "id": "circular-dependency", "category": "dependency", "severity": "high", "pattern": "import\\s+.*from\\s+['\"]\\.\\..*['\"]", "patternType": "regex", "contextPattern": "export.*import.*from.*same-module", "description": "Potential circular dependency detected. Circular imports cause initialization issues and tight coupling", "recommendation": "Extract shared code to a separate module, use dependency injection, or restructure the dependency graph", "fixExample": "// Before - A imports B, B imports A\n// moduleA.ts\nimport { funcB } from './moduleB';\nexport const funcA = () => funcB();\n\n// moduleB.ts\nimport { funcA } from './moduleA'; // circular!\n\n// After - extract shared logic\n// shared.ts\nexport const sharedLogic = () => { ... };\n\n// moduleA.ts\nimport { sharedLogic } from './shared';" }, { "id": "god-class", "category": "single-responsibility", "severity": "high", "pattern": "class\\s+\\w+\\s*\\{", "patternType": "regex", "methodThreshold": 15, "lineThreshold": 300, "description": "Class with too many methods or lines violates single responsibility principle", "recommendation": "Split into smaller, focused classes. Each class should have one reason to change", "fixExample": "// Before - UserManager handles everything\nclass UserManager {\n createUser() { ... }\n updateUser() { ... }\n sendEmail() { ... }\n generateReport() { ... }\n validatePassword() { ... }\n}\n\n// After - separated concerns\nclass UserRepository { create, update, delete }\nclass EmailService { sendEmail }\nclass ReportGenerator { generate }\nclass PasswordValidator { validate }" }, { "id": "layer-violation", "category": "layering", "severity": "high", "pattern": "import.*(?:repository|database|sql|prisma|mongoose).*from", "patternType": "regex", "contextPath": ["controller", "handler", "route", "component"], "description": "Direct database access from presentation layer violates layered architecture", "recommendation": "Access data through service/use-case layer. Keep controllers thin and delegate to services", "fixExample": "// Before - controller accesses DB directly\nimport { prisma } from './database';\nconst getUsers = async () => prisma.user.findMany();\n\n// After - use service layer\nimport { userService } from './services';\nconst getUsers = async () => userService.getAll();" }, { "id": "missing-interface", "category": "abstraction", "severity": "medium", "pattern": "new\\s+\\w+Service\\(|new\\s+\\w+Repository\\(", "patternType": "regex", "negativePatterns": ["interface", "implements", "inject"], "description": "Direct instantiation of services/repositories creates tight coupling", "recommendation": "Define interfaces and use dependency injection for loose coupling and testability", "fixExample": "// Before - tight coupling\nclass OrderService {\n private repo = new OrderRepository();\n}\n\n// After - loose coupling\ninterface IOrderRepository {\n findById(id: string): Promise;\n}\n\nclass OrderService {\n constructor(private repo: IOrderRepository) {}\n}" }, { "id": "mixed-concerns", "category": "separation-of-concerns", "severity": "medium", "pattern": "fetch\\s*\\(|axios\\.|http\\.", "patternType": "regex", "contextPath": ["component", "view", "page"], "description": "Network calls in UI components mix data fetching with presentation", "recommendation": "Extract data fetching to hooks, services, or state management layer", "fixExample": "// Before - fetch in component\nfunction UserList() {\n const [users, setUsers] = useState([]);\n useEffect(() => {\n fetch('/api/users').then(r => r.json()).then(setUsers);\n }, []);\n}\n\n// After - custom hook\nfunction useUsers() {\n return useQuery('users', () => userService.getAll());\n}\n\nfunction UserList() {\n const { data: users } = useUsers();\n}" } ] }