Igor Pro コーディング規約
Thomas Braun氏によってIgor Exchangeに投稿されているIgor Proのコーディング規約(非公式)が,簡潔で分かりやすかったので本人の許可を得て翻訳しました. ドキュメント作成ソフトのDoxygen等,日本のIgor Proユーザーにはおそらく馴染みのないものもありますが,規約の多くの部分がコーディングの参考にできると思います.
原文:
http://www.igorexchange.com/project/CodingConventions
https://github.com/t-b/igor-pro-coding-conventions
1 プロシージャ
コードはIgor Proの外部のプロシージャファイルに直接,書き込むべきです.
プロシージャファイル名はアルファベットの大文字小文字,アンダースコア,ハイフンのみで構成され,.ipfで終わります.
ファイルのエンコーディングはOSに依存します.しかし使用する文字は常にASCII文字に限られるべきです.Igor Pro 7でだけ使用するコードでは,テキストエンコーディングとしてUTF-8を用い
#pragma TextEncoding = "UTF-8"
を指定します.プロシージャファイルは
#pragma rtGlobals=3
およびその説明コメント*1で開始されます.改行コードは常にUNIXスタイル(LF)を用いるべきです.
2 空白文字とコメント
コメント
ファイル,関数,マクロ,定数の説明(ドキュメント)にはdoxygenを用います.
次のように,末尾のコメントの前には常に一つの空白文字を置くべきです.
if (a < 0) b = 1 else // positive numbers (including zero) b = 4711 endif
- コメントを行末に付すよりは,行を分けて書くべきです.
Doxygen
@paramキーワードに続けて引数の名前と説明を書く場合,引数の説明は関数に渡す順番に通りに並べるべきです.
/// @param pressure Pressure of the cell /// @param temperature Outdoor temperature /// @param length Length of a soccer field Function PerformCalculation(pressure, temperature, length) variable pressure, temperature, length // code End
- 関数が引数の値渡しと参照渡し*3の両方を使うとき場合は,in/out指定を@paramに付けるべきです.
/// @param[in] name Name of the device /// @param[out] type Device type /// @param[out] number Device number Function ParseString(name, type, number) string name variable &type, &number // code End
- オプション変数の説明は次のようにします.
/// @param verbose [optional, default = 0] Verbosely output /// the steps of the performed calculations Function DoCalculation([verbose]) variable verbose // code End
空白文字
各関数は他のコードから改行1行分だけ隔てて書くべきです.
インデントにはタブ文字を用い,(Igor Pro以外のソフトウェアでコーディングしていてタブ文字が使えない場合は)タブ文字には4つの空白文字を当てるべきです.
行を分けてコメントする場合,コメントのインデントの深さは周囲のコードに合わせます.
関数の引数の宣言,ローカル変数の宣言,関数の残りの部分はそれぞれ改行で隔てて書きます.
Function CalculatePressure(weight, size) variable weight, size variable i, numEntries // code End
a = b + c * (d + 1) / 5 if(a < b) c = a^2 + b^2 end Make/O/N={1, 2} data for(i = 0; i < numWaves; i += 1) a = i^2 endfor if(myStatus && myClock) e=f endif
- 行の末尾の余分な空白を避けるように心掛けてください.以下,空白文字を␣で,タブ文字を⇥で表します.
良い例: Function␣DoStuff() ⇥print␣"Hi" ⇥if(a␣<␣b) ⇥⇥c␣=␣a^2␣+␣b^2 ⇥end ⇥Make/O/N={1,␣2}␣data End 悪い例: Function␣DoStuff()␣ ⇥print␣"Hi"␣⇥ ⇥ ⇥if(a␣<␣b)␣␣␣␣ ⇥⇥c␣=␣a^2␣+␣b^2⇥ ⇥end␣ ⇥ ⇥Make/O/N={1,␣2}␣data␣ End
if/endif
,for/endfor
,do/while
,switch/endswitch
のようなコードブロックがプログラムのロジックを表している場合には,前後には改行を入れます.
for(i = 0; i < numEntries; i += 1) // code endfor if(a > b) c=d elseif(a == b) c=e else c=0 endif switch(mode) case MODE1: a = "myString" break case MODE2: a = "someOtherString" break default: Abort "unknown mode" break endswitch
以下のような場合は,直前の代入文がロジックの一部なのでif
やfor
の前に改行を入れません.
numEntries = ItemsInList(list) for(i = 0; i < numEntries; i += 1) // code endfor NVAR num = root:fancyNumber if(num < 5) // code endif
複数のend文が続く場合には,改行を省略します.
for(i = 0; i < numEntries; i += 1) // code if(i < 5) // code endif endfor
- 操作関数のフラグの間には空白を入れません.また,フラグへの代入を行う場合の
=
の前後にも空白を入れません.
良い例: Wave/Z/T/SDFR=dfr wv = myWave Function/S DoStuff() // code End 悪い例: Wave /Z /T /SDFR = dfr wv = myWave
- 引数の参照渡しに使う
&
は変数名の直前に置きます.
良い例: Function DoStuff(length, height, weight) variable &length, &height, &weight // code End 悪い例: Function DoStuff(length, height, weight) variable& length, & height,& weight // code End
3 コード
3.1 基本
1行は80文字を超えないようにします.
variable
/string
/wave
/dfref
の名前にはcamelCaseを使い,構造体の名前にはCamelCaseを使います.i
,j
,k
,l
という名前の変数はループカウンターとしてだけ使うべきです.後者ほど内側のループで使われます.一時的に値を格納するウェーブとして,フリーウェーブを使うべきです.
できる限り
SetDataFolder
を使わずにコードを書くべきです.関数が呼ばれるときに特定のデータフォルダをカレントフォルダとしていることを期待するなら,適切なドキュメントを書いておくべきです.関数中でカレントフォルダを変更した場合は常に,関数の終了前にカレントフォルダをもとに戻します.Igor Proのコードは大文字小文字の違いを問題にしませんが,可読性の向上のため,Igor Proのヘルプファイルに書かれている公式の名称に合わせて大文字小文字を書き分けるべきです.
Make/N=(10) data AppendToGraph/W=$graph data WAVE/Z wv SVAR sv = abcd STRUCT Rectangular rect print ItemsInList(list)
ただし,以下のふたつの場合は例外です*4.
variable storageCount string name
変数や関数を定義するときや,それらを使うときには,大文字小文字の使い方を変えてはいけません.
関数の戻り値とする値を,一時的に格納するために変数を使うべきではありません.
良い例: if(someCondition) // code return 0 else // code return 1 endif // 関数の戻り値が状態であることを知らせたいのなら, // 関数名をGetStatusForFooのようにするか.doxygenのコメントとして@returnを使うべきです. // あるいは,関数名とdoxygenコメントの両方を使うべきです. 悪い例: variable status // code if(someCondition) // code status = 0 else // code status = 1 endif return status
コメントアウトされたコードを残しておくべきではありません.
その必要がないなら,数値変数や文字列変数を初期化するべきではありません.もし変数の初期化を行うなら,それぞれ別の行で行うべきです.
良い例: variable i = 1 variable numEntries, maxLength string list 悪い例: variable i = 0, numEntries = ItemsInList(list), maxLength string list = ""
- 関数のオプション変数としてデフォルト値を使うなら,それをわざわざ書くべきではありません.
良い例: StringFromList(0, list) 悪い例: StringFromList(0, list, ";")
- 括弧は省略できるのなら省略するべきです.
良い例: variable a = b * (1 + 2) if(a < b || a < c) // code endif 悪い例: variable a = (b * (1 + 2)) if((a < b) || (a < c)) // code endif
- 優先度が等しい演算子を組み合わせるときには,括弧を使うべきです.
良い例: if((A || B) && C) // code endif if(A == (B >= C)) // code endif 悪い例: if(A || B && C) // same as above as these are left to right // code endif if(A == B >= C) // same as above as these are right to left // code endif
正確な結合則を記憶しておくのは難しく,エラーを起こしやすくなるからです.
DisplayHelpTopic "Operators"
も参照してください.
3.2 定数
- あるファイルの内部でだけ有効なstatic定数は,そのファイルの先頭で定義します.
- グローバル定数の名前はアルファベット大文字とアンダースコアのみで構成します,グローバル定数の定義はただ一つのファイルに集約されるべきです.
- マジックナンバー*5にはコメントで説明をつけるべきです.
static Constant DEFAULT_WAVE_SIZE = 128 // equals 2^8 which is // the width of the DAC signal
3.3 マクロ
- マクロはウィンドウ再構成マクロとしてだけ使うべきです.
- ウィンドウ再構成マクロを自分の手で書き換えるのは避けるべきです.パネルをデフォルトの状態に戻したいのなら,関数中で
DoWindow/R
を呼び出し,Igor Proにマクロを書き換えさせるべきです.
3.4 関数
関数の長さは50行(あるいは画面の高さの半分)に収めるようにします.
関数名にはCamelCaseを用います(ファイル名を表すために
SomeString_
といった接頭語を付けることは認められます).関数がそのプロシージャファイルの内部でしか使われないのなら,それらの関数は
static
にします*6.次のように,すべての変数を関数の初めの部分で定義します.
Function CalculatePressure(weight, size) variable weight, size variable i, numEntries // code End
これは,Igor Proではブロックスコープが存在しないからです*7.すなわち
if(someCondition) variable a = 4711 end print a
は正しいコードです.これはC/C++経験者を混乱させます.
4 リンク・文献
- ASCII: https://en.wikipedia.org/wiki/ASCII
- Doxygen: http://www.stack.nl/~dimitri/doxygen/index.html
- Git settings for Igor Pro code: http://www.igorexchange.com/node/6013
- Robert C. Martin, Clear Code: A Handbook of Agile Software Craftmanship, Prentice Hall (2008)
- How to write good commit messages: http://who-t.blogspot.de/2009/12/on-commit-messages.html
*1:訳注:新しいプロシージャウィンドウを作成したときに書いてある#pragma rtGlobals = 3 // Use modern global access method and strict wave access.を消すべきではないということ.
*2:訳注:Variable num ///< number of points のように,変数定義等の直後にその説明を置く場合
*3:訳注:例のように,変数名の頭に&を付けて引数を受け取ると,関数内での変数値の変更が関数の呼び出し元にも反映されるようになります.この機能を変数の参照渡しと呼びます.
*4:訳注:Igor ProヘルプファイルではVariable,Stringは大文字で始まります.この例外はおそらく,組み込み型が小文字で書かれるC/C++の慣習に合わせたものでしょう.
*5:訳注:プログラムに現れる,ぱっと見て意味の分からない数字のこと.
*6:訳注:関数定義をFunctionのかわりにstatic Functionで始めると,プロシージャファイルの外からその関数が使えなくなります.ただし,#pragma ModuleName=SomeStringによってモジュール化するとstaticな関数をファイルの外からも使うことができるようになります.
*7:訳注:if/endifブロックの内部で定義した変数はブロックの内部でだけ有効(ブロックスコープ)だと便利ですが,Igor Proではそうなっていない,ということ.