web-dev-qa-db-ja.com

Cでコードを小さなファイルに分離する

私は自分のコードをクリーンアップし、保守を容易にする過程にあります。これを行うには、5000行以上のファイルを別の小さなファイルに変換します。

アプリケーションと緊密に統合されていないユーティリティやその他のコンポーネントなどの明らかなものについて、個別のソースファイルとヘッダーファイルを正常に作成しました。

アプリケーションの残りの部分も小さなファイルに分割するのが良いだろうと今考えています。しかし、主に私に関する問題は、残されたすべてがグローバルに宣言された構造体の束を使用することです。

つまり、これは前進する選択です(他の提案も聞いて幸せです):

1)すべてを同じファイルに残すことができるため、すべての関数を静的として定義できます(これには利点があり、多くの場合推奨されます)。この場合、グローバルをこの大きなソースファイルの上部に残すのが簡単です。

[〜#〜]または[〜#〜]

2)小さいファイルに分割できます。どのパーツをどの新しいファイルに入れるかを決めるのは比較的簡単です。また、構造階層(どの部分がどの部分を呼び出すか)を理解することもそれほど難しくありません。しかし、私はこれらすべてのグローバルにどのように対処するのが最善かについては不確かです。すべての関数がそれらを何らかの方法で使用するので、それらをどこに配置する必要がありますか?

注:グローバルの使用は避けなければならないことを認識しています。ただし、これはメモリが限られている組み込みデバイスです。グローバルはメモリ使用量を減らすための最良の方法です。節約するメモリが多いほど、特定のタスクをより多く実行できます。

3
Remixed123

すべての構造体をtypedefし、それらの宣言を別のインクルードファイルに配置することをお勧めします。次に、「メイン」ファイルが最終的に何であれ、構造体のすべての実際のインスタンスを定義します。次に、ヘッダーを含め、他のファイルで必要なインスタンスexternを宣言します。リンカはすべての参照の照合を処理しますが、まったく問題ありません。

3
TMN

3番目のハイブリッド代替手段があります。これは、各グローバルを独自のモジュールに入れ、それをサポートする関数を作成することです。これにより、変数に関連するすべてのコードのOOP-yの利点が1か所に分離され、必要に応じて他の場所での再利用がはるかに容易になります。呼び出しを強制するのではなくインライン化できるようにサポート関数をヘッダーに配置すると、1つの大きなファイルにすべてを含めることができます。

例えば:

// foo.h

typedef int FooType;

extern FooType foo_global_do_not_use_directly;

static inline void foo_init() {
    foo_global_do_not_use_directly = 0;
}

static inline void foo_set(FooType new_foo) {
    foo_global_do_not_use_directly = new_foo;
}

static inline FooType foo() {
    return foo_global_do_not_use_directly;
}

// foo.c

// Always include the header even if you're not using a
// typedef so it gets compiled at least once.
#include "foo.h"

FooType foo_global_do_not_use_directly;

もちろん、残りのソースを調べて、シンボルを直接参照する代わりに、関数を使用するようにグローバルのすべての使用を調整する必要があります。その過程で、繰り返し実行され、独自の機能に値する他のものが見つかる場合があります。これらの操作の動作を変更する必要がある場合は、将来的にメリットがあります。

5
Blrfl

オプション1を使用します。グローバルを単一のファイルに残し、見つけやすいようにします

コメントで述べたように、これはOOPではありませんです。 「OOPのルール」(一般的な意味では非常に優れています)は、組み込みデバイス上の小さなプロジェクトには必ずしも適用されません。

1つのファイルに5000行あると、作業が面倒です。ソリューションの5000行はかなり小さいです。すでに他のものを移動している場合は、残っているものがそれほど大きくない可能性があります。分割すると、変更したい1つのグローバルを探すのに多くの時間を費やすことになります。

目標は、構造を明確に理解し、必要な変更を加え(そしてその影響を理解し)、「変更するもの」と「変更しないもの」を区別できるようにコードを整理しておくことです。

OOPは、現代の汎用コンピューターでその目標を達成するための一般的な方法です。これは唯一の方法ではありません。また、メモリが制限された組み込みデバイスでは最善の方法ではない場合があります。

1
Dan Pichelman