AWS CodeGuru ReviewerでPythonのコードを自動レビューしてもらおう

こんにちは。Kaneyasuです。
本記事はAmazon CodeGuruを使って、Pythonのコードを自動レビューを試みるという記事です。

# AWS CodeGuru Reviewerとは

https://aws.amazon.com/jp/codeguru/

Amazon CodeGuruはAIによるソースコードのセキュリティチェック、ソースコードのコードレビュー、アプリケーションのサンプリングからプロファイル作成を行うという3つの機能を持つサービスです。
それぞれ、Amazon CodeGuru セキュリティ、Amazon CodeGuru Reviewer
、Amazon CodeGuru Profilerと言います。
なぜかCodeGuruの公式ページではセキュリティの機能だけが前面に出ていますが、3つの機能があります。
本記事ではAmazon CodeGuru Reviewerを用いて自動コードレビューを試してみます。

なお、CodeGlueではなくGuruです。
ETLサービスにAWS Glueがあるため、スペルを間違えやすいですが、Guruです。

# AWS CodeGuru Reviewerの料金

https://aws.amazon.com/jp/codeguru/pricing/

10万行までは月額10$となります。
Amazon CodeGuru Reviewerを使用すると、その日に10ドルが即座に計上されます。

![Amazon CodeGuru Reviewerの料金の発生の仕方](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/50c7b9ff-9887-5079-7b4a-8ac17fd010b0.png)

# AWS CodeGuru Reviewerの使用方法

では使用方法に入っていきます。
AWS CodeGuru ReviewerはGitのリポジトリからソースコードを参照してコードレビューします。
従って、まずはGitのリポジトリと接続します。

AWS CodeGuruReviewerの左ペインで`リポジトリ`をクリック。
次に、`リポジトリを関連づけて分析を実行`をクリック。

![リポジトリの画面でボタンをクリック](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/1120c196-7050-5da2-e569-49d6e26cbadd.png)

新規登録画面となり、ソースプロバイダーを選択できます。
今回はAWS CodeCommitを選択します。
画面下にスクロールしてボタンをクリック、登録します。

![ソースプロバイダーを選択](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/6160ae32-9007-f729-d0bd-1d3d066cb74e.png)

登録後、左ペインの`コードレビュー`を選択します。
`フルリポジトリ分析`タブをクリックして、`フルリポジトリ分析を作成`をクリック。

![フルリポジトリ分析を作成をクリック](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/028c35df-27d2-0bb1-dd52-33b661fe86b6.png)

`フルリポジトリ分析を作成`の画面が開かれます。
`関連付けされたリポジトリ`に先ほど選んだソースプロバイダのリポジトリが出るはずです。
それから`ソースブランチ`を選択して、　`フルリポジトリ分析を作成`をクリックします。

![ブランチを選択してフルリポジトリ分析を作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/d71a7848-2e78-b8cc-cff2-65e853b87a33.png)

これで、選択したブランチのソース全体に対してコードレビューが走ります。

# AWS CodeGuru Reviewerのレビュー結果

上述のフルリポジトリ分析が終わるとレビューした指摘事項を見ることができます。
全体的な印象は下記の通りです。

- lintより賢く、細かいところを突いてくれる
- 大局的な視点、業務的な視点でのレビューは無理
- IaCのレビューをしてくれるのはありがたいが、過剰なことを言ってくることもある

IaCまで見てくれるのは嬉しいですね。
実際の指摘内容はこんな感じです。

## レビュー指摘①（Python）

```text:原文
To check if a container or sequence (string, list, tuple) is empty, use if not val. Do not compare its length using if len(val) == 0
```

```test:日本語訳
コンテナやシーケンス（文字列、リスト、タプル）が空かどうかをチェックするには、if not val を使用します。if len(val) == 0 を使って長さを比較しないでください。
```

```python:対象のソースコード
if len(val) > 0:
```

空判定に指摘が入りました。言われてみれば妥当ですが、細かい指摘ですね。

## レビュー指摘②（Python）

```text:原文
To return a single item from a list, we recommend using the list.index() method or indexing [] operator instead of a for loop.

Iteration when only one item is needed from list is inefficient and can make your code difficult 
```

```test:日本語訳
リストから単一の項目を返すには、forループの代わりにlist.index()メソッドまたはindexing []演算子を使用することをお勧めします。

リストから必要な項目が 1 つだけの場合に繰り返し処理を行うと、非効率的でコードが読みにくくなります。
```

```python:対象のソースコード
data_map: dict[str, list[str]] = {address: [key for key, value in host_mapping.items() if value == address] for address in address_list}
```

dictの再構成に指摘が入りました。こちら確かにindexの方が効率が良いようです。このコードは確かに読みにくく、良い指摘をもらえたと感じます。

## レビュー指摘③（Python）

```text:原文
This function calls 16 other functions. By comparison, 98% of the functions in the CodeGuru reference dataset use fewer. This indicates the function is highly coupled with other functions. A function that is highly coupled with other functions is difficult to understand and its behavior might change unexpectedly when one of its referenced functions is updated. High coupling could also increase the integration test complexity, maintenance cost and technical debt.
We recommend that you simplify this function or break it into multiple functions. For example, consider extracting the code blocks on lines 103-122, lines 125-131, lines 135-141, lines 146-155, lines 160-193 into separate functions.
The high number of functions called inside a function indicates that it is highly coupled with other functions. A function that is highly coupled with other functions is difficult to understand and its behavior might change unexpectedly when one of its called functions is updated. High coupling can also increase the integration test complexity, maintenance cost and technical debt.
```

```text:日本語訳
この関数は16の他の関数を呼び出している。これに対して、CodeGuruのリファレンス・データセットにある関数の98%は、より少ない数しか使っていません。これは、この関数が他の関数と高度に結合していることを示しています。他の関数と高度に結合している関数は、理解するのが難しく、参照されている関数の1つが更新されると、その動作が予期せず変更される可能性があります。また、高度な結合は、統合テストの複雑さ、保守コスト、技術的負債を増加させる可能性があります。

この関数を単純化するか、複数の関数に分割することを推奨します。例えば、103行目から122行目、125行目から131行目、135行目から141行目、146行目から155行目、160行目から193行目のコードブロックを別の関数に分割することを検討してください。

関数の内部で呼び出される関数の数が多いということは、その関数が他の関数と高度に結合してい ることを示しています。他の関数と高度に結合している関数は理解しづらく、呼び出された関数の1つが更新されると、その振る舞いが予期せず変化する可能性があります。高度な結合は、統合テストの複雑さ、保守コスト、技術的負債を増加させる可能性もあります。
```

メソッドが大きいすぎなので、分割した方がよいという指摘をしてくれました。

## レビュー指摘④（CloudFormationテンプレート）

```text:原文
Ensure that S3 buckets have cross-region replication enabled. By enabling cross-region replication for your S3 buckets, you create redundant copies of your data in different AWS regions. This helps improve data durability and availability, as well as provides protection against regional outages. It also allows you to comply with data residency requirements by replicating data to specific regions.
S3 buckets have cross-region replication not enabled. Ensure that S3 buckets have cross-region replication enabled.
```

```text:日本語訳
S3バケットでクロスリージョンレプリケーションが有効になっていることを確認する。S3バケットのクロスリージョンレプリケーションを有効にすることで、異なるAWSリージョンにデータの冗長コピーを作成する。これは、データの耐久性と可用性を向上させ、リージョン停止に対する保護を提供するのに役立ちます。また、特定のリージョンにデータをレプリケートすることで、データレジデンシー要件に準拠することもできます。

S3バケットのクロスリージョンレプリケーションが有効になっていない。S3バケットでクロスリージョンレプリケーションが有効になっていることを確認してください。
```

S3バケットのクロスリージョンレプリケーションを提案してくれました。
ありがたくはありますが、少々オーバースペックな提案でした。

## 増分コードレビュー

上記はフルリポジトリ分析による全体のコードレビューでした。
AWS CodeGuru Reviewerは、増分のコードレビューも可能です。
`リポジトリを関連づけて分析を実行`をしておけば、そのリポジトリでプルリクエストを作成すれば自動で増分レビューをしてくれます。

![プルリクエスト作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/1e7f9e5c-11d9-be4d-a810-e57f53204d34.png)

![数十秒後、CodeGuru側でレビュー開始](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/76db8db7-ad07-def8-c6ec-37918b328d20.png)

増分コードレビューの結果は、プルリクエストの`アクティビティ`タブに表示されます。

![増分コードレビューの結果は、プルリクエストのアクティビティタブに表示](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/199e33f9-6132-cded-b5fc-2a06ba47f223.png)

# AWS CodeGuru Reviewerの指摘事項をどう扱うか

AWS CodeGuru Reviewerは細かいところを見てくれており、lintよりも優秀だと感じました。
ただし、プロジェクトの事情は当然反映されないですし、全体の作りという観点での視点は無理のようです。
後者は将来はどうなるかはわかりませんが、現状レビュアーの完全な代替にはなりえないでしょう。
ですが、負荷軽減にはなりそうです。

プロジェクトの事情は反映されていないので、AWS CodeGuru Reviewerの指摘をオールクリアしないといけないとするのは現実的でないと思います。
事情を考えて対応しならいならそれでよいかと。
その辺どうするかはプルリクエストの作成者が、レビューアーが見る前にコメントとして書いておき、レビューアーの反応を見て判断を下す感じが落とし所かと思います。
lintを通した上の増分レビューならそこまでたくさんの指摘は出ないでしょうから、それで回るのではと予想しています。

# 最後に

今回はソースプロバイダにAWS CodeCommitを使用しました。
今後はGitHubも試してみたいと思っています。