M言語コーディング標準 - ワンポイント・アドバイス(Do's and Don'ts)

M言語コーディング標準のヘルプ:

すること

文字セット

グラフィックなASCII文字のみを使用してリテラル文字列を構成します。非グラフィック文字の場合は、$TEXT() を使用して、$CHAR() または $ZCHAR() 関数を使用して文字列を構築したり、リソース・ファイルを使用したり、コメントからソースコードを構築したりします。

プロダクション環境で VIEW "BADCHAR" を使用します。

国際化

文字指向の操作用の標準M関数 - $ASCII() 、$CHAR() 、$EXTRACT() 、$FIND() 、$JUSTIFY() 、$LENGTH() 、$PIECE() 、$TRANSLATE() 。ロジックが文字操作ではなくバイトで呼び出すときに、類似のバイト指向関数 - $ZASCII() 、$ZCHAR() 、$ZEXTRACT() / $ZSUBSTR() 、$ZFIND() 、$ZJUSTIFY() 、$ZLENGTH() 、$ZPIECE() 、$ZTRANSLATE () 。$ZSUBSTR() を使用して、バイト指向の操作が有効な文字結果を生成し、操作が厳密にバイト指向で、文字として意味がない場合は$ZEXTRACT() を使用します。

大文字小文字の変換には、$TRANSLATE() / $ZTRANSLATE() ではなく、ZCONVERT() を使用してください。

エイリアス変数とコンテナ

エイリアス変数とコンテナを使用すると、モジュール性と適切なオブジェクトのようなアプローチが促進されます。

パラメータ パッシング(引数の受け渡し)

パラメータ パッシング(引数の受け渡し)を使用すると、スコープのリスクを最小限に抑え、暗黙的にルーチン/サブルーチンのインタフェースを文書化を促進します。オプションでパラメータ・リストの最後に渡される変数を配置します。副作用を避けるため、参照渡しの変数名を分かりやすく選択してつけてください。アクチュアリスト( actuallist )とフォーマルリスト( formallist )で同じ名前を使用するとは、ひじょうに意味があることに注意してください。

ネイキッド参照(Naked References)

行の幅を減らし、読みやすさを大幅に改善する場合を除いて、ネイキッド参照を避けてください。このような場合、他のコードの呼び出しを介さずに、同じ行で完全な参照に続けてネイキッド参照があることを確認してください。

入口参照(entryref)

別のルーチンからではなく、シェルからの呼び出しのために最上位の入口参照(entryref)を使用してください。Mコードから呼び出されるだけの意図するルーチンのシェルから不注意で実行される危険がある場合は、$STACKを使用してシェルから呼び出されたかどうかを検証するコードで最上位の入口参照(entryref)を保護します。ラベルを必要としないと文書化されたインタフェースを備えた既存のユーティリティ・ルーチンは、この要件から免除されます。

複数のコマンドを含む行

長すぎない限り、可読性を向上するために複数の関連コマンドを含む行を使用してください。無関係な複数のコマンドを含む行は避けてください。

行の幅

行を132列より大きくしないでください。

[注意] 注意

M言語の行指向の性質は、1つの長い行がコード・ブロックよりも読みやすくなることがあることを意味します。そのような、時折ある長い行は、正当な理由がある場合には許されます。

エラー処理

すべてのプロダクションのコードには、エラートラップが必要です。コードの目的が直接モードを呼び出すことでない限り、エラー・ハンドラはBREAKを明示的または暗黙的に使用してはなりません。プログラム・スイート内の基本エラー・ハンドラ、および場合によっては他のエラーハンドラは、予測不可能なエラーのコンテキストを適切に保存する手段を提供する必要があります。

新しいコードは、通常、$ZTRAPエラー処理ではなく、$ETRAPエラー処理を使用するべきです。変更の安全性をテストして検証していない限り、エラー処理の変更がリスクを伴う可能性があるため(データベース内にある間接参照など)、既存のコードにエラー処理を保持します。

トランザクション処理

テストを除いて、トランザクションを再始動可能にコード化し、トランザクション内で分離されていないアクション(BREAK、JOB、LOCK ZSYSTEM、I / O)を回避します; トランザクションのサイズを最小限に抑え、解決策が強い耐久性を必要としない場合やアプリケーションロジックで耐久性を提供する場合は、TRANSACTION="BATCH" を使用してパフォーマンスを向上させます。LOCKが適切な場合は、トランザクションの外に置きます。

BREAK

アプリケーションが不注意にダイレクトモードに落ちないようにするには、特定の使用要件がある場合にのみBREAKコマンドを使用します。BREAKコマンドをZBREAKを配置したコマンドよりも永続的にする必要がある場合、または行の中に配置する場合、例えば、BREAK:($get(debug)&(<condition>)) などのデバッグ設定で条件を設定してください。

引数なしDo

この言語構造体は、$TESTをスタックする埋め込みサブルーチンをコード化する方法を提供します - 何らかの外部関数($$)も同様ですが、入口参照(entryref)引数を持つDOはそうではありません。それはまた、言語の行指向の構造からいくらかのコストを払っているにもかかわらず、いくらかの救済を提供します。

ロジックがサブルーチンの複数の起動を呼び出すとき、同じ引数なしDOの本体の複数のコピーを使用することは避けてください。

最後のレベル・インジケーター(li)と最初のコマンドまたはコメントの区切り文字の間にはスペースを入れてください。

レベル・インジケータは、たとえコメントであっても、1つ以上のレベルを終了させるので、注意してください。

GOTO と ZGOTO

ネストされたロジックやネストされた関数呼び出しを効果的に終了させるためのロジックの処理や、テストコードでの適切な場合を除いて、GOTOコマンドとZGOTOコマンドの使用は避けてください。これらのコマンドをテストコードの外で使用する場合は、[Z]GOTOを削除するリファクタリングよりもそのような使用がうまく動作する理由を説明するコメントを含める必要があります。

HALT, QUIT, HALT

逆の明確な要件がない限り、ルーチンを終了するには、HALTではなくQUITを選択します。

M仮想マシンのスタック・レベルを変更しないFORからのQUITと、スタック・レベルを変更するサブルーチン/ルーチンからのQUITの違いを考慮してください。これには、サブルーチンを呼び出すFORを終了するための状態フラグの使用が必要な場合があります。

必要に応じて、引数なし(次のようにスペース2個が必要)または適当なQUITの値の形式を選択します。サブルーチンをDOまたは外部関数($$)のいずれかで呼び出すことができる場合は、$ZQUIT_ANYWAY の設定に頼るのではなく、代替の出口を明示的にコーディングします。

サブルーチン / ルーチンがHALTで終了しない限り、サブルーチン / ルーチンの終了時にQUITが必要です。引数なしDOレベルの最後のQUITはオプションです。

ZHALTを使用して、終了が異常であることをシェルを起動して返します。

LOCK, ZALLOCATE, ZDEALLOCATE

常にLOCKコマンドまたはLOCK +コマンドでタイムアウトを指定してください。

デッドロックを最小限に抑えるために、リソース名の順序にプロトコルを使用します。ZALLOCATEおよびZDEALLOCATEではなく、標準インクリメンタルLOCK(+/-)を使用してください。

NEW

要件を満たす以外は、引数がなく排他的なNEWの使用を最小限に抑えます。これらの異形は、アプリケーションの基本ルーチンの初めに適切な場合があります。

READ

NOFOLLOWモードのファイルからREADする場合を除き、常にタイムアウトを使用してください。未処理または外部で検証されたデータを収集する場合を除いて、ローカル変数をREADし値が適切であることを検証する - 長さ、範囲、区切り文字、任意の値の制限をチェックします。入力が期待通りであると仮定して使用する前に、必ず入力を検証してください; 間接指定またはXECUTEで使用する場合、またはグローバル変数に永続的に格納する場合は、これが重要です。

SET

複数のノードを同じ値に設定する場合は、SET (A,B,C)=0 vs SET A=0,B=0,C=0 のように、別々にではなく、カッコ内に名前のリストを指定します。

XECUTE、間接指示、$ZSYSTEM および PIPEデバイス・コマンド

ランタイム・エラーを最小限に抑え、設計外のユーザーによる結果を防止するために、間接演算子、XECUTEコマンド、ZSYSTEMコマンド、およびPIPEデバイスコマンドで使用する文字列がプログラムの設計と実装のどちらかで有効であるか、使用前の値を検証することが必要です。

Else

注意してELSE使用してください。GT.Mは、外部関数または引数なしのDOコマンドの実行だけの時に$TESTをスタックするので、任意のXECUTEまたは引数ありDOは、$TESTを変更することの潜在的な副作用があります。

後付け条件

1つのコマンドまたは制御引数の転送の条件付けを行う場合と$TESTを設定する必要がない場合は、パフォーマンスにわずかな利点があり、条件をアクションに緊密に結びつけることで可読性を向上させる傾向をするために、後置条件を使用します。たとえば、IF <condition> SET より SET:<condition>を選択します。

$ZDATA() と $DATA()

論理がエイリアスの意味を含むことを無視する必要がない限り、$DATA() ではなく$ZDATA() を使用してください。

$Increment

INCREMENT() の副作用を利用するために、IFを使用してINCREMENT() の結果を破棄することができます。

$Next

$NEXT() ではなく$ORDER() を使用してください。これは非推奨です。

$Piece()

データの部分文字列抽出(piece)を複数回使用する場合は、同じデータの部分文字列(piece)を抽出するために$PIECE() を繰り返し呼び出すのではなく、ローカル変数にデータを抽出して再利用します。

$Random()

$RANDOM(1) は常に0を返しますので、決して適切ではありません。$RANDOM() の結果を適切な算術演算で調整して、目的の範囲を達成してください。

$ZPREVIOUS()

$ZPREVIOUS(x) ではなく標準$ORDER(x,-1) を使用してください。

$ETrap 対 $ZTRAP

正当な理由がない限り、$ZTRAPではなく$ETRAPを使用してください。

$KEY 対 $ZB

ターゲット・デバイスの$KEYを維持しない古いバージョンのGT.Mでコードを実行する必要がない限り、$ZBではなく$KEYを使用してください。

$STack 対 $ZLEVEL

算術演算の除去または$ZLEVELの既存の用途が、変化を起こすリスクが非常に高いことが多くない限り、$ZLEVELではなく$STACKを使用してください。

$ZCMDLINE

$ZCMDLINEからのすべての入力を、ユーザー入力用のREADからのものであるかのように検証します。

外部関数と特殊変数 ($$)

サブルーチンが単一の値または値の配列を返す必要がある場合は、スコープのリスクを最小限に抑えるために、DOを介した外部呼び出しを選択します。

トリガ

GT.Mはトリガ・コードのI / O操作を制限しませんが、トリガ・アプリケーションコード内でOPEN、USE、READ、WRITE、CLOSEを使用しないでください。このような操作は、開発および診断の目的に役立つ可能性があります。トリガはTPトランザクションとして暗黙的に実行され、JOB、LOCK、ZSYSTEM、外部呼び出しの実行と同様に、I / Oは分離のACIDプロパティに違反します。($&) .

トリガ・コードの包括的で強力なコーディング規則を使用するか、トリガの削除と置換を管理する際にユーザーが指定した名前に頼ってください。

デバッグにトリガを使用する場合を除いて、トリガを使用する領域はジャーナリングを使用してください。

コール・イン/コール・アウト(Call-in/Call-outs)

外部関数でgtm_malloc / gtm_freeを使用すると、外部呼び出しでメモリ管理の問題が発生した場合のパフォーマンスの向上とデバッグ機能の向上が得られます。

gtmxc_types.h で定義された gtm * t 型を使用して、ネイティブ型(int、float、charなど)の代わりに使用して、パラメータ型とのサイズの不一致を回避します。

自動再リング(Autorelink)

auto-relink-enable または auto-relink-disable は、$zroutine 内のプロセスの存続期間中のディレクトリを無効にします。

すべてのプロセスに同じ値の $gtm_linktmpdir を使用してください。内容がZRUPDATEの対象となるディレクトリを共有するすべてのプロセスが $gtm_linktmpdir に同じ値を使用するようにして、すべてのプロセスが更新通知を参照するようにします - $gtm_linktmpdir の値が異なると、$gtm_linktmpdirの値が1つのプロセスによるZRUPDATEは、その環境変数の値が異なるプロセスでは観測されません。

してはいけない事(べからず集)

ソースとオブジェクト ファイル

オブジェクト・ファイルの名前を変更しないでください。

ルーチン名を作成するとき、コンパイラはオブジェクト・ファイル名を最大31文字に切り捨てます。たとえば、Adatabaseenginewithscalabilityproven.mというソースファイルの場合、コンパイラはAdatabaseenginewithscalabilityp.oというオブジェクトファイルを生成します。したがって、GT.Mルーチンにファイル名が31文字を超えないようにしてください。

kill -9

Don't killing a process with kill -9 を使用してプロセスを強制終了しないでください。データベースが破損する可能性があります。代わりにMUPIP STOPまたはMUPIP INTRPTを使用してください。プロセスがMUPIP STOPに応答しない場合は、最後の手段としてkill -9を使用してください。kill -9 はプロセスを突然終了させ、データベース・ファイルを不適切に閉じたままにして、MUPIP RUNDOWNを必要とします。kill -9 はデータベースの損傷を引き起こす可能性があるため、kill -9 の直後にMUPIP INTEGを実行します。

root として操作する

root としてルーチンを実行しないでください。

GT.Mのインストール以外に、rootとしてGT.Mの操作を実行しないでください。

トリガ

グローバル変数の同じ部分文字を更新する可能性のあるチェイン・トリガとネスト・トリガを使用しないでください。特に、任意のトリガ実行順序のために、データベース更新のチェイン・トリガを持つ重要性を常に評価する必要があります。

DSEで ^#t にアクセスしないでください。ただし、GT.Mサポートチャネルのガイダンスは除きます。MUPIP TRIGGERと$ZTRIGGER()でトリガ定義を管理します。

ローカル変数

添字に指数の数値形式を使用しないでください。あいまいさにつながる可能性があります。数値添字は文字列の添字より先に照合するため、文字列の添字の "01E5" は、数値添字の 01E5 と同じではありません。

決して $ZWRTAC "変数"を設定しないでください。これらはGT.MによってZWRITE出力をより便利にするために使用されますが、他の目的ではサポートされていません。それらは ZWRITE と ZSHOW "V" の出力でそれらを見るかもしれないので、ここで言及されています。

inserted by FC2 system