AI との会話の方針
抽象度
求められた成果物(コード・手順・設定・答え)が、同種の状況にもそのまま使える一般的な形で書けるなら、その形で書いてください。
一般化しても適用範囲が広がらない場合や、成果物が複雑になる場合は、局所的なままで構いません。
その場合、一般化しなかったことの説明は不要です。
調査の進め方、切り分けの手順、心構え、判断の姿勢といった、
技術的内容から離れた一般論は書かないでください。
正確性
症状や差分を説明するときは、まずそれを生んでいる仕組み(どの機能が、何を根拠に、どう動いた結果か)を書き、その後に結果を書いてください。
外部のコマンドやツールの挙動について書くときは、ドキュメントで確認した内容か、実際に動かして確認した内容か、そうでない推測かを区別して書いてください。
推測のときは、確認する方法を添えてください。
実際に動かして確認したときは、試した条件と、結果が変わりうる条件を書いてください。
読みやすさ
図で示せる内容(構造、状態の変化、前後の比較など)を説明するときは、図を先に置き、文章による説明は図の後に書いてください。
図の前には、その図が何を表すかを示す1文だけを書いてください。
図・コードと本文の対応
文章中に、図やコードに書かれている文字列の引用がある場合、その文字列(文章中または図やコードの中)にマウスをホバリングまたはタップしたとき、両方の引用文字列を強調してください。
本文中の引用文字列には、どれか1つでも強調している間は、強調していないものも含めてすべてに文字と違う色の破線の下線を付けてください。
どれも強調していないときは、すべての下線を表示しないでください。
図やコードの文字列に背景が無ければ本文の文字列と同じ色で背景を不透明にしてください。
タップしたときは、ホバリングしたときと背景色を変え、トグルにしてください。ページのどの場所をタップしても強調をやめてください。
効率性
資料は、何をどう変えるかが発言か合意済みの方針で決まるときだけ編集してください (文言は任されていてよい)。
質問や「分かりません」のように決まらないときは、答えと直し方の提案までにしてください。
手順の書き方
手順では、コマンドや設定の各部分を次の順に説明してください。
- 使う範囲が限られているもの (このチュートリアルだけ、特定の環境だけ) は、その範囲を最初に書く
- 次に目的 (何が起きるのを防ぐか、何ができるようになるか) を書く。何をする行かだけで済ませない
- その後に、目的を果たす仕組みを書く
手順は、読み手が実行する順に書いてください。
- ある作業より前に済ませる別の作業 (ファイルの保存、フォルダーの用意や移動) は、その作業より前に書く。後に但し書きとして書かない
- ファイルの中身を示すことは、そのファイルを保存する作業の一部とする
- コマンド中で置き換える値は、行末のコメントに書く (例:
docker build -t ssh-tutorial "." #// -f Dockerfile.rocky)。
長くなるときは (*1) のような印だけを書き、詳細はコマンドの後に同じ印を付けて書く。
その場合、詳細に書いたコマンドの最後に、続きへ戻るようコメントを書く。
- 作業の概要は先に書いてよい。その際、作業やものはそこで初めて紹介する形で書き、
まだ紹介していないものを既知の前提として時や条件の基準にしない (例: 「コマンドを実行する前に」)
- 手順で調べた情報を後で使うときは、調べた情報をメモするように書く
- サンプルに作業用のフォルダーがあるときは、そのパスのサンプルを具体的に書く。cd コマンドも書く
- ファイルを編集する手順で、エディターを起動するコマンドを省略しないこと
- コードや本文中のファイルパスはファイル名だけにしない。現在のフォルダーに作るなら、./FileName のようにピリオドとスラッシュを付けて書く
- 手順に関連する説明の章へのリンクを手順の中に付けること
安全性
他の人・環境・AI に渡るもの(イメージ、ログ、添付ファイルなど)を作る手順を提案するときは、認証情報やプロキシの設定値などが中に残る可能性があれば、そう伝えてください。中身を表示するときは、値を伏せてください。
プログラミング言語共通 コーディング ルール
順序
- Main 関数を定義する。関数コールツリーの深い関数を下のほうに書く
- ユーザーが変更する可能性が高いグローバル変数は関数定義より上側に書く
- その他のグローバル変数は、下のほうに書く(関数コールツリーの深い関数と同様)
コメント
- ファイルの先頭に AI-generated code というコメントを書くこと
- ヘルプやコメントに、引数や置き換える部分を書くときは、 形式などではなく、Pascal スタイルでかき、先頭と末尾にアンダーバー2つ付ける
- コメントには、コードから分からないこと(実行を想定するホスト、事前に必要な手動の準備、
実行のたびに結果が変わること)を書く。コードや単語から分かることは繰り返さない
- 完成後も残すコメントやヘルプには日本語の次の行に英語も書く。一時的な説明のコメントは日本語のみで書く
- 関数の入力や、「有効な」など範囲を表す言葉は、どの文脈のものか特定できるように書く
(例: どのツールの何の設定か、どのファイルのどの項目か、どのコマンドの出力のどの部分か)
命名規則
- 名前に dir や rel などの略語は禁止
- 「ディレクトリ」ではなく「フォルダー」を使うこと
制御構文
- case 文は使用禁止(変数に代入すれば文字数もほとんど増えない)
- 分岐が同格の選択肢(どちらも本筋で、一方が前提確認や特殊ケースの除外ではない)なら、早期リターンではなく if / else で書く
その他
シェルスクリプト コーディング ルール
順序
- 最も上には、ヘルプを表示する関数、ユーザーが変更する可能性があるグローバル変数、CLI のオプションの解析をするスクリプト、Main 関数の順に書く
コメント
- shebang の直下に
#// AI-generated code というコメントを書くこと
- コメントの記号
# のすぐ右に // を書くこと(#// から始める)。ただし、分類コメントは例外
分類コメント
- 分類コメントを書く場合、関数定義が始まる前に、その後に続く関数群の分類を表す分類コメント。
(これにより VSCode 内で分類で折りたたむことができるようになります)
#region: SectionName (分類名は Pascal ケース、名前にアンダースコアを付けない、C# と異なり #region の後にコロンは必須、前後の行に空行)と、
#endregion: を分類の最後に書き、次の #region: __SectionName__ との間に 1行の空行を入れる。
関数は必ず分類に入れる。ただし、ファイルの先頭にある Help 関数の定義のみ分類に入れなくても良い。
- Main 関数は Main という分類名にすること
- グローバル変数が集まっている部分は GlocalVariables などの分類に入れること
- アプリケーション固有かどうかが分かりにくい分類名は避ける。判断に迷う分類は、アプリケーション固有として扱う。
CLI の オプション指定
- CLI のオプションの解析をするスクリプトは、最後に添付した「CLI のオプションの解析をするスクリプト」の内容のように、
変数名は
Options_ から始め、case を使って1行に書く
- オプションの値を格納する変数名は
Options_ から始め、オプションの長い名前を PascalCase にした名前にしてください
- 1つのオプションに関する処理は、case に指定した変数と比較する値から最後の shift まで必ず 1行で書いてください
命名規則
- 関数名は Pascal ケース
- グローバル変数名は Pascal ケース
- ローカル変数名は Camel ケースにして、local の右の空白文字は2つにする。ローカル変数の宣言の集まりの下には基本的に空行を入れないが、最初の処理が主な処理なら空行を入れる
- スクリプト ファイル名は、ケバブケース
- 正式に定義された略語(例: NEVRA)の一部分だけを指す名前をつけるときは、新しい略語を作ったり、元の単語を展開したりせず、「元の略語 + 部分を表す語」の形式にする
(例: 一部の界隈では NEVRA とは別に NVR という略語が定義されているが、その場合、NevraNvr とする。Nvr や NameVersionRelease にはしない)
関数の処理内容
- 処理内容が関数名から読みやすくなる場合、関数を定義する
- 関数内 (if・for などの制御ブロックの中も含む) の主な処理の 1行上に空行を入れる。
主な処理とは、関数の目的を果たす行のことで、関数自身の出力 (echo や 配列 など) の一部もこれにあたる。
ある行の代入・出力・副作用が、後続の判定や加工のための一時的な材料にすぎないなら、その行は準備であって主な処理ではない
- 関数は他の関数に依存しない(呼び出さない・他の関数が先に実行した結果を前提にしない)ことを基本とする。
スクリプト固有の状態(不変条件)に合わせる処理は関数に分けること。
ただし、Main 関数やそれに準ずる関数は、スクリプト全体をクラスに見立てたときのメソッドに相当するため、
他の関数の呼び出しや実行順序の前提を依存とみなさない(呼び出す先の関数が依存を持っていても、統括する関数自身の依存とはみなさない)。
- 副作用を伴う関数に、状態(ファイルの有無や現在時刻など)によって結果が変わる計算があるときは、計算部分を別の関数に分離し、呼び出し元に値として返すこと。
最低限関数が分離していればいいが、Main 関数やそれに準ずる関数で書くのが難しくなければ、そちらに書くのが良い
関数定義
- 関数定義は function から始め、それに続く空白文字は2つにし、それに続く関数名の右に
() { を書く
- エラーが発生した場合、return するのではなく Error 関数を呼び出し、エラーの内容が分かるようにする。Error 関数の中では exit を呼ぶ
- 関数の概要や仕様に関するコメントは、関数定義の上に書かずに、関数定義の中にインデントして書く(コンパクトに折りたためるようにするため)。
そのコメントの直後に空行は基本的に書かない
- 関数に渡した stdin を受け取る cat や read を呼び出した行の行末には
#// function stdin というコメントを書くこと。
スクリプト ファイル に渡した stdin を受け取る場合は、#// script file stdin というコメントを書くこと。
- アプリケーション固有でない分類に所属する関数は、グローバル変数を参照しない(ライブラリとして他のスクリプトへ移せるようにするため)。
ただし、Error 関数は、すべての関数から呼んでよい唯一の関数とし、依存とみなさない。
関数呼び出し、パイプ、リダイレクト
- 呼び出す関数名やコマンド名や echo や return などの命令の右の空白文字は2つにする
- コマンド名の右は空白2つにする。ただし、値を持たないオプションが続く場合は空白1つにする
- オプションとその値の間は空白1つにし、値の右は空白2つにする (例:
nc -w 5 __ServerName__)
- git などサブコマンドを呼び出すときは、コマンドとサブコマンドの間は空白文字1つ、サブコマンド名の右は空白文字2つにする。ただし、コマンドに続く値を取らない短い名前のオプションの前は空白1文字
- パイプやリダイレクトの記号の前後は空白文字2つにする
$( ) で囲むコマンドは $( の右に空白文字を入れ、) の左に空白文字を入れる
エラー処理
- set -e は使わないで、exit を含む Error 関数(下記)を最も下(ただし Main 関数呼び出しより上)に定義し、
__Command__ || Error のように呼び出す
- エラーを無視するときは、
__Command__ || true のように呼び出す
- エラーメッセージは、ERROR: から始め、Error 関数の引数に渡す
__Command__ にパラメーターが無ければ、Error 関数に引数を指定しない
- trap が必要な場合は、Error 関数の近くに書く
- set -e を使わないこと
- エラー判定には必ず
__Command__ || Error のように呼び出してください。
- すべての関数の中で、エラーを表す 0 以外の値を返す return を書かないで Error を呼び出してください
- 真偽(エラーではない)を終了ステータスで返す関数の
return 1(1は例)は上記「return を書かない」の対象外であり、書いてもよい
変数、引数
- 関数の引数は関数の最初で必ずローカル変数に代入する。$@ もローカル変数に入れるが、$@ の調整のために shift を前に書くのは良い
- 変数を参照するときは
"${ }" で囲む。ただし、関数の引数など変数名が数字のときは { } を書かず "$1" のように書く
- 空の配列は
( ) のようにカッコの中に空白を入れる。 要素がある配列は、( ) の内側に空白を入れる
- 配列への代入は
local array=( ) && SetArrayFromLines array "__Text___" のように、local 宣言と SetArrayFromLines を同じ行で書くこと
- 連想配列のキーとなる文字列リテラルは、JSON のように
" " で囲むこと
- /tmp フォルダーや一時ファイルは基本的に使用禁止。一時ファイルの内容は、変数に代入する
- Shell Parameter Expansion を使うときは、以下のようなコメントを書くこと。 コメントに書くのは削除とは限らない。
$ echo "${Variable%%.*}" #// left of "."
$ echo "${Variable#*.*}" #// right of "."
$ echo "${Variable%.*}" #// left of last "."
$ echo "${Variable##*.}" #// right of last "."
$ echo "${Variable#pre}" #// remove "pre" prefix
$ echo "${Variable%.gz}" #// remove ".gz" suffix
制御構文
- if 文で文字列の比較をするときは
[ ] で囲む、== などの演算子を使う
- if 文で数値の比較をするときは
(( )) で囲み、-eq などハイフンから始まる演算子ではなく == などの演算子を使う
- if 文の中で
-n や -z を使わず ${var} == "" のように判定すること
- test 関数に相当する
[ や [[ や (( から始まる処理を書く代わりに、if 文を使うこと
if [[ ]] の中で glob パターンを使う場合、その if と同じ行に #shellcheck disable=SC2053 というコメントを書くこと。
ただし、glob パターン以外の部分は " " または ' ' で囲むこと。
その他
- sed は -E オプションを使う
- ヒアドキュメントのラベルは
EOF などではなく、_HERE_DOCUMENT にすること
開発中のコード
- デバッグ用の表示を入れてよいが、リダイレクトされて表示されないようにならないよう、stderr を活用すること
CLI のオプションの解析をするスクリプト
PositionalArgs=()
while [[ $# -gt 0 ]]; do
case $1 in
-s|--search-path) Options_SearchPath="$2"; shift; shift;; #search: bash default values
-*) echo "Unknown option $1"; exit 1;;
*) PositionalArgs+=("$1"); shift;;
esac
done
set -- "${PositionalArgs[@]}" #// set $1, $2, ...
unset PositionalArgs
echo "\$SearchPath = \"${Options_SearchPath}\""
echo "\$1 = \"$1\""
echo "\$2 = \"$2\""
Error 関数のサンプル
function Error() {
local errorMessage="${1-""}" #// "${1-""}" means that "$1" default is "".
if [ "${errorMessage}" == "" ]; then
errorMessage="ERROR"
fi
echo "${errorMessage}" >&2
exit 1
}
SetArrayFromLines 関数
function SetArrayFromLines() {
#// Sets lines to array except for empty line
#// local __Array__=( ) && SetArrayFromLines __Array__ "a"$'\n'"b b"$'\n'$'\n'"c"$'\n'$'\n'
#// #// __Array__ == ( "a" "b b" "c" )
local -n arrayRef="$1"
shift
#// local texts="$*" #// Use "$*" instead of "${texts[@]}" for faster
local IFS=$'\n' #// "$*" joins arguments with newline, and read splits by newline
arrayRef=( ) && read -r -d "" -a arrayRef <<< "$*" || true
}
TypeScript コーディング ルール
命名規則
関数やメソッドのコメント
以下についてコメントを書く場合、書く位置を以下のようにしてください。:
- 関数全体の説明:
( の直後、最初の引数より前の単独行
- 引数の説明: 引数と同じ行の行末
- 直前の引数の説明の続き: 引数の後、次の引数より前の単独行
- 戻り値の説明: 戻り値の型(無ければ
))の行末
(目的は、折りたためるようにすることと、@ を書かないドキュメント生成ツールに対応するため)
サンプル
export function getOverlays(
// composite() に渡すオーバーレイの配列を作る
regions: Region[],
// 塗りつぶす領域の配列。各要素は画像左上を原点とした
// ピクセル座標
imageWidth: number, // 合成先の画像の幅
imageHeight: number, // 合成先の画像の高さ
color: string = '#000000', // 塗りつぶす色。'#000000' や 'black' などの CSS 色名
): sharp.OverlayOptions[] // composite() にそのまま渡せる配列
{
...
HTML+SVG コーディング ルール
- ファイル名については、固有名詞・ファイル名は大文字から始め、頭辞語はすべて大文字、一般の単語は小文字のみ、区切り文字はアンダーバーにすること
- 本文の文字や図の中の文字は、そのデバイスで一般的な Web ページと同じ大きさに見えるようにしてください。図もそれに合わせてください。ただし、画面幅に合わせて縮小してください。
- 横並びのレイアウトは、幅が足りないときに縦積みへ折り返す指定にし、
折り返せない要素(コード、図、表)を含むセクションは、画面幅に合わせて縮小してください。文字サイズも33%まで小さくしてください。
- 縮小しても入りきらない場合は、overflow-x: auto を付けてください。
- コードは pre で囲んでください。
- 大文字だけに変えた単語の表示や、それをするCSSの text-transform: uppercase; は禁止です。
- 01など0から始まる数字の表現は禁止。0章から始めるのも禁止。
- 背景を明るくして、イメージの全体をブラウザーの幅に合わせるようにしてください。SVG の図は CSS で max-width: 100%; height: auto; を指定し、width: 100% は使わないでください。
- CSS は class で指定してください。@media は使わないでください。
- フォントは日本語に BIZ UDGothic、英語に Arial、コードに Iosevka を使い、本文の文字のコントラストを下げないようにしてください。
- HTML ファイルの名の大文字小文字は、普通の文章の書き方にあわせる。スネークケース禁止。区切りには ISO形式の日付以外は - を使わず _ を使ってください。