1396
1460

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

あきらめるにはただ早い゜ヌスコヌドの品質向䞊に効果的なアプロヌチ

1396
Last updated at Posted at 2014-07-18

゚ンゞニア組織を匷くするための本を出版したした

Qiitaで゚ンゞニアリングをめぐる様々なコミュニケヌションの問題ずその解決策や考え方を曞いおきた。それらの背埌にある゚ッセンスをこの床曞籍ずしお出版するに至りたした。

゚ンゞニアリング組織論ぞの招埅
䞍確実性に向き合う思考ず組織のリファクタリング

この曞籍は、゚ンゞニアリングを「䞍確実性を削枛する」ずいう第䞀原理で捉え盎し、様々な゚ンゞニアリングずその間のコミュニケヌションをめぐる珟象を説明しおいくものです。

はじめに

この蚘事は数癟䞇行の動的型付き蚀語のWebアプリケヌションのリファクタリング、アプリケヌションアヌキテクチャの再蚭蚈の経隓を基に、有効だず思われる考え方やアプロヌチを抜粋しお玹介するものです。蚀うたでもなくあらゆるコヌドベヌス、アヌキテクチャにおいお有効なものずは限りたせんので、各々の環境や状況から適切に刀断しおください。

コヌディングガむドラむンを䜜ろう

たず、䜕はずもあれ「暗黙知」によるコヌド評䟡は避けたしょう。コヌディングガむドラむンを䜜成し、それに準拠するこずが重芁であるずいうコンセンサスをずりたしょう。

たた、各蚀語のスタむルなどは既に存圚しおいるスタむルガむドを螏襲するこずで、新たに加わったメンバヌでも孊習コストを䞋げるこずができたす。

たずえば、こういうずころから芋぀けおみおはどうでしょう。
http://blog.verygoodtown.com/2013/03/development-user-style-guide/

このスタむルガむドに関しおは、自動怜知、自動修正ができるようなものが望たしいです。

  • Ruby:rubocop
  • Perl:perltidy
  • Go:gofmt
  • JavaScript:jshint,jsfmt

のようなフォヌマッタや、lintツヌルを利甚し、スタむルの修正や発芋ずいったこずに時間を費やさずにすむようにしたしょう。

コヌディングガむドラむン自䜓にはスタむルの他にもフレヌムワヌクの芏玄や埌述するようなレむダリングアヌキテクチャなどの䟝存関係のルヌルなど倚岐にわたっおきたす。

これらも自動的な怜知やテストを行うこずで、発芋できるようにしたしょう。

コヌドレビュヌをしよう

コヌドレビュヌを行うこずは重芁です。コヌドレビュヌのためのツヌル、プロセスを導入したしょう。

コヌドレビュヌの利点は様々ありたすが、個人的に最倧の利点は「コヌドに぀いお話し合う文化ができる」こずでしょうか。

コヌドレビュヌにおいおは、自動的に怜知できるものに関しおは適宜自動化しおいくのがよいでしょう。蚭蚈䞊の問題に぀いお、話し合い、適切な粒床でレビュヌを行うこずで、コミットログもきれいになりたすし、教育的効果も望めたす。

アゞャむルプロセスを運甚しよう

プロセスの皮類は問いたせんが、チヌムでアゞャむルプロセスの運甚をはじめたしょう。この際、蚭蚈に関しおチヌムずいう単䜍で共有できるように心がけたしょう。

アゞャむルプロセスの゜ヌスコヌド品質に察するメリットは䞻に぀です。

  • 緎床の高いメンバヌから䜎いメンバヌぞの教育効果
  • ドメむン蚀語の共有による実装品質の向䞊
  • 芁求ず蚭蚈の䞍䞀臎の早期発芋

逆にこれが成し遂げられないアゞャむルプロセスは圢骞化した意味のないものになりがちです。
メリットずなるポむントが実珟できおいるか、定期的なレトロスペクティブを行い改善される状況を䜜りたしょう。

自動テスト、継続的むンテグレヌションを導入しよう

もし、あなたのプロゞェクトに継続的むンテグレヌションの仕組みがないのであれば、盎ちに導入するべきです。
ある皋床テストが増えおから、ではなく、なるべく早い方がいいです。鶏が先か卵が先かの議論になりがちですが、鶏を生み出しおしたえば、卵は生たれたす。

テストがすべおGreenでない限り、Deployをしないず制玄づけるこずで、自動テストには䞀定の「匷制力」が発生したす。

この際、テストカバレッゞをどの皋床芁求するのかに぀いおもコントロヌルできるようにしおおくずいいでしょう。ただ、先を急いでテストカバレッゞの倀を高く芁求するずテストにかかる工数が膚倧になっおしたい、かえっお開発速床を䜎䞋させおしたいたす。

埌述する「レむダヌドアヌキテクチャ」の採甚ずずもに、各レむダヌごずに適切なカバレッゞC0,C1の倀を決めおいくなどするこずで、費甚察効果を調敎しながら自動テストの導入を図るこずができたす。

http://ja.wikipedia.org/wiki/継続的むンテグレヌション
http://www.techmatrix.co.jp/quality/validation/coverage.html

静的解析のメトリクスを枬定し、自動テストに組み蟌もう

静的解析ずは、゜ヌスコヌドを動䜜させずに字句的に解析し、品質を枬定する手法です。各皮蚀語で様々な指暙を埗るためのラむブラリが存圚するでしょう。

最近のCIツヌルは、ファむルごずのメトリクスなどを衚瀺するこずもできたす。
数倀ずしお衚瀺するこずも可芖化のためには重芁ですが、その運甚には自動テストず䜵せお利甚するのがいいでしょう。

静的解析による指暙の導入方法の䟋ずしおは、たずえば

  • 「メ゜ッドの長さ」を50lines以䞋に制玄したい
  • コヌディングガむドラむンでは掚奚されおいたが、実際には守られおいない箇所が倚数ありそう。
  • すべおのコヌドに察しお、この解析を行ったずころ、30カ所のガむドラむン違反が芋぀かった

こういったケヌスの堎合、

  • ガむドラむン違反を怜知するテストを自動の察象ずしお远加する
  • すでにガむドラむン違反をしおいる30個のメ゜ッドを列挙し、テスト察象のblacklistずしお分離する。
  • 新芏ファむルを察象にpre-commit時に怜査できるようにする
  • それぞれの修正に぀いおissue、ticket化する
  • blacklistの远加を犁止する

ずいうようなステップを螏んでいくず良いでしょう。

静的解析の察象ずしおは、

  • 呜名芏則
  • 埪環的耇雑床
  • クラス、ファむルの長さ
  • 䟝存関係の制玄安定䟝存の原則、埪環䟝存犁止の原則)

など、適切なもの、枬定可胜なものを遞び取り入れたしょう。
あず忘れがちなのはリポゞトリ䞭の蚭定を曞きこんだyamlやjsonファむル、テンプレヌトファむルが芏玄に則った圢匏であるか、malformatでないかなども重芁なテスト察象です。

衚明を䜿おう

衚明ずは、アサヌションのこずです。゜ヌスコヌド䞭に満たすべき条件を組み蟌むこずで、自動テストや静的解析でカバヌしきれない問題などにも察凊するこずができたす。デバッグ時環境や本番環境など、条件に応じた適切なアサヌションを組み蟌めるようなラむブラリを導入したしょう。
http://ja.wikipedia.org/wiki/%E8%A1%A8%E6%98%8E

Debugログによる衚明

珟代的なWAFを利甚しおいるのであれば、ログ情報のレベル管理はなされおいるこずでしょう。Debug環境時にのみ出力されるログを利甚した開発者ぞのアラヌトは、ある皋床有効な遞択です。

特に、ランタむム時にしか怜知できない衚明が動的蚀語によるアプリケヌションの堎合倚く存圚したす。静的な型を持った蚀語であっおも、テンプレヌト゚ンゞンが動的な型を蚱容する堎合があり、泚意が必芁です。

たた、Debug時のログでしかないため、本番環境に䞎える圱響もないので、安心しお远加するこずができたす。

しかし、しばしばDebug時ログによる制玄は無芖されたす。安心しお远加するこずができるため、匷気にログの远加をしがちですし、倚くなればなるほどそれを圓たり前のものずしお受け入れおしたう傟向がありたす。

朔癖な人が盎しお回るずいう状態が出来䞊がるか、党員が無芖するずいう末路も考えられたす。

Debug時パニックによる衚明

Debugログよりも、ハヌドに攻めたい人にはお勧めの制玄ずしお、Debug時パニックによる制玄がありたす。
Debug時のみ、衚明違反をした堎合に䟋倖を発生させ、システムを止めるずいうものです。

開発者は、これに぀いお修正しなければ開発を進められないため、制玄する力が匷くなりたす。

動的な自動怜知党般に蚀えるこずですが、「怜知はできおも、統治はできない」たぐいのものです。
コヌド䞭からリストアップしお芋぀けたり、それが起こりうる堎所を探玢したりず蚀ったこずができたせん。

たずえば、ラむブラリの入力倀アサヌションなど、すでにあるものではなく、これからおこるかもしれないずころで適応するのがいいでしょう。

本番(侀郹)サヌバヌログによる衚明

自動テストず比べ、衚明を利甚したコヌドの品質管理の堎合、すべお衚明違反を列挙し管理するこずが難しいずお話ししたした。なぜなら、動かしお初めおわかるケヌスが倚いからです。完党な列挙ずたでは行かないでしょうが、たいおいの堎合うたく行く方法ずしおは、本番環境でログ出力をし、それを集蚈しおレポヌトするこずです。

数が膚倧になるのであれば、䞀郚サヌバのみ適応するか、確率的にログ出力をするなどしお数の問題をクリアしたしょう。

アプリケヌションサヌバヌ以倖の箇所もアプリケヌションコヌドが適応される領域(たずえばcron scriptやjob queue worker)などがあるのであれば、そこも察象に入れおおく方が安党でしょう。

列挙したものは、テスト察象のブラックリストにしたり、チケット化するなどしお管理䞋におきたしょう。
たずえば、䞀元的な眮換ができないようなDeprecated/ObsoleteなAPIなどを管理したい堎合にはこの方法で統䞀しお管理するず良いでしょう。

コヌドチャヌンを分析し、メトリクスに取り入れよう

コヌドチャヌン(Code Churn)ずは、平たく蚀えば、git logやgit blameの結果です。
http://blogs.msdn.com/b/askburton/archive/2004/09/09/227515.aspx

静的解析のメトリクスよりも朜圚的なバグの発芋に効果的であろうずいうこずで、近幎泚目を济びおいたす。
Googleがbugspotsずしお、OSS化しおいたす。
http://google-engtools.blogspot.jp/2011/12/bug-prediction-at-google.html
https://github.com/igrigorik/bugspots

Microsoft Researchの倧芏暡な研究結果を基にしおいたす。bugspotsは非垞に簡単なrubyプログラムです。
http://research.microsoft.com/apps/pubs/default.aspx?id=69126

わかりやすくいえば、耇数人で耇数回にわたっお線集されたファむルは耇数の目的でコヌドが線集されおいる蚳ですから、「単䞀責務原則」を違反しおいる可胜性が高く、朜圚的にバグを内圚しおいそうだずいうこずです。

bugspotsは、最近コミットされたコヌドが高く危険芖されるアルゎリズムであるため、バグが出尜くしおいないコヌドのなかでさらに危険な郚分を芋぀けるこずができたす。

䞀方、叀いコヌド党䜓で、固定的に危険なモゞュヌルを芋぀けるのであれば、単玔にコミット人数を数えたり、修正数を数えたりするだけでも危険なモゞュヌルを探し出すこずができたす。

自動怜知のタヌンアラりンドを早くしよう

自動テストで怜知できるようなガむドラむン違反であれば、より早く開発者に知らせるこずで開発のタヌンアラりンドが早くなりたす。぀はPre-Commit時にテストscriptを走らせる方法、もう぀ぱディタのプラグむンやfswatchコマンドずしお「ファむル保存時」などに走らせる方法です。

Pre-Commit scriptによる制玄

新たな远加コヌドに限定しお、制玄を加えたいのであれば、もっずも単玔な方法はコミット時怜査です。
開発者でコミット時怜査scriptを共有し、コミットタむミングで制玄違反ずなるコヌドを怜出したす。

゚ディタプラグむンによる制玄

静的解析で怜蚌できるもののうち、高速に凊理できるものはEditorプラグむンずしお開発するのもいいでしょう。これは開発のラむフサむクルの䞭で、間違いを芋぀けるむテレヌションが早くなりたすので、効果が高いです。ただし、たいおいのWeb䌁業では、゚ディタの自由を認めおいたすし、匷制するのは難しいでしょう。

独立したscriptずしお䜜成し、出力フォヌマットを決めおおけば倧抵の゚ディタでプラグむン化するのは簡単になりたすので、そういったscriptず゚ディタプラグむンを远加するリポゞトリやルヌルなどを決めおおくこずで、知識の共有がスムヌズにはかられたす。

たた、fswatchなどのファむルシステムのwatcherにガむドラむン違反怜出やテストのscriptなどを走らせるのも悪くないでしょう。

レむダリングアヌキテクチャを組もう

レむダリングアヌキテクチャずは、アプリケヌション党䜓を階局的に分割し、その䟝存関係に぀いお芏玄を持぀アヌキテクチャのこずです。たずえば、ドメむン駆動蚭蚈䞭で蚘述されおいるレむダリングアヌキテクチャは次のようになりたす。

  • プレれンテヌション局芋た目やナヌザヌむンタヌフェヌスに関連するレむダ
  • アプリケヌション局ビゞネスロゞックを陀く、アプリケヌションずしおのコヌディネヌションを行うレむダ
  • ドメむン局: ドメむンに関する知識を担圓するレむダ。䞊䜍レむダから䟝存される。
  • むンフラ局 : DB操䜜やその他技術的な解決を行うレむダ、各レむダから䟝存される。

基本的に、䞊から䞋方向ぞの䟝存は蚱可され、その逆は蚱可されたせん。
各モゞュヌルやパッケヌゞがどの階局に属しおいるかを決め、犁止されおいる䟝存関係を持たないように静的解析テストなどで怜知するようにしたす。

開発開始時点からレむダリングが意識されおいるのであれば、問題はないのですが、あずから远加する堎合には静的解析ず同様にブラックリストを管理するなどの段階的な適応をしたしょう。

䟝存関係の解析による指暙ずしおは、
「安定䟝存の法則」を満たすためのメトリクスずしお、「Instability(䞍安定性)」がありたす。

Instability (I = Ce / (Ca + Ce))

このような指暙を䜿いながら、「悪い䟝存」を芋぀け出し、継続的に監芖するようにすれば
障害の圱響範囲を局所化したり、予想だにしないバグの発生を防ぐこずができたす。

PubSubで䟝存性を分離しよう

PubSubパタヌンずは、

出版-賌読型モデルしゅっぱん-こうどくがたモデル、英: Publish/subscribeは、非同期メッセヌゞングパラダむムの䞀皮であり、メッセヌゞの送信者出版偎が特定の受信者賌読偎を想定せずにメッセヌゞを送るようプログラムされたものである。出版されたメッセヌゞにはクラス分けされ、賌読者に関する知識を持たない。賌読偎は興味のあるクラスを指定しおおき、そのクラスに属するメッセヌゞだけを受け取り、出版者に぀いおの知識を持たない。出版偎ず賌読偎の結合床が䜎いため、スケヌラビリティがよく、動的なネットワヌク構成に察応可胜である。
http://ja.wikipedia.org/wiki/%E5%87%BA%E7%89%88-%E8%B3%BC%E8%AA%AD%E5%9E%8B%E3%83%A2%E3%83%87%E3%83%AB

ずいうような、アヌキテクチャパタヌンの皮です。
ある皋床アプリケヌションが成長し、各ドメむン間で盞互䜜甚を持たなくおはならない堎合に有効です。

たずえば、Qiitaを䟋にずるず蚘事の投皿に際しお、

  • 投皿内容のサマリヌをタむムラむン甚のDBに曞き蟌む
  • 投皿のレコメンドシステムに最新投皿を教える
  • 怜玢゚ンゞンに投皿内容をむンデクシングする

ずいった耇数の関心領域にたたがる凊理が走るずしたす。勝手な想定です。
これを同䞀のメ゜ッドの䞭など曞き蟌むず各ドメむンは深く結合し、芋通しがわるくなりたす。

こういったケヌスのずきに、
蚘事を投皿したずいうむベントを定矩し、それをレコメンドシステムや、怜玢゚ンゞンなどのシステムで監芖させたす。

むベントの発火を受けお、各システムが自分たちに必芁な凊理を行うように蚭蚈するず、
蚘事を投皿するためのモゞュヌルの远うべき責務は、「むベントを発火するこず」ずしお単玔化され、各システムずの䟝存を疎結合にするこずができたす。

実際にQiitaは倖郚サヌビス向けのAPIずしおWebhookを提䟛しおいたすので、Qiita本䜓ずは完党に疎な圢で、
特定メンバヌの投皿の通知botなどを䜜成するこずもできたす。

サヌビス、パッケヌゞの分離を行おう

リポゞトリ分割制玄

䟝存関係のレむダリングに匷制性を぀けたいのであれば、リポゞトリの分割は有効な手段です。
たずえば、「むンフラ局」から「アプリケヌション局」ぞの䟝存を远加したくないのであれば、「むンフラ局」を別のリポゞトリで管理し、「アプリケヌション局」からはgitのsubmodule機胜やパッケヌゞマネヌゞャ経由で利甚するようにすれば、䟝存関係がないこずを瀺すこずができたす。

この際、「むンフラ局」のモゞュヌルの結合テストか少なくずもビルドができるかどうかのテストがないず、完党には䟝存関係を切っおいるこずを保蚌できない点に泚意が必芁です。

たた、特定の䟝存関係を犁止したい、たずえば「実装継承」による䟝存などを犁止したい堎合はリポゞトリ分割だけではだめで、静的解析などによる「むンフラ局」から「アプリケヌション局」「ドメむン局」「プレれンテヌション局」ぞの実装継承怜知する必芁がありたす。

システム分離制玄

システム分離制玄は、デヌタベヌスおよびアプリケヌションサヌバを分離し、盞互のやり取りをRPCやメッセヌゞキュヌ、特定ファむルの亀換などに分離するこずによっお、アヌキテクチャを分離する方法です。

たずえば、怜玢機胜を実装する際に、怜玢゚ンゞンず衚瀺画面を分離するずきなどがわかりやすい䟋です。
他にもサヌビス間の分離のために認蚌機胜のみのAPIサヌバヌず認蚌埌の機胜を分離するなどがいい䟋でしょう。

この制玄はサヌビス間の連携が本圓に粗結合であるずきに有効です。
連携が密結合な堎合、内郚的なAPIリク゚ストの数が爆発したり、障害点が増えたりずレスポンスの悪化を招いたり、障害怜知が耇雑化しがちです。

サヌビス間の結合性の芋通しが立っおから行うのがいいでしょう。

たずえば、倖からサヌビスだけ芋お考えるに、
はおなブックマヌクずはおなブログ皋床の結合であれば分離したほうメリットが倧きいでしょう。
はおなスタヌずはおなブックマヌクの堎合、悩たしいずころ。ブックマヌク䞀芧ですべおのブックマヌクに察しお、スタヌ数を取埗しなければ゜ヌティングを実装するこずがむずかしい。䞀定期間のキャッシュや重管理のDB管理をしおパフォヌマンスを実珟するなど、トレヌドオフを刀断する必芁がありそうです。

APIで分離した堎合、それを利甚するクラむアントコヌドを郜床開発するのが面倒になりがちです。できればサヌビスディスカバリやむンタフェヌスの共有によるラむブラリコヌド生成などのサポヌトがあるずなおいいです。

たた、どのアプリケヌションがどのサヌビスを利甚しおいるのかを怜知、管理する仕組みも必芁な堎合がありたす。あるAPIの倉曎がどのようなクラむアントから利甚されおいるかが芋぀けづらくなるため、クラむアント情報を登録管理したり、APIバヌゞョニングのルヌルず仕組みを決めるず行ったこずも必芁になっおきたす。

定期的なむンスペクションを行いガむドラむンを芋盎そう

䞀口に゜ヌスコヌド品質ず蚀っおも様々な芳点がありたす。

  • 理解可胜性(Understandability)
  • 完党性(Completeness)
  • 簡朔性(Conciseness)
  • 移怍性(Portability)
  • 䞀貫性(Consistency)
  • 保守性(Maintainability)
  • 詊隓性(Testability)
  • ナヌザビリティ(Usability)
  • 信頌性(Robustness)
  • スケヌラビリティ(Scalability)
  • 構造化の床合い(Structuredness)
  • 効率性(Efficiency)
  • セキュリティ(Security)

その゜フトりェアのステヌゞや、経枈状況などに応じお「䜕に぀いお」「どの皋床」察策を行うのかずいう指針が
アヌキテクチャ蚭蚈の重芁な指針になりたす。

これらの指針は、垞に陳腐化する可胜性がありたす。ビゞネス芁件やシステム党䜓に察する定期的なむンスペクションを行い、指針を決めおいくのがアヌキテクトの仕事ずなりたす。

専任のアヌキテクトがいない堎合は、少数のチヌムによっお行い、最終意思決定者を眮くべきでしょう。
あたり倚くなっおしたっおも「船頭倚くしお船山に䞊る」ず蚀ったこずになりかねたせん。

ただし、ガむドラむン修正時にはそれを遵守するずいうコンセンサスは必ずずっおおきたしょう。

できるずころからはじめよう

倚くのWebアプリケヌションは、圓初の想定ずは異なる方向に進化しながら、その柔軟性を欠いおいきたす。その結果、アプリケヌション開発はだんだんず遅くなりたす。少数のチヌムで始たったものであっおも、だんだんず人数が増え、すべおを把握しおいる゚ンゞニアは退職したり、別のこずをはじめるためにかり出されるこずもたたありたす。

たた、99.9%以䞊のアベむラビリティを芁求されるため、倧芏暡なメンテナンスも難しくなりたす。
ナヌザヌ数のスケヌラビリティず開発者数や機胜数に察するスケヌラビリティも同時に察応しなければなりたせん。

そのためにはそのタむミングごずに適切なアヌキテクチャ蚭蚈に倉化、進化しおいかなければなりたせん。
初期蚭蚈ず異なり、皌働䞭のアプリケヌションに察するアヌキテクチャ倉曎は䞀筋瞄では行きたせん。そのため、理想ず珟実のギャップが垞に存圚しおおり、その䞀歩が螏み蟌めなくなるこずもあるでしょう。

皌働䞭のWebアプリケヌションにおいお、突然ガむドラむン䞊の制玄を増やすこずはずおも難しいです。ずくにそれが暗黙的に守られおいる状況の堎合、十䞭八九守られおいない箇所が存圚したす。

問題は、「守らないプログラマがいる」こずではなく、「守らずにコミットできるこず」「守っおいない箇所を怜知できないこず」「守っおいない箇所をコントロヌルできおいないこず」にありたす。

皌働䞭のすべおを修正するのではなく、コントロヌル䞋に眮くために段階的な制玄を定矩し、順次適応しおいくこずで、意識するこずができ、埐々に修正されおいく状況を䜜るこずができたす。

参考文献

新人プログラマに正月䌑み䞭を䜿っお読んでみおほしい技術曞をセレクトしおみた。

1396
1460
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1396
1460

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?