Cの変数と関数に使用される命名規則[非公開]


12

CIで大規模プロジェクトをコーディングする際に問題が発生しました。さらにコードを書き続けると、コードを整理するのが難しくなることがあります。プログラムのさまざまな部分の関数と変数の命名が混同されているように見えるかもしれません。

それで、Cの変数と関数に使用できる便利な命名規則があるかどうかを考えていましたか?

ほとんどの言語は命名規則を提案しています。しかし、Cについては、これまで読んだ唯一のことは、コードの読みやすさを説明する名前でなければならないということです。

編集:

推奨される命名規則のいくつかの例の例:

Javaの命名規則をどこかで読みましたが、どこにあるのか覚えていません。


命名規則が推奨されている言語の例をいくつか引用してください。そして、それらの命名規則を見つけることができます。
フィリップ

@フィリップ追加例
アシームBansal

1
グローバルを使用しないため、変数に問題はありません。そして、関数名:モジュールの名前がある場合order.c、あなたは、関数に名前を付けることができorder_add()order_del()そして、そのような。名前が最初の8文字内で一意でなければならないことを伝える古いシステムが存在する場合があります。後で偶然にC ++に切り替えるorder::add()order::del()、書くのが大好きになります。
-ott--

回答:


17

さらにコードを書き続けると、コードを整理するのが難しくなることがあります。

これがあなたの問題です。組織を正しくし、スタイルをより簡単に流すべきです。

しないでください待って、あなたのコードを整理するために:あなたが行くように整理してコードを保持します。言語はあなたのためにそれをしませんが、コードは依然として低結合と高凝集度を持つモジュールに編成されるべきです。

これらのモジュールは、当然名前空間を提供します。モジュール名を短縮し(長い場合)、衝突を避けるために、モジュールに関数名のプレフィックスを付けます。

個々の識別子のレベルでは、これらはおおむね主観の昇順です。

  1. コンベンションを選んで、それに固執する
    • 例えば、function_like_this(struct TypeLikeThis variable)一般的です
  2. ハンガリー語の表記は絶対に避けてください(JNLに申し訳ありません)

    • 元々意図したとおりに使用しない限り、ひどいシステムバージョンではなくSimonyiのアプリの表記を意味します

      どうして?これについてのエッセイを書くこともできますが、代わりにJoel Spolskyによるこの記事を読んでから、もし興味があればもっと探しましょう。下部に、Simonyiのオリジナルの論文へのリンクがあります。

  3. 純粋に不透明なCookieタイプでない限り、ポインターのtypedefは避けてください-物事を混乱させるだけです

    struct Type *ok;
    typedef struct Type *TypePtr;
    TypePtr yuck;

    不透明なCookieタイプとはどういう意味ですか?つまり、モジュール(またはライブラリなど)内で使用され、クライアントコードに渡される必要があるものを意味しますが、そのクライアントコードは直接使用できません。それをライブラリに渡すだけです。

    たとえば、データベースライブラリは次のようなインターフェイスを公開します。

    /* Lots of buffering, IPC and metadata magic held in here.
       No, you don't get to look inside. */
    struct DBContextT;
    /* In fact, you only ever get a pointer, so let's give it a nice name */
    typedef struct DBContexT *DBContext;
    
    DBContext db_allocate_context(/*maybe some optional flags?*/);
    void db_release_context(DBContext);
    int db_connect(DBContext, const char *connect);
    int db_disconnect(DBContext);
    int db_execute(DBContext, const char *sql);

    これで、内部を見ることができないため、コンテキストはクライアントコードに対して不透明になります。それをライブラリに渡すだけです。そのようなFILEものも不透明であり、整数ファイル記述子もCookieですが、不透明ではありません。


設計上の注意

私は説明なしで低結合と高凝集度というフレーズを使用しましたが、それについて少し気分が悪いです。あなたはそれを検索し、おそらくいくつかの良い結果を見つけることができますが、私は簡単にそれに対処しようとします(もう一度、エッセイを書くことができますが、しようとしません)。

上にスケッチしたDBライブラリは、小さなインターフェースを外部に公開するため、結合低いことを示しています。実装の詳細を(部分的に不透明なCookieトリックを使用して)隠すことにより、クライアントコードがそれらの詳細に依存するのを防ぎます。

不透明なCookieの代わりに、そのコンテンツが見えるようにコンテキスト構造体を宣言し、データベースへのTCP接続用のソケットファイル記述子が含まれていると想像してください。DBが同じマシンで実行されているときに共有メモリセグメントの使用をサポートするように実装を後で変更する場合、クライアントは単に再リンクするのではなく、再コンパイルする必要があります。さらに悪いことに、クライアントはファイル記述子の使用を開始することもできました。たとえばsetsockopt、デフォルトのバッファサイズを変更するために呼び出した場合、コードの変更も必要になります。これらの詳細はすべて、実用的な場合はモジュール内に隠し、モジュール間の結合を低くする必要があります。

この例では、モジュール内のすべてのメソッドが同じタスク(DBアクセス)に関係しているという点で、高い凝集度も示しています。これは、実装の詳細(つまり、Cookieの内容)について知る必要があるコードのみが実際にアクセスできることを意味し、デバッグを簡素化します。

また、単一の懸念事項があることで、これらの機能をグループ化するプレフィックスを簡単に選択できることもわかります。

さて、この例が良いと言うのは簡単です(特に完全ではないので)が、すぐには助けにはなりません。トリックは、コードを記述して拡張する際に、同様のことを行う関数や同じタイプで動作する関数(独自のモジュールの候補になる可能性がある)、および多くの別個のことを行う関数を監視することです。本当に関連しており、分割の候補になるかもしれません。


なぜハンガリー人が避けられているのか理解してもらえますか?それについてもっと知りたいだけです。:)
JNL

@JNL:コメントは短すぎて適切に説明できません。新しい質問として投稿することをお勧めします。
バートヴァンインゲンシェナウ

with low coupling and high cohesion。どういう意味ですか?また、不透明なCookieタイプについて説明してください。それが何を意味するのか分かりません。
アシームバンサル

私は両方に簡潔に対処しようとしましたが、簡潔に率直に失敗しました。うまくいけば、それがあなたを始めさせるでしょう。
役に立たない

数日後に返信しています。そのために残念。の説明を読みましたlow coupling and high cohesion。したがって、基本的には、可能なときに物事をカプセル化することを意味し、実際に必要な機能がアクセスできるように行う必要があります。いくつかのことが頭をよぎりましたが、それでも私はあなたの言い分を得たと思います。
アシームBansal

5

あなたは心の中で3つのことを続ければ私の意見では、ネーミングの問題の90%は解決されています、可能な限り記述として、あなたの変数名や関数名を作る b)の機能がaddNumbers命名されている場合、すなわち(あなたのコード全体で一貫して、A 2番目の関数は、numbersMulではなく、multiplyNumbersという名前にする必要があります。c)名前を入力する必要があるため、可能であれば名前を短くしてください。

このトピックの他の側面を見たい場合は、命名規則に関するウィキペディアのページに注意すべきことの良いリストがあります。また、CおよびC ++のセクションもあります。

CおよびC ++では、キーワードと標準ライブラリ識別子はほとんど小文字です。C標準ライブラリでは、省略名が最も一般的です(たとえば、文字が英数字かどうかをテストする関数のisalnum)。C++標準ライブラリでは、単語の区切り文字としてアンダースコア(out_of_rangeなど)がよく使用されます。マクロを表す識別子は、慣例により、大文字とアンダースコアのみを使用して記述されます(これは、定数にすべて大文字の識別子を使用する多くのプログラミング言語の規則に関連しています)。二重アンダースコアを含む名前、またはアンダースコアと大文字で始まる名前は実装用に予約されているため(コンパイラ、標準ライブラリ)、使用しないでください(reserved__または_Reservedなど)。[5] [6] これは表面的にはストローピングに似ていますが、セマンティクスは異なります。


3
「可能な場合は名前を短くしてください」IDEでオートコンプリートを使用すると、関数名は、一度入力するだけで必要なだけ長くてわかりやすいものにすることができます。
ジョエル

1
@ジョエルのひどいアドバイス。誰もがあなたと同じIDEを使用するわけではありません。
ジェームズ

6
@James必要はありません。まともなIDEを使用できます。そうすれば、生産性のために明快さを犠牲にする必要はありません。
ジョエル

IDEという用語は、今や少し薄くなっています。技術的にはNotepad ++は、プロジェクトをコンパイルして実行するように構成できるためIDEです。ただし、主にテキストエディターです。そして、それは自動補完します。
フィリップ

5

Cの唯一の厳しい制約は、名前空間がないことです。したがって、あなたが作る方法を見つけるために持っているrename()あなたの機能ファイルシステムとは別のライブラリrename()あなたの機能メディアライブラリを。通常の解決策は、次のような接頭辞、次のとおりです。filesystem_rename()media_rename()

他の一般的なアドバイスは、プロジェクトまたはチーム内で一貫性を保つことです。可読性が向上します。


+1:ライブラリ内のエクスポートされたシンボルの場合、特にそうです。「申し訳ありませんが、そのファイルシステムライブラリはそのメディアライブラリに対応していません。両方ともエクスポートされた関数名が変更されているためです
。– Residuum

2

グローバルに受け入れられている形式を探している場合

MISRA / JSF / AUTOSARは、C / C ++コードの命名と編成に関するあらゆる業界標準のほぼ100%をカバーしています。問題は、彼らが無料で手に入れることができないということです。すなわち、各ガイドブックにはいくらかの費用がかかります。MISRA 2008 C / C ++コーディング標準の本はおそらく約50米ドルかかることを知っています。

これらは、ジャーナルを書くときの参考文献と追加読書のためのハーバード参照と考えることができます。私はMISRAを使用しましたが、関数と変数に名前を付け、適切に使用できるように整理するのに良い方法です。

一時的なものを探しているなら

PythonとJava用に提供したリファレンスは大丈夫だと思います。Javadocスタイルのコメント、命名、コードの編成を採用している人々を見てきました。実際、私の最後のプロジェクトでは、Javaのような関数/変数名でC ++コードを作成する必要がありました。この背後にある2つの理由:

1)フォローするのが明らかに簡単だった。

2)プロダクションコードの要件は、セーフティクリティカルなソフトウェアシステム標準の根拠に触れていません。

3)レガシーコードは(何らかの形で)その形式でした。

4)DoxygenはJavadocスタイルのコメントを許可しました。その瞬間、私たちはdoxygenを使用して制作スタッフ向けのドキュメントを生成していました。

多くのプログラマーはこれに反対しますが、個人的には、C / C ++でjavadocスタイルの関数/変数の命名を採用することに何の問題もないことを個人的に知っています。もちろん、フロー制御、スレッドの安全性などを整理する慣行は、いずれにしても対処する必要があります。しかし、私はここで応募者ではありません。また、量産コード形式の要件がどれほど厳しいのかもわかりません。トピック外の領域に流用することなく、要件を確認し、特定の命名規則にどのように依存しているかを調べ、鉱山および他の回答で言及されている解決策を検討することをお勧めします

これが役に立てば幸いです!?


実際、私はこれを個人的なCコードに求めていました。しかし、私はあなたの提案を覚えています。
アシームBansal

@AseemBansal個人または専門家、それらは学ぶのに適していますし、履歴書を付けるのにも適しています:) ....あなた次第です。
hagubear

0

命名時に考慮すべき重要なことはほとんどありません。

  1. actionObjectまたはObjectActionタイプを調べます(CではなくObjectです。しかし、一般に他のオブジェクト指向言語にアクセスするとき) これは役立つはずです

  2. 休息は一貫性があり、短く、説明的であることは確かです。

  3. また、定義されたすべての変数と関数の唯一の目的を持ちます。たとえば、値を一時的に保存する場合は、intにnTempValという名前を付けます。
  4. 変数は名詞であり、メソッドは動詞でなければなりません。

6
ハンガリー語の表記(変数の前に型を示す文字を付ける)は、終わりのない痛みにつながります。ありがたいことに、大部分は時代遅れになりました。
ロボット

@StevenBurnapなぜハンガリー形式が避けられたのか不思議でしたか?私はそれが彼らが学校で教えてくれたものだと信じており、私もいくつかの職場でそのようなコードを見てきました。ハンガリー語ではない場合、どちらをお勧めしますか。ありがとう
-JNL

1
最適な命名規則は、一貫して使用されるものの1つであり、明確でわかりやすい名前は、過度の略語や冗長なプレフィックスを避けることなく、比較的短く保つことが理想的です。ハンガリー語の表記法には実際の実用性がほとんどなく、コードの読み取りが難しくなり、型の変更が難しくなります。
ロボット

2
ハンガリーの表記法になった当初の意図と憎悪の説明は次のとおり
Wrong.html-レジデューム

@Residuumそれは良いリンクでした。たくさん助けました。感謝します。
JNL

0

ほとんどの答えは良いですが、C ++やJavaのような他の言語で名前空間を使用するのと同様に、ライブラリとインクルードファイルの命名規則についていくつか述べたいと思います。

ライブラリを構築する場合、エクスポートされたシンボルの一般的なプレフィックス、つまりグローバル関数、typedef、変数を見つけます。これにより、他のライブラリとの衝突を防ぎ、関数が自分のものであると識別します。これはハンガリー語表記のアプリです。

さらに進んで、エクスポートされたシンボルをグループ化することもできます。libcurlは、グローバルシンボルにcurl_ *、さまざまなインターフェイスにcurl_easy _ *、curl_multi_ *、およびcurl_share_ *を使用します。そのため、すべての関数にcurl_ *を使用することに加えて、さまざまなインターフェイスに別のレベルの「名前空間」を追加しました。curl_multi_*ハンドルでcurl_easy_ *関数を呼び出すのは間違っているようです。 haxx.se/libcurl/c/

エクスポートされたシンボルのルールを維持し、#includeedファイルの静的関数にルールを使用する必要があります。これらの関数の共通プレフィックスを見つけてください。「my_string」というファイルに静的文字列ユーティリティ関数があるかもしれませんか?これらのすべての関数の先頭にmy_string_ *を付けます。


エクスポートされたシンボルとは、私が正しい場合、グローバル変数、関数、typedefなどを意味します。エクスポートされたシンボルのグループ化について少し説明できますか?前の段落で既に説明したと思います。3番目の段落に何を追加しましたか?
アシームバンサル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.