メインコンテンツまでスキップ

コーディング規約

Bazbiiプロジェクトのコーディング規約とスタイルガイドを説明します。

コーディング規約の概要

言語別の規約

  • Go: Go標準のコーディング規約(gofmt、go vet)
  • TypeScript: ESLint + TypeScript標準規約
  • Protocol Buffers: buf lintによるチェック

自動フォーマット

すべてのコードは自動フォーマットツールで統一します。

Goコーディング規約

基本方針

  • gofmt: コードフォーマットは自動化
  • go vet: 静的解析を実行
  • 命名規則: Go標準の命名規則に従う

命名規則

パッケージ名

// ✅ 良い例
package post
package postgres
package logmsg

// ❌ 避けるべき例
package postService // 冗長
package PostService // 大文字で始まらない

型名

// ✅ 良い例
type Post struct { ... }
type PostService struct { ... }
type PostID uuid.UUID

// ❌ 避けるべき例
type post struct { ... } // 公開型は大文字で始める

関数名

// ✅ 良い例
func CreatePost(ctx context.Context, input CreateInput) (PostID, error)
func (s *Service) CreateUserPost(ctx context.Context, input CreateInput) (PostID, error)

// ❌ 避けるべき例
func create_post(...) // スネークケースは使わない

エラーハンドリング

// ✅ 良い例
id, err := service.CreatePost(ctx, input)
if err != nil {
return nil, err
}

// ❌ 避けるべき例
id, _ := service.CreatePost(ctx, input) // エラーを無視しない

Context使用

// ✅ 良い例
func (r *Repo) FindByID(ctx context.Context, id PostID) (*Post, error) {
// ctxを下位レイヤーに渡す
return r.db.QueryContext(ctx, query, id)
}

// ❌ 避けるべき例
func (r *Repo) FindByID(id PostID) (*Post, error) {
// contextを省略しない
}

インターフェース設計

// ✅ 良い例: 小さいインターフェース
type PostRepository interface {
FindByID(ctx context.Context, id PostID) (*Post, error)
Insert(ctx context.Context, post Post) (PostID, error)
}

// ❌ 避けるべき例: 大きなインターフェース
type Repository interface {
FindPostByID(...)
FindUserByID(...)
FindAllPosts(...)
// 多くのメソッド
}

コメント

// ✅ 良い例
// CreateUserPost creates a new post by a user.
// It validates the input and emits a domain event on success.
func (s *Service) CreateUserPost(ctx context.Context, input CreateUserPostInput) (PostID, error) {
...
}

// ❌ 避けるべき例
// create post // 簡潔すぎる、英語でない
func CreatePost(...) { ... } // コメントなし

コードフォーマット

# 自動フォーマット
make go/fmt

# 静的解析
make go/vet

TypeScriptコーディング規約

基本方針

  • ESLint: コード品質チェック
  • Prettier: コードフォーマット(検討中)
  • TypeScript: 型安全性を重視

命名規則

変数・関数

// ✅ 良い例(camelCase)
const postId = "123";
function createPost(input: CreatePostInput): Promise<Post> { ... }

// ❌ 避けるべき例
const post_id = "123"; // スネークケース
const PostId = "123"; // パスカルケース(型名以外)

型・インターフェース

// ✅ 良い例(PascalCase)
interface CreatePostInput {
h3Hex: string;
text: string;
}

type PostID = string;

// ❌ 避けるべき例
interface createPostInput { ... } // 小文字で始まらない

コンポーネント

// ✅ 良い例(PascalCase)
export function PostCard({ post }: { post: Post }) {
return <div>...</div>;
}

// ❌ 避けるべき例
export function postCard(...) { ... } // 小文字で始まらない

型定義

// ✅ 良い例: 明示的な型定義
function createPost(input: CreatePostInput): Promise<Post> {
...
}

// ❌ 避けるべき例: anyの使用
function createPost(input: any): any {
...
}

非同期処理

// ✅ 良い例: async/await
async function fetchPost(id: PostID): Promise<Post> {
const response = await fetch(`/api/posts/${id}`);
return response.json();
}

// ❌ 避けるべき例: Promiseチェーン
function fetchPost(id: PostID): Promise<Post> {
return fetch(`/api/posts/${id}`).then(res => res.json());
}

エラーハンドリング

// ✅ 良い例
try {
const post = await createPost(input);
return post;
} catch (error) {
console.error("Failed to create post:", error);
throw error;
}

// ❌ 避けるべき例
const post = await createPost(input); // エラーハンドリングなし

コードフォーマット

# ESLintチェック
pnpm lint

# 自動修正
pnpm lint --fix

Protocol Buffers規約

ファイル構造

// ✅ 良い例
syntax = "proto3";

package bazbii.post.v1;

option go_package = "go.bazbii.app/packages/proto-gen-go/bazbii/post/v1";

message CreateRequest {
string h3_hex = 1;
string text = 2;
}

命名規則

  • メッセージ: PascalCase
  • フィールド: snake_case
  • サービス: PascalCase
  • メソッド: PascalCase

バージョニング

// パッケージ名でバージョン管理
package bazbii.post.v1;
package bazbii.post.v2;

リントチェック

# Protocol Buffersリント
make proto/lint

# 破壊的変更チェック
make proto/breaking

コーディング規約のチェック

自動チェック

# Goコード品質チェック
make go/fmt # フォーマットチェック
make go/vet # 静的解析

# TypeScriptコード品質チェック
pnpm lint

# Protocol Buffersチェック
make proto/lint

コミット前チェック

開発ワークフローで以下のチェックを実行:

  1. フォーマットチェック: make go/fmt
  2. 静的解析: make go/vet
  3. テスト実行: make go/test
  4. リントチェック: pnpm lint, make proto/lint

コードレビュー方針

レビューチェックリスト

  • コーディング規約に準拠しているか
  • 適切なエラーハンドリングがされているか
  • テストが追加されているか
  • ドキュメントが更新されているか
  • セキュリティ上の問題がないか

レビューの優先事項

  1. 機能性: 要件を満たしているか
  2. テスト: 適切にテストされているか
  3. 保守性: 将来の変更に対応できるか
  4. パフォーマンス: パフォーマンスに問題がないか

ベストプラクティス

1. 一貫性の維持

  • 同じパターンを使い回す
  • 既存のコードスタイルに合わせる

2. 可読性の重視

  • 明確な変数名・関数名
  • 適切なコメント(なぜそうするか)

3. 型安全性

  • 型を明示的に定義
  • anyの使用を避ける

4. エラーハンドリング

  • エラーを無視しない
  • 適切なエラーメッセージ

関連ドキュメント