こんにちは
最近アプリケーションエンジニアと言いつつ、サーバーだらけ触ってるキムです。
今回はPJの品質管理と、今回品質管理で投入したツールの設定と、使い方について共有しようと思ってます。
入る前に
- golangciとcode climateを利用した経験になります。
- 詳細設定は各自PJの状況に合わせて調整したほうが良いです。
- 無理してプッシュするよりチームメンバーが納得できる範囲内で妥協することと、メンバーとの認識合わせを通じて、メンバー自ら努力するように環境を作るのが大事だと思います。
- golangciはGo言語に特化されてるツールです。言語ごとに色んなツールが存在するので、Go言語以外の言語を使う方はそれぞれ調べtください。
- code climate以外にもウェブを利用して、PJレポジトリを管理してくれるサービスはいくつかあります。こちらも調べてみてください。
- Sonar Qubeなどがありますね
品質管理てなんでするのか
品質管理はこんな意味を持ってます。
皆さんはコードの品質を管理してますか??
ユーザーに提供してるアプリケーションの品質を管理するのはものすごく重要なものです。 品質をちゃんと管理してないていうのは比較すると、 普段我々が使ってる色んな商品が何も品質保証無しで我々提供してると同じ意味合いになります。 そんな商品だと、皆さんは安心して購入できるでしょうか?
もちろんサービスをリリースする前には様々なテストを実装してると思います。これを専門的に行う人々をQAエンジニアと様な名前で読んでますし、彼らの存在は単純にリリース前のテストを行う人々ていう意味からはじめ、様々な役割を果たしてます。
この図は一番簡単に書いた、サービスがリリースされる前までのプロセスになります。省略された部分もあると思いますが、大きく見るとほとんどこのパターンで進めてると思います。
上記で話した、QAエンジニアが活躍するところは③の周りになります。
この記事で話したいのは図の①と②になります。
①はGolangCiの部分です、 ②はCodeClimate部分になります。
高いレベルのテストに入る前にコードレベルでの品質管理を厳しく行うことで、QAエンジニアの負担を減らせるし(簡単な動作バグや修正のデグレはまじで疲れますね。)、自分たちのコード品質に自身を持つことができ、コードを管理する基準を作ることでチーム員たちが共通の認識を持つことができます。
golangci について
Goにはbuilt-in
で提供してるPackageではfmtを含めていくつか有用なLintを提供してます。
このようなツールは単純にコーディングミスを探すことから、コードのインデントを整理したり(fmt)、不要なImportを消してくれたり(goimport)、変数や・関数を定義したけど使ってないことを教えてくれたりして、よりコードをきれいに管理できるように手伝ってくれます。
その中に、Golangを使う場合一番Publicなものがgolangciていうツールであります。 このツールは簡単なCiからはじめ、いろんなLinterを組み合わせて利用することで、プロジェクトをより簡単に管理してくれます。
提供してくれるLinterもこんなに多いので、どんな役割をするのか確認しながら、本人のPJで使えそうなものを投入しましょう。
code climateにていて
code climateは私達が、基本的にCLIベースでチェックしてたことをウェブ画面で、数値化されてより理解しやすいようにやってくれるし、PJが持ってる潜在的なIssueを事前に対応できるように、表示してくれたりするUI/UXを提供してくれるサービスであります。
独自的な計算アルゴリズムを利用して、PJのメンテナンス数値や、該当Issuesを対応することにかかる予想時間を表示してくれたりします。
更にGithubとの連携を利用して簡単にCodeClimateのIssueをGithubのIssuesにしてわかりやすくしたり、PRにコメントを作成してくれるので、いろんなワークフローが作れます。
ざっくり見る全体図
事前準備
- CodeClimateアカウントを持ってるのか
- Code Climateと、Githubのレポジトリを連動させる。
作業の流れ
- Localで作業する
- GitにPushする
- Github Actionsが走って
golangci-lint
チェック、coverage report
を作成 - 作成したレポートをCode Climateに転送
- Code ClimateでPJの状態を確認
カスタム設定について
golangci
公式ドキュメントを見ると、PJのRootに下記4パターンのフォーマットに設定ファイルを準備することで、ルールをカスタマイズするのが可能になります。
- golangci.yml
- golangci.yaml
- golangci.toml
- golangci.json
## golangci.yml
## code climate 側でチェックしてることと一番関係高い部分をカスタムで入れてます。
linters-settings:
nestif:
# minimal complexity of if statements to report, 5 by default
min-complexity: 4
gocognit:
# minimal code complexity to report, 30 by default (but we recommend 10-20)
min-complexity: 20
gofmt:
# simplify code: gofmt with `-s` option, true by default
simplify: true
nakedret:
# make an issue if func has more lines of code than this setting and it has naked returns; default is 30
max-func-lines: 100
issues:
# Excluding configuration per-path, per-linter, per-text and per-source
# テストコードの場合除外する。
exclude-rules:
- path: _test\.go
linters:
- errcheck
- gocognit
- nestif
- gofmt
linters:
# 利用するLinter
enable:
- nestif
- gocognit
- gofmt
- nakedret
fast: false
そして、このページをみると、普段提供してるDefaultのLinter以外に色んなLinterを提供してるので、この設定を追加して利用できます。
code climate
同じく公式ドキュメントを見ると会のフォーマットでチェック内容をカスタマイズするのができます。
このファイルがない場合、Defaultの値でチェックを行うし、簡単にチェックのOn/Offぐらいなら、設定ファイルを準備するより、ウェブページを利用するのがより簡単にできる。
- .codeclimate.yml
- .codeclimate.json
このページを見ると、各項目ごとにどんな内容をチェックするのかが、確認でき・設定するのができます。
version: "2" # required to adjust maintainability checks
checks:
argument-count: # parameter count
config:
threshold: 4
complex-logic:
config:
threshold: 15
file-lines:
config:
threshold: 500
method-complexity:
config:
threshold: 15
method-count:
config:
threshold: 20
method-lines:
config:
threshold: 50
nested-control-flow:
config:
threshold: 4
return-statements:
config:
threshold: 4
similar-code:
config:
threshold: # language-specific defaults. an override will affect all languages.
identical-code:
config:
threshold: # language-specific defaults. an override will affect all languages.
# 管理画面で除外するパターン
exclude_patterns:
- "config/"
- "db/"
- "dist/"
- "features/"
- "**/node_modules/"
- "script/"
- "**/spec/"
- "**/test/"
- "**/tests/"
- "**/vendor/"
- "**/*.d.ts"
- "**/*_mock.go"
ちょっと気になる項目がありますよね? おそらく下記2項目かと思います。
complex-logic: ## ロジックの複雑さ
config:
threshold: 4
method-complexity: ## メソッドの複雑さ
config:
threshold: 5
他の項目はなんとなくわかるが、この項目だけはなんか気になりますね。
どんな内容をチェックするのか…
公式ドキュメントを見ると、CodeClimate側では2つの軸で、複雑さを計算してるといいます。
本当にざっくり説明すると Cognitive Complexityは「人間が理解するのに問題ないのか」、をチェックすることです。 そして、Cyclomatic Complexityは「マシンが理解するのに問題ないのか」をチェックする方法です。
もし、より深く理解したいのであれば、こちらを読んでみてください。
そして、Qiitaではこのページでかならい優しく説明してくれてます。 おすすめです。
そして下記の2項目もまります。
similar-code: ## コードのかぶり
config:
threshold: # language-specific defaults. an override will affect all languages.
identical-code: ## 処理のかぶり
config:
threshold: # language-specific defaults. an override will affect all languages.
それぞれかぶりをチェックする項目であります。 基本的に各言語の設定に頼ってます。
簡単に説明すると、
func test1(a, b) int {
a = a + 1
return a + b
}
func test2(a, b) int {
a = a * 3
return a + b
}
ほんとにざっくり書きましたが、話してる内容は似てると思います。
similar
は、コード自体の重複ですね。 コードを書く時になんとなく名前だけ微妙に異なって、ほぼ同じぐらいのコードがあります。 このような場合検知され、Issuesになります。
identical
はやってる処理がほぼ似てる場合になります。
Aを取得して、Bを処理
、 Cを取得して、Bを処理
のように名前だけ微妙に異なって、処理はほぼ同じ場合、このようなものがあるから、Refactorしたほうがいいよ的な案内を出してくれるものです。
基準が言語に依存されてるので、自分もよくわかりません… もし、関連情報があれば教えていただくと助かります。
まとめ、
この作業を行いながら、コード品質管理について色々勉強する機械になりました。
単純に「テストコードを書いて、カバレッジを達成する」的なエンジニアとして活動してきましたが、このプロセスと投入しながら自ら品質てなんで管理しなきゃいけないのかとかあれこれ考えるチャンスになりました。
そして、このような指標を設定して、チーム員たちの目標を設定して、より高いチームワークを持つことができる機械になると思います。
ぜひ、みなさんもコード品質について深く考えて皆さんのPJにも投入して見てください。
まだ内容も足りないし、きれいじゃない記事ですが、読んで頂いてありがとうございます。