🏗️ Refactor architecture to improve maintainability
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 30/100
- Loại issue
- Tái cấu trúc
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- git, javascript
Hướng nghiên cứu
Bắt đầu bằng cách đọc index.js, utils/sanitizeCommitMessage.js và phần 1 của claudedocs/quality-analysis-report.md để lập bản đồ các trách nhiệm hiện tại. Hãy so sánh cấu trúc đó với bố cục src/ được đề xuất và các giai đoạn triển khai trước khi thực hiện thay đổi. Công việc được xem là hoàn tất khi các tiêu chí chấp nhận đã nêu được đáp ứng, các bài kiểm thử hiện có đều chạy thành công và CLI vẫn tương thích ngược.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Problem
The current architecture has all logic in a single 389-line index.js file with multiple responsibilities, making it difficult to maintain and test.
Current issues:
- Single file handles: CLI routing, OpenAI API, config I/O, git operations, user prompts
- Global mutable state (
openai,model,language,apiKey) gitExtension()function is 202 lines (lines 184-386)gptCommit()mixes business logic with I/O operations- Hard to test components in isolation
Current Structure
index.js (389 lines)
├─ Global variables (state)
├─ saveConfig() / loadConfig()
├─ maskApiKey()
├─ getGitSummary()
├─ gptCommit()
└─ gitExtension() (CLI setup)
utils/
└─ sanitizeCommitMessage.js
Proposed Modular Structure
src/
├─ index.js # Entry point (~50 lines)
├─ cli/
│ ├─ commands/
│ │ ├─ commit.js # Commit command handler
│ │ ├─ model.js # Model selection command
│ │ ├─ language.js # Language selection command
│ │ ├─ prefix.js # Prefix toggle command
│ │ ├─ apiKey.js # API key management command
│ │ └─ config.js # Config display command
│ └─ index.js # CLI setup with Commander
├─ services/
│ ├─ OpenAIService.js # OpenAI API interactions
│ ├─ GitService.js # Git operations
│ └─ ConfigService.js # Configuration management
├─ prompts/
│ ├─ modelSelection.js # Model selection prompt
│ ├─ languageSelection.js # Language selection prompt
│ ├─ confirmCommit.js # Commit confirmation prompt
│ └─ apiKeyPrompts.js # API key prompts
└─ utils/
├─ sanitizeCommitMessage.js
└─ validators.js # Input validation utilities
Example Refactoring
Before (index.js - mixed concerns):
const gptCommit = async () => {
const gitSummary = await getGitSummary()
if (!gitSummary) {
console.log('No changes to commit. Commit canceled.')
process.exit(0)
}
const messages = [ /* ... */ ]
const parameters = { /* ... */ }
const response = await openai.chat.completions.create(parameters)
const message = response.choices[0].message.content.trim()
const sanitizedMessage = sanitizeCommitMessage(message)
const confirm = await prompts({ /* ... */ })
if (confirm.value) {
execSync(`git commit -m "${sanitizedMessage}"`)
console.log('Committed with the suggested message.')
} else {
console.log('Commit canceled.')
}
}
After (separation of concerns):
// src/services/OpenAIService.js
export class OpenAIService {
constructor(apiKey, model, language) {
this.openai = new OpenAI({ apiKey })
this.model = model
this.language = language
}
async generateCommitMessage(gitDiff, usePrefix) {
const messages = this.buildMessages(gitDiff, usePrefix)
const response = await this.callWithRetry({
model: this.model,
messages
})
return response.choices[0].message.content.trim()
}
buildMessages(gitDiff, usePrefix) { /* ... */ }
async callWithRetry(params, retries = 3) { /* ... */ }
}
// src/services/GitService.js
export class GitService {
async getStagedDiff() {
const { stdout } = await exec(
"git diff --cached -- . ':(exclude)*lock.json' ':(exclude)*lock.yaml'"
)
return stdout.trim() || null
}
async commit(message) {
execSync(`git commit -m "${message}"`)
}
}
// src/cli/commands/commit.js
export async function commitCommand(config) {
const gitService = new GitService()
const openaiService = new OpenAIService(
config.apiKey,
config.model,
config.language
)
const gitDiff = await gitService.getStagedDiff()
if (!gitDiff) {
console.log('No changes to commit.')
return
}
const message = await openaiService.generateCommitMessage(
gitDiff,
config.prefixEnabled
)
const sanitized = sanitizeCommitMessage(message)
if (await confirmCommitPrompt(sanitized)) {
await gitService.commit(sanitized)
console.log('✅ Committed successfully.')
} else {
console.log('Commit canceled.')
}
}
Benefits
- ✅ Single Responsibility: Each module has one clear purpose
- ✅ Testability: Easy to test components in isolation
- ✅ Maintainability: Easier to locate and modify functionality
- ✅ Scalability: Simple to add new commands and features
- ✅ Reusability: Services can be reused across commands
- ✅ State Management: Eliminate global mutable state
Implementation Plan
Phase 1: Extract Services (Week 1)
- Create
src/services/OpenAIService.js - Create
src/services/GitService.js - Create
src/services/ConfigService.js - Add tests for each service
- Update index.js to use services
Phase 2: Extract Commands (Week 2)
- Create
src/cli/commands/directory - Extract each command to separate file
- Add tests for command handlers
- Update CLI setup to use command files
Phase 3: Extract Prompts (Week 3)
- Create
src/prompts/directory - Extract prompt logic from commands
- Add tests for prompts
- Update commands to use prompt modules
Phase 4: Cleanup (Week 4)
- Remove global state from index.js
- Update all imports and exports
- Run full test suite
- Update documentation
- Verify backward compatibility
Acceptance Criteria
- index.js reduced to < 100 lines (entry point only)
- Each service/command file < 200 lines
- No global mutable state
- 100% test coverage for new services
- All existing tests pass
- No breaking changes to CLI interface
Priority
High - Enables future development and maintenance
Related
Quality analysis report: claudedocs/quality-analysis-report.md section 1
Migration Notes
- Maintain backward compatibility during refactoring
- Use feature flags if needed for gradual rollout
- Document breaking changes clearly
- Update CLAUDE.md with new architecture
- Ngôn ngữ chính
- JavaScript
- Star
- 36
- Fork
- 3
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của laststance/git-gpt-commit
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 20/100
laststance/git-gpt-commit#76 ·
-
fix error with giant diffĐang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 25/100
laststance/git-gpt-commit#75 ·
-
enhancement low-priority performance
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
laststance/git-gpt-commit#72 ·
-
enhancement low-priority standards
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
laststance/git-gpt-commit#70 ·
-
documentation good first issue medium-priority
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
laststance/git-gpt-commit#69 ·
Tất cả issue của laststance/git-gpt-commit
Issue tương tự
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 85/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
vercel-labs/agent-skills#348 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
NanmiCoder/dsh-agent-teams#289 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 70/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 83/100
c1overzz/dsh-bili-scroll#124 ·
Maintainer thường phản hồi trong vòng 1 ngày