Slide 1

Slide 1 text

Railsでスピード重視で立ち上げた プロダクトの数年後あるある集
 組織拡大と共に発生するソフトウェア品質の課題と裏話LT@目黒
 2023/10/20 もとき


Slide 2

Slide 2 text

自己紹介
 - 元木駿(もときしゅん)
 - GitHub: shuuuuun
 - 2015年に面白法人カヤックへ新卒で入社し、広告系のWeb受託開発などに従事。 2019年より移住スカウトサービス「SMOUT」に携わり、現在はテックリードを務め る。
 - はじめはフロントエンドで経験を積み、その後バックエンドに転向して現在はSRE領 域も含めて柔軟なエンジニアとしてやっています
 - プライベートでは昨年子どもが産まれ、先日1歳になりました 👶


Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

本日はそんなサービス開発に関わってきた経験を踏まえて、「技術的負債」をテーマに 話します


Slide 6

Slide 6 text

技術的負債とは?
 > 実装当時に最適解と考えられたものが、時間の経過とともに、最適とは評価され得な くなったもの
 引用:技術的負債とステークホルダと説明責任と / The Debt - Speaker Deck 
 
 > シュミットの定義によれば、技術的負債(実際には、アーキテクチャ資本の資本コス ト)はある機能を付け加えたいときに掛かるコストの差として表現されました。「理想的 なシステム」との差です。
 引用:エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング 
 


Slide 7

Slide 7 text

技術的負債とは?
 実装当時に最適解と考えられたものが時間の経過とともに最適ではなくなり、機能の追 加や改修が困難になっているもの
 
 


Slide 8

Slide 8 text

時間の経過がもたらすもの
 - ビジネスを取り巻く状況の変化
 - 自身の持つ知識や理解、洞察力の深化
 - システムに関わる組織・チームの規模や役割の変化
 - テクノロジの進歩や深化、新たな技術的選択肢の登場
 引用:https://speakerdeck.com/toricls/the-debt?slide=16 
 


Slide 9

Slide 9 text

技術的負債の発生要因
 - ビジネス(サービス)を取り巻く状況の変化
 - サービスの開発フェーズにより、重視されるポイントが変化するパターン
 - 様々な理由により要件が想定以上に変化し、システムの追従が困難になるパターン
 - 要件の変化に対して柔軟なシステムを作るのが理想ではあるが、未来の予測は非常に難しい
 - 負債の解消が困難で後回しになり、さらなる負債となるパターン
 - 自身(開発者)の持つ知識や理解、洞察力の深化
 - 開発者の(技術面/ドメイン知識面の)成長によって負債が明らかになるパターン
 - 新たに参画した開発者の新たな視点の洞察により負債が発見されるパターン
 - システムに関わる組織・チームの規模や役割の変化
 - 開発者の増減や入れ替わりによって過去の経緯が抜け落ちてしまうパターン
 - 組織として得意とする技術が変遷し、そのシステムの技術を扱える開発者が少なくなるパターン
 - テクノロジの進歩や深化、新たな技術的選択肢の登場
 - 利用している言語・フレームワーク・ライブラリ・ツールがより便利になるパターン
 - 利用しているものよりもさらに便利なものが現れるパターン


Slide 10

Slide 10 text

背景:スピード重視の初期開発
 - サービスの初期フェーズには、できるだけ早く動くものをリリースし、ユーザーに価 値を届けてビジネス的な価値を確認するため、スピード重視の開発が行われていた
 - フレームワークには初期開発の生産性が高いRuby on Railsを採用
 - 初期インフラ構成はAWS Elastic BeanstalkによるEC2の管理を採用


Slide 11

Slide 11 text

背景:開発メンバーの入れ替わり
 - 長い年月の中で開発メンバーの増減や入れ替わりがあり、初期開発メンバーはほぼ いなくなっている


Slide 12

Slide 12 text

技術的負債 事例集
 あるある
 テクノロジの進歩や深化、新たな技術的選択肢の登場
 自身(開発者)の持つ知識や理解、洞察力の深化
 ビジネス(サービス)を取り巻く状況の変化
 システムに関わる組織・チームの規模や役割の変化


Slide 13

Slide 13 text

初期フェーズのPR/コミットログの説明が少ない
 サービスの開発フェーズにより、重視されるポイントが変化するパターン
 開発者の増減や入れ替わりによって過去の経緯が抜け落ちてしまうパターン
 - スピード重視でとにかく素早く実装しリリースすることを優先し、PRやコミットログ の説明が最小限となっていて、メンバーが入れ替わり実装時の経緯を知りたくても 分からないケース
 - 不確実性の高い初期開発では密なコミュニケーションのもと開発が行われ、テキストによるコンテキ ストの共有の必要性が薄かった
 - 当時の選択としては妥当であっても、年月が経ちメンバーが入れ替わると、ドキュメ ント化されていない実装時の経緯は引き継がれずに抜け落ちることになる
 - →急いでいてもできるだけ説明を書こう


Slide 14

Slide 14 text

初期フェーズのPR/コミットログの説明が少ない
 - 


Slide 15

Slide 15 text

スキーマ情報やコード上のコメントが少ない
 - データベースのテーブル名やフィールド名、ソースコードのモデルの命名などで、コ メント等による補足情報が少ないようなケース
 - 実装時は名前を見れば自明なので省略されがちだが、プロダクトが育っていくタイ ミングで呼び名が変わり、メンバーが入れ替わると経緯が抜け落ちて分かりにくく なり、混乱のもととなる
 - →自明に見えてもできるだけコメントを残そう
 開発者の増減や入れ替わりによって過去の経緯が抜け落ちてしまうパターン


Slide 16

Slide 16 text

使わなくなったコード・カラムが残り続けてる
 - 使わなくなったコードやDBのカラムが残っているケース
 - あとで復活させるかもしれないと残していたり、リリース後に消そうと思って忘れてしまったり。
 - 後から見ると使われているのかどうかも分からなくなり、改修時に利用実態の調査 が必要になったり、無駄な複雑性を残して開発者を混乱させてしまう
 - →不要になったらすぐに消そう
 開発者の増減や入れ替わりによって過去の経緯が抜け落ちてしまうパターン


Slide 17

Slide 17 text

既存コードの経緯や影響範囲がわからず怖くて消せない
 - 運用の年月が経ち開発者が入れ替わり、システムの規模が大きくなってくると、既 存コードの実装経緯がわからなかったり、変更の影響範囲が予測しきれないことが 出てくる
 - 不要になったコードに気づかず放置されたり、不要に見えるが影響範囲に自信が持 てず放置されたり、不要かどうかの調査に時間がかかるため後回しにしてしまったり して、負債がどんどん増えていく
 - →慎重な確認と思い切って消す勇気
 開発者の増減や入れ替わりによって過去の経緯が抜け落ちてしまうパターン
 負債の解消が困難で後回しになり、さらなる負債となるパターン


Slide 18

Slide 18 text

TODOコメントがTODOのまま
 - 実装時に書いたTODOコメントが放置され、時間の経過とともに腐っていき(周辺の 仕様が変化し、書いた当初の意味はなくなっていく)、後の開発者を混乱させる ケース
 - 必須ではない要件を実装せず後回しにすることが妥当なケースは多々あるが、大抵 の場合、TODOコメントを書くだけではチームのタスク管理ツール等には組み込まれ ないため放置される
 ビジネス(サービス)を取り巻く状況の変化


Slide 19

Slide 19 text

すばやく実装できるライブラリの多用による柔軟性の低下
 - さまざまなデータの属性をタグライブラリ(acts_as_taggable_on)を活用して表現 することで、スキーマを変更することなく素早く実装できたが、後のワーディングの 変更が困難に
 - →汎用的に使える便利なツールも乱用しすぎてはいけない
 様々な理由により要件が想定以上に変化し、システムの追従が困難になるパターン


Slide 20

Slide 20 text

ポリモーフィック関連付けの多用による複雑さの増加
 - ポリモーフィック関連付け(polymorphic association)を利用し、あるモデルに 複数のモデルを関連付けできるように汎用化していたが、結果として数年経っても 1つのモデルからしか利用していない
 - さらに、コードの各所でそのモデルが来ることが前提となっていて、別のモデルを利用することはでき ない状態
 - 過度な抽象化により必要以上に複雑になり、開発者を混乱させる
 - →未来を予測することは難しいが、迷ったときはシンプルに(YAGNI)
 自身(開発者)の持つ知識や理解、洞察力の深化
 ビジネスを取り巻く状況の変化


Slide 21

Slide 21 text

モデルのvalidationのみ設定し、DBの制約がない
 - ActiveRecordモデルのvalidationは設定されているが、DB層でのNOT NULL制約や UNIQUE制約が未設定のまま運用されているケース
 - 通常の利用フローでは問題は起きなくても、バリデーションをすり抜けるイレギュラーなデータ追加は 運用の年月が長くなれば高確率で発生しているため、データ不整合のもととなる
 - データ不整合が発生した状態では制約が追加できないので、データの移行作業が必要になる
 - →基本的にDB層の制約も設定しておこう
 自身(開発者)の持つ知識や理解、洞察力の深化


Slide 22

Slide 22 text

データの増加によるパフォーマンスの悪化
 - データが少ないときは問題なかったが、プロダクトが成長しデータが増えるにつ れ、パフォーマンスが悪化していく
 - N+1、スロークエリなど
 - Rails(ActiveRecord)を利用してると実際に発行されるSQLが分かりづらい部分も
 
 ビジネス(サービス)を取り巻く状況の変化


Slide 23

Slide 23 text

古い通知データが残り続けて億レベルのレコード数に
 - 日々大量に増えていく各ユーザーへの通知データ。初期の頃は問題なく動いていた が、数年の年月で非常に大きなテーブルとなり、パフォーマンスの悪化や負荷増 大、障害発生の要因となっていた
 - SELECTが遅いためインデックスを追加しようとしたところALTER TABLEが想定以上に長時間かかって も終わらず、障害発生...
 - ビジネス上も保持が必要なデータではなかったため、古いデータを削除することに
 - 単純に不要な行をDELETEするにもとても時間がかかり終わらないので、新しいテーブルを作り必要な 行のみコピーしたあとにテーブルをrenameする作戦に
 - RDS Blue/Green Deploymentsを利用することでダウンタイムを最小限に抑え、約 1千万件のデータをコピーし1億レコードのテーブルを削除した
 ビジネス(サービス)を取り巻く状況の変化


Slide 24

Slide 24 text

EBからECS Fargateに移行した話
 - それまで利用していたElasticBeanstalkでのインフラ管理から、ECS Fargateのコ ンテナ実行基盤に移行した
 - ElasticBeanstalkで管理するEC2のOS(Amazon Linux 1)のサポート終了が近づき、新OSへの移行 対応にもそれなりにコストがかかってしまう状態となっていた
 - Webサーバーの潮流としてはコンテナ化がデファクトスタンダードとなっており、ECS Fargateは社内 外でも採用事例が多く、マネージドであるため移行が完了すれば運用コストが下げられる見込みが あった
 - ※2021年ごろ実施
 - 移行コストはある程度かかったが、大きな負債として実害が出る前に対応できた
 テクノロジの進歩や深化、新たな技術的選択肢の登場


Slide 25

Slide 25 text

ページごとに段階的にNuxtにリプレイスしてる話
 - 当初はRailsと密結合していたViewを切り離し、フロントエンドのフレームワークに Nuxtを利用したアーキテクチャに段階的に移行している
 - ※2021年ごろ〜
 - 溜まっていた負債
 - 初期開発で利用したbootstrapやjqueryが部分的に残存・混在しており、改修の難易度が上がって いた
 - シンプルなrails view(slim)でhtmlを構築してる部分と、webpackerでvueを組み込んでhtmlを構築 してる部分の混在
 - バックエンド/フロントエンドの分業制との相性
 - Railsを扱えるフロントエンドエンジニアの減少
 - 現代的なSPAのユーザー体験
 テクノロジの進歩や深化、新たな技術的選択肢の登場
 システムに関わる組織・チームの規模や役割の変化


Slide 26

Slide 26 text

- なぜ「段階的」なのか
 - 技術的負債とは「機能の追加や改修が困難になっているもの」
 - 変更が不要な箇所であれば移行を進める理由は少ない
 - ※複数のアーキテクチャが混在していることによる開発者の混乱などのデメリットはある
 - 移行しない箇所は確実に化石になって改修の困難さは増加していくが、意図的に後回しにすることで 貴重なリソースを他の開発に当てられる
 - ページごとに機能の追加や改修が必要になったタイミングで、既存スタック(Rails view)での改修の 困難さと新スタック(Nuxt)移行のメリットを推し量り、都度判断している
 ページごとに段階的にNuxtにリプレイスしてる話
 テクノロジの進歩や深化、新たな技術的選択肢の登場
 システムに関わる組織・チームの規模や役割の変化


Slide 27

Slide 27 text

- Nuxt 3がリリースされ、同時にVue 2からVue 3へアップデートされたため、それま で利用していたv2とは大きく刷新
 - しばらく旧バージョンを使い続けることはできるが、ビジネス観点で他の開発の状況も踏まえて、 2022末-2023初めごろに実施
 - Nuxt Bridgeというv2とv3の橋渡しとなるバージョンを利用していたが、このbridgeも上手く機能せ ず、当プロジェクトでは全面書き直しに
 - 移行コストはかなり大きくかかったが、結果として後に負債を残さずクリーンな状態 にアップデートすることができた
 Nuxt v2 から v3 に移行した話
 テクノロジの進歩や深化、新たな技術的選択肢の登場


Slide 28

Slide 28 text

おわりに


Slide 29

Slide 29 text

- 長く続くサービス開発では、日々このような技術的負債に向き合いながら開発をし ています
 - 技術的負債はネガティブな面が語られがちなものではありますが、課題を解決して よりよいシステムにしていく面白さもありますね
 おわりに:


Slide 30

Slide 30 text

おわりに:技術的負債を増やさないために
 - 技術的負債は時間の経過とともに自然にできるものだと理解し、悲観しすぎないよ うにしましょう
 - 学ぶことで負債の発生を未然に防いだり減らすことができるものもあります。日々勉 強!
 - よく考えずに放置すると雪だるま式に増えていくので、継続的に過去の負債を返済し ていきましょう


Slide 31

Slide 31 text

参考文献
 - 技術的負債とステークホルダと説明責任と / The Debt - Speaker Deck
 - 質とスピード(2022春版、質疑応答用資料付き) / Quality and Speed 2022 Spring Edition - Speaker Deck
 - 【翻訳】技術的負債という概念の生みの親 Ward Cunningham 自身による説明 - t-wadaのブログ
 - エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタ リング 


Slide 32

Slide 32 text

ありがとうございました!


Slide 33

Slide 33 text

面白法人カヤックの 技術情報・採用情報は、 X (旧Twitter)で発信してます! フォローお願いします!