Pattern Detection
Documentation for pattern detection
Pattern Detection
VDK's pattern detection system is one of its most powerful features, automatically identifying architectural patterns, design patterns, and coding conventions in your codebase to generate intelligent AI assistant rules.
Overview
Pattern detection analyzes your project to identify:
- Architectural Patterns: High-level system organization (MVC, MVVM, microservices)
- Design Patterns: Common programming patterns (Singleton, Factory, Observer)
- Framework Patterns: Framework-specific patterns (React hooks, Django models)
- Organizational Patterns: Code organization and structure patterns
- Custom Patterns: Project-specific patterns and conventions
How Pattern Detection Works
1. File Structure Analysis
VDK examines your directory structure to identify organizational patterns:
src/
├── components/ # Component-based architecture
│ ├── ui/ # Atomic design pattern
│ ├── layout/ # Layout components
│ └── features/ # Feature-based organization
├── hooks/ # Custom hooks pattern
├── services/ # Service layer pattern
├── stores/ # State management pattern
└── utils/ # Utility pattern
Detected Patterns:
- Component-based architecture
- Atomic design system
- Feature-based organization
- Custom hooks pattern
- Service layer separation
2. Code Analysis
Static analysis of code files to identify programming patterns:
// Singleton pattern detection
class DatabaseConnection {
private static instance: DatabaseConnection;
static getInstance(): DatabaseConnection {
if (!DatabaseConnection.instance) {
DatabaseConnection.instance = new DatabaseConnection();
}
return DatabaseConnection.instance;
}
}
// Factory pattern detection
class ComponentFactory {
createComponent(type: string): Component {
switch (type) {
case 'button': return new ButtonComponent();
case 'input': return new InputComponent();
default: throw new Error('Unknown component type');
}
}
}
// Observer pattern detection
class EventEmitter {
private listeners: Map<string, Function[]> = new Map();
on(event: string, callback: Function): void {
// Observer pattern implementation
}
}
3. Framework-Specific Analysis
Recognition of framework-specific patterns and conventions:
React Patterns
// Custom hooks pattern
function useUserData(userId: string) {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchUser(userId).then(setUser).finally(() => setLoading(false));
}, [userId]);
return { user, loading };
}
// Higher-Order Component pattern
function withAuth<T extends object>(Component: React.ComponentType<T>) {
return function AuthenticatedComponent(props: T) {
const { isAuthenticated } = useAuth();
if (!isAuthenticated) {
return <LoginForm />;
}
return <Component {...props} />;
};
}
// Render props pattern
function DataProvider({ children }: { children: (data: Data) => ReactNode }) {
const [data, setData] = useState<Data>();
return children(data);
}
Next.js Patterns
// App Router patterns
export default async function UserPage({ params }: { params: { id: string } }) {
const user = await getUser(params.id); // Server component data fetching
return <UserProfile user={user} />;
}
// Server actions pattern
'use server'
export async function createUser(formData: FormData) {
const name = formData.get('name') as string;
const user = await prisma.user.create({ data: { name } });
revalidatePath('/users');
return user;
}
// Route handlers pattern
export async function GET(request: NextRequest) {
const users = await prisma.user.findMany();
return NextResponse.json(users);
}
Detected Pattern Categories
Architectural Patterns
MVC (Model-View-Controller)
Detection Criteria:
- Separate model, view, controller directories
- Clear separation of concerns
- Data flow from model through controller to view
Example Structure:
├── models/ # Data models
├── views/ # View components
├── controllers/ # Business logic
└── routes/ # Route definitions
MVVM (Model-View-ViewModel)
Detection Criteria:
- ViewModel layer between model and view
- Data binding patterns
- Reactive state management
Example Structure:
├── models/ # Data models
├── views/ # UI components
├── viewmodels/ # View models
└── services/ # Data services
Component-Based Architecture
Detection Criteria:
- Component-centric organization
- Reusable component patterns
- Component composition
Example Structure:
├── components/
│ ├── ui/ # Base components
│ ├── layout/ # Layout components
│ └── features/ # Feature components
Microservices
Detection Criteria:
- Service-oriented directory structure
- Independent service modules
- API gateway patterns
Example Structure:
├── services/
│ ├── auth/ # Authentication service
│ ├── users/ # User service
│ └── orders/ # Order service
└── gateway/ # API gateway
Design Patterns
Repository Pattern
// Pattern detection criteria
interface UserRepository {
findById(id: string): Promise<User | null>;
findAll(): Promise<User[]>;
create(user: CreateUserInput): Promise<User>;
update(id: string, user: UpdateUserInput): Promise<User>;
delete(id: string): Promise<void>;
}
class DatabaseUserRepository implements UserRepository {
// Implementation
}
Factory Pattern
// Pattern detection criteria
abstract class ComponentFactory {
abstract createComponent(type: string): Component;
}
class UIComponentFactory extends ComponentFactory {
createComponent(type: string): Component {
// Factory implementation
}
}
Dependency Injection
// Pattern detection criteria
class UserService {
constructor(
private userRepository: UserRepository,
private emailService: EmailService
) {}
}
// Container or IoC patterns
const container = new Container();
container.bind(UserRepository).to(DatabaseUserRepository);
Framework-Specific Patterns
React Patterns
Custom Hooks Pattern:
// Detection: Functions starting with 'use' that use React hooks
function useApi<T>(url: string): { data: T | null; loading: boolean; error: Error | null } {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}
Context Pattern:
// Detection: createContext usage with Provider components
const UserContext = createContext<User | null>(null);
export function UserProvider({ children }: { children: ReactNode }) {
const [user, setUser] = useState<User | null>(null);
return (
<UserContext.Provider value={user}>
{children}
</UserContext.Provider>
);
}
Compound Components:
// Detection: Components with sub-components as static properties
function Accordion({ children }: { children: ReactNode }) {
return <div className="accordion">{children}</div>;
}
Accordion.Item = function AccordionItem({ children }: { children: ReactNode }) {
return <div className="accordion-item">{children}</div>;
};
Accordion.Header = function AccordionHeader({ children }: { children: ReactNode }) {
return <div className="accordion-header">{children}</div>;
};
Next.js Patterns
App Router Pattern:
// Detection: app/ directory with page.tsx, layout.tsx files
app/
├── layout.tsx # Root layout
├── page.tsx # Home page
├── users/
│ ├── page.tsx # Users page
│ └── [id]/
│ └── page.tsx # Dynamic user page
└── api/
└── users/
└── route.ts # API route
Server Components Pattern:
// Detection: Async components without 'use client'
export default async function UsersList() {
const users = await getUsers(); // Server-side data fetching
return (
<div>
{users.map(user => (
<UserCard key={user.id} user={user} />
))}
</div>
);
}
Server Actions Pattern:
// Detection: 'use server' directive with form actions
'use server'
export async function createUser(formData: FormData) {
const name = formData.get('name') as string;
const email = formData.get('email') as string;
const user = await prisma.user.create({
data: { name, email }
});
revalidatePath('/users');
redirect(`/users/${user.id}`);
}
State Management Patterns
Redux Pattern
// Detection: Actions, reducers, store structure
// Actions
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
// Action creators
const increment = () => ({ type: INCREMENT });
const decrement = () => ({ type: DECREMENT });
// Reducer
function counterReducer(state = { count: 0 }, action) {
switch (action.type) {
case INCREMENT:
return { count: state.count + 1 };
case DECREMENT:
return { count: state.count - 1 };
default:
return state;
}
}
Zustand Pattern
// Detection: create() function with store definition
import { create } from 'zustand';
interface UserState {
users: User[];
addUser: (user: User) => void;
removeUser: (id: string) => void;
}
const useUserStore = create<UserState>((set) => ({
users: [],
addUser: (user) => set((state) => ({ users: [...state.users, user] })),
removeUser: (id) => set((state) => ({ users: state.users.filter(u => u.id !== id) })),
}));
Pattern Detection Configuration
Enable/Disable Pattern Categories
Configure which patterns to detect in vdk.config.json
:
{
"scanner": {
"patternDetection": {
"architectural": {
"enabled": true,
"patterns": ["mvc", "mvvm", "component-based", "microservices", "layered"]
},
"design": {
"enabled": true,
"patterns": ["singleton", "factory", "observer", "repository", "strategy"]
},
"framework": {
"enabled": true,
"react": ["hooks", "context", "hoc", "render-props"],
"nextjs": ["app-router", "server-components", "server-actions"],
"express": ["middleware", "routing", "controllers"]
},
"organizational": {
"enabled": true,
"patterns": ["feature-based", "atomic-design", "domain-driven"]
}
}
}
}
Custom Pattern Detection
Define custom patterns for your project:
{
"scanner": {
"customPatterns": [
{
"name": "API Response Pattern",
"description": "Standardized API response structure",
"criteria": {
"filePattern": "**/*api*.ts",
"codePattern": "interface.*Response.*{.*data:.*message:.*success:",
"examples": ["ApiResponse", "DataResponse", "ErrorResponse"]
}
},
{
"name": "Error Handling Pattern",
"description": "Custom error handling utilities",
"criteria": {
"filePattern": "**/error*.ts",
"codePattern": "class.*Error.*extends.*Error",
"examples": ["ValidationError", "NotFoundError", "UnauthorizedError"]
}
}
]
}
}
Pattern Analysis Output
Pattern Report
VDK generates detailed pattern analysis:
{
"patternAnalysis": {
"architectural": {
"primary": "Component-based",
"secondary": ["Feature-based organization"],
"confidence": 0.95
},
"design": {
"detected": [
{
"pattern": "Repository Pattern",
"files": ["lib/repositories/user.ts", "lib/repositories/post.ts"],
"confidence": 0.9
},
{
"pattern": "Factory Pattern",
"files": ["lib/factories/component-factory.ts"],
"confidence": 0.85
}
]
},
"framework": {
"react": {
"hooks": {
"custom": ["useUser", "useAuth", "useApi"],
"usage": "extensive"
},
"context": {
"providers": ["UserProvider", "ThemeProvider"],
"usage": "moderate"
}
},
"nextjs": {
"appRouter": true,
"serverComponents": "primary",
"serverActions": "moderate"
}
},
"organizational": {
"structure": "Feature-based",
"consistency": 0.92,
"adherence": "high"
}
}
}
Generated Rules Based on Patterns
VDK creates specific rules based on detected patterns:
Repository Pattern Rules
# Repository Pattern
## Pattern Usage
This project uses the Repository pattern for data access abstraction.
## Implementation Guidelines
- Create repository interfaces for each entity
- Implement concrete repositories for different data sources
- Use dependency injection for repository instances
## Example Implementation
```typescript
interface UserRepository {
findById(id: string): Promise<User | null>;
findAll(): Promise<User[]>;
create(user: CreateUserInput): Promise<User>;
}
class PrismaUserRepository implements UserRepository {
constructor(private prisma: PrismaClient) {}
async findById(id: string): Promise<User | null> {
return this.prisma.user.findUnique({ where: { id } });
}
}
#### Custom Hooks Rules
```markdown
# Custom Hooks Pattern
## Hook Conventions
- Prefix all custom hooks with 'use'
- Return objects for multiple values
- Handle cleanup in useEffect
## Example Custom Hook
```typescript
function useUserData(userId: string) {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
let cancelled = false;
fetchUser(userId)
.then(user => {
if (!cancelled) {
setUser(user);
setError(null);
}
})
.catch(error => {
if (!cancelled) {
setError(error);
}
})
.finally(() => {
if (!cancelled) {
setLoading(false);
}
});
return () => {
cancelled = true;
};
}, [userId]);
return { user, loading, error };
}
## Advanced Pattern Detection
### Cross-File Pattern Analysis
VDK analyzes relationships between files to detect complex patterns:
```typescript
// File: services/user-service.ts
export class UserService {
constructor(private userRepo: UserRepository) {}
async createUser(data: CreateUserInput): Promise<User> {
return this.userRepo.create(data);
}
}
// File: repositories/user-repository.ts
export interface UserRepository {
create(data: CreateUserInput): Promise<User>;
}
// File: repositories/prisma-user-repository.ts
export class PrismaUserRepository implements UserRepository {
// Implementation
}
// Detected Pattern: Service + Repository + Dependency Injection
Temporal Pattern Analysis
Detecting patterns that evolve over time:
// Version 1: Simple component
function UserCard({ user }) {
return <div>{user.name}</div>;
}
// Version 2: Enhanced with props interface
interface UserCardProps {
user: User;
}
function UserCard({ user }: UserCardProps) {
return <div>{user.name}</div>;
}
// Version 3: Added error handling
function UserCard({ user }: UserCardProps) {
if (!user) return <div>User not found</div>;
return <div>{user.name}</div>;
}
// Detected Evolution: Progressive enhancement pattern
Anti-Pattern Detection
VDK can also identify anti-patterns to avoid:
// Anti-pattern: Prop drilling
function App() {
const user = useUser();
return <Dashboard user={user} />;
}
function Dashboard({ user }: { user: User }) {
return <Sidebar user={user} />;
}
function Sidebar({ user }: { user: User }) {
return <UserMenu user={user} />;
}
// Suggestion: Use Context or state management
Pattern-Based Rule Generation
Intelligent Rule Creation
VDK generates rules that match your detected patterns:
- Pattern Recognition: Identifies specific patterns in use
- Context Analysis: Understands how patterns are implemented
- Rule Generation: Creates guidelines that match your style
- Example Creation: Provides examples based on your actual code
Dynamic Rule Updates
As patterns evolve, VDK updates rules accordingly:
# After adding new patterns
vdk init --overwrite
# Update AI memory with new patterns
vdk claude-code --update-memory
# Check pattern analysis
vdk analyze --patterns
Best Practices for Pattern Detection
1. Maintain Consistent Patterns
// ✅ Consistent repository pattern
interface UserRepository {
findById(id: string): Promise<User | null>;
}
interface PostRepository {
findById(id: string): Promise<Post | null>;
}
// ❌ Inconsistent naming
interface UserRepo {
getUser(id: string): Promise<User | null>;
}
interface PostService {
findPost(id: string): Promise<Post | null>;
}
2. Document Pattern Decisions
/**
* Repository Pattern Implementation
*
* We use the Repository pattern to abstract data access logic.
* Each entity has its own repository interface and implementation.
* This allows for easier testing and data source switching.
*/
export interface UserRepository {
// Interface definition
}
3. Use TypeScript for Better Detection
TypeScript provides better pattern detection through type information:
// Better pattern detection with TypeScript
interface ApiResponse<T> {
data: T;
message: string;
success: boolean;
}
// Vs. JavaScript (harder to detect patterns)
function createResponse(data, message, success) {
return { data, message, success };
}
Next Steps
- Technology Analysis - Understanding technology detection
- Configuration Guide - Configure pattern detection
- Rule Generation - How patterns become rules
- Custom Patterns - Define custom patterns