web-dev-qa-db-ja.com

再利用可能なコンポーネントのC ++ソースコードの構成

C++の学習プロジェクトの一部として、カスタムテンプレートコンテナーを実装しています。コンテナーは、シリアル化、メモリ管理、イテレーターなどのさまざまなコンポーネントを利用します。コードを整理するための最良の方法は何ですか。

オプション1:すべてを1つのヘッダーファイルに入れる:

私はこれをオンラインのいくつかの例で見ました。しかし、これを行うと、最終的に数千行のファイルができます。

// container.hpp
template <typename params>
class Container {

public:
    // params is a struct with typedefs and static variables 
    // used to configure the container at compile time

    // I define additional typedefs and static variables here from params::

public:
    class iterator {

        // can use the typedefs and variables above
    };

    class memory {

        // can use the typedefs and variables above
    };
};

オプション2:コードを複数のヘッダーに分割する

各ファイルには、1つのコンポーネントの実装が含まれています。

// memory.hpp
template <typename Container>
class memory {

public:
    // typedefs and static variables from Container::

};

// iterator.hpp
template <typename Container>
class iterator {

public:
    // typedefs and static variables from Container::

};

// container.hpp
#include "iterator.hpp"
#include "memory.hpp"

template <typename params>
class Container {
public: 
    // typedefs and static variables here from params::


    typedef Container<params> self_type;


    iterator<self_type> begin();

private:
    memory<self_type> mem;
};

選択する議論は何ですか?

ソリューション1はよりクリーンに見えます。コンテナータイプをソリューション2のメモリとイテレーターに渡す必要があるという問題がありましたが、同時にコードはソリューション2の異なるファイルに編成されています。各ファイルには、1つのコンポーネントの実装が含まれています。

それは単に個人的な好みの問題ですか?または、あるソリューションを他のソリューションよりも選択する客観的な理由はありますか?または、完全に異なるより良いアプローチはありますか?

2
NBWL

それは単に個人の好みの問題ですか、それとも他のソリューションよりも1つのソリューションを選択する理由がありますか? (または完全に異なるアプローチ)。

いいえ、それは個人的な好みの問題ではありません。

複数のコンポーネントを別々のヘッダーファイルに実装することをお勧めします(2番目のソリューションで提案したとおり)。

これは増加します

  • 読みやすさ
  • 保守性
  • 再利用性
0

要するに

オプション2の方が優れており、これには客観的な理由があります。そして、はい、アプローチを改善することができます。

詳細:オプション2が推奨される理由

オプション1には懸念の分離がありません。これは何を意味するのでしょうか?

  • ある日、プロジェクトに、シリアライゼーションのエキスパート、イテレーションのスペシャリスト、メモリ管理の第一人者がいるチームを雇う余裕があると想像してください。
  • オプション1では、この架空のチームが共同で作業することが困難になります。それらはすべて同じファイルで動作します。そして、適切なリポジトリ管理があっても、マージの競合や、誰が何を担当しているかについての多くの論争が発生するでしょう。

オプション2は、ソリューションのコンポーネント間の明確な境界を定義します。これには多くの利点があります:

  • 読みやすい小さいファイル:たとえば、必ずしもcontainer.hppを読み取らなくても、iterator.hppの内容を把握できます。
  • 簡単な変更;
  • 潜在的に再利用可能なサブコンポーネントを奨励します。

詳細:より良い方法は?

すべてのコンポーネントを独自の名前空間に含める必要があります。これは重要です。オプション1ではiteratorは独自の名前ではなくContainer::iteratorとして公開されますが、オプション2では名前空間なしではiteratorと呼ばれるため、いくつかのあいまいさ。

別の可能な改善点は、各テンプレートクラスの定義を2つのファイルの実装から分離することです。

  • これはもちろんファイルを増やします。 C++テンプレートの完全なコードは、それらが使用されるコンパイル単位に含まれている必要があるため、それは役に立たないと考えるかもしれません。
  • ただし、少なくともソースコードでは、インターフェイスを実装から分離するという追加の利点があります。

最後に、boost headersのガイドラインでさらにインスピレーションを得られるかもしれません。

2
Christophe