web-dev-qa-db-ja.com

Cの設計原則、ベストプラクティス、および設計パターン(または手続き型プログラミング全般)

Cプロジェクトの設計中に従うことができる既知の設計原則、ベストプラクティス、および設計パターンはありますか?または一般的な手続き型(命令型)プログラミングの有用な設計原則ですか?

(私は「オブジェクト指向生成」の子であり、初めて大規模なCプロジェクトを設計する必要があります)

90
Dimi

情報の隠蔽-Parnasによって支持されている( Software Fundamentals )。

ヘッダーと可視性の慎重な管理:

  • ソースファイル内の、外部の世界から隠されている可能性のあるものはすべてあるべきです。文書化された外部インターフェイスのみを公開する必要があります。
  • 公開されるものはすべてヘッダーで宣言されます。
  • そのヘッダーは、機能が必要な場所(および定義されている場所)で使用されます。
  • ヘッダーは自己完結型です-必要なときにそれを使用し、「他のヘッダーも含める必要がある」ことを心配する必要はありません作業。
  • ヘッダーは自己保護されているため、複数回含まれていても問題ありません。

    #ifndef HEADER_H_INCLUDED
    #define HEADER_H_INCLUDED
    ...rest of header contents, including other #include lines if necessary
    #endif /* HEADER_H_INCLUDED */
    
  • 「オブジェクト」(通常は構造体)で機能する一連の関数を設計し、それを使用するコード内の構造体の内部を突くのではなく、それらの関数を使用します。それは自己課せられたカプセル化と考えてください。

62

ANSI-Cによるオブジェクト指向プログラミング というタイトルの無料の無料オンラインブックがあります。 Cでのオブジェクト指向コードの記述。 google search 「オブジェクト指向C」の場合、他の多くの良い例とリソースも得られます。

プロジェクトが安全性を重視する場合は、 MISRA-C が適切なルールセットです。これは主に埋め込みcを対象としていますが、他の分野でも有用です。

私は自分自身をOOコーダーであると考えており、埋め込みCで多くの作業を行っています。特に大規模なプロジェクトの場合、私ができる最善のアドバイスはやり過ぎないことです。 OO ANSI C上のフレームワークは非常に魅力的かもしれませんが、それを正しくするには多大な時間と労力が必要です。手に入れるほど、代わりにフレームワークのデバッグに費やす時間が長くなります。 realプロジェクトで作業すること。明確な頭でタスクにアプローチし、 [〜#〜] yagniをしっかりと把握します。 [〜#〜] 。幸運を祈ります!

22
e.James

私の3つのアドバイス:

  • 単体テストを作成します。彼らはあなたが進むにつれてあなたの問題に合った設計にあなたがゼロに役立つのを助けます。事前に瞑想された思考に(単独で)依存するよりもはるかに優れています。
  • メモリリークディテクタ(あらゆる種類のライブラリがあります)をインストールして、初日から実行します。プログラム/テストが終了したらすぐに、このライブラリにすべてのリークを出力させます。これにより、リークが導入されたらすぐにリークをキャッチできるため、その修正が非常に簡単になります。
  • CでOOPのコードを書きます。それほど難しくはありません。メソッドのオーバーライドをエミュレートすることは可能ですが、単純なオブジェクトのエミュレーションから始めることをお勧めします。

以下に例を示します。

typedef struct Vector {
  int size;
  int limit;
  int* ints; 
} Vector;

Vector* Vector_new() {
  Vector* res = (Vector*) malloc(sizeof(Vector));
  res->limit = 10;
  res->size = 0;
  res->ints = (int*) malloc(sizeof(int) * res.limit);

  return res;
}


void Vector_destroy(Vector* v) {
  free(v->ints);
  free(v);
}

void Vector_add(Vector* v, int n) {
  if(v->size == v->limit) {
    v->limit = v->limit * 2 + 10;
    v->ints = realloc(v->ints, v->limit);     
  }

  v->ints[v->size] = n;
  ++v->size;
}

int Vector_get(Vector* v, int index) {
  if(index >= 0 && index < v->size)
    return v->ints[index];

  assert false;
}
21
Itay Maman

OOPは技術ではなく方法論です。したがって、私の最初のアドバイスは、手続き型プログラミングと考えるのをやめることです。

E.Jamesのポイントでは、オブジェクト指向言語を再作成したり、その機能を持っているふりをしたりしたくないのです。いくつかの簡単な原則に固執することで、すべての正しいことを実行できます。

  1. すべてを試運転します。
  2. 変化するものを見つけてカプセル化します。
  3. インターフェイスへの設計。
7
MaxGuernseyIII

SEI CERT C Coding Standardには、 ルールと共通の優れたプラクティスの優れたセット と、使用を避けようとするものが用意されています。

4
Rami