JA Development Guides Code Styles - aku11i/phantom GitHub Wiki
English | 日本語
このガイドでは、Phantomのコーディング規約とスタイルガイドラインを文書化しています。これらに従うことで、コードベース全体の一貫性が保証されます。
ソース: CLAUDE.md#L10
- コードコメントなし - 自己文書化されたコードを書く
- 既存のパターンに従う - 個人の好みより一貫性
- 英語のみ - すべてのコード、コミット、ドキュメントは英語で
- 型安全性 - TypeScriptを最大限活用
ソース: biome.json
PhantomはフォーマットとリンティングにBiomeを使用します:
{
"formatter": {
"enabled": true,
"indentStyle": "tab",
"indentWidth": 2,
"lineWidth": 100,
"lineEnding": "lf",
"quoteStyle": "double",
"trailingComma": "all",
"semicolons": "always"
}
}
- インデントにはタブを使用
- タブ幅は2スペースとして表示
// ✓ 良い
function example() {
if (condition) {
doSomething();
}
}
// ✗ 悪い - スペース
function example() {
if (condition) {
doSomething();
}
}
- 文字列にはダブルクォートを使用
// ✓ 良い
const message = "Hello, world!";
const html = `<div class="container">`;
// ✗ 悪い
const message = 'Hello, world!';
- 常にセミコロンを使用
// ✓ 良い
const name = "phantom";
import { Result } from "./types.js";
// ✗ 悪い
const name = "phantom"
import { Result } from "./types.js"
- 複数行の構造では末尾のカンマを使用
// ✓ 良い
const config = {
name: "phantom",
version: "1.0.0",
author: "aku11i",
};
// ✗ 悪い
const config = {
name: "phantom",
version: "1.0.0",
author: "aku11i"
};
関数パラメーターと戻り値には常に明示的な型を使用:
// ✓ 良い
function createWorktree(name: string, branch?: string): Promise<Result<WorktreeInfo>> {
// 実装
}
// ✗ 悪い - 型がない
function createWorktree(name, branch) {
// 実装
}
オブジェクトの形状にはinterface
、ユニオンとプリミティブにはtype
を使用:
// ✓ 良い - オブジェクトにはinterface
interface WorktreeInfo {
name: string;
path: string;
branch: string;
isMain: boolean;
}
// ✓ 良い - ユニオンにはtype
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E };
// ✗ 悪い - シンプルなオブジェクトにtype
type WorktreeInfo = {
name: string;
// ...
};
リテラル型にはas const
を使用:
// ✓ 良い
const COMMANDS = ["create", "delete", "list", "exec", "shell"] as const;
type Command = typeof COMMANDS[number];
// ✗ 悪い
const COMMANDS = ["create", "delete", "list", "exec", "shell"];
ソース: src/cli/handlers/create.ts
インポートを一貫して順序付け:
// 1. Node.js組み込み
import { existsSync } from "node:fs";
import { join } from "node:path";
// 2. 外部依存関係(ランタイムにはなし)
// 3. 内部 - 絶対パス
import { Result } from "../../core/types/result.js";
import { createWorktree } from "../../core/worktree/create.js";
// 4. 内部 - 相対パス
import { output } from "../output.js";
インポートには常に.js
拡張子を含める:
// ✓ 良い - ESMは拡張子を必要とする
import { createWorktree } from "./create.js";
// ✗ 悪い - ランタイムで失敗する
import { createWorktree } from "./create";
名前付きエクスポートを使用、デフォルトエクスポートは避ける:
// ✓ 良い - 名前付きエクスポート
export function createWorktree() { }
export function deleteWorktree() { }
// ✗ 悪い - デフォルトエクスポート
export default function createWorktree() { }
camelCaseを使用:
// ✓ 良い
const worktreeName = "feature";
function validateWorktreeName(name: string) { }
// ✗ 悪い
const worktree_name = "feature";
function ValidateWorktreeName(name: string) { }
真の定数にはUPPER_SNAKE_CASEを使用:
// ✓ 良い
const MAX_NAME_LENGTH = 50;
const DEFAULT_BRANCH = "main";
// ✗ 悪い
const maxNameLength = 50;
const default_branch = "main";
PascalCaseを使用:
// ✓ 良い
interface WorktreeInfo { }
type CommandHandler = () => void;
// ✗ 悪い
interface worktreeInfo { }
type commandHandler = () => void;
ファイル名にはkebab-caseを使用:
✓ 良い:
- create-worktree.ts
- git-executor.ts
- list-worktrees.test.ts
✗ 悪い:
- createWorktree.ts
- GitExecutor.ts
- listWorktrees.test.ts
関数は短く、焦点を絞って保つ:
// ✓ 良い - 単一責任
function validateWorktreeName(name: string): Result<void> {
if (!name) {
return Result.error(new Error("Name is required"));
}
if (name.includes("/") || name.includes("..")) {
return Result.error(new Error("Invalid characters in name"));
}
return Result.ok();
}
// ✗ 悪い - やりすぎ
function createAndValidateWorktree(name: string, showOutput: boolean) {
// 検証ロジック
// 作成ロジック
// 出力ロジック
// 責任が多すぎる
}
ネストを減らすために早期リターンを使用:
// ✓ 良い - 早期リターン
function processWorktree(name: string): Result<void> {
if (!name) {
return Result.error(new Error("Name required"));
}
if (invalidCharacters(name)) {
return Result.error(new Error("Invalid name"));
}
// メインロジック
return Result.ok();
}
// ✗ 悪い - ネストした条件
function processWorktree(name: string): Result<void> {
if (name) {
if (!invalidCharacters(name)) {
// メインロジック
return Result.ok();
} else {
return Result.error(new Error("Invalid name"));
}
} else {
return Result.error(new Error("Name required"));
}
}
副作用のない純粋関数を優先:
// ✓ 良い - 純粋関数
function calculatePath(basePath: string, name: string): string {
return join(basePath, name);
}
// ✗ 悪い - 副作用
let globalPath: string;
function calculatePath(basePath: string, name: string): void {
globalPath = join(basePath, name); // 副作用
}
失敗する可能性のある操作には常にResult型を使用:
// ✓ 良い - 明示的なエラーハンドリング
function parseConfig(content: string): Result<Config> {
try {
const config = JSON.parse(content);
return Result.ok(config);
} catch (error) {
return Result.error(new Error(`Invalid config: ${error.message}`));
}
}
// ✗ 悪い - 例外を投げる
function parseConfig(content: string): Config {
return JSON.parse(content); // エラー時にスロー
}
エラーメッセージは役に立つものにする:
// ✓ 良い - 説明的なエラー
return Result.error(
new Error(`Worktree '${name}' already exists at ${path}`)
);
// ✗ 悪い - 曖昧なエラー
return Result.error(new Error("Error"));
プロミスよりasync/awaitを優先:
// ✓ 良い
async function loadConfig(): Promise<Result<Config>> {
const result = await readFile("config.json");
if (!result.ok) {
return result;
}
return parseConfig(result.value);
}
// ✗ 悪い - プロミスチェーン
function loadConfig(): Promise<Result<Config>> {
return readFile("config.json")
.then(result => {
if (!result.ok) {
return result;
}
return parseConfig(result.value);
});
}
async関数でエラーを適切に処理:
// ✓ 良い
async function execute(): Promise<Result<void>> {
try {
await riskyOperation();
return Result.ok();
} catch (error) {
return Result.error(error as Error);
}
}
// ✗ 悪い - 未処理のリジェクション
async function execute(): Promise<void> {
await riskyOperation(); // スローできる
}
各モジュールには明確な目的が1つあるべき:
// ✓ 良い - 焦点を絞ったモジュール
// validate.ts - 検証のみ
export function validateWorktreeName(name: string): Result<void> { }
// create.ts - 作成のみ
export function createWorktree(name: string): Result<WorktreeInfo> { }
// ✗ 悪い - 混在した責任
// worktree.ts - すべてを行う
export function validateAndCreateWorktree() { }
export function formatWorktreeOutput() { }
export function deleteWorktreeWithLogging() { }
依存関係は下向きに流れるべき:
✓ 良い:
CLI → Core → Infrastructure
✗ 悪い:
Core → CLI (上向き依存)
Arrange-Act-Assertパターンに従う:
it("should create worktree with branch", async () => {
// Arrange
const name = "feature";
const branch = "develop";
mockGit.execute.mockReturnValue(Result.ok(""));
// Act
const result = await createWorktree(name, branch);
// Assert
assert.strictEqual(result.ok, true);
if (result.ok) {
assert.strictEqual(result.value.branch, branch);
}
});
説明的なテスト名を使用:
// ✓ 良い
describe("validateWorktreeName", () => {
it("should accept alphanumeric names with hyphens");
it("should reject names with path separators");
it("should reject empty names");
});
// ✗ 悪い
describe("validate", () => {
it("works");
it("fails");
});
コメントの代わりに自己文書化されたコードを書く:
// ✗ 悪い - コメントが必要
// 名前に無効な文字が含まれているかチェック
if (n.indexOf("/") >= 0 || n.indexOf("..") >= 0) {
return false;
}
// ✓ 良い - 自己文書化
const containsPathSeparator = name.includes("/");
const containsParentReference = name.includes("..");
if (containsPathSeparator || containsParentReference) {
return Result.error(new Error("Name cannot contain path separators"));
}
説明的な関数名を使用:
// ✓ 良い
function isValidWorktreeName(name: string): boolean { }
function getWorktreeByName(name: string): Result<WorktreeInfo> { }
// ✗ 悪い
function check(n: string): boolean { }
function get(n: string): Result<WorktreeInfo> { }
従来のコミットに従う:
✓ 良い:
feat: add support for custom worktree paths
fix: handle spaces in repository names
docs: update README with new commands
test: add tests for error scenarios
refactor: extract git operations to separate module
✗ 悪い:
Updated stuff
Fix
Changes
WIP
コミットを焦点を絞って保つ:
✓ 良い:
- コミットごとに1つの論理的な変更
- すべてのテストが合格
- 無関係な変更なし
✗ 悪い:
- 複数の無関係な変更
- 壊れたテスト
- デバッグコードが含まれている
ソース: biome.json
主要なリンティングルール:
{
"linter": {
"rules": {
"recommended": true,
"style": {
"noParameterAssign": "error",
"noVar": "error",
"useConst": "error",
"useTemplate": "warn"
},
"complexity": {
"noForEach": "off",
"useOptionalChain": "warn"
},
"correctness": {
"noUnusedVariables": "error",
"noUnusedImports": "error"
}
}
}
}
# コードをチェック
pnpm lint
# 問題を自動修正
pnpm fix
# 特定のファイルをチェック
npx biome check src/core/worktree/create.ts
- 一貫性 - 既存のパターンに従う
- 明確性 - 読みやすく、自己文書化されたコードを書く
- シンプルさ - 巧妙なコードを避け、明白な解決策を優先
- 型安全性 - TypeScriptの機能を最大限使用
- エラーハンドリング - Result型を一貫して使用
- テスト - すべての新しいコードにテストを書く
- コメントなし - コードにコメントが必要な場合は、リファクタリング
覚えておいてください:コードは書かれるよりもはるかに頻繁に読まれます。読みやすさのために最適化してください。