convention-refactor
Convention Refactor
Refactor existing code to comply with Sellernote conventions. Changes are structural/pattern-only -- business logic must remain unchanged.
Convention Loading
Conventions are loaded dynamically based on the target files. Before starting, Read the relevant reference files from references/ within this skill directory.
Loading Strategy
-
Always read (apply to all refactoring):
references/COMMON_CONVENTION.md- Naming, error handlingreferences/TYPESCRIPT_CONVENTION.md- TS style, imports, types
-
Read when refactoring backend files:
references/BACKEND_CONVENTION.md- 3-layer architecture, namingreferences/BACKEND_ARCHITECTURE_CONVENTION.md- Layer responsibilitiesreferences/NESTJS_CONVENTION.md- NestJS patterns, decoratorsreferences/API_SPEC_CONVENTION.md- Endpoint designreferences/SECURITY_CONVENTION.md- Auth, guardsreferences/TYPEORM_CONVENTION.md- Entity patternsreferences/DATABASE_CONVENTION.md- DB modelingreferences/MYSQL_CONVENTION.md- MySQL-specific rulesreferences/PRISMA_CONVENTION.md- Prisma schema patterns, client usage
-
Read when refactoring frontend files:
references/FRONTEND_CONVENTION.md- Frontend common rulesreferences/FRONTEND_ARCHITECTURE_CONVENTION.md- Component typesreferences/NEXTJS_CONVENTION.md- App Router patternsreferences/STATE_CONVENTION.md- State managementreferences/STYLING_CONVENTION.md- Tailwind CSS v4, cn(), DS componentsreferences/FORM_CONVENTION.md- Form patternsreferences/TESTING_CONVENTION.md- Test patterns (Vitest, Storybook, RTL, Playwright)references/REACT_CONVENTION.md- React 19 patterns, hooks, performance, anti-patternsreferences/REACT_ROUTER_CONVENTION.md- React Router 7 Framework Mode, route modulesreferences/API_CLIENT_CONVENTION.md- API client common rules, token managementreferences/API_CLIENT_AXIOS_CONVENTION.md- Axios implementation, interceptors
Workflow
Step 1: Determine Refactoring Scope
Identify what needs refactoring from one of these sources:
| Source | How to Identify |
|---|---|
| convention-code-review output | User pastes or references a review report |
| Specific files | User points to file(s) or directory |
| Specific rule | User names a convention rule to apply |
| Entire module | User asks to align a module with conventions |
List all files that will be touched and classify them (backend/frontend/common).
Step 2: Analyze Current State
For each file in scope:
- Read the file completely
- Identify all convention violations (use same checklist as
convention-code-review) - Classify violations by severity: MUST -> SHOULD -> RECOMMEND
- Note any business logic that must be preserved during refactoring
Step 3: Present Refactoring Plan
[MUST] Always present the plan to the user before making any changes.
## Refactoring Plan
### Files to modify: N
### Changes (in execution order):
#### 1. [MUST] Extract business logic from Controller to Service
- File: `src/modules/order/order.controller.ts`
- Current: Lines 25-50 contain price calculation logic
- Change: Move calculation to `OrderService.calculateTotal()`
- Impact: Controller becomes thinner, Service gains method
#### 2. [MUST] Replace raw @ApiProperty with @SellernoteApi* decorators
- File: `src/modules/order/dto/create-order.dto.ts`
- Current: Uses `@ApiProperty()` and `@IsString()` from class-validator
- Change: Replace with `@SellernoteApiString()`, `@SellernoteApiDecimal()`
- Impact: Same validation behavior, unified decorator pattern
#### 3. [MUST] Change money fields from number to string + big.js
- Files: `create-order.dto.ts`, `order.service.ts`, `order-response.dto.ts`
- Current: `totalAmount: number` with native arithmetic
- Change: `totalAmount: string` + `@SellernoteApiDecimal` + `big.js` arithmetic
- Impact: API contract change (number -> string for money fields)
...
### Shall I proceed? (y/n)
Wait for user confirmation before applying any changes.
Step 4: Apply Changes Incrementally
Apply changes one convention rule at a time, in severity order:
- MUST violations first (architecture-breaking issues)
- SHOULD violations second (strong recommendations)
- RECOMMEND violations last (nice-to-haves)
Within each severity level, apply in this order:
Backend Refactoring Patterns
Controller -> Service extraction:
Before: Controller contains business logic
After: Controller delegates to Service; logic moved to Service method
- Move calculation, validation, and data transformation logic to Service
- Keep only HTTP concerns (parameter extraction, response mapping) in Controller
Service -> Repository extraction:
Before: Service contains raw QueryBuilder or TypeORM repository calls
After: Service calls Repository methods; queries moved to Repository
- Move
createQueryBuilder(),find(),findOne()chains to Repository - Service calls named Repository methods instead
QueryRunner -> @Transactional():
Before: Manual QueryRunner with try/catch/finally
After: @Transactional() decorator on Service method
- Remove QueryRunner injection and manual transaction management
- Add
@Transactional()decorator to the Service method - Remove
try { await queryRunner.startTransaction() }pattern
number -> big.js for money:
Before: totalAmount: number; total = price * quantity;
After: totalAmount: string; total = new Big(price).times(quantity).toFixed(2);
- Change type from
numbertostringin DTOs and interfaces - Replace
@SellernoteApiNumberwith@SellernoteApiDecimalin DTOs - Replace native arithmetic with
big.jsoperations in Service - Add
DecimalTransformerto Entity column if applicable
@ApiProperty -> @SellernoteApi:*
Before: @ApiProperty() + @IsString() + @IsNotEmpty()
After: @SellernoteApiString({ description: '...', isRequired: true })
- Replace all
@ApiProperty,@IsString,@IsNumber, etc. - Use corresponding
@SellernoteApi*decorator - Move validation config into decorator options
Entity convention alignment:
Before: Entity with raw TypeORM BaseEntity, native enum, no Relation<>
After: Custom BaseEntity, varchar enum, Relation<T> wrapper
- Change
extends BaseEntityto custom BaseEntity from@/common/entities/base.entity - Change
@Column({ type: 'enum', enum: Status })to@Column({ type: 'varchar', length: 50 }) - Wrap relation types:
user: User->user: Relation<User> - Add
DecimalTransformerto decimal columns
Prisma schema convention alignment:
Before: Schema without @db.* types, missing @@map, missing @@index on FK
After: All fields have @db.*, @@map on models/fields, @@index on all FK columns
- Add
@db.*native type annotations to all fields - Add
@@map("snake_case")to models and@map("snake_case")to fields - Add
@@index([fkField])for every FK column - Replace implicit many-to-many with explicit join model
TypeORM to Prisma migration:
Before: TypeORM entities with @Entity, @Column, BaseEntity inheritance
After: Prisma schema models with @@map, @db.*, 공통 필드 반복 정의
- Convert TypeORM Entity class to Prisma model in schema.prisma
- Replace BaseEntity inheritance with 공통 필드 반복 정의
- Replace
DecimalTransformerwith Prisma.Decimal handling in service - Replace
@Transactional()withprisma.$transaction() - Replace Repository pattern with direct PrismaService usage
Frontend Refactoring Patterns
Component type-location alignment:
Before: Business logic component in components/ui/
After: Moved to components/feature/ with 'use client'
- Move components that use hooks/store/queries to
components/feature/ - Keep pure presentational components in
components/ui/
Dependency direction fix:
Before: UI component imports from store/queries
After: UI component receives data via props; Feature component provides data
- Extract store/query usage into parent Feature component
- Pass data down as props to UI component
'use client' placement:
Before: 'use client' on page.tsx or layout component
After: 'use client' only on leaf Feature components
- Remove
'use client'frompage.tsxand layout files - Add
'use client'to Feature components that use client-side hooks
Design token application:
Before: className="text-[#1976d2] p-[16px]"
After: className="text-primary-main p-4"
- Replace hardcoded hex colors with design token references
- Replace arbitrary values with Tailwind utility classes
- Use
cn()for conditional className merging
Query pattern alignment:
Before: useEffect + fetch for data loading
After: TanStack Query hook with query-key-factory
- Create query key factory in
queries/queryKeys/ - Create custom query hook using
useQuery() - Remove manual
useEffect+useStatedata fetching pattern
Step 5: Verify No Business Logic Changes
After all changes are applied, verify:
- All existing API endpoints still accept the same inputs
- All existing API endpoints still return the same outputs (except money type changes if applicable)
- Business rules and calculations produce the same results
- No new features or behaviors were introduced
- No existing features or behaviors were removed
If money fields changed from number to string, explicitly note this as an intentional API contract change required by convention.
Step 6: Generate Summary Report
## Refactoring Summary
### Changes Applied
- [MUST] 3 violations fixed
- [SHOULD] 2 violations fixed
- [RECOMMEND] 1 violation fixed
### Files Modified
1. `order.controller.ts` - Extracted business logic to Service
2. `order.service.ts` - Added big.js for money, @Transactional()
3. `create-order.dto.ts` - Replaced @ApiProperty with @SellernoteApi*
4. `order.entity.ts` - Added Relation<>, DecimalTransformer
### API Contract Changes
- `POST /orders` body: `totalAmount` changed from `number` to `string`
- `GET /orders/:id` response: `totalAmount` changed from `number` to `string`
### Remaining Violations (not addressed)
- None / [List any skipped items with reason]
Key Rules Summary
| Rule | Detail |
|---|---|
| MUST | Never change business logic -- only structural/pattern changes |
| MUST | Present plan before any changes -- get user confirmation |
| MUST | Apply incrementally -- one convention rule at a time |
| MUST | Fix MUST violations before SHOULD, SHOULD before RECOMMEND |
| MUST | Verify behavior preservation after changes |
| MUST | Report any API contract changes explicitly |
| MUST NOT | Add new features or functionality during refactoring |
| MUST NOT | Remove existing features or functionality during refactoring |
Cross-Skill References
- Identify violations: Use the
convention-code-reviewskill to get a full violation report first - NestJS implementation details: Use
nestjs-api-devfor correct NestJS patterns - Entity/TypeORM patterns: Use
typeorm-devfor Entity refactoring details - Frontend UI patterns: Use
nextjs-ui-devfor correct component patterns - Data layer patterns: Use
nextjs-data-providerfor query/state refactoring - Prisma schema/client patterns: Use
prisma-devfor Prisma-specific refactoring - PR 생성: Use the
github-prskill to create a GitHub pull request