わるいインセンティブに負けないためのコード規約と戦略
はじめに
僕はわるいインセンティブに駆られている開発者だった。
わるいインセンティブとはどういうものか。この説明のために今置かれている状況について説明させてほしい。
チームは新規開発で複数の案件を抱えている。また、ビジネス的な観点から多くのピボットが入る。
機能開発とリリースのせめぎあいの中にいると多くの開発者がこう考えるはずだ。
「今はリリースを優先し、汚くて多少可読性が悪いし一般的にはだめなコードだけどマージしてしまおう」
「動くコードが優先! まずは動くものを作る」
しかし、この誘惑は積み重なる程に泥沼に変わってしまう。
リファクタリングの時間は取れず、密結合なコードは剥がしきれず作り直しには予算と人員が足りない。こんなループの中で戦うことになる。
僕は全てはわるいインセンティブによるものだと仮定した。
わるいインセンティブとは早く品質の悪いコードを出したほうが結局評価につながるというもの。いわゆる囚人のジレンマである。
この状況から完全に抜け出すことは難しい。
しかし、なるべく囚人のジレンマから逃れることを仕組みとしてできるのではないかと考え以下の本を読んだ。
- リーダブルコード
- 読みやすいコードのガイドライン
- A Philosophy of Software Design
このブログポストは本を読んだ上で何を考えてどういうアクションをしたのかをかいつまんで書き残したものである。
このポストの対象読者はチームのコード規約を考えたいと考える人やチームで以上の本を輪読して次のアクションを考えている人である。
なお読んだ本の内容に直接触れるものではないため、上記の本の内容が知りたいという人には向かない内容である。
コード規約と戦略
今回はわるいインセンティブに負けないことを目的とする。そのためにコード規約を定め明文化しメンテナンスを続けることを戦略とする。
コード規約を定めることで一般的には
- 保守性の担保
- 変更に強いプロジェクトの運営
- コード品質の向上
を見込むことができると本にはある。これがもしも一定のレベルで達成ができるとしたら結果としてわるいインセンティブを防ぐことができるのではないかと考えた。
規約のメンテナンスがコストとして存在してしまうが、そのコストと引き換えにならないほどに捨てやすいコンポーネントやリファクタリングが可能なコードはメリットをもたらすと判断した。
チームのコード規約の作成までに考えること
ツール選定
- 仕組み化可能なこと
- Gitなどバージョン管理可能なツールで管理可能なこと
- 自前で作るよりもOSSなどでメンテナンスされているものを選ぶ
以上の3点を軸にツールを選定する。
候補はESInt、 Prettier、 Romeとした。OSSとして実績があることやメンテナンスが盛んなこと、有名企業が自社で使っている規約を公開しておりその思想にあやかることができる点で候補とした。
その中で今回は一番一般的であると思われるESIntとPrettierを利用する。
ルール設定
チームのコード規約を設定するにあたり、以下の点に注意する必要がある。
規約が明確であること
規約が守られるようにすること規約が明確でないと、開発者はどのようにコードを書くべきかわからず、混乱を招くことがある。また、明確であっても守られなければ意味がないため、守られるようにする仕組みを用意する必要がある。
具体的なルール設定のポイントとしては、以下のようなものが挙げられる。
- インデントのスペース数
- ブロックの開始位置、終了位置の指定方法
- 変数名、関数名の命名規則
- コメントの書き方、コメントの必要性
- エラー処理の方法
コードレビュー
コードレビューは、規約が守られているかを確認する上で非常に重要な役割を果たす。レビュアーが規約に沿って書かれているかをチェックし、違反があれば指摘することで、規約の遵守を促すことができる。
ただし、レビュアーが全てをチェックすることは非常に時間がかかるため、特に重要なポイントについて中心的なレビュアーがチェックする、あるいは自動化ツールでチェックするなどの工夫が必要となる。
コミュニケーション
コード規約を策定する上で、コミュニケーションは欠かせない要素である。
全員がルールに納得し、遵守することができるよう、ルールの策定にはチーム全員が参加することが望ましい。
また、ルールの変更や修正についても、適宜コミュニケーションを行い、全員が理解できるようにすることが大切である。
メンテナンス方針を決める
フェーズを決めフェーズが変化するときにメンテナンスを入れる。
フェーズはチームの人数、抱えるプロジェクトの数を軸にする。なぜチームの人数と抱えるプロジェクトの数を軸とするかというと、新規事業チームなので開発チーム人数の変動が短い周期で起きやすい。なので人数を軸に入れる。
また、いくつもの新規事業案のPoCが並列で走ることがある。
並列数はチームにとっての負担であるため、負担を最小にする動きをするべきと判断しその足かせにならないようにする。
規約をどう守り、メンテナンスするか
規約は基本的に厳格なものとしてチームの生産性などを様子を見ながら徐々にゆるくする方針を取る。 規約を守ることはコストではいけない。なので開発者にはなるべくVScodeやIntellijを利用してもらい、IDEのプラグインから支援を受けられる状況を作る。 また、変更があるときにはプルリクエストを出して変更することを徹底する。
普段している開発の中にいかにコストが少ない形でコード規約を入れ込むかを重視する。
これらは守ることも大事だが意識しなくても守れている、その結果わるいインセンティブに流されないという状況がベストであると考える。
また、規約を入れ込む環境やチームの状況を把握することが重要である。まずは自分のチームのヘルスチェックと目指す方向性を把握することが重要である。
まとめ
わるいインセンティブに負けずに、良質なコードを書くためには、コード規約の策定が必要である。
コード規約を明確に定め、守られるようにすることで、品質の悪いコードを出しても評価されるというジレンマから抜け出しチームを救うことができる。
まずは今のチームとコードの現状を知るところから始めるのはどうだろうか?
誤字脱字と記載もれがあったんので追記(2023/03/19)
『プログラムはなぜ動くのか』感想
読み始めたモチベーション
プログラミングはしてきたがその基礎部分が弱いと感じたため。自分の取り扱うものがどういう仕組で動くのかや、基礎的な知識を体系的に学びなおしたいと思った。特にメモリなどはフロントエンドでコードを書いていると意識することが少ないため理解が曖昧な部分が多かった。 メモリの仕組みや2進数、どんな環境で自分の書いたコードが実行されているのかを体系的に説明できるようにしたい。
この本の対象になりそうな読者
- プログラムを書いてはいるがコンピュータの中身でどんなことがされているのかを知らない人
- プログラミング初学者
- 体系的なコンピュータの仕組みが知りたい人
全体的な感想
各章のはじめに導入としてウォーミングアップがあり、その内容に答えられるかどうかで自分の理解度がわかるのがとてもいいなとおもった。まずはウオーミングアップをやってみてわからなかった部分や間違いをメモしておいて本章をよみ、本章を読み終わったときにもう一度ウオーミングアップをやってみると言うのを繰り返して読んでいった。 各章は図解もありつつそこまでボリュームがあるわけではないので読み進めやすい。読み進めていて理解が追いつかないときには理解ができていない箇所をググって動画を探して理解すると読み進めやすくなった。
おそらくこの内容は大学や専門学校、高専では入学後すぐにやるような内容なのだろう。恥ずかしながらこういった基礎を避けてエンジニアとして働き始めてしまった私は聞いたことがあるが説明ができない、間違った理解をしているものが多かった。 フロントエンドの実装を多く取り扱うとこのあたりのことを知らないくてもある程度は仕事になってしまうが、知っているのと知らないのでは大違いだ。 どういう仕組で自分の書いたコードが実行されていくのかがわからないというのはエラーの原因やドツボにハマったときに抜け出せるかという点で大きな違いがある。 また、ライブラリやより専門的な内容に触れたいと思ったときに致命的になる。
一度立ち止まってこういう知識を整理し、きちんと学ぶ機会が設けられてよかったと感じた。 学びが多かったのと同じくらい危機感やわからないといままを放置する怖さが勝った。
勉強になった、印象に残った箇所
全章が勉強になったが印象に残ったのはCPUの章だ。 まず自分は実行の流れを説明できなかった。プログラムが機械語にコンパイルするところは説明できたが、メモリに保管しCPUが実行する流れがわかっていなかった。 また機械語へのコンパイルもインタプリタ型言語とコンパイル型言語の説明がきちんとできていなかった。
JavaやScala、TSを扱ってきたがJavaやScalaはコンパイル型言語であることくらいしかわかっておらず、その実行がどのようにされるかを考えてこなかった浅さを思い知った。 こういう基本的なことがおざなりであることが足元を掬われる原因になるので今後も勉強を続けていこうと思った。
OSの章も勉強になったことが多かった。 自分がOSが提供してくれることがまず説明できていない時点で結構やばいなと思った。ハードウェアを動かすのはOSなのでOSに対してアプリケーションを作っている意識を持つことが重要なんだろうなと思った。 思い通りの動きができないときにはOSへの理解が足りていないのかも?と疑う視点を手に入れることができた。今までは考えたことがなかった視点だ。
読んで見て試したいこと
『プロを目指す人のためのTypeScript入門 安全なコードの書き方から高度な型の使い方まで』の感想
読み始めたモチベーション
業務で使っているがモジュール周りの知識不足を感じていたため。ちゃんとTypeScriptという言語と向き合ったことがなかったと感じたので1から知識を整理しつつ理解を深めたいと思った。
この本の対象になりそうな読者
- TypeScript初学者
- よりTypeScriptへの理解を深めたい方
- チームでの知識前提を揃えるための輪読会などを開く方
全体的な感想
TypeScriptの本といいつつもJavaScriptにも触れられておりJS+TSの本という感じだった。 内容は厳密だが初心者が抑えるべき内容に絞られており読み進めやすい。これ一冊で十分かと言われると疑問は残るが、ここから始めるには必要十分だと思う。 自分の場合は読みながら疑問に思ったものやもっと知りたいものはMDNなどのドキュメントを参照したり、仕様を都度確認して読み進める方針をとった。
後半の内容が個人的には印象に残っていて、EMSやTSのコンパイラオプションなどは普段はあんまり深く意識しないため新しい発見がおおかった。inport/exportって何気なくしてしまうけど仕組みをわかっていて適切な名前付けができてなかったと思った。
勉強になった、印象に残った箇所
asによる型アサーション便利だけど使いどこは考えものだなとおもった。なるべく使わない方針をとりたい。 as constの効果が書かれていて勉強になった。使えるところがあるのならば積極的に使っていきたい。
7章のTypeScriptのモジュールシステムがとても印象的だった。どういう点で印象に残ったかというと、今までなんとなくでやってしまっていたnamed exportやdefaultについて端的に説明書されていて自分の中で今までのやり方の何が良くなかったかや今後どうしようかといった考えが一気に前に進んだため。
exportのときには名前の競合が起きないようにくらいしか気を使っていなかった。 しかしこれだとアプリケーションが複雑になるにつれて名前の競合が避けられなくなっってしまう可能性がある。ドメイン名も名前に含めるようにするといいという示唆があり、それがとてもいいなと思った。
default exportは export * from '...'
には含まれないのも知らなかった。
この辺がわかってなかった。なんとなくでやっているとこういうところで落とし穴にハマるので気をつけたい。
読んで見て試したいこと
【良いコード/悪いコードで学ぶ設計入門】を読んで設計に入門する。
書評【良いコード/悪いコードで学ぶ設計入門】
以降の文章では「良いコード/悪いコードで学ぶ設計入門」を本書、「良いコード/悪いコードで学ぶ設計入門」を書いた方を著者、この書評を書いた人間を筆者とする。
本書の対象とする読者
- 設計初心者
- 新卒1〜3年目
- より良いコードを書きたい人
- リファクタリングでコードを良くしたいがとっかかりがないと感じる人。
総評
筆者自身について
筆者は設計については無知である。
これまでの仕事では良いコードを書こうという意思はあるもののまずは動くもの、次にリリースを優先してきたタイプの開発者である。
本書を手にとって感じた一番の最初の感想は自分がリファクタリングをおろそかにした結果、成長機会を失って来た事実と焦りだ。
一方でこの機会に設計について再度学習をし直し、日々の業務に活かすチャンスでもあると感じた。
本書は幅広い設計のあり方や、知識に触れてそのバックグラウンドを徹底して固める内容ではない。なので設計に対してのより深い考察を得たい読者には不向きかもしれない。
オブジェクト指向を使いながらデザインパターンなど設計の中でも実践しやすいものを選び、良い例と悪い例の実例を交えて紹介する。
この例がたくさん掲載されているのが自分にとって有益で、考えを広げたりユースケースを想像する材料となった。
本書を読んで得たもの
悪いコードが及ぼす影響は幅広い。
サービスのスケールアップやコードの変更のコストを増加させる。
コードの変更のコストが増えるというのはその分だけ事業の成長を遅らせることになる。
筆者は設計に無知だと前述したが、設計自体に無知だったというよりは本書で紹介される悪しき構造や悪しき設計に対して鈍感だった。
この鈍感さというのは非常に厄介である。
何が良い例なのか、何が悪い例なのか、悪い例はどのような結果をもたらすのかという知識が欠如していると実際にあるコードから学ぶことができないのだ。
この設計は参考になるなとか、書いた人の意図と仕様を読み取ることができない。
そのため成長が鈍化していくのだ。
開発者の成長の鈍化というのはサービスの鈍化につながると筆者は考える。
自分が原因でサービスが鈍化していたかもしれないと振り返り、これからどうするのかを考える良い機会と例をあたえてもらえた。
本書を読んだモチベーション
本書を手にとったモチベーションは2つ
1. 自分の中に良い設計と悪い設計の引き出しが増え、読み終わったときに自分の書いたコードを見返して悪い設計を知覚できるようになりたい
2. OSSや他のチームのコードを読んだときに設計者の意図を汲み取れるようになりたい
本書を読み勧めていく中でこのモチベーションを満たしてくれる箇所は複数あった。
一例を紹介すると、凝集度にふれる第5章の箇所だ。
凝集度の話題は掘り下げればいくらでも掘り下げることができる。だが、本書は最低限抑えなくてはいけないポイントにしぼって凝集度を紹介し、悪い例を挙げる。
そして良い例を示し、凝集度を適切に扱うことがいかに変更に強い構造を生むのかを解説する。
この箇所だけを読んで凝集度に関してわかった気になるのは危険だが、考えを取り入れ自分の中で深めていくのには適しているとおもった。
15章、16章、17章では著者の経験などをもとにどのような設計思想に基づき考察がされているか述べられる。
個人的にはこの章から読み始めると1章〜14章の内容が更に鮮明になると感じる。
著者は最先端の設計をしようとしているのではない。
あくまで保守性の高さに重きをおき、その中でも変更容易性を最重要視している。
なぜ変更容易性がここまで重視されるのか?
- 悪しきコードが間違った教育をしてしまう
- 改善の困難さが高品質な実装に触れる機会を失わせる
- 変更容易性が低いコードはそれ自体がコストであり時を奪う
という理由が列挙される。
同意する部分ももちろん多いが全員に当てはまることではない。筆者はこの理由がもろに当てはまり自身の成長を鈍化させたので同意する理由がおおきかったというのを忘れないでほしい。
また、本書ではカバーできなかった領域やより深い知識を得るための方法にも触れている。
本書を読み終えたあとで買うべき本やインプットとアウトプットの比率にも触れている。初学者に優しい点である。
感想
本書は初学者が自分の現在の状態に気づき、コードをどう直せばいいのか、悪い例がどのような悪影響を自分やチームにあたえるのかを学ぶにはとても良い教材になる。
この本を手にとって筆者のように自分の過去の過ちや成長の鈍化に心が痛くなる人ももしかしたらいるかもしれない。
しかし、諦めずここから勉強と改善がスタートできると思えば儲けものなのではないだろうか?
まとめ
本書を手に取る前は間違った経験則と自身の未熟さに気がつくことができない未熟さがあった。
本書はそれを気が付かせ、その改善の手引をしてくれる。
「良い設計とはなんだろうか?」とか、「保守性の高さとはなんだろうか?」と先輩や上司に聞かれて困ったことがある人、なんでこんなに簡単そうな変更にコストがかかるのかと非エンジニアと揉めたことがある人は一度本書を手にとって見てほしい。
直接問題を解決してくれるクリティカルな解法が載っているわけではない。
だが、丁寧にユースケースをなぞりながら悪しき構造を知覚できる、という一番最初で一番大事なスタートラインに立たせてくれるのが本書である。