Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
最初が肝心!技術的負債解消に向けて最初にやるべきこと/first-step-to-pay-of...
Search
Takehiro Kaneko
April 11, 2023
Programming
1.4k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
最初が肝心!技術的負債解消に向けて最初にやるべきこと/first-step-to-pay-off-technical-debt
Takehiro Kaneko
April 11, 2023
More Decks by Takehiro Kaneko
See All by Takehiro Kaneko
大規模UIKitベースアプリへのTCAの段階的導入/gradual-adoption-of-tca-in-a-large-scale-uikit-based-app
takehilo
2
680
むやみにActionを送信してはいけない/do-not-send-actions-thoughtlessly
takehilo
3
1.7k
SwiftUI+TCAに挑戦!NewsPicks iOSアプリのリアーキテクチャ/re-architecture-newspicks-ios-app-with-swiftui-and-tca
takehilo
1
3.2k
iOSアプリ開発に MVVM+Redux パターンを使い始めた話/ios-mvvm-redux-pattern
takehilo
1
1.5k
RxBlocking Deep Dive
takehilo
1
1.1k
RxTest/RxBlockingテストパターン / RxTest RxBlocking Test Patterns
takehilo
5
1.7k
Other Decks in Programming
See All in Programming
使用 Meilisearch 建立新聞搜尋工具
johnroyer
0
170
Claude Team Plan導入・ガイド
tk3fftk
0
240
Prismを使った型安全な暗号化_関数型まつり2026
_fhhmm
0
150
AI時代、エンジニアはどう育つのか -未経験エンジニアの成長を間近で見て考えたこと-
thasu0123
0
150
PHPだって関数型したい 〜できること、できないこと〜 / fp-in-php
jsoizo
1
250
Android CLI
fornewid
0
170
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
210
吝嗇家のためのAI活用 / AI development for miser - ChatGPT + Issue Driven Development
tooppoo
0
200
AIが無かった頃の素敵な出会いの話
codmoninc
1
220
初めてのKubernetes 本番運用でハマった話
oku053
0
130
これからAgentCoreを触る方へトレンドはGatewayです
har1101
6
500
Haskell/Servantを通してWebミドルウェアを捉え直す
pizzacat83
1
610
Featured
See All Featured
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
410
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
280
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
410
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
270
Rebuilding a faster, lazier Slack
samanthasiow
85
9.6k
Crafting Experiences
bethany
1
230
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Git: the NoSQL Database
bkeepers
PRO
432
67k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
280
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
320
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.4k
Transcript
最初が肝心! 技術的負債解消に向けて最初にやるべきこと 2023.04.12 モバイルアプリの技術的負債 みんなで学ぶ Lunch LT NewsPicks iOSエンジニア /
金子 雄大
00 自己紹介 ©NewsPicks Inc. All Rights Reserved. 金子 雄大
NewsPicks iOSエンジニア @takehilo_kaneko takehilo takehilo
00 NewsPicksについて ©NewsPicks Inc. All Rights Reserved.
00 前回登壇のイベント ©NewsPicks Inc. All Rights Reserved. • 今日と同じく技術的負債の解消がテーマ
• アーカイブ動画が公開されてるので、今日と合わ せて是非ご参考に https://uzabase-tech.connpass.com/event/253143/
©NewsPicks Inc. All Rights Reserved. 01 リアーキテクチャ実施の背景
01 ビジネス優先で走り続けてきた ©NewsPicks Inc. All Rights Reserved. iOSアプリのコードは限界に来ていた... •
NewsPicksはリリースからまもなく10年を迎える • その間、何度もUIがリニューアルされてきた • 一方で、コードの保守性は置き去りにされたまま ここまで来てしまった
01 技術的負債解消のアプローチ ©NewsPicks Inc. All Rights Reserved. • 既存のアーキテクチャのまま負債を返済していくことはもはや不可能 •
ただし、ゼロから作り直すための時間とリソースは無い 新しいアーキテクチャを作成し、既存の画面・機能を少しずつ新しい アーキテクチャで作り直していくことにした
01 今日伝えたいこと ©NewsPicks Inc. All Rights Reserved. 作り直しに取りかかる前にやっておいたほうが良いことがある • 技術的負債が生まれにくくすること
• たとえ技術的負債が生まれても、返済可能な状態を維持できるようにすること 具体的に何をすべきかをこの後話していく
©NewsPicks Inc. All Rights Reserved. 02 作り直しをする前に 最初にやるべきこと
02 最初にやるべきこと ©NewsPicks Inc. All Rights Reserved. • コードをレイヤー分けしてマルチモジュール化し、依存の方向を強制する •
ユニットテストの実装を強制する環境を作る 強制するというのがポイント!
©NewsPicks Inc. All Rights Reserved. 02 マルチモジュール化して 依存の方向を強制する
02 レイヤー分けと依存の方向の例 ©NewsPicks Inc. All Rights Reserved. • 新しいアーキテクチャのモジュールから古い コード(Legacy)を参照できないようにする
• PresentationとInfrastructureはDomainにの み依存し、直接参照し合わないようにする
02 なぜ依存の方向を強制するのか? ©NewsPicks Inc. All Rights Reserved. • フォルダ分けをしただけでシングルモジュール構成のままだと、新しいコードから古 いコードを利用できてしまう
◦ 負債を返済しているつもりが、新たな負債を生み出すことに... • モジュールを分けて依存の方向を強制してしまえば、これができなくなる 「古いコードは参照しない」というルールを決めても、それを継続し続 けるのは実は難しい ルールを強制してあげることで、新しいコードをキレイな状態に保ちな がら、負債を返済していくことができる
02 依存の方向を強制することによるその他のメリット ©NewsPicks Inc. All Rights Reserved. • 何でも屋クラスが作られづらくなり、各クラスの責務が明確になる。さらに、その状 態を維持しやすい
• ライブラリへの依存がモジュールに閉じるので、ライブラリを使ったコードが散らば らないし、ライブラリの更新、差し替えもしやすくなる 負債が生まれにくく、かつ生まれても返済可能な状態を維持できる!
02 どうしても古いコードを使いたいときは ©NewsPicks Inc. All Rights Reserved. • Adapterパターンを使って古いコードを参照する(後述) ◦
戻り値の型を新しいコードのものに変換するなどして、新しいコードの都合に 合わせるようにする • 利用は最低限にすること
02 Adapterパターンを使った古いコードの利用方法 ©NewsPicks Inc. All Rights Reserved. • 利用したいクラス(例: SelfLogic)がLegacyモジュールにあるとする
• Domainモジュールに利用したい機能のインタフェースを定義したプロトコル(例: SeflLogicAdapter)を作成する • SelfLogicをSelfLogicAdapterに準拠させる • DIコンテナがPresentationモジュールのクラスにSelfLogicをインジェクトする
02 Adapterパターンを使った古いコードの利用方法 ©NewsPicks Inc. All Rights Reserved. // MARK: -
Domainモジュール protocol SelfLogicAdapter { func someLogic() } // MARK: - Legacyモジュール class SelfLogic { func someLogic() {...} } // SelfLogicAdapterに準拠させる extension SelfLogic: SelfLogicAdapter {} // MARK: - Presentationモジュール class NewsFeedresenter { private let selfLogic: SelfLogicAdapter init(selfLogic: SelfLogicAdapter) { // 実体はSelfLogicインスタンス self.selfLogic = selfLogic } } • インジェクションをどうやるかはプロ ジェクトによって異なる
02 The Composable ArchitectureでのDIの例 ©NewsPicks Inc. All Rights Reserved. //
MARK: - Domainモジュール public enum SelfLogicAdapterKey: TestDependencyKey { public static let testValue: SelfLogicAdapter = MockSelfLogic() public static let previewValue: SelfLogicAdapter = MockSelfLogic() } public extension DependencyValues { var selfLogic: SelfLogicAdapter { get { self[SelfLogicAdapterKey.self] } set { self[SelfLogicAdapterKey.self] = newValue } } } // MARK: - Legacyモジュール extension SelfLogicAdapterKey: DependencyKey { public static let liveValue: SelfLogicAdapter = SelfLogic.shared } // MARK: - Presentationモジュール struct NewsFeedReducer: ReducerProtocol { @Dependency(\.selfLogic) var selfLogic func reduce(into state: inout State, action: Action) -> EffectTask<Action> { ... selfLogic.someLogic() } } • DependencyValuesを使ってReducerに SelfLogicをインジェクトしている
©NewsPicks Inc. All Rights Reserved. 02 ユニットテストの 実装を強制する
02 ユニットテストの実装を強制している例 ©NewsPicks Inc. All Rights Reserved. • 例えば、変更したファイルのカバレッジが ◦%以下ならPRをマージできないようにして
しまう
02 なぜユニットテストの実装を強制するのか? ©NewsPicks Inc. All Rights Reserved. • ユニットテストを実装するためには、テスタブルな設計にしなければならない。その結 果、ロジックがシンプルで、可読性が高くなりやすい
◦ 何でも屋クラスや、複雑過ぎるメソッドが作られづらくなる(負債化しにくくな る) • ユニットテストの実装がしづらいと感じたら、プロダクションコードを見直すことにな り、より良い設計にしようという意識が働く ◦ どうすれば良い設計になるかをチームで議論する機会が明らかに増えた • ユニットテストがあると、リファクタしやすくなる ◦ 負債を継続的に返済していくための環境ができる 負債が生まれにくく、かつ生まれても返済可能な状態を維持できる!
02 ユニットテストはバランスが大事 ©NewsPicks Inc. All Rights Reserved. • マルチモジュール化して依存の方向を強制したり、テスタブルにした結果、テストする までもないシンプルなコードが多くなった
◦ ロジックがほとんどないシンプルなコード、変わることがほとんどないコードにつ いては、テストを書いてもコスパが悪い • 比較的変更の多いプレゼンテーションロジックを中心にテストを書くのが良い
©NewsPicks Inc. All Rights Reserved. 03 さいごに
03 新しく作ったコードもすぐに負債になり得る ©NewsPicks Inc. All Rights Reserved. • 新しく作ったコードが完璧なものとは限らない •
設計に不備があったり、納期を優先しなければならない状況は常に発生する 技術的負債を返済可能な状態を維持していることが重要! 技術的負債解消プロジェクトを何度もやることにならないように 最初にしっかり準備をしよう!
03 偉人の金言 ©NewsPicks Inc. All Rights Reserved. 自信過剰による再設計は、元のプロジェクトと同じように崩壊する 速く進む唯一の方法は、うまく進むことである Clean
Architecture 達人に学ぶソフトウェアの構造と設計 より
©NewsPicks Inc. All Rights Reserved. Thank you!!