🏗️ Refactor architecture to improve maintainability
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 30/100
- issue の種類
- リファクタリング
- 明瞭さ
- おおむね明確
- 活発さ
- 停滞
- 技術スタック
- git, javascript
調査の方向性
まず index.js、utils/sanitizeCommitMessage.js、および claudedocs/quality-analysis-report.md のセクション 1 を読んで、現在の責務を把握してください。変更を加える前に、その構造を提案されている src/ レイアウトおよび実装フェーズと比較してください。記載された受け入れ基準を満たし、既存のテストが成功し、CLI の後方互換性が維持されていれば完了です。
索引モデルが issue の本文から書いたものです。
説明
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
- 主要言語
- JavaScript
- スター
- 36
- フォーク
- 3
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
laststance/git-gpt-commit のほかの issue
-
難易度 5/5 1週間以上 初心者へのやさしさ 20/100
laststance/git-gpt-commit#76 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 25/100
laststance/git-gpt-commit#75 ·
-
enhancement low-priority performance
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
laststance/git-gpt-commit#72 ·
-
enhancement low-priority standards
難易度 5/5 1週間以上 初心者へのやさしさ 25/100
laststance/git-gpt-commit#70 ·
-
documentation good first issue medium-priority
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
laststance/git-gpt-commit#69 ·
laststance/git-gpt-commit の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
メンテナーはふだん 2 日以内に返信
-
area-clientside-dartpad
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
メンテナーはふだん 2 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
alphagov/public-asset-checker#378 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
S: triage
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
メンテナーはふだん 2 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
apache/rocketmq-dashboard#7242 ·
メンテナーはふだん 3 日以内に返信