💎

オープンソースRailsリポジトリの統計比較

2023/09/03に公開

Rails開発のあたりをつける

オープンソースRailsリポジトリの統計を比較してみる

RailsはオープンソースのWebサービスの実装が豊富です。以前公開されていない商用Webサービスのrails statsは比較したのですが、今回公開されているものについても調べたので比較してみます。

リポジトリの設定そのままで動かしたので、元がちゃんと設定されていないとパースもれはあるかもしれません。

Redmine

commit 9315481cdfefed08d0e1bfa0701de872ba6d241b

テストがRspecベースでないのは他と違う点ですね。Code to Test Ratioは低く、テーブル数も少ない。

 $ bundle exec rails stats
+----------------------+--------+--------+---------+---------+-----+-------+
| Name                 |  Lines |    LOC | Classes | Methods | M/C | LOC/M |
+----------------------+--------+--------+---------+---------+-----+-------+
| Controllers          |   8829 |   6599 |      55 |     534 |   9 |    10 |
| Helpers              |   6711 |   4923 |       1 |     395 | 395 |    10 |
| Jobs                 |    112 |     88 |       3 |       9 |   3 |     7 |
| Models               |  19585 |  14174 |     102 |    1502 |  14 |     7 |
| Libraries            |  20353 |  14511 |     149 |    1180 |   7 |    10 |
| Controller tests     |      0 |      0 |       0 |       0 |   0 |     0 |
| Helper tests         |   4150 |   3224 |      21 |     283 |  13 |     9 |
| Model tests          |      0 |      0 |       0 |       0 |   0 |     0 |
| Mailer tests         |      0 |      0 |       0 |       0 |   0 |     0 |
| Integration tests    |  10351 |   7269 |     101 |     575 |   5 |    10 |
| System tests         |   1504 |   1022 |      10 |      65 |   6 |    13 |
+----------------------+--------+--------+---------+---------+-----+-------+
| Total                |  71595 |  51810 |     442 |    4543 |  10 |     9 |
+----------------------+--------+--------+---------+---------+-----+-------+
  Code LOC: 40295     Test LOC: 11515     Code to Test Ratio: 1:0.3

Mastodon

commit 728eb6a15387da9074ccc024c9002f74ff829470

規模の割にspecを細かく概念を分けています。

 $ RAILS_ENV=development bundle exec rails stats
+----------------------+--------+--------+---------+---------+-----+-------+
| Name                 |  Lines |    LOC | Classes | Methods | M/C | LOC/M |
+----------------------+--------+--------+---------+---------+-----+-------+
| Controllers          |  12340 |   9255 |     247 |    1533 |   6 |     4 |
| Helpers              |   1612 |   1295 |       0 |     144 |   0 |     6 |
| Models               |  12884 |   8600 |     168 |    1170 |   6 |     5 |
| Mailers              |    399 |    298 |       4 |      38 |   9 |     5 |
| Views                |    310 |    201 |       0 |       0 |   0 |     0 |
| JavaScript           |  32723 |  26838 |       0 |     489 |   0 |    52 |
| Libraries            |   7756 |   5732 |      94 |     286 |   3 |    18 |
| Chewy specs          |    124 |    100 |       0 |       4 |   0 |    23 |
| Config specs         |    106 |     75 |       0 |       1 |   0 |    73 |
| Controller specs     |  15700 |  11988 |       0 |      43 |   0 |   276 |
| Fabrication specs    |     14 |     10 |       0 |       0 |   0 |     0 |
| Feature specs        |    434 |    271 |       0 |       1 |   0 |   269 |
| Generator specs      |     27 |     20 |       0 |       0 |   0 |     0 |
| Helper specs         |   1326 |   1038 |       0 |       7 |   0 |   146 |
| Lib specs            |   9841 |   7667 |       0 |      10 |   0 |   764 |
| Locale specs         |     35 |     28 |       0 |       0 |   0 |     0 |
| Mailer specs         |    602 |    445 |       3 |      27 |   9 |    14 |
| Model specs          |   8655 |   6733 |       0 |      15 |   0 |   446 |
| Policy specs         |   1245 |    991 |       0 |       0 |   0 |     0 |
| Presenter specs      |    404 |    318 |       0 |       0 |   0 |     0 |
| Request specs        |   5575 |   4089 |       0 |       4 |   0 |  1020 |
| Routing specs        |    207 |    161 |       0 |       0 |   0 |     0 |
| Serializer specs     |    324 |    253 |       0 |       0 |   0 |     0 |
| Service specs        |   7600 |   6043 |       0 |      16 |   0 |   375 |
| System specs         |     45 |     31 |       0 |       0 |   0 |     0 |
| Validator specs      |    762 |    592 |       0 |       3 |   0 |   195 |
| View specs           |     48 |     35 |       0 |       0 |   0 |     0 |
| Worker specs         |   1704 |   1280 |       0 |       1 |   0 |  1278 |
| App Libraries        |   8680 |   6416 |     158 |     984 |   6 |     4 |
| Presenters           |    348 |    273 |      13 |      34 |   2 |     6 |
| Services             |   6593 |   4788 |      91 |     590 |   6 |     6 |
| Validators           |    537 |    385 |      19 |      59 |   3 |     4 |
| Workers              |   2305 |   1635 |      87 |     172 |   1 |     7 |
+----------------------+--------+--------+---------+---------+-----+-------+
| Total                | 141265 | 107884 |     884 |    5631 |   6 |    17 |
+----------------------+--------+--------+---------+---------+-----+-------+
  Code LOC: 65716     Test LOC: 42168     Code to Test Ratio: 1:0.6

Forem

commit ca6e6355493ddb49a31f697dd64baa2904356df6

dev.toの見た目は控えめにいって素朴な印象。それに対応してフロントのコードが少ないです。

 $ bundle exec rails stats
+----------------------+--------+--------+---------+---------+-----+-------+
| Name                 |  Lines |    LOC | Classes | Methods | M/C | LOC/M |
+----------------------+--------+--------+---------+---------+-----+-------+
| Controllers          |  10858 |   8513 |     167 |     851 |   5 |     8 |
| Helpers              |   1280 |    951 |       0 |     142 |   0 |     4 |
| Models               |   8526 |   5840 |     113 |     676 |   5 |     6 |
| Mailers              |    285 |    225 |       5 |      28 |   5 |     6 |
| Views                |  21570 |  19904 |       0 |       0 |   0 |     0 |
| JavaScripts          |   5672 |   4138 |       0 |     163 |   0 |    23 |
| Stylesheets          |  17530 |  14900 |       0 |       0 |   0 |     0 |
| JavaScript           |  21635 |  15225 |       0 |     338 |   0 |    43 |
| Libraries            |   2803 |   2387 |     148 |     170 |   1 |    12 |
| Controller specs     |    110 |     90 |       0 |       0 |   0 |     0 |
| Decorator specs      |   1317 |   1111 |       0 |       1 |   0 |  1109 |
| Form specs           |     70 |     59 |       0 |       0 |   0 |     0 |
| Generator specs      |      5 |      4 |       0 |       0 |   0 |     0 |
| Helper specs         |   1294 |   1050 |       0 |       1 |   0 |  1048 |
| Initializer specs    |    293 |    244 |       0 |       1 |   0 |   242 |
| Lib specs            |   2510 |   2011 |       2 |      10 |   5 |   199 |
| Liquid_tag specs     |   3301 |   2719 |       0 |      59 |   0 |    44 |
| Mailer specs         |    729 |    575 |       5 |      24 |   4 |    21 |
| Model specs          |  11286 |   8998 |       1 |       7 |   7 |  1283 |
| Policy specs         |   1452 |   1061 |       0 |       1 |   0 |  1059 |
| Query specs          |   1431 |   1101 |       0 |       2 |   0 |   548 |
| Refinement specs     |     10 |      9 |       0 |       0 |   0 |     0 |
| Request specs        |  29241 |  23601 |       1 |      80 |  80 |   293 |
| Routing specs        |    152 |    124 |       0 |       0 |   0 |     0 |
| Sanitizer specs      |     66 |     58 |       0 |       0 |   0 |     0 |
| Serializer specs     |    264 |    218 |       0 |       0 |   0 |     0 |
| Service specs        |  15712 |  12645 |       0 |      49 |   0 |   256 |
| System specs         |   6155 |   4930 |       0 |      23 |   0 |   212 |
| Task specs           |     78 |     59 |       0 |       0 |   0 |     0 |
| Uploader specs       |    335 |    264 |       0 |       0 |   0 |     0 |
| Validator specs      |    184 |    137 |       0 |       6 |   0 |    20 |
| View_object specs    |     87 |     68 |       0 |       0 |   0 |     0 |
| View specs           |    403 |    323 |       0 |       1 |   0 |   321 |
| Worker specs         |   3185 |   2556 |       0 |       3 |   0 |   850 |
+----------------------+--------+--------+---------+---------+-----+-------+
| Total                | 169829 | 136098 |     442 |    2636 |   5 |    49 |
+----------------------+--------+--------+---------+---------+-----+-------+
  Code LOC: 72083     Test LOC: 64015     Code to Test Ratio: 1:0.9

Discourse

commit 4f8d52bbcb3d6e55eec7c8a789bd4f22b491c4aa

一番フロントヘビーなリポジトリ。コード量もGitLabの次に多いです。

$ bundle exec rails stats
+----------------------+--------+--------+---------+---------+-----+-------+
| Name                 |  Lines |    LOC | Classes | Methods | M/C | LOC/M |
+----------------------+--------+--------+---------+---------+-----+-------+
| Controllers          |  19897 |  15856 |     111 |    1035 |   9 |    13 |
| Helpers              |   1203 |    958 |       0 |     120 |   0 |     5 |
| Jobs                 |   8510 |   6768 |     202 |     425 |   2 |    13 |
| Models               |  40354 |  29270 |     271 |    2447 |   9 |     9 |
| Mailers              |   1136 |    949 |       9 |      51 |   5 |    16 |
| Views                |   3131 |   2821 |       0 |       0 |   0 |     0 |
| JavaScripts          | 254029 | 214041 |       0 |    5185 |   0 |    39 |
| Stylesheets          |  38779 |  33250 |       0 |       0 |   0 |     0 |
| Libraries            |  75276 |  58686 |     602 |    4917 |   8 |     9 |
| Helper specs         |   1078 |    869 |       0 |       2 |   0 |   432 |
| Import_export specs  |    246 |    189 |       0 |       1 |   0 |   187 |
| Initializer specs    |    129 |     93 |       0 |       0 |   0 |     0 |
| Integration specs    |   3273 |   2762 |       0 |      12 |   0 |   228 |
| Integrity specs      |    371 |    295 |       0 |       9 |   0 |    30 |
| Job specs            |  10087 |   7982 |       5 |      36 |   7 |   219 |
| Lib specs            |  74837 |  60645 |      49 |     296 |   6 |   202 |
| Mailer specs         |   1916 |   1576 |       0 |       1 |   0 |  1574 |
| Model specs          |  44934 |  36027 |       6 |     115 |  19 |   311 |
| Multisite specs      |    834 |    676 |       2 |      10 |   5 |    65 |
| Request specs        |  60027 |  48287 |       1 |      78 |  78 |   617 |
| Script specs         |   1137 |    967 |       1 |       6 |   6 |   159 |
| Serializer specs     |   5139 |   4099 |       0 |      11 |   0 |   370 |
| Service specs        |  15175 |  12244 |       0 |      38 |   0 |   320 |
| System specs         |   7181 |   5564 |      47 |     419 |   8 |    11 |
| Task specs           |    674 |    507 |       0 |       5 |   0 |    99 |
| View specs           |    108 |     84 |       0 |       0 |   0 |     0 |
+----------------------+--------+--------+---------+---------+-----+-------+
| Total                | 669461 | 545465 |    1306 |   15219 |  11 |    33 |
+----------------------+--------+--------+---------+---------+-----+-------+
  Code LOC: 362599     Test LOC: 182866     Code to Test Ratio: 1:0.5

GitLab

commit bcdfc757c31b2e71adaea24a2b9343aaac252a65

一番巨大なリポジトリ。セットアップでつまずく部分多数。

$ bundle exec rails stats
+----------------------+---------+---------+---------+---------+-----+-------+
| Name                 |   Lines |     LOC | Classes | Methods | M/C | LOC/M |
+----------------------+---------+---------+---------+---------+-----+-------+
| Controllers          |   32803 |   24239 |     345 |    3179 |   9 |     5 |
| Helpers              |   18669 |   14554 |       1 |    1803 | 1803 |     6 |
| Models               |   83027 |   59217 |     725 |    7643 |  10 |     5 |
| Mailers              |    2492 |    1857 |      10 |     258 |  25 |     5 |
| Channels             |     142 |      97 |       4 |      11 |   2 |     6 |
| Views                |    1046 |     814 |       0 |       0 |   0 |     0 |
| JavaScripts          |  134131 |   99295 |       0 |     968 |   0 |   100 |
| Stylesheets          |   47170 |   38792 |       0 |       0 |   0 |     0 |
| Libraries            |  251796 |  184939 |    3550 |   19198 |   5 |     7 |
| Bin specs            |     717 |     574 |       0 |       0 |   0 |     0 |
| Channel specs        |     103 |      74 |       0 |       0 |   0 |     0 |
| Command specs        |     672 |     525 |       0 |       0 |   0 |     0 |
| Component specs      |    2630 |    2046 |      10 |      28 |   2 |    71 |
| Config specs         |     923 |     748 |       0 |       2 |   0 |   372 |
| Contract specs       |    1799 |    1538 |       1 |      17 |  17 |    88 |
| Controller specs     |   63009 |   48053 |       1 |     366 | 366 |   129 |
| Db specs             |     835 |     636 |       0 |      16 |   0 |    37 |
| Dependency specs     |      26 |      20 |       0 |       0 |   0 |     0 |
| Experiment specs     |     411 |     298 |       0 |       0 |   0 |     0 |
| Feature specs        |   93841 |   70386 |       0 |     528 |   0 |   131 |
| Finder specs         |   21757 |   16461 |       0 |      31 |   0 |   529 |
| Graphql specs        |   32982 |   24901 |       0 |     192 |   0 |   127 |
| Haml_lint specs      |     228 |     161 |       0 |       0 |   0 |     0 |
| Helper specs         |   29231 |   23025 |       0 |      54 |   0 |   424 |
| Initializer specs    |    4053 |    3054 |       0 |      31 |   0 |    96 |
| Lib specs            |  335839 |  261381 |      18 |    1194 |  66 |   216 |
| Mailer specs         |    5032 |    3915 |       0 |      10 |   0 |   389 |
| Metrics_server specs |     260 |     191 |       0 |       0 |   0 |     0 |
| Migration specs      |   11854 |    9121 |       0 |      24 |   0 |   378 |
| Model specs          |  162193 |  123999 |       4 |     286 |  71 |   431 |
| Policy specs         |   13495 |   10241 |       0 |      22 |   0 |   463 |
| Presenter specs      |    8461 |    6458 |       0 |       8 |   0 |   805 |
| Rack_server specs    |      82 |      60 |       0 |       2 |   0 |    28 |
| Request specs        |  146710 |  113690 |       0 |     473 |   0 |   238 |
| Routing specs        |    2332 |    1683 |       0 |       3 |   0 |   559 |
| Rubocop specs        |   14034 |   11662 |     319 |     281 |   0 |    39 |
| Script specs         |    4542 |    3534 |       0 |       5 |   0 |   704 |
| Serializer specs     |   12556 |    9752 |       0 |       6 |   0 |  1623 |
| Service specs        |  146314 |  112737 |       2 |     389 | 194 |   287 |
| Sidekiq specs        |      20 |      16 |       0 |       0 |   0 |     0 |
| Sidekiq_cluster specs |     122 |      96 |       0 |       0 |   0 |     0 |
| Spam specs           |      31 |      25 |       0 |       0 |   0 |     0 |
| Support_spec specs   |    2761 |    2150 |       0 |      29 |   0 |    72 |
| Task specs           |    7182 |    5470 |       0 |      28 |   0 |   193 |
| Tooling specs        |    7347 |    5791 |       3 |       6 |   2 |   963 |
| Uploader specs       |    4005 |    3051 |       1 |      10 |  10 |   303 |
| Validator specs      |    1813 |    1279 |       0 |       8 |   0 |   157 |
| View specs           |   10235 |    7583 |       0 |      27 |   0 |   278 |
| Worker specs         |   28213 |   21376 |       0 |      87 |   0 |   243 |
+----------------------+---------+---------+---------+---------+-----+-------+
| Total                | 1749926 | 1331565 |    4994 |   37223 |   7 |    33 |
+----------------------+---------+---------+---------+---------+-----+-------+
  Code LOC: 423804     Test LOC: 907761     Code to Test Ratio: 1:2.1

統計の比較

個々の統計が出揃ったので比較してみます。

コード部分

total code loc

コード全ての行数. GitLabが外部ライブラリーに切り出している部分があるのは事実なんですが、思ったよりDiscourseは巨大なリポジトリですね。

num model class

モデルのクラス数。ニアリーイコールテーブル数。

JavaScript LOC/Code LOC

テストを除くアプリコードの内JavaScriptの割合。この値はアプリケーションの種類によってばらつきが出る部分。

model per controller

モデルLOC/コントローラーLOC。サービス層他のレイヤーもあるのでノイズはありますが、ファットモデルになっているか。ABCサイズの比較だとGitLabは悪い値ではないので、そっちで見た方が負債具合は正しく評価できるかもしれません。

テスト部分

code to test ratio

Code to Test Ratio。GitLabは高くRedmineは低い。

test distribution

テスト分布。ControllerやGraphQLはRequest specに参入、Feature SpecもSystem Specに参入。

オープンソースプロジェクトはしばしばクローズドソースより品質が高くセキュアで安定していると言われることがあります。沢山の目によってウォッチされているので最終的に良いものに収束していくと。

バグが出て修正する時、セットでテストを書くことが多いと思います。そういう意味で
沢山の目によってウォッチされているオープンソースプロジェクトにおいてテストコード量はアプリケーションの複雑さと比例している可能性はあると思っています。

テストピラミッドとトロフィー

一般にテストコードを増やす戦略としてピラミッドまたはトロフィーの形が正解とされることが多いです。

テストピラミッドの場合は

  1. Unitテスト
  2. Integrationテスト
  3. End-to-Endテスト

でUnitテストが一番厚く、End-to-Endテストが一番薄いのが良いとされます。End-to-Endテストは一番実行時間が長く、画面のテストの場合、デザインの変更に弱いからです。

別の意見として、特にフロントエンドにおいてTesting Trophyというものがあります。

testing trophy

End to End, Integration, Unit, Staticに分けEnd to Endが薄く、Unitテストは厚く、IntegrationはUnitテストに負けるが厚くといった感じでしょうか。

ただトロフィーはピラミッドより不定形です。

実際作者の元案だとIntegration部分が太った形みたいですね。ピラミッドよりトロフィーは造形次第で形が変わるという印象はあります。

Railsもといバックエンドのリポジトリでテスト勾配はどうするのが正解でしょうか?

Testing Rubyのご提案

オープンソースRailsリポジトリから学べることは

  1. Modelテスト
  2. Requestテスト
  3. Systemテスト

モデルのテストはリクエスト(Controller)テストより微妙に少ないくらいでした。モデルのテストはユニットテストの一部でしかないのはあるのですが、思ったよりモデルのテストは少ない印象です。しいていうならTesting Rubyでしょうか。

testing ruby

サービス層が必要な程度にアプリケーションが複雑になってくると複雑さがモデルのレイヤーよりコントローラーやサービスなどよりアプリのハンドリング部分のレイヤーに移転するのはあると思います。実際モデルコードの比率は規模が大きくなるほど減っています。

model ratio

フロントとバックエンド両方厚くあるプロダクトの場合、テストコードの実行時間のコスパで言えば以下のようになると思います。1が一番高速で壊れにくいです。

  1. Modelテスト
  2. Requestテスト
  3. Integration(APIシナリオ)テスト
  4. End-to-Endテスト

一方でテストのコスパとは別の視点で、そもそもアプリケーションの規模が大きくなってくると同一テーブルを複数のユースケースで取り回すケースが増えてきて、そもそもモデルのレイヤーの比率が減る、それによって複雑性に対応するテストコードを書いていくと収束点としてTesting Rubyになる可能性はあります。

Discussion