Quantcast
Channel: Sider Blog
Viewing all 182 articles
Browse latest View live

Reek を使って嫌な感じのコードを取り除きましょう

$
0
0

コードを書いたり、読んでいて、何となく嫌な感じのするコードに出くわしたことはないでしょうか。そういったコードの存在はシステムの保守性や可読性を損なうものになります。Reekというツールではそれをコードスメル(悪臭のするコード)と呼んでいます。

Reek は多数のルールに基づいてRubyのコードを精査してくれます。そうして出力された結果を元に修正していくことで可読性の高いコードに直せるでしょう。今回はReekの利用法を紹介します。

Reek のインストール

インストールは Rubygems を使って行います。

$ gem install reek

Reek は 2.1〜2.4の MRI ruby に対応しています。JRubyやRubinius向けは公式ではサポートされていないものの動作するようです。

Reek の実行

実行は簡単で、ディレクトリを指定して reekコマンドを実行するだけです。

$ reek /path/to/project

ディレクトリまたは個別ファイルを指定できます。

そうすると問題のありそうな箇所をリストアップしてくれます。

$ reek . | more
lib/ncmb/acl.rb -- 16 warnings:
  [29]:BooleanParameter: NCMB::Acl#public has boolean parameter 'bol' [https://github.com/troessner/reek/blob/master/docs/Boolean-Parameter.md]
  [38]:BooleanParameter: NCMB::Acl#role has boolean parameter 'value' [https://github.com/troessner/reek/blob/master/docs/Boolean-Parameter.md]
  [33]:BooleanParameter: NCMB::Acl#user has boolean parameter 'value' [https://github.com/troessner/reek/blob/master/docs/Boolean-Parameter.md]
  [39, 40]:DuplicateMethodCall: NCMB::Acl#role calls '@fields[role.name.to_sym]' 2 times [https://github.com/troessner/reek/blob/master/docs/Duplicate-Method-Call.md]
  [39, 39, 40]:DuplicateMethodCall: NCMB::Acl#role calls 'role.name' 3 times [https://github.com/troessner/reek/blob/master/docs/Duplicate-Method-Call.md]
  [39, 39, 40]:DuplicateMethodCall: NCMB::Acl#role calls 'role.name.to_sym' 3 times [https://github.com/troessner/reek/blob/master/docs/Duplicate-Method-Call.md]

何の問題があるのかを提示したドキュメントのURLも出力されますので確認しやすくなっています。

-f [format]オプションを指定することで出力フォーマットが指定できます。例えばHTMLで出力する場合は次のようになります。

$ reek -f html . > result.html

f:id:a_nakatsugawa:20170619091636p:plain

フォーマットは text(デフォルト)/html/yaml/json/xml/code_climate が指定できます。

todo ファイルを作る

恐らく最初に Reek を実行すると多数の警告が出るはずです。それらをすべて、いきなり対応するのは困難でしょう。そこで一旦 todo ファイルを作成してみましょう。

$ reek -t .
'.todo.reek' generated! You can now use this as a starting point for your configuration.

こうすると .todo.reek というファイルが生成されます。これは警告内容をすべてオフにした Reek 用の設定ファイルです。内容は次のようになっています。

$ cat .todo.reek
---
BooleanParameter:
  exclude:
  - NCMB::Acl#public
  - NCMB::Acl#role
  - NCMB::Acl#user
DuplicateMethodCall:
  exclude:
  - NCMB::Acl#role

つまり、この設定ファイルを指定して実行すると警告が一切出ません。設定ファイルの指定は -cオプションになります。

$ reek -c .todo.reek 
Inspecting 32 file(s):
................................
 
0 total warnings

もちろんこのままでは意味がありませんので、徐々に設定を有効にしながら修正を進めていけば良いでしょう。

Reekはデフォルトで .reek という設定ファイルを読み込んで使います。ある程度の設定ができあがってきたら、 .reek にリネームすると良いでしょう。なお、SideCIでのオススメ設定はこちらの内容になります。

指摘される例とその回避策

例えば一つのクラスが多くのメソッドを持っていることを指摘します。デフォルトでは15以上のメソッドを持っていると TooManyMethods の警告が出ます。他にもイテレータがネストになっていると NestedIterators の警告が出ます(デフォルトは1つのネストで警告)。他にも複数回のメソッド呼び出しに対する警告もあります。

こうした警告の中には回避しようのない場合もあるはずです。設定ファイルを記述する方法もありますが、ソースコード中のコメントで回避することもできます。例えば複数回の呼び出しに対する警告を回避する場合は記述です。この時だけ設定を変更できます。

# :reek:DuplicateMethodCall { max_calls: 2 }
def user(user, read_or_write, value = true)
  @fields[user.objectId.to_sym] = {read: true, write: true} unless @fields[user.objectId.to_sym]
  @fields[user.objectId.to_sym][read_or_write.to_sym] = value
end

Reek の指摘はとても数多いので、コメントや設定ファイルを使って必要なものだけをピックアップして採用するのが良さそうです。SideCIのオススメ設定ファイルを利用するのもぜひ検討してください。


Reek は個人のローカルコンピュータ上で実行することもできますが、複数人での開発体制になったならばクラウドで全員分まとめてチェックできる仕組みが便利です。SideCIはReekにも対応しており、皆さんのRubyプロジェクトを保守性、可読性ともに高い状態に維持します。トライアルも提供していますのでぜひご利用ください


Dockerで素早くRubocopによる自動コードレビューを実現する

$
0
0

RuboCopを使えばRubyのコードを静的解析してコードレビューを他の人にして貰う前にいくらかの内容を機械的にチェックできるようになります。RuboCopのインストール自体はRubygemsでできるのでさほど難しいものではありませんが、ローカル環境の変更はなるべく控えたい方もいるでしょう。そこでDockerを使ってローカルの環境に依存せずにRuboCop環境を整える方法を紹介します。

Dockerについて

Dockerについては皆さん知っていると思いますので簡単に説明すると、Linuxコンテナ技術になります。OS全体を仮想化するのではなく、最低限のライブラリやアプリケーション単位でコンテナと呼ばれる仮想環境を作ります。そのためOS単位での仮想環境に比べると軽量で、瞬時に立ち上がるのがメリットです。分かりやすく言えば各プロセスを仮想環境として保護することでセキュアでリソースが確保された状態で実行できるようになります。

f:id:a_nakatsugawa:20170601114401p:plain

DockerはLinux用に提供されていますが、WindowsやmacOSでも利用できます。こちら(Windows版macOS版)からダウンロードできますので、各自の環境にインストールしてください。

RuboCopを試す

では実際の方法ですが、レビューしたいRubyプロジェクトへ移動して次のようにコマンドを打ちます。今回はcagedata/rubocop - Docker Hubのコンテナを利用しています。Rubyは2.3になります。

$ docker run --rm --volume "$PWD:/app" cagedata/rubocop

初回はコンテナイメージをダウンロードするので若干時間がかかります。ダウンロード、デプロイが完了すると次のように実行結果が表示されます。

$ docker run --rm --volume "$PWD:/app" cagedata/rubocop
Inspecting 35 files
.CCCCC.C...CWCWWCCCCWWCCCWWW..WWCCC
 
Offenses:
 
ncmb-ruby-client.gemspec:12:24: C: Use %q only for strings that contain both single quotes and double quotes.
  spec.description   = %q(A simple Ruby client for the nifty cloud mobile backend REST API)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  :

次回以降はすでにコンテナイメージがありますので、ローカルでRuboCopコマンドを実行するとほぼ変わらない速度で結果が得られるようになります。

バージョンアップなど

この Dockerfile(Docker用の設定ファイル)は次のようになっています。

FROM ruby:2.3
MAINTAINER "Dave Long <dlong@cagedata.com>"
 
ARG version=0.43.0
 
RUN gem install rubocop -v ${version}
 
WORKDIR /app
VOLUME /app
 
COPY docker-entrypoint.sh /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]

RuboCopのバージョンは0.43.0固定となっています。もし更新された時には手動で書き換えて、改めてDockerコンテナのビルドを行う必要があるようです。

手軽に実行できますのでお試しください。


なおSideCIでは常に最新版のRuboCopを利用できます。もちろんDockerをインストールするような手間もなく、クラウド上ですぐに実行環境が手に入ります。無料トライアルもありますので、ぜひご登録ください

PHP_CodeSniffer 3.0への移行のご案内

$
0
0

PHP_CodeSnifferはPHPのコーディングスタンダードのチェックを自動化し、チームで統一するための非常に優れたツールです。SideCIでは、バージョン2.9.1をサポートしており、既に多くのお客様にご利用いただいております。

先日、PHP_CodeSniffer 3.0がリリースされました。従来、解析ツールのアップデートはバックグラウンドで自動的に行われておりましたが、今回のアップデートでは後方互換性のため、設定の切り替えによって2.9.xと3.0を同時にご利用いただけるようになっております。

ご利用方法

ルートディレクトリ配下にsideci.ymlを作成していただき、以下のようにversion: 3を指定することで、今すぐPHP_CodeSniffer 3.0をお試しいただけます。

linter:
  code_sniffer:
    version: 3

なお、特にバージョンを指定されない場合には、従来通り2.9.xによる解析が実行されます。

後方互換性について

多くの場合、特別な設定無しに3.0をそのままご利用いただけますが、PEARやPSR2などの標準で用意されているコーディングスタンダード以外をご利用の場合には、3.0のために設定の修正が必要になる場合がございます。詳しくは公式のアップグレードガイドをご覧ください。

また、2.9.xではCakePHP, CodeIgniter, FuelPHP, Symfony, WordPressなどのサードパーティ製コーディングスタンダードをサポートしておりましたが、3.0では、2017年7月3日時点でCakePHPのみの対応となります。それぞれのバージョンでご利用いただけるコーディングスタンダードは以下の通りです。

2.9.x

$ phpcs -i
The installed coding standards are FuelPHP, Symfony2, CodeIgniter, CakePHP, PEAR, Zend, Squiz, PSR2, PHPCS, PSR1, MySource, WordPress-Docs, WordPress-Extra, WordPress-VIP, WordPress and WordPress-Core

3.0

$ phpcs3 -i
The installed coding standards are MySource, PEAR, PSR1, PSR2, Squiz, Zend and CakePHP

今後のサポートについて

PHP_CodeSnifferの新機能は3.0以降のみに取り込まれていき、2.9.xにはセキュリティパッチと深刻なバグ修正のみの反映となります。そのため、可能な限り多くのお客様に3.0をご利用いただければと考えております。本機能に関しまして、ご不明点がある場合には、お気軽にSideCI上のチャットボタンからお問い合わせください。

※本機能はアビシニアンモードのみ対象となります。クラシックモードをご利用のお客様は従来通り2.9.xのみのサポートとなります。

Go言語用のあらゆるLinterを丸っと並列実行する、gometalinterを使いこなそう

$
0
0

多くのプログラミング言語でもそのコードの静的解析を行い警告を出すツール、いわゆるLinterが存在します。特に最近出てきたプログラミング言語ではLinterがよく作られているようです。Linterがあることによって、良いコードの書き方がLinterのソースコードに蓄積され、それを使うことで、より良く開発を進めていく事が出来るでしょう。

Go言語でも同じく、Linterが存在しています。ただし、他の言語と違って、非常に多くのLinterが目的に応じて存在しています。PythonやRuby、PHPなどの言語では主要なLinterは10以下程度ですが、Go言語ではこの記事執筆時点で20以上のLinterが存在しています。それらを一つ一つ使ってチェックしていたら時間がかかってしまうでしょう。そこでそれらのLinterを並列して丸っと実行し、結果を正規化・見やすいようにまとめてくれる、gometalinterを紹介します。

gometalinterのインストール

gometalinterは goコマンドを使ってインストールできます。

go get -u github.com/alecthomas/gometalinter

gometalinter自体はLint機能は持っていませんので、外部のLintツールをインストールする必要があります。 --installオプションでまとめてインストールできます。

$ gometalinter --install
Installing:
  interfacer
    :
  misspell

これでセットアップが完了です。対応しているツールは以下の通りです。

以下のLinterはデフォルトで無効になっていますので、使う場合には --enableオプションで指定する必要があります。

gometalinterの使い方

使い方は簡単で、任意のGoプロジェクトのディレクトリまたはファイルを指定して gometalinterコマンドを実行するだけです。そうすると、どのファイルのどの場所でどんな指摘があったかが出力されます。その際、Lintツール名も表示されます。

$ gometalinter .
options.go:21:1:warning: ALL is unused (deadcode)
datastore.go:19:6:warning: don't use underscores in Go names; type memberinfo_st should be memberinfoSt (golint)
main.go:25:7:warning: don't use underscores in Go names; const sw_version should be swVersion (golint)
tagsparser.go:142:6:warning: don't use underscores in Go names; func datatype_supported should be datatypeSupported (golint)
dotmaker.go:46:8:warning: should omit comparison to bool constant, can be simplified to opt_blackbox (S1002) (gosimple)

後はこの内容に沿って修正していけば良いだけです。

オプションについて

主なオプションを紹介します。まず解析対象から外す場合は --excludeオプションを指定します。

$ gometalinter --exclude options.go .

Linterが多数使われるので、 --sortオプションで並べ替えが指定できます。指定できるのは path/line/column/severity/message/linterとなっています。

$ gometalinter --sort=linter .

出力フォーマットを変える場合は --checkstyleまたは --jsonで指定します。それぞれ CheckStyleフォーマット、JSONフォーマットで出力します。

設定ファイルについて

gometalinterも他のLintツール同様に設定ファイルで動作を変えられます。デフォルトで config.goというファイルになります。例えば以下のよう記述します。見ての通りですが、まずすべてのLinterを無効にして、その後使うLinterを指定します。

{
  "DisableAll": true,
  "Enable": ["deadcode", "unconvert"]
}

gometalinterを使えば多数あるLintツールを一まとめにして管理できます。ツールごとにコンセプトが違いますので指摘事項も異なります。すべてのツールをクリアすれば良いという訳ではありませんが、多くのツールを通過できるコードはそれだけ品質の高いコードになっていることでしょう。

SideCIではgometalinterをサポートしています。チーム内でGoプロジェクトを採用しているのであればぜひご利用ください。無料トライアルも提供していますので、まずはお試しを

TypeScriptの静的コード解析ツールTSLintを使い、コードレビューの前工程でコードをチェックしまいましょう

$
0
0

素のJavaScriptをチーム内でそのまま使うのを嫌がる方は少なくありません。型の定義ができなかったり、括弧が多く、分かりづらいコードになりやすいといった問題がよく言われます。そこで注目されているのがMicrosoft社がメインで開発を行っている代替言語のTypeScriptです。TypeScriptは変換処理を行うとJavaScriptになります。

そんなTypeScriptであってもチーム開発においては適切にコードレビューを行う必要があります。それをレビューの前工程、開発段階で少しでも楽にすることが出来る、静的コード解析ツールであるTSLintを紹介します。

TSLintのインストール

TSLintのインストールは npmコマンドで行います。

$ npm install tslint -g

インストールすると tslintコマンドが使えるようになります。

TSLintの使い方

TSLintは解析対象の .tsファイルを指定して実行します。パターンで記述することで複数ファイルも指定可能です。実行すると、修正した方が良いポイントについて出力されます。

$ tslint './*.ts'

ERROR: ajv.d.ts[156, 21]: Array type using 'Array<T>' is forbidden for simple types. Use 'T[]' instead.
ERROR: ajv.d.ts[15, 28]: Don't use 'Object' as a type. Avoid using the `Object` type. Did you mean `object`?
ERROR: ajv.d.ts[7, 13]: interface name must start with a capitalized I
ERROR: ajv.d.ts[219, 13]: interface name must start with a capitalized I

後はこの指摘事項に沿って修正していくだけです。

自動修正する

よくある指摘(例えば行の最後にスペースが入っているなど)であれば --fixオプションを使って自動修正ができます。

$ tslint --fix './*.ts'

このオプションで修正されないのは一行の最大文字数であったり、JSDocの記述、変数名の付け方(インタフェースは大文字のIではじまるべき)などについてです。こうした指摘については手動で対応していく必要があります。

設定を変更する

TSLintも他の解析器同様に設定ファイルで動作を変えられるようになっています。まず、 --initオプションを使ってベースになる設定ファイル tslint.jsonを生成します。内容としては次のようになります。

$ cat tslint.json 
{
    "defaultSeverity": "error",
    "extends": [
        "tslint:recommended"
    ],
    "jsRules": {},
    "rules": {},
    "rulesDirectory": []
}

この設定ファイルを編集することで指摘事項を制限できます。

出力フォーマットを変更する

デフォルトでは標準出力にエラーメッセージを出すだけですが、 --formatオプションを指定することで異なるフォーマットで出力できるようになります。例えば jsonと指定すれば結果がJSONになります。

[{"endPosition":{"character":33,"line":14,"position":658},"failure":"Don't use 'Object' as a type. Avoid using the `Object` type. Did you mean `object`?","name":"ajv.d.ts","ruleName":"ban-types","ruleSeverity":"ERROR","startPosition":{"character":27,"line":14,"position":652}},{"endPosition":{"character":25,"line":195,"position":7585},"failure":"Don't use 'Object' as a type. Avoid using the `Object` type. Did you mean `object`?","name":"ajv.d.ts","ruleName":"ban-types","ruleSeverity":"ERROR","startPosition":{"character":19,"line":195,"position":7579}}]

対応しているフォーマットとしてはJSONの他、 stylish / verbose / pmd / msbuild / checkstyle / vso / fileslist / codeFrameになります。


TypeScriptは大手企業を中心に広まっていますが、Visual Studio Codeなどのカジュアルなプログラミングエディタがサポートしていることもあって中小企業やスタートアップでも採用するケースが増えています。自社でTypeScriptを使っていくならばTSLintを使っていきましょう。

私たちの提供するSideCIはTSLintに対応しています。個人の開発であればローカルにインストールすれば良いですが、チーム開発であればクラウド上で自動でコードレビューを行ってくれる仕組みは効率的な開発体制につながるはずです。

SideCIは無料トライアルを提供しています。ぜひお試しください。

Brakeman を使って Rails プロジェクトのセキュリティインシデントを防ぎましょう

$
0
0

Rails の登場によってRubyが世界中のWeb開発に使われるようになっています。Rails はとても高機能で便利なフレームワークですが、何でもやってくれる安心感からか、セキュリティに気を配らずに実装されてしまうケースも見受けられます。適当な書き方をしてしまうと、 容易にセキュリティインシデントの原因となるコードを産んでしまうでしょう。

そこで使ってみたいのが Brakemanになります。セキュリティに重点を置いたRailsプロジェクトの静的解析ツールになります。

Brakeman のインストール

Brakeman は Rubygems でインストールできます。

$ gem install brakeman

もちろん Rails プロジェクトの Gemfileに記述してインストールも可能です。

group :development do
  gem 'brakeman', :require => false
end

Brakeman の使い方

使い方は brakemanコマンドをRailsプロジェクトを指定して実行するだけです。

$ brakeman /path/to/rails/project

そうすると解析が実行されて結果が出ます。例えば以下のような結果が出ます。リダイレクトであったり、ビューに関する警告が出ています。

+BRAKEMAN REPORT+

Application path: /path/to/rails/project
Rails version: 4.2.8
Brakeman version: 3.6.2
Started at 2017-06-11 16:22:29 +0900
Duration: 0.357863 seconds
Checks run: BasicAuth, BasicAuthTimingAttack, ContentTag, CreateWith, CrossSiteScripting, DefaultRoutes, Deserialize, DetailedExceptions, DigestDoS, DynamicFinders, EscapeFunction, Evaluation, Execute, FileAccess, FileDisclosure, FilterSkipping, ForgerySetting, HeaderDoS, I18nXSS, JRubyXML, JSONEncoding, JSONParsing, LinkTo, LinkToHref, MailTo, MassAssignment, MimeTypeDoS, ModelAttrAccessible, ModelAttributes, ModelSerialize, NestedAttributes, NestedAttributesBypass, NumberToCurrency, QuoteTableName, Redirect, RegexDoS, Render, RenderDoS, RenderInline, ResponseSplitting, RouteDoS, SQL, SQLCVEs, SSLVerify, SafeBufferManipulation, SanitizeMethods, SelectTag, SelectVulnerability, Send, SendFile, SessionManipulation, SessionSettings, SimpleFormat, SingleQuotes, SkipBeforeFilter, StripTags, SymbolDoSCVE, TranslateBug, UnsafeReflection, ValidationRegex, WithoutProtection, XMLDoS, YAMLParsing


+SUMMARY+

+-------------------+-------+
| Scanned/Reported  | Total |
+-------------------+-------+
| Controllers       | 14    |
| Models            | 7     |
| Templates         | 23    |
| Errors            | 0     |
| Security Warnings | 8 (1) |
+-------------------+-------+

+----------------------+-------+
| Warning Type         | Total |
+----------------------+-------+
| Cross Site Scripting | 5     |
| Dynamic Render Path  | 2     |
| Redirect             | 1     |
+----------------------+-------+


+SECURITY WARNINGS+

+------------+-------------------+----------+----------------------+------------------------------------------------------------------------------------------------------------------->>
| Confidence | Class             | Method   | Warning Type         | Message                                                                                                           >>
+------------+-------------------+----------+----------------------+------------------------------------------------------------------------------------------------------------------->>
| High       | OauthsController  | callback | Redirect             | Possible unprotected redirect near line 14: redirect_to(+Bot.find_by_domain(request.host.split(".")[0]).admin_edit>>
| Medium     | ScriptsController | show     | Cross Site Scripting | Unescaped model attribute rendered inline near line 9: render(text => +ChatLog.find_by_uniq_key(params[:id]).bot.c>>
+------------+-------------------+----------+----------------------+------------------------------------------------------------------------------------------------------------------->>


View Warnings:

+------------+------------------------------------------------+----------------------+------------------------------------------------------------------------------------------------->>
| Confidence | Template                                       | Warning Type         | Message                                                                                         >>
+------------+------------------------------------------------+----------------------+------------------------------------------------------------------------------------------------->>
| Medium     | shared/_bot_header (Template:admin/bots/index) | Cross Site Scripting | Unsafe model attribute in link_to href near line 12: link_to(+current_user.bots.find_by_domain(r>>
| Medium     | shared/_bot_header (Template:admin/bots/index) | Cross Site Scripting | Unsafe model attribute in link_to href near line 17: link_to(+current_user.bots.find_by_domain(r>>
| Medium     | docs/show (DocsController#show)                | Dynamic Render Path  | Render path contains parameter value near line 4: render(partial => "shared/doc_#{+params[:id].g>>
| Medium     | docs/show (DocsController#show)                | Dynamic Render Path  | Render path contains parameter value near line 9: render(partial => "shared/doc_#{+params[:id].g>>
| Weak       | bots/show (BotsController#index)               | Cross Site Scripting | Unescaped model attribute near line 17: markdown.render(strip_tags(+Bot.find_by_domain(request.h>>
| Weak       | bots/show (BotsController#index)               | Cross Site Scripting | Unescaped model attribute near line 24: markdown.render(strip_tags(+Bot.find_by_domain(request.h>>
+------------+------------------------------------------------+----------------------+------------------------------------------------------------------------------------------------->>

後はこの指摘に沿って修正していくだけです。

結果の内容は標準出力の他、HTML/JSON/CSV/TSV/Markdown/Code Climateに対応しています。それぞれ拡張子または -fオプションで指定します。複数のファイル出力に対応しているので拡張子で指定した法が分かりやすいです。

$ brakeman -o output.html -o output.json

f:id:a_nakatsugawa:20170629160716p:plain

対応するRailsのバージョンなど

Brakeman はRails 2.3 〜 5.x まで幅広く使います。Ruby 1.8の構文解析にも対応していますが、Ruby自体は1.9.3以上が必須となっています。

過去の結果と比較する

--compareオプションを使うと過去の結果と比較できます。これはJSONファイルを使うようなので、出力ファイルとしてJSONファイルを用意しておく必要があります。そうすると新しい問題が発生している(または直っている)ことが容易に確認できるようになります。

$ brakeman --compare  output.json
Checks finished, collecting results...
{
  "new": [
    {
      "warning_type": "Cross Site Scripting",
      "warning_code": 84,
      "fingerprint": "947ce5634858e206076c3d1f6379c11ccb62aa3430b427150975388a5d3c4a68",
      "check_name": "RenderInline",
      "message": "Unescaped parameter value rendered inline",
      "file": "app/controllers/bots_controller.rb",
      "line": 15,
      "link": "http://brakemanscanner.org/docs/warning_types/cross_site_scripting/",
      "code": "render(text => params[\"hub.challenge\"], { :layout => false })",
      "render_path": null,
      "location": {
        "type": "method",
        "class": "BotsController",
        "method": "index"
      },
      "user_input": "params[\"hub.challenge\"]",
      "confidence": "High"
    }
  ],
  "fixed": [

  ]
}

Rails プロジェクトが重たいときには

Rails はモノリシックなシステムになりがちで、規模が大きくなりやすいです。そのため Brakeman でのチェックも時間がかかるようになるかも知れません。そこで --fasterオプションをつけて解析を高速化できます。これは高速にはなりますが、チェック項目が減るようです。

設定ファイルを作成する

Brakeman でも他の静的解析ツールと同様に設定ファイルでチェック項目の制御ができます。特徴的なのは警告や注意ごとに、それを無効にするかどうか対話で決められることでしょう。設定ファイルは config/brakeman.ignoreに保存されます。生成する際には -Iオプションを使います。

$ brakeman -I
  :
Checks finished, collecting results...
Filtering warnings...
Input file: |config/brakeman.ignore|            
No such file. Continue with empty config? y
1. Inspect all warnings
2. Hide previously ignored warnings
3. Prune obsolete ignored warnings
4. Skip - use current ignore configuration
?  1
--------------------
Actions:
i - Add warning to ignore list
n - Add warning to ignore list and add note
s - Skip this warning (will remain ignored or shown)
u - Remove this warning from ignore list
a - Ignore this warning and all remaining warnings
k - Skip this warning and all remaining warnings
q - Quit, do not update ignored warnings
? - Display this help
--------------------
Confidence: Weak
Category: Cross Site Scripting
Message: Unescaped model attribute
Code: markdown.render(strip_tags(Bot.find_by_domain(request.host.split(".")[0]).readme.to_s))
File: app/views/bots/show.html.erb
Line: 17
Action: (i, n, k, u, a, s, q, ?) i
--------------------
Ignoring 8 warnings
Showing 0 warnings
1. Save changes
2. Start over
3. Quit, do not save changes
?  1
Output file: |config/brakeman.ignore| 

この設定ファイルですべて警告を無効にすると警告は出なくなります。それではよくありませんので、内容を確認して早急に直すべきものは修正していきます。問題ないことが分かっているものについては無効にしておいても良いでしょう。


Rails はとても高機能なフレームワークですが、セキュリティを万全にしてくれる訳ではありません。これはどのようなプログラミング言語、フレームワークでも同じです。ちょっとしたミスがセキュリティインシデントにつながります。Brakemanを使うことでそうした問題のいくらかを発見、修正できるようになるでしょう。

SideCI の自動コードレビューでは Brakeman にも対応しています。個人であればローカルに Brakeman をインストールすれば済みますが、チームでの開発体制ではクラウドでチェックする方が効率的かつプロジェクト全体のコード品質向上につながるはずです。

SideCIでは無料トライアルも可能です。ぜひ皆さんのRailsプロジェクトでお試しください

JSHintを使ってJavaScriptのコードを自動レビューしよう

$
0
0

JavaScriptは一つの実行内容に対して複数の書き方が存在します。また、コールバック地獄と比喩される非同期処理の積み重ねなど、ソースコードが分かりづらくなる要因が多数存在します。一人で小さなスクリプトを書く分には構いませんが、多人数で大きなWebアプリケーションを作り上げる際には問題が起こりやすいプログラミング言語です。

そこでまずコードを自動レビューして、悪い部分を修正していきましょう。そこで使えるのがJSHintになります。

JSHintのインストール

JSHintは npmコマンドでインストールできます。

$ npm install -g jshint

これで jshintコマンドが使えるようになります。

package.jsonに記載して該当のプロジェクト、ディレクトリにインストールして使う事もできます。

JSHint の使い方

一番オーソドックスな使い方は jshintコマンドに解析したいJavaScript/Node.jsプロジェクトのパスを渡す方法です。これはファイルでもディレクトリでも大丈夫です。

$ jshint path/to/javascript

なお、Node.jsのプロジェクトでは npm を使ってインストールしたライブラリが node_modules というディレクトリに入ります。この中にあるファイルは自分たちで開発したものではないので、チェック対象外にするのが良いでしょう。この時には --excludeを使います。

$ jshint --exclude="node_modules/" path/to/javascript

実際に実行すると、次のように指摘事項が標準出力されます。

$ jshint --exclude="node_modules/" path/to/javascript
index.js: line 2, col 3, Comma warnings can be turned off with 'laxcomma'.
index.js: line 1, col 26, Misleading line break before ','; readers may interpret this as an expression boundary.
index.js: line 9, col 19, ['BOT_URL'] is better written in dot notation.
index.js: line 9, col 30, Missing semicolon.

4 errors

後はこの指摘事項に沿って修正していくことで、最終的に何も出力が出なければ完了になります。

オプションについて

--reporterオプションを使うと出力形式を変更できます。checkstyleを指定するとCheckStyle互換のXML形式で出力されます。

$ jshint --exclude="node_modules/" --reporter=checkstyle path/to/javascript
<?xml version="1.0" encoding="utf-8"?>
<checkstyle version="4.3">
    <file name="index.js">
        <error line="9" column="27" severity="warning" message="Missing semicolon." source="jshint.W033" />
    </file>
</checkstyle>

unixを指定すると行と文字数のカウントがシンプルになります。

$ jshint --exclude="node_modules/" --reporter=unix path/to/javascript
index.js:9:27: Missing semicolon.

1 error

その他、 --extractオプションを指定するとHTMLファイル内に書かれているJavaScriptについてチェックしてくれるようになります。

$ jshint --exclude="node_modules/*" --extract="auto" index.html 
index.html: line 16, col 46, Missing semicolon.

1 error

設定の指定

設定ファイルは .jshintrcという名前で設定します。内容はJSONで、次のような内容になります。以下は定義されていない変数をエラーとし、使われていない変数があってもエラーにします。さらにグローバル変数としてMY_GLOBALを指定することで未定義エラーを防止します。

{
  "undef": true,
  "unused": true,
  "globals": {
    "MY_GLOBAL": true
  }
}

または各JavaScriptファイル内にコメントで定義もできます。使いやすい方を採用してください。

/* jshint undef: true, unused: true */
/* globals MY_GLOBAL */

ES6で書かれたファイルをチェックする場合は /*jshint esversion: 6 */を指定します。もちろん .jshintrcを使って全体に対して設定を適用できます。

また、チェック対象外にしたい行は // jshint ignore:lineと記述します。この他のオプションについては JSHint Options Referenceを参考にしてください。


JSHint は長い間メンテナンスされています。その中には多くのナレッジが詰まっています。他の解析器に比べて機能は決して多くありませんが、必要十分な機能は揃っています。

SideCI の自動コードレビューでは JSHint にも対応しています。個人であればローカルに JSHint をインストールすれば良いでしょう。チームで開発している時にはGitHubのPull Request単位で自動コードレビューを行うSideCIをぜひお試しください。

SideCIでは無料トライアルも可能です。ぜひ皆さんのRailsプロジェクトで試してみてください

SCSSの静的解析、改善にscss-lintを使いましょう

$
0
0

コードレビューというとプログラマ向けの仕組みに感じますが、そんなことはありません。Webデザイナーにとっても役立つケースがあります。例えばCSSはテキストで書かれるものなので差分が取れます。更新部分だけをコードレビューできれば、日々の運用の中でメンテナンス性を維持できます。

CSSを拡張して書けるようにしたSCSSはWebデザイナーの中でも広く使われています。開発の中でSCSSを使われているのであれば、scss-lintを使ってコードをチェックしてみましょう。

scss-lintのインストール

scss-lintはRubygemsを使ってインストールできます。

$ gem install scss-lint

これで scss-lintコマンドが使えるようになります。開発チームで実際に導入される際には Gemfileに追記し、bundlerで管理すると全員で同じバージョンのものを使えるので便利です。

scss-lintの使い方

scss-lintの使い方は簡単で、SCSSファイルのあるディレクトリまたはファイルを指定するだけです。実行すると、解析された結果が標準出力されます。

$ scss-lint app/assets/stylesheets/
app/assets/stylesheets/jobs.css.scss:2:21 [W] HexNotation: Color `#EAEAEA` should be written as `#eaeaea`
app/assets/stylesheets/jobs.css.scss:2:21 [W] ColorVariable: Color literals like `#EAEAEA` should only be used in variable declarations; they should be referred to via variable everywhere else.
app/assets/stylesheets/jobs.css.scss:4:11 [W] ZeroUnit: `0px` should be written without units as `0`
app/assets/stylesheets/jobs.css.scss:12:3 [W] PropertySortOrder: Properties should be ordered background-color, font-family, padding
app/assets/stylesheets/jobs.css.scss:14:21 [W] ColorVariable: Color literals like `white` should only be used in variable declarations; they should be referred to via variable everywhere else.

エラー項目の指摘と同時にどう修正すれば良いかも出してくれるのが便利です。

表示結果について

表示結果は --formatオプションで変更できます。例えばよくあるエラーをリストアップには Statsを指定します。そうすると以下のように多いエラー順で一覧にしてくれます。

$ scss-lint --format Stats app/assets/stylesheets/
238  SpaceAfterPropertyColon        (across  6 files)
162  SpaceBeforeBrace               (across 10 files)
 92  ColorVariable                  (across  8 files)
 51  PseudoElement                  (across  5 files)
 50  SingleLinePerSelector          (across  9 files)

Filesを指定すると単にエラーのあるファイル名だけを標準出力します。

$ scss-lint --format Files app/assets/stylesheets/
app/assets/stylesheets/application.css
app/assets/stylesheets/bootstrap-notify.css
app/assets/stylesheets/bootstrap-responsive.min.css
app/assets/stylesheets/bootstrap-tagmanager.css
app/assets/stylesheets/bootstrap.min.css

TAPは一つ一つのエラーを分割し、より細かく内容を出力してください。

$ scss-lint --format TAP app/assets/stylesheets/ | more
TAP version 13
1..9514
ok 1 - app/assets/stylesheets/ads.css.scss
ok 2 - app/assets/stylesheets/api/ads.css.scss
ok 3 - app/assets/stylesheets/api/articles.css.scss
ok 4 - app/assets/stylesheets/api/users.css.scss
not ok 5 - app/assets/stylesheets/application.css:1:1 Comment
  ---
  message: Use `//` comments everywhere
  severity: warning
  file: app/assets/stylesheets/application.css
  line: 1
  column: 1
  name: Comment
  ...
not ok 6 - app/assets/stylesheets/application.css:23:1 SingleLinePerSelector
  ---
  message: Each selector in a comma sequence should be on its own single line
  severity: warning
  file: app/assets/stylesheets/application.css
  line: 23
  column: 1
  name: SingleLinePerSelector
  ...

チェックできる内容について

あらかじめ用意されているチェック項目(Linter)は --show-lintersオプションで確認できます。

$ scss-lint --show-linters
Installed linters:
 - BangFormat
 - BemDepth
 - BorderZero
 - ChainedClasses
 - ColorKeyword
 - ColorVariable
 - Comment
   :

設定について

scss-lint の設定は .scss-lint.ymlというファイルで行います。例えば以下のような記述になります。

scss_files: 'app/assets/stylesheets/**/*.css.scss'

exclude: 'app/assets/stylesheets/plugins/**'

linters:
  BorderZero:
    enabled: false

  Indentation:
    exclude:
      - 'path/to/file.scss'
      - 'path/to/directory/**'
    severity: warning
    width: 2

解析するファイルやディレクトリも指定するので、設定ファイルさえ書いておけば scss-lintコマンドだけで済むようになります。そして前述したチェック項目(Linter)ごとに有効/無効を設定したり、除外するディレクトリやファイルを細かく指定できます。


CSSは構造化ができなかったり、変数でまとめて管理するようなことができないためにSCSSやStylusといった拡張言語が生み出されています。それらを使うことで管理しやすくなりますが、それでも継続的に更新していく中で全体のメンテナンス性が悪くなっていくのはよくあることです。そういった事態に陥らないようscss-lintを使ってメンテナンス性を維持するのは大切です。

SideCIはscss-lintに対応していますので、チームで開発されている際にはぜひ導入を検討してみてください。Pull RequestベースでSCSSファイルを検証し、自動コードレビューできるようになります。

無料トライアルも提供していますので、ぜひお試しください。


Hamlを使っているならhaml-lintを使ってコードレビューを楽にしよう

$
0
0

Hamlというのは主にRuby on Railsで使われているマークアップ言語です。Railsで標準で採用されているテンプレートエンジンであるERBよりも少ない記述量で記載することが出来ます。HTMLはXMLがベースになっているので冗長的な書き方も多く、書くのが面倒に感じる方もいるでしょう。Hamlはインデントで構造を表すので慣れれば分かりやすく感じるでしょう。下記はHamlの例です。

%section.container
  %h1= post.title
  %h2= post.subtitle
  .content
    = post.content

HTMLは適当に書いてもそれなりに表示されてしまうため、更新を重ねていく内に徐々にメンテナンス性が悪くなっていきます。それはHamlについても同じでしょう。そこでHamlの内容を静的に解析し、修正すべきポイントを指摘してくれるhaml-lintを使ってみましょう。

haml-lintのインストール

haml-lintはRubygemsを使ってインストールできます。

$ gem install haml_lint

haml-lintの使い方

基本的な使い方はHamlファイルのあるディレクトリまたはHamlファイルを指定して haml-lintコマンドを実行します。そうすると修正すべきポイントが標準出力されます。

$ haml-lint .
custom_templating_extension.text.html.haml:3 [W] TrailingWhitespace: Line contains trailing whitespace
custom_templating_extension.text.plain.haml:5 [W] FinalNewline: Files should end with a trailing newline

後はこの指摘に従って修正していくだけです。

結果の出力フォーマットについて

デフォルトでは標準出力として指摘事項が出力されます。これを変更するには --reporterオプションを使います。例えば checkstyleと指定すると CheckStyle フォーマットで出力されます。

$ haml-lint --reporter checkstyle .
<?xml version="1.0" encoding="utf-8"?><checkstyle version="5.7"><file name="custom_templating_extension.text.html.haml"><error line="5" severity="warning" message="Files should end with a trailing newline" source="FinalNewline" /><error line="1" severity="warning" message="Line contains trailing whitespace" source="TrailingWhitespace" /><error line="3" severity="warning" message="Line contains trailing whitespace" source="TrailingWhitespace" /></file><file name="custom_templating_extension.text.plain.haml"><error line="5" severity="warning" message="Files should end with a trailing newline" source="FinalNewline" /><error line="1" severity="warning" message="Line contains trailing whitespace" source="TrailingWhitespace" /><error line="3" severity="warning" message="Line contains trailing whitespace" source="TrailingWhitespace" /></file></checkstyle>

さらに jsonも指定できます。

$ haml-lint --reporter json .
{"metadata":{"haml_lint_version":"0.26.0","ruby_engine":"ruby","ruby_patchlevel":"111","ruby_platform":"x86_64-darwin16"},"files":[{"path":"custom_templating_extension.text.html.haml","offenses":[{"severity":"warning","message":"Files should end with a trailing newline","location":{"line":5},"linter_name":"FinalNewline"},{"severity":"warning","message":"Line contains trailing whitespace","location":{"line":1},"linter_name":"TrailingWhitespace"},{"severity":"warning","message":"Line contains trailing whitespace","location":{"line":3},"linter_name":"TrailingWhitespace"}]},{"path":"custom_templating_extension.text.plain.haml","offenses":[{"severity":"warning","message":"Files should end with a trailing newline","location":{"line":5},"linter_name":"FinalNewline"},{"severity":"warning","message":"Line contains trailing whitespace","location":{"line":1},"linter_name":"TrailingWhitespace"},{"severity":"warning","message":"Line contains trailing whitespace","location":{"line":3},"linter_name":"TrailingWhitespace"}]}],"summary":{"offense_count":6,"target_file_count":2,"inspected_file_count":2}}

解析できる内容について

解析できる項目(Linter)は --show-lintersオプションで確認できます。多数のLinterがデフォルトで用意されています。

$ haml-lint --show-linters
Available linters:
 - AltText
 - ClassAttributeWithStaticValue
 - ClassesBeforeIds
   :

解析する内容を制御するのは .haml-lint.ymlというファイルになります。内容は例えば次のようになります。前述のLinterごとに有効、無効を切り替えたり、細かいパラメータを変更できます。

linters:
  ImplicitDiv:
    enabled: false
    severity: error

  LineLength:
    max: 100

Hamlはタグを書かないのでHTML構造こそ崩れづらいものの、idとクラスの書き順など自由度は高いフォーマットになります。その結果、書く人によって品質がバラバラになってしまいます。ぜひhaml-lintを使って可読性の高い、メンテナンスしやすい状態を維持してください。

SideCIではhaml-lintをサポートしています。チームで開発されているのであれば、SideCIを使って自動コードレビューできる仕組みが便利です。長期的にメンテナンスできるシステムを維持するためにもぜひ使ってみてください。

SideCIは無料トライアルも可能です。ぜひお試しください。

CoffeeScriptのコードを静的解析器のCoffeeLintにレビューしてもらおう

$
0
0

素のJavaScriptが書きづらいと感じる方は少なくありません。波括弧や普通の括弧が多く、読みづらいと感じてしまいます。そんな中作られたのが代替言語のCoffeeScriptです。CoffeeScriptは変換用のコマンドを介して素のJavaScriptになります。CoffeeScript自体はRubyやPythonから学び取った点の多い、可読性の高いシンプルな構文となっています。

CoffeeLintはそんなCoffeeScriptの静的解析ツールです。CoffeeScriptは書きやすくなったとは言え、やはり解析器を使うと多数の指摘が上がってくるはずです。

CoffeeLintのインストール

CoffeeLintのインストールはnpmコマンドで行います。

$ npm install coffeelint -g

CoffeeLintの使い方

使い方は簡単で、 coffeelintコマンドに続けてCoffeeScriptプロジェクトのパス(ディレクトリ、ファイルどちらも可)を指定します。実行すると下記のように指摘事項が出力されます。

$ coffeelint /path/to/coffeescript/project
  ✓ calc-test.coffee
  ✗ calc.coffee
     ✗ #10: Throwing strings is forbidden.
  ✗ chartController.coffee
     ✗ #16: Line ends with trailing whitespace.
  ✗ controller/own_controller.coffee
     ✗ #2: Line contains inconsistent indentation. Expected 2 got 1.
     ✗ #2: Line contains tab indentation.
     ✗ #2: Line ends with trailing whitespace.
     ✗ #15: Line contains tab indentation.
     ✗ #28: Line contains tab indentation.

後はこの指摘事項に沿って修正していくだけです。CoffeeLintでは問題のないファイルに✓マークが付くので、作業している感があります。

$ coffeelint .
  ✓ calc-test.coffee
  ✓ calc.coffee
  ✓ chartController.coffee
  ✓ controller/own_controller.coffee
  ✓ db.coffee

設定ファイルを作成する

設定ファイルは coffeelint.jsonというファイルになります。ここにJSONで設定を記述していくのですが、イチから作るのは大変です。そこで --makeconfigを使ってベースを生成できます。

$ coffeelint --makeconfig > coffeelint.json

設定ファイルの内容、指摘事項などは CoffeeLint - Lint your CoffeeScriptを参考にしてください。

カスタムルールの適用

CoffeeLintでは自分でルールを追加できます。 coffeelintrule - npm searchで見ると、執筆時点で50以上のルールが作られています。これらのルールは coffeelint.jsonの中でmoduleとして指定できます(なおSideCIではmoduleには未対応です)。

例えば下記は最初に改行がない場合は警告とする newline_at_eofというルールを追加し、その際のモジュールとして coffeelint-newline-at-eofを追加する場合の設定方法です。

{
    "newline_at_eof": {
        "module": "coffeelint-newline-at-eof",
        "level": "warn"
    }
}

オプションについて

主なオプションについて紹介します。 出力フォーマットを変える時には --reporterオプションを使います。例えば checkstyleとすると結果を CheckStyle 形式で出力します。

$ coffeelint --reporter=checkstyle .
<?xml version="1.0" encoding="utf-8"?>
<checkstyle version="4.3">
<file name="descriptor.coffee">
<error line="2"
    severity="error"
    message="Line contains a trailing semicolon; context: "
    source="coffeelint"/>
</file>
</checkstyle>

csvを指定するとCSVで出力されます。

$ coffeelint --reporter csv .
path,lineNumber,lineNumberEnd,level,message
descriptor.coffee,2,,error,Line contains a trailing semicolon
hello.coffee,2,,error,Line ends with trailing whitespace

--quietオプションを指定すると問題のないファイルについては何も出力せず、エラーのみ表示されるようになります。


CoffeeScriptはシンプルな構文ですが、一行が長かったり、空白の使い方など他のプログラミング言語と変わらない記述ミスがあるものです。そういった指摘事項を修正することでコードの品質を上げられるようになります。

SideCIはCoffeeScriptに対応しています。CoffeeScriptを使ったプロジェクトに対してぜひCoffeeLintを使ってコードレビューを実施してください。複数人での開発であれば特にコードレビューを行うことによるメリットは強く感じてもらえるはずです。

SideCI - 綺麗なコードと文化を作るコードレビューのためのCI

SideCIはレビューにフォーカスするため、負債カンバンを廃止しました

$
0
0

こんにちは。今日は私たちSideCIのメンバーにとって、また、ユーザの皆様にとって、大きなアナウンスをさせて頂きます。

2016年8月末より技術的負債を可視化し、その返済を支援する機能である「負債カンバン」を提供しておりました。本機能はベータ版として、Ruby on Railsプロジェクトに限定して提供しておりましたが、2017年6月28日をもって一度本機能をクローズさせて頂きました。

TechCrunchにて「自動コードレビュー「SideCI」が、技術的負債を可視化する「負債カンバン」提供開始」といった形でご紹介頂くなど、大きく反響があった機能ですが、少なくても直近1年ほどはコードレビューの自動化にフォーカスするため、一度クローズするという判断をするに至りました。

f:id:sideci:20170714195548p:plain負債カンバンのイメージ

負債カンバンの成り立ち

SideCIを提供していく中で、「SideCIによるレビューの自動化によって新しく書くコードについては品質が担保されるようになった。一方で、過去に書いたコードがボトルネックになっている部分がある」といった課題をお聞きする機会が多くありました。そのため、その課題を解決するための機能を開発していこうという決定をし、製品内容の検討をはじめました。

技術的負債については、次のような声をよくお聞きしました。

  • 開発を進めるに当たってボトルネックになっている、技術的負債を返していきたい
  • 技術的負債がどこにあるか、どんなものがあるかはエンジニア個々人が定性的な感覚として持っているのみで、チーム内の共通認識はない

そのため、負債カンバンは次のような機能を解決策として盛り込みました。

  • 技術的負債を可視化する
  • 負債の深刻度合い、改修することによる投資対効果を判別し、優先度を付ける
  • 優先度をカンバン形式で表示することで、どこから取り組むべきかをわかりやすく示す

これらの機能によって、負債が可視化され、どこから返済していくべきなのかがわかりやすく、また、チーム内で共通の認識として持てるようになったと考えています。

負債カンバンの課題

一方で、負債カンバンには大きな課題が残っています。それは、技術的負債を返済するためのモチベーション、時間、その他色々な技術的負債の返済にあたって必要なプロセスを解消することが出来ていない点です。そのため、負債カンバンで可視化された技術的負債に納得感を持って頂ける方々、共通認識としての納得感(メンバー間の肌感のズレの少なさ)を持って頂くところまでは実現できているものの、実際の技術的負債の返済に貢献しているケースはまれでした。

可視化はあくまで第一歩に過ぎず、可視化したものを片付けていくための機能群が必要だと考えています。

一方で、SideCIはレビューの自動化に注力しており、レビューの自動化の点においてもたくさんのやるべきことが残っている中で、「レビューに時間がかかる」という課題とはまったく別の課題である、「技術的負債の返済が進まない」に対して商品開発を続けることは、適切ではないと判断致しました。

また、SideCIは生産性の向上への寄与を第一に考えており、レビュー自動化を提供しています。技術的負債は返済することは生産性の向上に繋がる点も大きくありますが、生産性の向上に寄与する技術的負債のみを機械的に発見することは難易度が高く、現状ではノイズが混ざってしまいがちです。

例えば、1行が300文字になっているコードを全て80文字にしたからといって、開発生産性が上がるわけではありません。インデントがタブとスペースが混同されているコードをどちらかに揃えても、生産性は上がりません。スパゲッティコードを解きほぐすリファクタリングは後々の生産性の向上に繋がりますが、とても難易度が高く、すぐに取り組めるものではありません。また、コードから読み解けない技術的負債が本質的な問題のこともよく有りますが、それはコードの静的解析から発見することは難しいです。

生産性に寄与する返済すべき技術的負債のみを見つけ、改善することは、2017年現代ではまだ難しいのです。

もちろん、私たちはそれに真摯に取り組むため、スパゲッティコードを見つけるのに役に立つ、Ruby言語でよく使われいるMetricFu内部の循環複雑度計算機saikuroに代わる新しい循環複雑度計算機のcycromaticを開発したりもしましたが、まだまだ道のりは遠いと考えるに至りました。

負債カンバンの今後の位置づけ

負債カンバンは2017年6月28日にクローズされました。いっときの間、負債カンバンの開発プロジェクトは凍結されます。 「技術的負債の返済が進まない」という課題の代わりに、「技術的負債が今後増えることをレビュー自動化によって防ぐ」ことに今まで以上にフォーカスします。

また合わせて、類似した別の観点として、「今はとっても急いでいるのでこのPullRequestに含まれる技術的負債は認識しつつもMergeする、あとで返済する」といったシーンで実際にあとで返済出来るようにする、新しいカタチの負債カンバンを作ることが1案としてあります。もしかしたらそれはカンバンではないかもしれませんが。

今後のSideCI

私たちはコードレビューの自動化を支援する、カスタムルールをRuboCopのCop追加などに比べて圧倒的に簡単に追加することが出来るQuerlyや、誤検知を恐れずにルールを書いていけるようにするための新WebUIである、アビシニアンモードの提供などを行ってきました。 現在では「アビシニアンモード」がSideCIの標準の挙動となり、従来のコメントを行うモードはオプションの機能に変更になりました。

このアビシニアンモードが標準になることで、SideCIに以下がデータとして蓄積されるようになりました。

  • どのような指摘が納得感があるか(実際に修正されるか)
  • どのような指摘が意味が無いか(無視されがちか)
  • 意味がないとしたらその理由は何か

これらを活用し、新しい機能群を提供していく事を計画しています。

おわりに

SideCIは世界で最も良いレビューの自動化サービスとして開発を続けて参ります。 ご利用いただき、ユーザの皆様方とともに、成長を続けていければ幸いです。

Railsを書き始めたばかりの人に特にオススメ。Rails流のコードの書き方を教えてくれる rails_best_practices を使ってみましょう

$
0
0

Ruby on Rails を使ったシステム開発では The Rails way や Rails 流と言った開発手法に沿って行うことで高い生産性を保持できるようになります。つまり流儀をきちんと学び、それに従って開発するのが大事です。

そうした流儀、ベストプラクティスをチェックできるツールが rails_best_practices になります。単に文章などで読むだけでなく、コードを静的解析して指摘するツールを使うことで、何が間違っていてどう書くべきなのかがはっきりと分かるようになるでしょう。

rails_best_practices のインストール

rails_best_practices のインストールは Rubygems を使って行えます。

$ gem install rails_best_practices

または Rails プロジェクトの Gemfileに記述してインストールもできます。

rails_best_practicesの使い方

rails_best_practices をインストールすると rails_best_practicesコマンドが使えるようになります。実行時に Rails プロジェクトのパスを渡すだけです。

$ rails_best_practices .
Source Code: |====================================================================================================|
/path/to/rails/project/db/schema.rb:16 - always add db index (bots => [user_id])
/path/to/rails/project/db/schema.rb:80 - always add db index (temporary_tokens => [bot_id])
/path/to/rails/project/app/controllers/bots_controller.rb:18 - move model logic into model (Resque use_count > 4)
/path/to/rails/project/app/helpers/user_sessions_helper.rb:1 - remove empty helpers
/path/to/rails/project/app/helpers/application_helper.rb:2 - remove unused methods (ApplicationHelper#get_bot_site)
/path/to/rails/project/app/models/chat_log.rb:19 - remove unused methods (ChatLog#slack_demo)

後はこの指摘に沿って修正していくだけです。 上記の一例の場合には、データベースへのインデックスのつけ忘れや、RailsではロジックはControllerではなくModelに書きましょう、使っていないメソッドや使っていないhelperファイルを削除しましょうといった事が示されています。

デフォルトは標準出力ですが、他のフォーマットで出力する場合は -f(フォーマット指定)、 --output-file(出力先ファイル名) を使います。

$ rails_best_practices -f html --output-file result.html

f:id:a_nakatsugawa:20170629161205p:plain

さらに GitやHgと連携してコミットIDやコーダーの名前を出力することもできます。これでより分かりやすくなるでしょう。

$ rails_best_practices --with-git -f html --output-file result.html

f:id:a_nakatsugawa:20170629161215p:plain

その他のオプション

特定のディレクトリを除く場合は -eオプションを使います。複数ディレクトリある場合はカンマ繋ぎになります。

$ rails_best_practices -e "db/migrate,vendor" .

test ディレクトリを含める場合は --test、spec ディレクトリは --spec、 vendor ディレクトリは --vendor、そして features ディレクトリは --featuresをそれぞれ指定します。

設定ファイルを作成する

デフォルトの設定ファイルのパスは config/rails_best_practices.ymlになります。まず最初は -gを付けてベースになるファイルを生成するのが良いでしょう。

$ rails_best_practices -g

そうすると以下のような YAML ファイルが生成されます。

AddModelVirtualAttributeCheck: { }
AlwaysAddDbIndexCheck: { }
#CheckSaveReturnValueCheck: { }
#CheckDestroyReturnValueCheck: { }
DefaultScopeIsEvilCheck: { }
  :

例えばスペースや空白行に関する警告を出さないようにしたい場合は次のような設定を追加します。

RemoveTrailingWhitespaceCheck: { ignored_files: '*' }

rails_best_practices が指摘する内容は Rails Best Practices - Rails Best Practicesに記事として書かれています。コードの変更前、変更後も書かれているので、分かりやすいはずです。rails_best_practices によって指摘された内容をサイトの記事でチェックして修正していくことで、より Rails らしい書き方ができるようになるでしょう。

SideCI の自動コードレビューでは rails_best_practices にも対応しています。個人であればローカルに rails_best_practices をインストールすれば良いでしょうが、チームでの開発体制ではクラウドでチェックする方が効率的かつプロジェクト全体のコード品質向上につながるはずです。ぜひご利用ください。

SideCIでは無料トライアルも可能です。ぜひ皆さんのRailsプロジェクトで試してみてください

bundlerのoutdatedコマンドを使ってGemfileの古いライブラリをチェックしましょう

$
0
0

RubyプロジェクトではBundlerを使って依存ライブラリの管理を行うのが一般的です。ライブラリのインストールは簡単にできますが、その後適切に最新バージョンを追いかけないとセキュリティ上のリスクが発生することや、アップデートの差分が大きくなりすぎてアップデートしたくでも難しくなりがちです。

bundle updateを実行すればアップデートは可能ですが、予期せぬ動作になってしまう可能性は当然含んでおり、テストは不可欠です。そこで、アップデートする前にまず、そもそもアップデートする必要があるgemがあるかどうかを簡単に調べる bundler outdatedコマンド を使ってみましょう。

bundler outdatedの使い方

bundlerのoutdated` はbundler 1.1(2012年)以降で実装された機能です。そのためbundlerが使われている殆どのプロジェクトで、特に何もせずに利用できるはずです。

利用する際には任意のRubyプロジェクトの直下で( Gemfileがあるディレクトリで) bundle outdatedを実行するだけです。そうすると新しいバージョンがあるライブラリが一覧出力されます。

$ bundle outdated
Fetching gem metadata from https://rubygems.org/............
Fetching version metadata from https://rubygems.org/..
Resolving dependencies...

Outdated gems included in the bundle:
  * diff-lcs (newest 1.3, installed 1.2.5)
  * json (newest 2.1.0, installed 1.8.3)
    :
  * simplecov-html (newest 0.10.1, installed 0.10.0)

ここで出力されたgemを1つずつ差分を見ていくことで安全にgemをアップデートすることが出来ます。1つずつupdateしていっても良いですし、それがまどろっこしい場合はbundle updateを行ってしまって、テストで動作を確認するのでもよいかもしれません。

bundler outdatedのオプション

オプションは多数あります。例えば --minorをつけると新しいマイナーバージョンが出ているものだけ表示します。同様に --major--patchもあります。あまり大きなバージョンアップをすると動作が変わってしまうこともあるので、今使っているメジャーバージョンのマイナーバージョンアップがあるかどうかを調べたいと言った場合に使えます。なお、これらのオプションはbundle updateにも存在しています。

リモートをチェックしない場合は --localを指定します。逆にプレリリース版まで含めてチェックしたい場合は --preを指定します。

development などグループを指定する場合には --groupまたは --groupsを使います。特定のグループ管理化にあるライブラリだけをチェックできます。


ライブラリのバージョンが古いと最新ドキュメントに載っている機能が使えなかったり、セキュリティリスクになることがあります。かといって無条件にアップデートしてしまうのも怖いでしょう。まずは bundlerのoutdatedコマンド を使って新しいバージョンがあるかチェックしてみましょう。updateコマンドと違って実際にインストールはされないので実行時間も短く済みます。

Gemのアップデートを見やすくするSaaSのGemnasiumというサービスもあります。まだ試したことがない方は試してみて頂ければと思います。https://gemnasium.com/

その他にも、エンジニアの開発効率を上げる、便利なSaaSが多く存在しています。コードレビューの自動化サービスとしてはSideCIがあります。。

SideCIでは2週間の無料トライアルを提供しています。ぜひお試しください!

Goのソースコード解析に標準ツールのgo vetを使ってみましょう

$
0
0

企業内においてGoを利用するケースが増えています。コンパイル系であり静的型付けの言語で、実行速度も速いのが特徴です。さらに仕様がシンプルなので習得が容易、かつ書かれたプログラムはマルチプラットフォームで動作します。

人気が出るに従ってチームでGoプロジェクトを進めるケースも多くなるでしょう。そうした中でコードの品質を保ち、保守性を良くするために、ソフトウェアを使ってコードをチェックしましょう。。幾つかのソフトウェアがありますが、今回はGoに標準で組み込まれているgo vetを紹介します。

go vetの使い方

go vetは go tool vet [directory]といった指定方法で実行します。directoryはGoのソースコードが入ったディレクトリを指定します。

$ go tool vet path/to/go/project

実行すると、問題のある箇所について指摘が出力されます。

$ go tool vet ./alecthomas/gometalinter/
adjcmartix.go:85: suspect or: char != "" || char != " "
main.go:55: arg usage in Fprint call is a function value, not a function call
resolve.go:161: unreachable code
sparse.go:58: _m might be too small for shift of 32

後はこの指摘事項に沿ってソースコードを修正していくだけです。

ヘルプ

go vet のヘルプは go doc cmd/vetで出力できます。

$ go doc cmd/vet
Vet examines Go source code and reports suspicious constructs, such as
Printf calls whose arguments do not align with the format string. Vet uses
heuristics that do not guarantee all reports are genuine problems, but it
can find errors not caught by the compilers.

It can be invoked three ways:

By package, from the go tool:

    go vet package/path/name

vets the package whose path is provided.

By files:

    go tool vet source/directory/*.go
  :

オプションについて

解析する項目をオプションで指定できます。デフォルトでは -allが指定されており、すべての項目をチェックを実行してくれます。例えば、到達しないコードのみを見つける場合は -unreachableを使います。

$ go tool vet -unreachable ./alecthomas/
alecthomas/gometalinter/_linters/src/golang.org/x/text/unicode/cldr/resolve.go:161: unreachable code
alecthomas/gometalinter/vendor/gopkg.in/yaml.v2/decode.go:123: unreachable code

他にポインタを数値に変換する際に unsafe.Pointerを使っていると警告を出せる -unsafeptrオプションがあります。

$ go tool vet -unsafeptr ./alecthomas/
alecthomas/gometalinter/_linters/src/golang.org/x/tools/go/ssa/interp/external.go:302: possible misuse of unsafe.Pointer

// コードは次のようになっています
if pc != 0 {
  fn = (*ssa.Function)(unsafe.Pointer(pc)) // indeed unsafe!
}

基本的にはすべての項目をチェックで良いと思いますが、必要に応じてフラグを指定して、必要な種類の項目・解析のみを実行してください。


go vet は標準的な、これまでの経験上問題と推測される点を指摘します。つまり指摘事項が必ずしも問題とは限りません。とは言えコンパイラでは問題がない内容でも指摘してくれるでしょう。内容に沿って修正することで、分かりやすいコードに仕上げられるでしょう。

Go言語用のコード解析ツールはCPUリソースを多く消費するものが多くあります。そのため、ローカルのPCで実行するには時間がかかってしまって煩わしく感じることがあるかもしれません。そんな際にはGitHubでPull Requestと連携してGo言語用解析ツールを実行する、コードレビューの自動化用のCIサービスであるSideCIがお役に立てると思います。SideCIはgo vetにも対応しています。無料トライアルがありますので、まずはお試しください

SideCIはPull Requestにコメントできるようになりました

$
0
0

SideCI は従来、Pull Request を解析し、指摘があった際はコミットステータスを fail にして、sideci.com 上で指摘事項を確認し、対応していただいておりました。今回、それに加えて新たに Pull Request にコメントを行う機能を追加しました。これにより、Pull Request ページを離れることなく、より簡単に解析器が指摘した内容を確認することができます。

f:id:a_ksi19:20170831165847p:plain

積極的に指摘する Querly のような解析器や、細かく指摘するために厳しく設定した解析器を利用する場合、コメントされる指摘事項に多くの偽陽性が含まれることがあります。これは、GitHub 上の Pull Request のページに多くのコメントがつくことを意味しており、指摘された内容を直すのか無視するのかを注意深く確認する必要があります。この場合は、必要に応じて sideci.com からクローズするなどの対応を行うことをおすすめいたします。

指摘数が多い場合、それらの指摘はサマリとしてまとめられ、以下のようにコメントされます。

f:id:a_ksi19:20170831165922p:plain

なお、この機能はリポジトリ設定画面より設定することができます。

f:id:a_ksi19:20170831165946p:plain

また、RuboCop、ESLint、PHP_CodeSniffer など、日本語化が行われている解析器を利用していて、指摘する際の言語を日本語に設定している場合、Pull Requestへのコメントは日本語で行われます。 ※ 一部の指摘については翻訳されていない場合もございますので、予めご了承ください。


SideCIでのクラシックモード廃止のお知らせ

$
0
0

SideCIは、2017年10月31日をもちまして、サービスの正式リリース時より稼働しておりました、クラシックモードを廃止することをお知らせいたします。

  • お客様にご登録いただいておりますリポジトリは、11月1日以降すべて強制的に新規モードに切り替わります
  • 新規モードは既に稼働しており、2017年9月6日時点で移行することが可能です
    • 新規モードは完全な互換性を保つものではありません
    • 一部の解析器の設定に問題が生じることがあり、また開発チームでのレビューのワークフローに変更が必要となることがあります

新規モードへの移行に伴う問題の発生を防ぐため、お客様ご自身での、前もっての移行をお願いいたします。

クラシックモードについて

SideCIでは、現在アビシニアンモードとクラシックモードという2つの異なるインターフェイスをそれぞれ提供しております。

f:id:a_ksi19:20170906160053p:plainアビシニアンモードのスクリーンショット

f:id:a_ksi19:20170906160109p:plainクラシックモードのスクリーンショット

現在、「クラシックモードのスクリーンショット」と同様の画面でSideCIをお使いになっている場合、アビシニアンモードへ移行していただく必要があります。

アビシニアンモードでは以下の点が、クラシックモードと比較した場合の主な改善点です。

  • より安定した解析システム
  • Pull Request commits に対してより向上した差分の追跡
  • commit やその解析結果の一元的な管理
  • 解析ログの表示

これらの詳細については、以下の弊社記事をご覧ください。

さらに、新たなSideCIでは、下記に挙げる点においてクラシックモードと異なります。

  • 自動修正機能のサポート廃止
  • Commit Status制御の簡略化

自動修正機能は、SideCIにおいて今後サポートする予定はございません。もし自動修正を行う場合は、お客様のローカル環境で実行してください。

Commit Statusの制御は簡略化され、ツールによってにCommit Statusへの影響を設定することはできなくなりました。SideCIの解析において問題が発見された場合には、常にCommit Statusが赤に設定されます。

発見された問題を修正せずにマージするには、SideCIのWebアプリから「クローズ」操作を行ってください。明示的なクローズの操作の導入により、開発者がその問題についてどのように考えているのかが、レビュアーに伝わるようになりました。

移行方法

アビシニアンモードへの切り替え

モードの切り替えは、リポジトリ設定画面より行うことができます。

f:id:a_ksi19:20170906160133p:plain

モード切り替え後、新たにPull Requestを開くか、既存のPull Requestに新たにcommitを積むとアビシニアンモードでの解析が実行されます。

Pull Reqeustへの指摘のコメント

アビシニアンモードは、一元的な解析結果の管理を行うために設計されていますが、設定することにより、クラシックモードのように、Pull Requestに対してコメントを行うことができます。こちらの詳細は以下の記事をご覧ください。

解析における非互換性について

2つのモード間における各解析器は、概ね互換性を保っておりますが、一部非互換な部分があります。これにつきましては、以下のドキュメントをご覧ください。

もし、不整合な点や不具合を見つけた場合、お知らせいただけますと幸いでございます。

解析実行時のトラブルシューティング

f:id:a_ksi19:20170906160250p:plain

解析実行時、解析の実行が失敗したり、意図しない挙動になった場合、解析ログを表示することでトラブルシューティングを行うことができます。上記画像は、Pull Requestの解析結果画面において、解析器名の横にある「Trace」をクリックすることで確認することができます。

f:id:a_ksi19:20170906160222p:plain

クラシックモードを使いたいお客様は、リポジトリを設定画面より戻すことが可能です。ただし、この場合でも10月31日を最後に強制的にアビシニアンモードに切り替わります。

f:id:a_ksi19:20170906160259p:plain

まとめ

  • クラシックモードは2017年10月31日をもって廃止します
  • クラシックモードをお使いのお客様は予め、モードの切り替えをお願いします

すべてのリポジトリは、11月1日以降自動的にクラシックモードから切り替わります。しかし、自動的なモード移行はお客様の開発フローを破壊的に変更してしまう可能性があるため、お客様各位の前もっての移行をお願いいたします。

SideCIでMisspellが使えるようになりました🎉

$
0
0

こんにちは。id:Pockeです。

SideCIで新しい解析器がご利用いただけるようになりましたので報告させていただきます。
今回追加された解析器は、Misspellです。Misspellを使用することで、ソースコードやその中のコメント、ドキュメントなどに含まれる英単語のタイプミスを検出することができます。

f:id:Pocke:20171017191528p:plain

SideCIでの使い方

SideCI上で設定を行っていただくことで、Misspellをお使い頂くことが可能です。

まず、Misspellを有効にしたい対象のリポジトリの設定画面を開いてください。

f:id:Pocke:20171017191614p:plain

つぎに、設定画面の解析ツール選択の中の、Misspellにチェックを入れてください。

f:id:Pocke:20171017191629p:plain

これで、次回の解析からMisspellが使用されるようになります。

US / UK のロケールの選択や、無視したい単語などがある場合、sideci.ymlをお使い頂くことで設定が可能です。 詳しくは、こちらをご覧ください。 https://docs.sideci.com/tools/misspell.html

注意点

なお、Misspellはアビシニアンモードのみの提供となっております。 クラシックモードをお使いのお客様は、アビシニアンモードに切り替えの上Misspellをお使いください。 また、クラシックモードは今月末の2017/10/31に終了予定となっておりますので、クラシックモードをお使いのお客様はお早めにお切り替えください。

blog-ja.sideci.com

また、何かありましたらお気軽にお問い合わせください。

SideCIでJavaが検査できるようになりました

$
0
0

SideCIは最も使われているプログラミング言語の1つであるJavaのサポートをはじめました。 現在PMDとCheckstyleの2つのツールを提供していますが、これ以外にもサポートを希望するツールがありましたらお気軽にお問い合わせください!

PMDとCheckstyleとは何なのか

これらはJavaの静的解析器の中でも人気のあるツールで、コードのクオリティの改善を手助けします。

PMDはソースコードからプログラミングにおけるよくある間違いを見つけ出します。 たとえば、あなたのコードが使われていない変数を含んでいた場合、PMDはその変数が使われていないことを見つけ出します。これによってその変数への代入を削除することができるでしょう。 また、あなたのコードがExceptionのような一般的すぎる例外をキャッチしていた場合も、PMDはそれを見つけ出します。これによってより限定的で適切な例外を指定することができるでしょう。 このように、PMDはより良いJavaのコードを書くことを手助けします。

一方、Checkstyleはスタイルチェッカです。Checkstyleはコーディング規約への違反を自動的に見つけ出し、コードをきれいに保つ手助けをします。 一度コーディング規約に合った設定を行えば、コーディング規約への違反とは無縁のコーディングを送ることができるでしょう!

SideCIでの使い方

SideCIでこれらのツールを使うことには、単独で使うことに比べて2つの利点があります。

  • SideCIは既存のプロジェクトへこれらのツールを導入することをサポートします。SideCIではPull Requestの変更に含まれる指摘のみがレポートされるため、既存のコードに対する大量の指摘の嵐に悩まされることはもうありません。
  • ナンセンスな指摘はSideCIの指摘管理画面から無視をすることができます。SideCIでは、解析器の間違いによるCIの失敗のために新しくコミットをpushする必要はもうありません。

この素晴らしいツールとSideCIによって、Javaプログラマの皆様の開発がより楽しくなることを願っています!

ご意見、ご要望などございましたらお気軽にお問い合わせください!

Javaのコーディング規約チェックツールCheckstyleの使い方、CIとの統合、オープンソースプロジェクトでの活用事例

$
0
0

目次

  • Checkstyle概要
  • CheckstyleとIDEの統合
  • Checkstyle標準のチェック項目のカテゴリー
  • Checkstyleとビルドツールの統合
  • Checkstyle標準のチェック項目のカテゴリー
  • 標準で配布されているコーディング規約
  • オープンソースプロジェクトとCheckstyle
  • ElasticSearchプロジェクトでのCheckstyleの利用
  • まとめ

Checkstyle概要

Checkstyleは、プログラマーがコーディング規約に則ったJavaコードを書くのを補助する開発ツールです。 以下は、Checkstyleのサイトからの、日本語訳した引用になります。

(Checkstyleは)コーディング規約のチェックという大切ではあるけれども退屈なタスクを自動化し、プログラマーの貴重な時間を節約します。 プロジェクトで定められたコーディング規約を確実に守りつつ、プロジェクトを進めるための非常に有用なツールです。

また、Checkstyleは、クラス設計やメソッド設計の問題を発見や、コードのレイアウト・フォーマットのチェックなどの、ソースコードの様々な側面を検査を行うことができます。 こうしたチェックの種類や詳細は、前述のChecksytleサイトのChecksをご覧ください。

Checkstyleのチェック項目は、豊富な設定パラメータでカスタマイズすることができるため、すでにコーディング規約がある場合でも、 概ねその規約に適合するルールを記述できます。 またプロジェクトのコーディング規約がまだない場合は、「Sun Javaコーディング規約」や、「Google Java Style」等の 広く利用されているコーディング規約のチェックを行う設定ファイルがあらかじめ用意されているので、 それらを使用することでコーディング規約をプロジェクトのプロセスに簡単に組み込むことができます。

Checkstyleでは、XMLファイルを使用してルールを記述します。 記述したルールに基づくチェックは、Checkstyle標準ではjavaコマンド及びantタスクで提供されていますが、 実プロジェクトで利用する場合は、IDEへの組み込み、及びビルドツールへの組み込みで使用することが一般的です。

IDEへの組み込みでは、各種IDE向けのプラグインが提供されているので、それらを利用することでプログラマは ソースコードを書きながらリアルタイムにチェックを行うことができます。

ビルドツールへの組み込みでは、現在広く利用されているビルドツールである、maven及びgradleが標準でCheckstyle用タスクを提供しており、 ビルドプロセスにCheckstyleのチェックを簡単に組み込むことができます。 ビルドツールへの組込を行うことで、プロジェクトのソースコード全体で規約が守れているかどうかを、常に確認することができます。

但し、ビルドツールへの組込は制約として非常に強力であり、1件でも指摘があればコードをマージ出来なくなります。 Checkstyleがまだ導入されていないプロジェクトや、コーディング規約が厳格な制約でない場合には、 その用途向けに作られたSideCIなどの専用のWebサービスを利用するのが良いかもしれません。

一つのXMLファイルによるルールの記述を利用して、IDEでのチェック、CIのプロセス(ビルドツールもしくはSideCI)でのチェックの両方を行うことができるので、 Checkstyleを利用するのであれば、両方でのチェックをプロジェクトに組み込むのがよいでしょう。

CheckstyleとIDEの統合

Checkstyleは、Eclipse, IDEA, Netbeans等、JavaのメジャーなIDEとプラグインで統合するだけでなく、 EmacsやVim、Atom、Sublime Textなどのより軽量なエディタ向けのプラグインも提供されているため、それらと統合して使用することができます。

IDEのプラグインを利用することで、リアルタイムでチェックを行い、違反をエディタ上に表示することができ、 また違反の一覧を表示しそこから違反箇所へジャンプする機能などが提供されます。 IDEへの統合を行うことで、プログラマーの日々のプログラミングの作業において、 ストレスなくコーディング規約に則ったコーディングを行うことができます。

Eclipse用のCheckstyleプラグインです。 リアルタイムでのチェック、違反の表示、一覧の表示と違反箇所へのジャンプなどの機能が提供されます。 また、このプラグインはCheckstyle設定ファイル(checkstyle.xml)のGUIベースの編集ツールとしても 非常に高機能で、Checkstyleのマニュアルをあまり見ずとも、ルールを記述していくことが可能です。

IntelliJ IDEA用のCheckstyleプラグインです。 Checkstyleでのチェックの実行、違反箇所へのジャンプなどの機能が提供されます。 設定ファイルの編集機能は提供されていないようです。

Netbeans用のCheckstyleプラグインです。 リアルタイムでのチェック、違反の表示、一覧の表示と違反箇所へのジャンプなどの機能が提供されます。 設定ファイルの編集機能は提供されていないようです。

Checkstyleとビルドツールの統合

Checkstyleのデフォルトでは、antとの統合がサポートされています。 また、現在に広く使われているビルドツールである、mavenやgradleの場合は、 ビルドツール側でCheckstyle用のプラグインが提供されています。 ビルドツールと統合することで、CI(継続的インテグレーション)にCheckstyleによるチェックを組み込み、 プロジェクト全体でコーディング規約が守られているかを常に確認し、保証することができます。

100%コーディング規約を守るのではなく、あくまでコーディングのガイドラインである、といった緩さの規約として運用する場合は、 ビルドツールとの統合は難しいかもしれません。その際には他の方法を検討すべきでしょう。

Checkstyle標準のチェック項目のカテゴリー

2017年12月時点の最新バージョンである、Checkstyleバージョン8.5では、 14のカテゴリーに分かれた154のルールが実装され、それぞれのルール毎に複数のパラメータで動作をカスタマイズできます。 ここですべてのルールを取り上げることは出来ないので、カテゴリー毎にどのような ルールが定義されているかの概要を記述します。

Annotations(アノテーションに関するルール)

アノテーションに関するルールを設定します。アノテーションの対象(クラス、メソッド、引数 etc.)毎に、 記述スタイル(アノテーションを実装と同一行に書くか別の行にするか、複数のアノテーションを同一行に まとめるか否か etc.)を定義します。また、@Override, @Deprecatedの使用の強制、@SuppressWarnings の使用制限などを記述できます。

Block Checks(Javaのブロックに関するルール)

Javaのブロック(中括弧で囲まれた領域)に関するルールを設定します。 中括弧前後の改行の配置や、空のコードブロックを許容するかなどを記述できます。

Class Design(クラス設計に関するルール)

クラス設計に関するルールを設定します。 主に、コンストラクタやメソッドの可視性(private〜public)に関するルールや、 その他の修飾子(final, abstract etc.)に関するルールを設定します。

Coding(コーディングスタイルに関するルール)

コーディングスタイル(コードの体裁)に関する多くのルール(43個)を設定します。 概ね、コーディングスタイルに関わるルールで、他のカテゴリーに入らないルールが、 このカテゴリーに集められているイメージです。 数が多いためすべてを記述することはできませんが、例えば、以下のようなルールが存在します。 - 配列の最後の要素の後ろにカンマをつけるかどうか - 空の文を許容するかどうか - if文、for文、try文などのネスト数の制限 - マジックナンバーの禁止 - switch文にdefault句を強制

Headers(ファイルヘッダーに関するルール)

各ソースファイルのヘッダー部分の記述に関するルールを設定します。 著作権やライセンスに関する記述など、プロジェクトで共通のヘッダーを利用する場合は、 このカテゴリーのルールを使用して、記述することができます。

Imports(import文に関するルール)

Javaのimport文に関するルールを設定します。 ワイルドカードによるimportの禁止、static importの禁止や、importの順番などを記述できます。 また、プロジェクトで使用を禁止するクラスがある場合、(例えばjava.sqlの使用を禁止等) importを禁止するルールを記述することで、実質的に使用されていないことをチェックできます。

Javadoc Comments(Javadocコメントに関するルール)

Javadocコメントに関するルールを設定します。 メソッドやフィールドの可視性毎にJavadocコメントの記述を強制したり、 またJavadocの@句(@param, @return etc.)の順序を強制することができます。

Metrics(メトリクスに関するルール)

主にメソッド・クラスの複雑度・クラスの依存関係数などのメトリクスを測定し、 一定以上の複雑度、依存関係をもつソースコード等を検出します。 リファクタリングが必要であろうソースコードを抽出することができます。

Miscellaneous(その他のルール)

他のカテゴリーに属さない、雑多なルールがこのカテゴリーに配置されています。 現在の実装では、以下のようなルールが配置されています。 - ソースコードやコメントのインデント方法 - 配列の記述方法(クラス名にを付けるか、変数名にをつけるか) - ファイル末尾に改行をつけるか - long値のリテラルで大文字Lの使用を強制(100L etc. 小文字のlは数字の1と見分けがつきにくいため) - TODOコメントの存在確認 - propertiesファイルのキーが重複していないことの確認 - Unicodeエスケープの使用禁止(UTF-8でそのまま記述することを推奨) - その他

Modifiers(修飾子に関するルール)

クラスやメソッド等の修飾子(private〜public, final etc.)に関するルールを設定します。 修飾子が複数ある場合の順番や、冗長な修飾子(interface型のmethodのpublic修飾子など)を 許容するかどうか、等が設定できます。

Naming Conventions(命名規則に関するルール)

各種命名規則に関するルールを設定します。 クラス名・メソッド名・引数名・ローカル変数名等、Javaで出現する名前の種類毎に、 正規表現でルールを記述出来るため、概ねどのような命名規則にも対応することができます。 またデフォルトの正規表現は、概ねJavaで一般的な命名規則に従ったものになっているため、 正規表現のパラメータを省略してルールを記述することで、一般的なJavaの命名規則に基づく チェックを行うことができます。

Regexp(正規表現でのルール)

正規表現を利用して、javaファイルやその他ファイル(propertiesファイルなど)の検査を行うためのルールを設定します。 任意の正規表現でルールを記述出来るため、標準のルールをつかって直接的に記述することが難しい、 プロジェクト固有の規約を記述する用途で、幅広く利用することができます。

Size Violations(サイズ違反に関するルール)

javaファイルの行数、メソッド毎の行数、行の長さ等、各要素のサイズに基づくルールを設定します。 過度にサイズが大きいファイル・メソッド等を検出することで、 リファクタリングが必要であろうソースコードを抽出することができます。

Whitespace(空白に関するルール)

空白に関するルールを設定します。 Javaの文法における各要素の前後に空白を入れるかどうかを、事細かに設定できます。 また、半角スペース以外のスペース文字がないことの確認するルール等も設定できます。

標準で配布されているコーディング規約

Javaプロジェクトで広く採用されているコーディング規約である、「Sun Javaコーディング規約」と 「Google Java Style」のルールを記述した設定ファイルが、Checkstyleのサイトで配布されています。 プロジェクトのコーディング規約をこれから決める場合は、これら広く採用されている規約を そのまま採用したり、必要な部分を抽出して採用したりすることで、規約を決めるコストを節減でき、 また、実績ある規約を採用することで、無用な問題を避けることができます。

  • Sun Java コーディング規約
    • Java Foundation Class(JDKに含まれる標準クラス群)のソースコードは、 Sun Javaコーディング規約に従って記述されているため、OpenJDK等のプロジェクトでは、 この規約が採用されています。
    • 1997年リリース版以降、すでに規約自体のメンテナンスが行われない旨アナウンスされてます。
    • 1997年以降の新しいJDKの拡張(アノテーション、ラムダ式等)に対応する規約がありません。
    • 1行80文字(テキスト端末の制限に由来)のルールなど、若干時代遅れと思われるルールが含まれています。
  • Google Java Style
    • 2013年に最初のリリースがされて以降、継続的にメンテナンスされ、現在の最新版は2017年9月リリース版です。
    • 比較的新しいオープンソースプロジェクトでは、よく採用されています。

Google Java Styleは、概ね一般的に受け入れやすい ルールとなっているため、これからプロジェクトのコーディング規約を決める場合であれば、 Google Java Styleをベースにするのがよいと思われます。

オープンソースプロジェクトとCheckstyle

オープンソースプロジェクトにおけるCheckstyleの利用状況

Githubで公開されているJavaプロジェクトから、Githubでの人気度を表すスター数のTop 10プロジェクトを抽出し、 Checkstyleがどのように利用されているか調査しました。調査結果は以下の通りです。

プロジェクト名 プロジェクト概要 checkstyle.xmlの有無 ビルドツールへの組込 コーディング規約
ReactiveX/RxJava 非同期プログラミング用API gradle 比較的少数のルールのみ採用
iluwatar/java-design-patterns デザインパターンのJavaによる実装 maven Google Java Styleベース
elastic/elasticsearch 分散検索エンジン gradle 比較的少数のルールのみ採用
square/retrofit 型安全なHTTPクライアントライブラリ maven Google Java Styleベース
square/okhttp Android向けHTTPクライアントライブラリ maven Google Java Styleベース
google/guava Google Core Libraries for Java - - Google Java Style
PhilJay/MPAndroidChart Android向けグラフライブラリ - -
JetBrains/kotlin プログラミング言語 - -
JakeWharton/butterknife Android向けView Injectionライブラリ gradle Google Java Styleベース
bumptech/glide Android向けメディア管理ライブラリ gradle 独自ルールで多数のチェックを実行

TOP 10 Javaプロジェクトの内、7プロジェクトでcheckstyle.xmlが提供され、それらのすべてのプロジェクトで、 mavenまたはgradleのビルドプロセスにCheckstyleが組み込まれています。 Github上で公開されているような、比較的新しいプロジェクトの場合、Checkstyleが広く利用されていることがわかります。

一方で、Tomcat(1999年〜), Struts(2000年〜), Spring(2003年〜)など、Checkstyle(2001年〜)と 同じくらい歴史が長いプロジェクトにおいては、あまり広くは利用されていないようです。 やはり、大規模プロジェクトの途中からCheckstyleを導入するのは、それなりにハードルが高いのかもしれません。 上記プロジェクトのレポジトリで、checkstyle.xmlが提供されているのはTomcatのみで、 そのTomcatの場合でも、ビルドツールへの組み込みは行われていない模様です。

ElasticSearchプロジェクトでのCheckstyleの利用

ここでは、githubのスター数Top10 Javaプロジェクトの一つである、ElasticSearchプロジェクトでの Checkstyleの利用方法を採り上げます。

ElasticSearchは、分散環境に対応した検索エンジンの実装で、現在Javaで最も活発に開発が行われている オープンソースプロジェクトの一つです。 ElasticSearchプロジェクトは、2010年に開発が開始された比較的新しいプロジェクトで、開発開始以降、 2017年12月現在で、29000回以上のコミット・900人以上による貢献が行われている、大規模プロジェクトです。

checkstyle.xmlの設定項目

Gitの履歴を見ると、ElasticSearchプロジェクトでのCheckstyle導入は、2016年初頭からのようです。 プロジェクトの途中からの導入であるため、チェックするルールは比較的少数のルールから初めています。 ルールを追加したり、やむを得ない事情ができた場合にはルールを外したりしながら、 すぐには直せない違反によるノイズを抑えつつ、順次チェックの拡充を図っているように見えます。 ReactiveX/RxJavaプロジェクトなどでも、同様の経緯を見て取ることができます。

たくさんのチェックを行っても、検出した問題を放置することになっては意味がありません。 大量のチェック違反を放置しておくと、それがノイズとなり、すぐに直さなくてはならない 違反を見逃すことになりかねません。 チェック違反を放置することになるのであれば、チェック自体を行わない方がよい、という考え方が 根底にあるものと思われます。

一方で、プロジェクトの開始からCheckstyleを利用している場合は、Google Java Styleを ほとんどそのまま採用しているプロジェクトが多いようです。 プロジェクトの最初からCheckstyleでのチェックを常に実行するのであれば、 実績あるコーディング規約をそのまま採用するのは合理的であると言えます。

プロジェクト固有のチェックの追加

ElasticSearchプロジェクトでは、分散処理での性能を確保するため、java.io.Serializableによる Javaデフォルトのシリアライズは使用せず、独自のシリアライズの仕組みを使用しています。 そのためプロジェクト全体で、java.io.Serializableインターフェースや、 serialVersionUIDフィールドの使用を禁止しています。 禁止が守られることをCheckstyleで確認するため、正規表現でのルールが使用されています。

<module name="RegexpSinglelineJava">
  <property name="format" value="serialVersionUID" />
  <property name="message" value="Do not declare serialVersionUID." />
  <property name="ignoreComments" value="true" />
</module>
<module name="RegexpSinglelineJava">
  <property name="format" value="java\.io\.Serializable" />
  <property name="message" value="References java.io.Serializable." />
  <property name="ignoreComments" value="true" />
</module>

上記の正規表現によるルールの記述は、単なる文字列によるマッチングであるため、Javaソースコードの 意味的には完璧なチェックにはなっていません。 例えば、本来意味的には許容すべき「serialVersionUIDFake」といったフィールド名も禁止してしまいますし、 逆にimport java.io.*でimportし、implements Serializableとすることで、 このルールを回避しSerializableを無理矢理使用することも可能です (その場合でも、import文での*の使用を禁止するルールにはひっかかります)。

しかし、そのような明らかに悪意があるようなケースをのぞけば、概ね実用上十分なチェックはできます。 Checkstyleのチェック用のクラスを独自に実装することで、意味的により厳密なチェックを行うことも可能ですが、 多くの場合、正規表現のルールを使用することで、必要十分なルールを記述することができます。

チェック例外の設定

プロジェクトでコーディング規約への準拠を徹底的に行うと決めたとしても、 例外的にチェック違反を許容したい場合は、どうしても生じます。

例えば、ElasticSearchプロジェクトのソースコードには、ANTLRツールにより自動生成された ソースが含まれますが、自動生成したソースにコーディング規約のチェックするのは意味がありません。 また、JNA(Java Native Access)などの、特殊なAPIを利用するソースコードでも、 例外的に違反を許容する必要が生じています。 また、ElasticSerchプロジェクトのソース内に、行の長さの制限を違反ソースがたくさんあることがわかっているものの、 すぐには修正を行わない、という決断をしたようで、それらのファイルもチェック違反の例外として設定されています。

このように例外を記述するために、ElasticSearchプロジェクトでは、Checkstyleの提供する仕組みである、 checkstyle_sppressions.xmlによる例外設定を使用しています。

<!-- These files are generated by ANTLR so its silly to hold them to our rules. -->
<suppress files="org[/\\]elasticsearch[/\\]painless[/\\]antlr[/\\]PainlessLexer\.java" checks="." />
<suppress files="org[/\\]elasticsearch[/\\]painless[/\\]antlr[/\\]PainlessParser(|BaseVisitor|Visitor)\.java" checks="." />

同様の例外は、ソースコードに直接@SuppressWarningsアノテーションを記述することでも実現できますが、 checkstyle_sppressions.xmlによる指定を利用すれば、ソースコード本体に余分記述を埋め込まずにすみます。

いずれにしろ、きちんと例外の設定方法を確立し、チェック違反を放置し大量のノイズを生み出すのを 避けることが重要です。大量のノイズは真に対応すべき問題を隠してしまうので、放置するぐらいであれば、 チェック自体を行わない方がよいでしょう。

まとめ

  • CheckstyleによるチェックをIDE、ビルドツールの両方に組み込むことで、コーディング規約に則った プログラミングをストレスなく行うことができるとともに、プロジェクト全体でコーディング規約が 守られていることを保証することができます。
  • プロジェクトの最初からCheckstyleを導入する場合は、Google Java Styleを採用すれば、 あらかじめ用意されたルールをそのまま使用できるので導入が容易になり、実績のある規約を 採用することで無用のトラブルを避けることができます。
  • プロジェクトの途中からCheckstyleを導入する場合は、最小限のルールから初めて、順次ルールを 増やしていくアプローチが有効です。チェック違反を長期間放置することになるのであれば、 真の問題を隠すノイズとなってしまうので、そのチェックは一旦外した方がよいでしょう。
  • プロジェクト固有の特殊な規約がある場合でも、正規表現によるルール記述などを工夫すれば、 必要十分なチェックを行えることが多いです。

SideCIを利用することで、プロジェクトのレビュープロセスに、Checkstyleでのチェックを簡単に組み込むことができます。 SideCIでは、「Sun Javaコーディング規約」や「Google Java Style」によるチェックをすぐに利用することができます。 また必要な場合には、プロジェクト独自のcheckstyle.xmlを記述し、それを元にチェックを行うことも可能です。

Checkstyleがまだ導入されていないプロジェクトの場合、はじめは多くの警告が出て戸惑うかもしれません。 SideCIではプルリクエスト単位で新しく書いたコードだけCheckstyleで確認していくことが出来るので、少しずつCheckstyleを導入していくことが出来ます。 また、指摘・ルールについて、無効化したいものなどについての議論を開始することも出来ます。 まだCheckstyleをプロジェクト全体に導入していない場合、無料でSideCIをお試し頂ければ幸いです。

Code Review Meetup #1 コードレビューで集まろうを開催しました。

$
0
0

少し珍しいコードレビューをテーマにしたMeetUpを当社主催で実施しました。
今回はその記念すべき第1回目です。金曜日の夜にもか関わらず、約40名のコードレビューに興味があるユーザに参加いただきました。


概要
開催日時 2018年1月19日(金) 19:00 - 20:45
開催場所 東京都渋谷区 Voyageグループ大会議室パンゲア
参加人数 約40名
主催 SideCI社

f:id:sideci:20180119200422j:plain


講演1 : エネチェンジ社でのSideCI利用事例について

ゲスト講演としてエネチェンジ社のチーフエンジニア川西様より同社におけるSIdeCIの利用事例を紹介していただきました。


講演スライドはこちら
www.slideshare.net

講演2 : RuboCop for Code Review

当社所属のRuboCopコアコントリビュターよりプレゼンテーション。 speakerdeck.com


LT大会はもちろんコードレビュー縛り

■CodeYourRubyでオープンなコードレビューを体験しよう

f:id:sideci:20180119202140j:plain CodeYourRubyの紹介。

Rubyを仕事にするために絶賛勉強中なエンジニアが、自分の書いたコードをGitHubのオープンな場でレビューしてもらうためのリポジトリです。

興味がある人は以下よりどうぞ。
これからRubyで仕事したい人のためのリポジトリ「Code Your Ruby」を作りました - Qiita

■レビューを加速させる仕組みづくり

f:id:sideci:20180119203048j:plain教育系サービスを提供するQuipper社の開発者。 ヨーロッパと日本に開発チームがあることから、向こう側のチームによるコードレビューを逃してしまうと余分に1日をロスするらしいです。 そこでSlackに通知してくれるbotを作成したのでその紹介。
レビュー待ちの Pull Request 一覧を Slack に定期的に通知する - valid,invalid

■コードレビューのアンチパターンについて考えてみた

f:id:sideci:20180119204122j:plain最後は株式会社サイカの@who_you_meさん


まとめ

特に事前打ち合わせはしていませんでしたが、皆さまコードレビューにまつわる素晴らしいプレゼンを展開してくれました。コードレビューを組み入れた開発手法のみならず、チームビルディングや個人で作っているサービスなどバラエティー豊かな話を聞くことができました。

少し話題がRubyよりになってしまったので、次はできる限り言語の枠に縛られない感じでやりたいかなと思ってます。

次回のCode Review Meetupについては、開催検討中ですが、他の会社やグループでやってみたい!ということであればぜひ#2の運営をお手伝いさせていただきます。 GitHubにオーガナイゼーションを作成しましたので、開催の参考になるDocumentなどを今後追加していきたいと思います。

CodeReviewMeetup · GitHub

Viewing all 182 articles
Browse latest View live