【自動整形】[ formatter / Beautifier ] でソースコードの可読性を上げ品質向上に繋げよう

# **はじめに**

　ソースコードはやはり、読みやすいに越したことはない。しかし「読みやすさ」というものは人によって基準が異なり、技術レベルや経験によって大きくブレるところでもある。
　個人的にコードを書いて動かす程度であればそれでも問題はないが、OSS利用が当たり前になり、また、自分一人で作り上げることが出来るアプリケーションなどたかが知れており、様々なエンジニアと成果物を共有しながらプログラムを書くことが多い現在では、不都合が生じることも多々ある。
　そんな時にソースコードの記載ルール（インデントはスペース？タブ？／if文の折り返し場所は？条件内のスペースは？）がエンジニアによってバラバラだったり、もしくは一人のエンジニアが書いたコード内でも場所によって無秩序に記載されている場合、コードを読むだけで一苦労だったりする。
　そのような課題を解決してくれるツールが、「 **formatter** 」 と呼ばれる自動フォーマッティングツールだ。本記事は「 **clang-format** 」と呼ばれる formatterツール に注目し、概要から導入方法、効果的な運用方法について記載する（つもりである）。

# **想定読者**

本記事はベテランエンジニアの方々にとっては見飽きた情報ばかりのはずだ。

逆に、下記のような方には有効な記事となるかもしれない。

- チーム開発のリーダーを任されたは良いがコードレビューに多大な時間を割かれている方
- プログラムを初めて1〜2年、ある程度の柔軟性を持ってコーディング出来るようになったけど、より効率的に開発がしたい方
- 製品品質の向上を目指してコードレビューやチェックリストでチェックしているが、主に物量的な面で課題を感じている方

# **チーム開発とコードレビュー**

　例え性善説の立場であったとしても、ソフトウェア技術に関する価値基準や経験値はエンジニアごとに異なるため、同一の目標に向かって製品を作っている場合、そういった細かな差異が製品品質と作業効率に大きく関わってくる。
　特に小規模チームでの開発に慣れたチームがスケールする際に「今までやってこなかったから」と、コードフォーマットの統一やコードレビューを疎かにしていると、ソースコードレベルでも精神的なレベルでも小さな負債が積み上がっていくこととなる。また、仕様の伝達漏れや認識の齟齬により、外形レベルのバグが積み重なる状況で、ソースコードレベルの基礎的だが時間が必要な作業に時間を取られるとなると、担当リーダーやプロジェクトリーダーは気が遠くなるほどのストレスを感じることが往々にしてある。
　チーム開発において、相応の製品品質が求められる場合はコードレビューが必須となるし、そのコードレビューというのは、ある程度の仕組みを整えることが出来ない状況では、チェックの漏れや膨大な時間の浪費に繋がってしまう。

# **フォーマッタ・ツールの必要性**

　大前提として、小さな単位で開発したり、コードを見返したりだとかの作業が発生しないのであれば、導入する必要はないはずだ。
　ただし、チームの規模が大きい場合や継続的にメンテナンスが必要な場合においては、エンジニアごとにコーディングルールが違うだけで、まるで「ここは塩味」「ここは醤油味」とでも言えるような、不思議な味のスパゲッティコードと戦う羽目になってしまうであろうことを考えると、早い段階で「使える」ようになっておいて損はないはずだ。
　また、導入コストや習得コストを加味して「コストに見合うリターンがある場合に導入する」という大前提はあるにしろ、一人でプログラミングする際にも、一々フォーマットを気にしながら書くということは少ないだろうから、そういった意味でもいくつか有効なフォーマッタを使えるようになっておくことは今後のエンジニアライフを少しだけ快適にしてくれるかもしれない。

# **様々なフォーマッタ・ツール**

## **外観**

　「**formatter**」 と言っても、単純なコメント行などを解析してくれるものから、言語ごとの特徴を解析して整形してくれるものまで様々あり、種類も多様である。ここでは特徴的なフォーマッタ・ツールと解析可能な言語について記載する。

## **Beautifiers（抜粋）**

**Beautifier （清書ツール／整形ツール）** と呼ばれるものを記す。

|Beautifier|Language|Web Site|
|:--|:--|:--|
|align-yaml|YAML|[here](https://github.com/jonschlinkert/align-yaml)|
|beautysh|bash|[here](https://github.com/bemeurer/beautysh)|
|clang-format| C/C++/Java/JavaScript/Objective-C/Protobuf|[here](https://clang.llvm.org/docs/ClangFormat.html)|
|atom-beautify|HTML/CSS/JavaScript/PHP/Python/Ruby/<br>Java/C/C++/C#/Objective-C/<br>CoffeeScript/TypeScript/<br>Coldfusion/SQL/and more|[here](https://atom.io/packages/atom-beautify)|
|puppet-lint|Puppet|[here](puppet-lint)|
|Rubocop|Ruby|[here](https://github.com/bbatsov/rubocop)|
|Pretty Diff|HTML/CSS/javascript/<br>csv/JSON/Twig/XML|[here](https://github.com/prettydiff/prettydiff)|
|Nginx Beautify|nginx|[here](https://github.com/denysvitali/nginxbeautify)|
|Perltidy|Perl|[here](http://perltidy.sourceforge.net/)|
|Python|autopep8|[here](https://github.com/hhatto/autopep8)|

この他にも多くの **Beautifier** が存在し、Atomプラグインである [[atom-beautify](https://atom.io/packages/atom-beautify)] の公式ページにより多くの情報が載っているので、もし気になる方がいれば見てみると良い。

## **参考**

- [atom-beautify - Atom](https://atom.io/packages/atom-beautify)
- [bbatsov/rubocop - GitHub](https://github.com/bbatsov/rubocop)
- [Python のコーディング規約 PEP8 に準拠する - Qiita](http://qiita.com/ynakayama/items/8616f4c0c6e372de9a42)
- [bemeurer/beautysh - GitHub](https://github.com/bemeurer/beautysh)

# **What is clang-format**

## **概要**

 clang-format は下記の言語を整形することが出来、コマンドライン上で使用することも、vim や EMACS、Atom といったテキストエディタと統合して使用することも出来る。

- C
- C++
- Objective-C
- Java
- JavaScript
- Protobuf

[[ClangFormat — Clang 5 documentation](https://clang.llvm.org/docs/ClangFormat.html)]

ちなみに、Clang（クラン）という名を関したコンパイラが存在する。
これについては Wikipedia の解説を引用する。

> Clang ([ˈklæŋ]：クランのように発音)は、プログラミング言語 C、C++、Objective-C、Objective-C++ 向けのコンパイラフロントエンドである。バックエンドとして LLVM を使用しており、LLVM 2.6以降は LLVM の一部としてリリースされている。
プロジェクトの目標は、GNUコンパイラコレクション (GCC) を置き換えることのできるコンパイラを提供することである。開発は完全にオープンソースの方法で進められており、アップルやGoogleといった大企業も参加・資金提供している。ソースコードは、University of Illinois/NCSA License（英語版）ライセンスで提供されている。
macOSおよびiOS（ともにXcodeの付属として）、ならびにFreeBSDにおいて標準のコンパイラとして採用されている。
Clang プロジェクトではコンパイラのフロントエンドに加えてClang静的コード解析ツールも開発している。

引用：[Clang - Wikipedia](https://ja.wikipedia.org/wiki/Clang)

## **導入方法**

### **導入手順**

#### **for Mac**

Macの場合は homebrew を使ってインストールする。（その他の方法もある）

```console:Command
$ brew tap tcr/tcr
$ brew install clang-format
```

#### **for Windows**

Windowsの場合はダウンロードページからバイナリをダウンロード出来る。

- [LLVM Download Page](http://releases.llvm.org/download.html)

## **設定**

clang-format の設定は .clang-format に記載する。
今回は [[こちらのサイト](http://yasuharu519.hatenablog.com/entry/2015/12/13/210825)] で丁寧に解説がされていたので、引用／参照させて頂いた。

```yaml:.clang-format.sample.yaml
---
BasedOnStyle: 'Google'
AccessModifierOffset: -2
AlignEscapedNewlinesLeft: true
AlignConsecutiveAssignments: false
AlignEscapedNewlinesLeft: true
AlignTrailingComments: true, 
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: 'Inline'
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: false
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BreakBeforeBinaryOperators: 'None'
BreakBeforeBraces: 'Allman'
BreakConstructorInitializersBeforeComma: true
ColumnLimit: 80
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
DerivePointerBinding: true
IndentCaseLabels: true
IndentWidth: 2
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 1
NamespaceIndentation: 'None'
PointerAlignment: 'Left'
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: 'ControlStatements'
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
Standard: 'Cpp11'
TabWidth: 4
UseTab: 'Never'
```
引用：[yasuharu519/.clang-format.sample.yaml - GitHub](https://gist.github.com/yasuharu519/0a26ea6e70ae23ff0acd#file-clang-format-sample-yaml)

## **参考**

- [clang-format を イイ感じに設定する - def yasuharu519(self):](http://yasuharu519.hatenablog.com/entry/2015/12/13/210825)
- [Clang-Format Style Options - Clang 5 documentation](http://clang.llvm.org/docs/ClangFormatStyleOptions.html)
- [ClangFormatスタイルオプション - Algo13](http://algo13.net/clang/clang-format-style-oputions.html)

## **実行**

### **for Mac**

```console:Command
$ clang-format [options] [<file> ...]

// findコマンド などで対象ファイルを見つけて一括で処理することも可能。
```

### **for Windows**

下記を参照。

- [クイックスタート - ClangFormat](http://algo13.net/clang/clang-format.html#id3)

# **運用に向けて**

## **導入するツール**

　ツールによって対象とする言語やルールが異なるので、適切なツールを調査、選定して導入しよう。
Atomを使用している場合は比較的簡単に導入出来るはず。

## **フォーマッティング・ルール**

　整形ルールについてはプロジェクトごと、言語ごと、チームごとで適宜変更するのが良いが、基本的なルールについては設定ファイル以前にドキュメントとして文書に書き起こしておくと良い。

## **いつやる？**

　突然にチームに導入しようとしても、習得コストや作業コストなどの負荷が少なからず発生することもあり失敗してしまうケースの方が多いのではないだろうか。まずは自分自身で環境を整備し、少しずつメンバーに広めてゆく方が文化を形成しやすいはずだ。

　チーム内へツールの導入と文化が根付き始めると、どのタイミングで整形してソース共有するかも決めなければならない。基本的にはGitやSVNにコミットする前のローカル開発環境上で整形してからコミットするというルールを設けよう。

## **誰がやる？**

　最初は一人からの導入にはなるはずだが、最終的にはエンジニア個人個人が実行出来るようにしたい。チームメンバーにそういった作業を依頼するのであれば、手順書などの作成も必要になってくるだろう。

# **品質向上に向けた取り組み**

　一人で作るにしろ、チームで作るにしろ、**各工程で実施する ベスト・プラクティス** や、 **計測すべきソフトウェア・メトリクス** というのはある程度決まっている。また、 **レビューの種類とチェック内容**
 などもある程度の標準が存在する。

　今回はソースコードの可読性向上に向けたツール導入に注目したが、導入後の使用タイミングは恐らく下記のようになり、かなり部分的な影響という見え方も出来るかもしれない。ただし、動作の根本となるソースコードの可読性を上げておくことは、長期的な視点でみると非常に重要になってくるため、意識しておいて損はないはずだ。

```text:コーディングとレビュー
コーディング
　↓　　↑
　↓　←ここでソースコードのformating（整形）
　↓　　↑
机上デバッグ　：　レビュー実施、静的コード解析ツールでソースコード分析
　↓
（コンパイル）
　↓
（デプロイ）
　↓
動的デバッグ
```


## **ソースコードレビューとは**

　そもそもの話しにはなってしまうが、ソースコードレビューの外観について理解したい場合は、下記のIPAが公開しているページが分かりやすい。

- [第2章 脆弱性回避策とソフトウェア開発工程 - IPA](https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/c103.html)

　また、Wikipedia の記述も分かりやすいので引用させて頂く。
（引用：[コードレビュー - Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%BC%E3%83%89%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC)）

> ## 概要
プログラマのスキルによらず、書き下ろされたばかりのソースコードは潜在的にバグやセキュリティホール（書式文字列問題、競合状態、メモリリーク、バッファオーバーランなど）などの不具合が入り込んでいることが多い。ソフトウェア品質を高めるためにはこのような不具合を除去していく必要がある。この不具合を発見し修正するための1つの方法が、ソースコードの査読を行うこと、すなわちコードレビューである。
オンラインのソフトウェアリポジトリ（匿名のCVSなど）を使うと、複数の個人が共同でコードレビューを行うことができる。
コードレビューを自動化するソフトウェアを使うと、ソフトウェア開発者の代わりに典型的なセキュリティホールを見つける作業を行ってくれる。そのようなソフトウェアの例として、Flawfinder や Rough Auditing Tool for Security(RATS) などがある。

> # 効果
コードレビューを実施することにより以下のような効果が期待できる。
レビューで発見された同様・類似バグについてレビュー参加者内での共通認識を図ることができる。
バグの隠蔽を減少させることが期待できる。
レビューを行うことへの意識により、人に見せるコードを書くようになるため可読性が向上する。
コーディング規約等に対する各自の認識のずれを修正することができる。
ただし、その性質から開発工程上の問題点も多く、批判もある（#批判の項目を参照）。

## **参考**

* [テストとコードレビューの目的 - Qiita](http://qiita.com/necojackarc/items/0efa125ce1ea90e739f0)
* [コードレビューをより効果的にする方法 - InfoQ](https://www.infoq.com/jp/articles/effective-code-reviews)
* [ソースコードの品質向上のための効果的で効率的なコードレビュー - SlideShare](https://www.slideshare.net/MoriharuOhzu/ss-9224836)
* [静的解析ツールの効果的活用方法 - FUJITSU](http://www.fujitsu.com/downloads/JP/archive/imgjp/group/fct/v4/events/exhibit/esec2014-17-01.pdf)

# **おわりに**

とまぁ、色々と書いてみたけれど、記事の主な目的は、最近、iOS / Android / PHP を始めとして、多言語のソースコードレビューを行う必要が発生しつつあるので、導入手順の備忘録と教育用メモとしてのアウトプットでした。 
　当初は **clang-format** の導入手順と概要について書き始めたら、有効なツールを色々見つけたりだとか、そもそも論的なところの解説を書いてみたりだとかで、かなり内容が膨れてしまいました。
漏れや記載漏れなどあれば都度更新しおうかしら、という感じです。

# **参考**

## **設定について知る**
- [Clang-Format Style Options - Clang 5 documentation](http://clang.llvm.org/docs/ClangFormatStyleOptions.html)
- [ClangFormatスタイルオプション - Algo13](http://algo13.net/clang/clang-format-style-oputions.html)

## **概要について知る**
- [静的コード解析 - Wikipedia](https://ja.wikipedia.org/wiki/%E9%9D%99%E7%9A%84%E3%82%B3%E3%83%BC%E3%83%89%E8%A7%A3%E6%9E%90)
- [コードレビューのベストプラクティス - POSTD](http://postd.cc/code-review-best-practices/)
- [テストとコードレビューの目的 - Qiita](http://qiita.com/necojackarc/items/0efa125ce1ea90e739f0)
- [clang-format を イイ感じに設定する - def yasuharu519(self):](http://yasuharu519.hatenablog.com/entry/2015/12/13/210825)