Aikido

1ファイルにつき1クラスを使用すべき理由:コードの整理とナビゲーションの改善

可読性

ルール

1ファイルに つき 1クラス。
単一ファイルに 複数の クラスが あると、 コードの
整理が 不明瞭になり、 ナビゲートが 困難になります。

サポート言語: 45+

はじめに

単一ファイルに複数のクラスを配置すると、コードベースをナビゲートする際に特定のクラスを見つけるのが困難になります。開発者が検索する際に UserRepository という名前のファイルに埋もれている場合、すぐには見つけられないでしょう。 database.js 他の5つのクラスと並んでいます。これは最小驚きの原則に反し、チームメンバーがクラス定義を探すのに時間を浪費するため、開発を遅らせます。

なぜ重要なのか

コードの保守性:1ファイルあたりのクラスが複数あると、責務間の境界が不明確になります。あるクラスの変更が必要な場合、開発者は無関係なクラスを含むファイルを開く必要があり、認知負荷が増大し、誤って間違ったコードを変更するリスクが高まります。

ナビゲーションと発見可能性: 複数のクラスがファイルを共有している場合、IDEやテキストエディタは正確な「定義へ移動」を提供することに苦労します。開発者は、必要なクラスに直接ジャンプするのではなく、ファイル内を検索するのに時間を費やします。これは、数百のクラスを持つ大規模なコードベースでさらに複雑になります。

Version control conflicts: 複数のクラスが1つのファイルを共有する場合、異なる開発者による異なるクラスへの変更はマージの競合を引き起こします。ファイルを分離することで、各開発者が自身のファイルで作業するため、調整のオーバーヘッドなしに並行開発が可能になります。

コード例

❌ 非準拠:

// database.js
class UserRepository {
    async findById(id) {
        return db.users.findOne({ id });
    }
}

class OrderRepository {
    async findByUser(userId) {
        return db.orders.find({ userId });
    }
}

class ProductRepository {
    async findInStock() {
        return db.products.find({ stock: { $gt: 0 } });
    }
}

module.exports = { UserRepository, OrderRepository, ProductRepository };

誤っている理由: という名前の1つのファイルにある3つの関連性のないリポジトリクラス database.js。検索中 OrderRepository それがどこにあるかを知る必要があります。 database.js ~ではなく OrderRepository.js。ファイル変更が複数のクラスに影響を与え、不要なマージコンフリクトを引き起こします。

✅ 準拠済み:

// UserRepository.js
class UserRepository {
    async findById(id) {
        return db.users.findOne({ id });
    }
}
module.exports = UserRepository;

// OrderRepository.js
class OrderRepository {
    async findByUser(userId) {
        return db.orders.find({ userId });
    }
}
module.exports = OrderRepository;

// ProductRepository.js
class ProductRepository {
    async findInStock() {
        return db.products.find({ stock: { $gt: 0 } });
    }
}
module.exports = ProductRepository;

これが重要である理由: 各クラスを独自のファイルにすることで、ナビゲーションが予測可能になります。IDEは直接ジャンプできます。 OrderRepository.js クラスを検索する際。あるリポジトリへの変更は他のリポジトリに影響せず、不要なマージ競合を排除します。

まとめ

予測可能なナビゲーションのために、ファイル名には含まれるクラスの名前を付けます。この慣習は、特定のクラスを素早く見つけることが重要な大規模なコードベースにも対応できます。ファイルが増えることよりも、それらが提供する組織的な明確さの方が価値があります。

よくある質問

ご質問がありますか?

小さなヘルパークラスやプライベートクラスについてはどうですか?

1つの親クラスのみで使用される小さなヘルパークラスは、真に実装の詳細である限り、同じファイル内に保持できます。ただし、ヘルパーが再利用されたり、20〜30行を超える規模になったりする場合は、それらを抽出してください。1つのパブリッククラスをサポートするためだけに存在するプライベートクラスは、妥当な例外となります。

これはTypeScriptのインターフェースと型に適用されますか?

クラスで使用される型とインターフェースは、同じファイル内に配置できます。ただし、複数のファイルで共有される型は、独自の型定義ファイルに属します。重要なのは、その定義がそのファイルのみで使用されるのか、それとも他の場所でも必要とされるのか、ということです。

標準的な慣行で複数のクラスを持つPythonのような言語についてはどうですか?

Pythonの慣習は異なりますが、原則は同じです。凝集性のあるモジュールを形成する場合は関連するクラスをグループ化し、無関係なクラスを混在させるのは避けてください。UserとUserProfileを含むmodels.pyは理にかなっていますが、20の無関係なクラスを含むutils.pyはそうではありません。

親クラスや子クラスのような関連するクラスを、どのように整理しますか?

それらを同じディレクトリ内の別々のファイルに配置します。AnimalとDogの場合、animals/Animal.jsとanimals/Dog.jsを使用します。ディレクトリ構造は、1ファイル1クラスを維持しながら関係性を示します。これは、関連するクラスを1つのファイルにまとめるよりも拡張性が高くなります。

クラスを抽出すると多くの小さなファイルが作成される場合はどうなりますか?

少数の大きなファイルよりも、多数の小さなファイルの方が望ましいです。最新のIDEは数千のファイルを効率的に処理します。ファイルシステムナビゲーションは、大きなファイル内を検索するよりも高速です。各クラスがどこにあるかを正確に把握できる明瞭さは、「ファイルが多すぎる」という認識よりも重要です。

今すぐ、安全な環境へ。

コード、クラウド、ランタイムを1つの中央システムでセキュアに。
脆弱性を迅速に発見し、自動的に修正。

クレジットカードは不要です | スキャン結果は32秒で表示されます。