コードレビュー観点
- レビュアーは受け入れテストを実施しているか
- PR(Pull Request)作成者は修正した機能について、設計書も更新しているかどうか
- PR作成者は修正した機能に対して、ユニットテストの構築ならびに修正まで実施しているか
- 作成、更新したプログラムがアーキテクチャならびにデザインパターンに準拠しているか
- ログを組み込めているか
- 例外処理ちゃんとしているか
コードがうまく設計されている
機能性がコードのユーザーにとって適切である
UI の変更がある場合、よく考えられていて見た目も適切である
並行処理がある場合、安全に行われている
コードが必要以上に複雑でない
開発者は将来必要になるかもしれないものではなく、現在必要だとわかっているものを実装している
コードには適切なユニットテストがある
テストがうまく設計されている
開発者はあらゆるものに明確な名前を使った
コメントは明確で有意義なもので、「何」ではなく「なぜ」を説明している
コードは適切にドキュメント化されている(一般的には g3doc で)
コードはスタイルガイドに準拠している
今だと自分だとパッと読めないやつはGPTに追加で確認してもらうとかは良さそう
擬似コードを用いたメソッド設計におけるベストプラクティスについて、以下に詳細を説明します。これらのガイドラインを遵守することで、メソッドの可読性、保守性、再利用性を高めることができます。
1. 明確な命名規則
-
意味のある名前を使用する: メソッド名はその機能を具体的に表現するようにします。例えば、
calculateTotal
やfindUserById
など。 - 一貫性を保つ: プロジェクト全体で命名規則を統一し、同じ動作には同じ命名パターンを使用します。
2. シンプルで理解しやすいロジック
- 単一責任の原則: 各メソッドは一つの明確な機能に焦点を当てるように設計します。
- 複雑さを避ける: ロジックが複雑にならないように、必要に応じてメソッドを分割します。
3. 一貫性のあるインデントとフォーマット
- インデントを統一: 可読性を高めるために、インデントを一貫して使用します(例:スペース4つ)。
- ブロック構造を明確に: 条件分岐やループなどのブロックを明確に区別します。
4. モジュール性と再利用性
- 汎用的な設計: 再利用可能なコンポーネントとして設計し、特定の状況に依存しないようにします。
- パラメータの活用: 必要な情報をパラメータとして受け取ることで、メソッドの汎用性を高めます。
5. コメントの活用
- 必要最低限のコメント: コードの意図や複雑な部分を説明するためにコメントを追加します。ただし、自己説明的なコードを書くことを優先します。
- ドキュメントコメント: メソッドの目的、パラメータ、戻り値についての説明を記述します。
6. 入出力の明確化
- 入力パラメータの定義: メソッドが受け取るデータの種類と役割を明確にします。
- 出力の明示: メソッドが返すデータや結果を明確に示します。
7. エラーハンドリングの考慮
- エラーチェック: 入力データの検証や例外処理を組み込み、予期しない状況に対処します。
- 明確なエラーメッセージ: エラー発生時にわかりやすいメッセージを提供します。
8. テストのしやすさ
- テスト可能な設計: メソッドが独立してテストできるように設計します。
- 明確な動作: メソッドの動作が明確であるため、ユニットテストを容易に実施できます。
例: ユーザー情報を取得するメソッドの擬似コード
以下に、上記のベストプラクティスを取り入れた擬似コードの例を示します。
/**
* 指定されたユーザーIDに基づいてユーザー情報を取得する。
*
* @param userId ユーザーの一意識別子
* @return ユーザー情報オブジェクト
* @throws UserNotFoundException ユーザーが存在しない場合
*/
function getUserById(userId):
if userId is null or userId is empty:
throw InvalidParameterException("ユーザーIDが無効です。")
user = database.findUserById(userId)
if user is null:
throw UserNotFoundException("指定されたユーザーが見つかりません。")
return user
この例のポイント
-
明確な命名: メソッド名
getUserById
はその機能を具体的に示しています。 - ドキュメントコメント: メソッドの目的、パラメータ、戻り値、例外について説明しています。
- エラーハンドリング: 入力の検証とユーザーが見つからなかった場合の処理を行っています。
- シンプルなロジック: メソッドは単一の責任(ユーザー情報の取得)に集中しています。
- 一貫したフォーマット: インデントやブロックの構造が統一されており、読みやすさを確保しています。
まとめ
擬似コードを用いたメソッド設計においては、以下のポイントを意識することが重要です。
- 明確で一貫性のある命名
- シンプルで明確なロジック
- 一貫したフォーマットとインデント
- モジュール性と再利用性の確保
- 適切なコメントの追加
- 入出力の明確化
- エラーハンドリングの実装
- テストのしやすさ
これらのベストプラクティスを遵守することで、擬似コードによるメソッド設計が効果的かつ効率的に行えるようになります。
コードの動作確認: すべてのテストがパスしているか確認し、意図した通りに動作することを確認します。特に新しい機能や修正が正しく機能しているかを重点的にテストします14。
コミットメッセージ: コミットメッセージが明確で、何を変更したのかが分かるようになっているか確認します。PRのタイトルや説明も適切であるべきです1。
不要なコードの削除: デバッグ用のコードやメモ的なコメントが残っていないかを確認します1。
重複コードの排除: コード内に重複がないか、もし重複がある場合はその理由を明確にします1。
ブランチの確認: マージ先のブランチが正しいかどうかを再確認します1。
スタイルガイドへの準拠: プロジェクトで定められたコーディングスタイルやガイドラインに従っているか確認します13。
エラーハンドリング: エラー処理が適切に行われているか、例外処理が不足していないかを確認します1。
パフォーマンスへの配慮: 新しいコードがパフォーマンスに悪影響を与えないよう配慮されているか確認します1。
ドキュメントの更新: 変更内容に応じて関連するドキュメントやコメントも更新されているか確認します1。
可読性と一貫性: コードが他の開発者にとって理解しやすいものであるか、一貫性が保たれているか確認します3。
テストの網羅性: 十分なテストケースを用意し、特に境界値やエッジケースを考慮したテストを行います3。
リファクタリングの余地: コードが複雑になりすぎている場合や、重複したロジックが存在する場合は、それを整理します3。
コメントの充実度: コードの意図や背景を説明するコメントが適切に追加されているか確認します3。
レビューしづらさの解消: 自分が怪しいと思う部分にはリファクタリングやコメントを追加し、他のレビュアーが理解しやすいように配慮します4。
プルリクエストの単位を細分化: 一つのプルリクエストには一つの目的だけを持たせることで、レビュアーが理解しやすくなります4。
セルフレビューでやること
→ 何かを自動化できないか常に考える
実装前
-
仕様の確認
- デザインに添っているように見えるのであって、データの扱いは仕様の思想にあっているか?
- それは自分で考えた仕様ではないのか
- テストケースの確認
- ユースケースに対応できるもの
- エッジケース等も考慮されたもの
- インターフェース/クラスの設計をイメージ
- インターフェースとテストケースを先に書いてテストさせる
- テストケースにあったコードを生成させる
- 擬似コードによるメソッド設計
コード書いた後〜Push前
- 基本的に全てのコードにGPT(全体感、個に問い合わせて懸念点がないか事前にレビューさせる
- チェックリストを確認して自分でも問題ないことを確認
- AIにレビュー済みか(基本的に0 retentionのモノを使う)
- 仕様に沿った実装か
- エラー処理が適切に行われているか、例外処理が不足していないか
- バリデーションが最初にできているか(ガード節)
- デバッグ用のコードやメモ的なコメントが残っていないか
- トランザクションが適切に行われているか
- ログが適切に行われているか
-
新しいコードがパフォーマンスに悪影響を与えないよう配慮されているか
- 1つ1つのmethodの挙動を(内部のSQL処理まで丁寧に)気にする
- gpto1-mini → genspark
- 1つ1つのmethodの挙動を(内部のSQL処理まで丁寧に)気にする
- セキュリティ懸念はないか
- コード内に重複がないか、もし重複がある場合はその理由を記載
-
独自実装になっていないか、標準のAPIが利用できないか、他の方法はないのか
→ @Docs でベストプラクティスに沿ってるか聞く/GPTにそのまま聞く - SOLIDに基づいているか
PR起票前(ダブルチェックも兼ねる)
- PRのタイトル/ 説明 が適切か
- 仕様に沿った実装か、自分の仕様ではないか(再喝)
- テストが全てパスしているか/ユースケースに対応できているか
- コード内に重複がないか、もし重複がある場合はその理由を記載
- デバッグ用のコードやメモ的なコメントが残っていないか
- マージ先のブランチが正しいかどうか
- ラベルがXXLになっていないか
- 変更内容に応じて関連するドキュメントやコメントも更新されているか
- コードの意図や背景を説明するコメントが適切に追加されているか
- リファクタリングの余地: コードが複雑になりすぎている場合や、重複したロジックが存在する場合はそれを整理
- レビュワーに憑依して問題ないか最後にチェック
- プルリクエストの単位を細分化: 一つのプルリクエストには一つの目的だけを持たせる
→ レビュワーになった時は1行1行全て理解する。なんとなくでレビューしない。
(gpt-o1miniやgensparkでレビュー効率は上げられる)
仕様決め
- 要件の明確化
- why, what, howを整理
- why: ユーザー価値や将来のビジョン(思想)について双方で言語化できる状態
- what: 概念について認識あってるかきく
- how: データをどう出すかの議論セットに(データモデルはpdmも共有)
- 優先順位付け: 細かい部分でもやる(1時間以上かかるものに関しては)
- why, what, howを整理
→ データの扱い等の細かいところをGPTに漏れがないか聞けないか?
テストケースの作成
- テスト対象の成果物がある
- テスト設計ができている
- ホワイトボックス
- 制御パス: C1
- ブラックボックス
- 同値分割、境界値、直行配列
- 正常/異常
- 同値分割、境界値、直行配列
- ホワイトボックス
- テスト容易性(testability)を満たしている。
設計、実装の段階から、テストし易いプログラム、データにする
- 問題の所定を特定 -> なんちゃってプロブレムはくそ
- 原因を探る
- 施策
全体的な意識:
- 抽象化思考「要するに?」
- 具体化思考「例えば?」
- 水平思考「他には?」: ここ大事
- 批判的思考「本当に?」: ここ大事
数式でモデル化, 原因をプロセスで構造化させる
思考としては抽象化
発言は具体化