2012年8月7日火曜日

JPLのコーディング規約を読む(part 1)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
コーディング規約のソースはこちら。 JPL Institutional Coding Standard for the C Programming Language, (PDF)
JPLといってもAPLの親戚言語かではなくて ジェット推進研究所(Jet Propulsion Laboratory)のほうのJPLです。 言い方を変えると、オポチュニティとスピリットを作ったところです。
探査機の制御とかが念頭にあると思われるので、web applicationやサーバ、GUIアプリケーションとは違った方針になっているでしょう。実>際、page 6のScopeで
The coding rules defined here primarily target the development of mission critical flight software written in the C programming language. This means that the rules are focused on embedded software applications, which generally operate under stricter resource constraints than, e.g., ground software.
となると、とにかくエラーがあることは話にならないし、仮にあとから修正することも非常に困難な訳です。 (このへんwebとか非常にだらしない・・・。宇宙機での変更は不可能ではないが宇宙の彼方にプログラムを転送して(すごく遅い!)、再起動という>恐ろしいことになります。) 打ち上げや、軌道変更、誘導、着陸でミスをすれば膨大な開発期間とコストが一瞬でパーになりプロジェクトが失敗に終わるわけです。 太陽電池が展開できないとかなら電力が無くて死亡、アンテナの向きがおかしいとかでも地球側と通信できなくなってやはりダメでしょう。

RFCとかその他いろいろな仕様書関連である、Shallとかmustとかの意味が一般英語と異なるので、ちゃんと定義があります。

  • Shall indicates a requirement that must be followed, with compliance verified.
  • Should indicates a preference that must be addressed, but with deviations allowed, provided that an adequate justification is given for each deviation

shallは例外のない絶対で、shouldはそうされることがきわめて好ましいが十分な正当化があれば行ってもよい、ということです。

これで最低限の準備ができたので、Page 4のsummaryにある31箇条+2をみていきましょうか。いきなり欄の一番下です。

*) All rules are shall rules, except those marked with an asterix.

つまり、アスタリスクが付いていないやつは絶対まもれ、といっているのです。

それでは1-19の適当訳とコメント。のこりはpart2かな。

  1. Language Compliance 「言語の仕様に従え」
    1. Do not stray outside the language definition

      変態的なマクロとかを書いて拡張っぽいことをするとかを指しているのかな?本体を読めば詳細がわかるのでしょう。

    2. Compile with all warnings enabled; use static source code analyzers.

      gccだったら-Wallかな。clangにもなにかあるはず。今時lintでも無いと思うけど、代わりになる道具はありそうだ。

  2. Predictable Execution 「予測・予期可能な実行」

    1. Use verifiable loop bounds for all loops meant to be terminating.

      脱出する意図のあるループ構造には検証可能な脱出条件を使いなさい。

    2. Do not use direct or indirect recursion.

      再帰呼び出しを直接間接を問わず使うべからず。

      理由は簡単に予想が付く。スタックがオーバーフローする可能性があるからだ。 リソースが制限されている組み込みのジャンルではおそらく普通だろう。

    3. Do not use dynamic memory allocation after task initialization

      タスクの初期化後にメモリを動的に確保するな

      これはちょっとよくわからない。予想不能な量のメモリを消費するなということだろうか?

    4. *Use IPC messages for task communication.

      IPCメッセージはタスク間通信に使え。

      よくわからず。ところでOSは何を使っているのだろうねぇ。

    5. Do not use task delays for task synchronization.

      task遅延をタスク同期に用いるな。

      taskの定義が曖昧なので前者とともに謎

    6. *Explicitly transfer write-permission (ownership) for shared data objects.

      共有されているオブジェクトの書き込み権限(所有権)は明示的に引き渡せ

      おそらくは「タスク間で」だと思われる。それほどの驚きはない。 最近流行の変更不能なvalueだけでコードを書くようなスタイルは 予想不能な量のメモリを使用するため採用できない。従って昔ながら(?)の lockを使ったプログラミングにならざるを得ない。当然lockの取得がらみで問題が起こるので、 このような規約を採用することになるのだろう。 *つきなのは当然で、どのようにshareされるかは解きたい問題とそれの解決手法次第だから。

    7. Place restrictions on the use of semaphores and locks.

      セマフォとロックの使い方に関して制限を設けよ

      dead lockは困りますからねぇ・・・

    8. Use memory protection, safety margins, barrier patterns.

      メモリ保護、安全マージン、バリアパターンを使え。

      メモリ保護はOSの機能かな?これは驚かない。 安全マージンとバリアパターンが具体的に何を意味しているかがわからない。 読めば出てくるのかもしれない。予想としては配列の前後に0xdeadbeafとかを埋め込むってことかな?

    9. Do not use goto, setjmp or longjmp.

      setjump, longjump, goto禁止

      とくに驚かない。構造化プログラムってことだね。 Duff's device みたいな変態は許されるのだろうかねぇ・・・。

    10. Do not use selective value assignments to elements of an enum list.

      enumリストで選択的に値を代入するな。

      おそらく次のようなコードを意味するのだと思う。

      enum Kitty { MIMI , YUKI = 5 , RENA };

      これをやると値が非連続になり、バグの元になるのだろう。

  3. Defensive Coding 「防御的プログラミング」

    [プログラミング原則][防御的プログラミング]防御的プログラミングとかが参考になるのでは。

    1. Declare data objects at smallest possible level of scope.

      可能な限り最小のスコープになるようにオブジェクトを宣言せよ。

      lisp系のletとかでもそうですね。そこそこ書いたことがあれば守っているはずの基本原則でな。

    2. Check the return value of non-void functions, or explicitly cast to (void).

      関数の戻り値はチェックしなさい。void関数なら明示的にvoidにキャストしなさい。

      キャストせよ、というのは新鮮。ほぼvoidな関数を使うなに同義ではないだろうか。 そのようなキャストを行うコードは変に見えるだろう。発想として、 間違ったコードは間違って 見えるようにする に似ているように思える。24にも関係する。

    3. Check the validity of values passed to functions.

      関数に渡された値を検証せよ

      契約・表明プログラミングの流れをくみますねぇ。おそらく。

    4. Use static and dynamic assertions as sanity checks.

      静的・動的表明を健全性検証に使え。

    5. * Use U32, I16, etc instead of predefined C data types such as int, short, etc.

      U32やI16を使い、Cであらかじめ規定されているint, shortなどの型は使うな。

      組み込み的。コンパイラによって何に変換されるか不明な型は使わない、ということだろう。

    6. Make the order of evaluation in compound expressions explicit.

      複合式の評価順序を明示せよ

      1 + 2 * 5とは書けないのかな?

    7. Do not use expressions with side effects

      副作用のある式を使うな。

      ということは、while(x =read())みたいなことはできんのかな?

0 件のコメント: