Upgrade to Pro — share decks privately, control downloads, hide ads and more …

最初が肝心!技術的負債解消に向けて最初にやるべきこと/first-step-to-pay-off-technical-debt

 最初が肝心!技術的負債解消に向けて最初にやるべきこと/first-step-to-pay-off-technical-debt

Takehiro Kaneko

April 11, 2023
Tweet

More Decks by Takehiro Kaneko

Other Decks in Programming

Transcript

  1. 00 自己紹介 ©NewsPicks Inc. All Rights Reserved. 
 金子 雄大

    NewsPicks iOSエンジニア @takehilo_kaneko takehilo takehilo
  2. 00 前回登壇のイベント ©NewsPicks Inc. All Rights Reserved. 
 • 今日と同じく技術的負債の解消がテーマ

    • アーカイブ動画が公開されてるので、今日と合わ せて是非ご参考に https://uzabase-tech.connpass.com/event/253143/
  3. 01 ビジネス優先で走り続けてきた ©NewsPicks Inc. All Rights Reserved. 
 iOSアプリのコードは限界に来ていた... •

    NewsPicksはリリースからまもなく10年を迎える • その間、何度もUIがリニューアルされてきた • 一方で、コードの保守性は置き去りにされたまま ここまで来てしまった
  4. 01 技術的負債解消のアプローチ ©NewsPicks Inc. All Rights Reserved.
 • 既存のアーキテクチャのまま負債を返済していくことはもはや不可能 •

    ただし、ゼロから作り直すための時間とリソースは無い 新しいアーキテクチャを作成し、既存の画面・機能を少しずつ新しい アーキテクチャで作り直していくことにした
  5. 01 今日伝えたいこと ©NewsPicks Inc. All Rights Reserved.
 作り直しに取りかかる前にやっておいたほうが良いことがある • 技術的負債が生まれにくくすること

    • たとえ技術的負債が生まれても、返済可能な状態を維持できるようにすること 具体的に何をすべきかをこの後話していく
  6. 02 なぜ依存の方向を強制するのか? ©NewsPicks Inc. All Rights Reserved.
 • フォルダ分けをしただけでシングルモジュール構成のままだと、新しいコードから古 いコードを利用できてしまう

    ◦ 負債を返済しているつもりが、新たな負債を生み出すことに... • モジュールを分けて依存の方向を強制してしまえば、これができなくなる 「古いコードは参照しない」というルールを決めても、それを継続し続 けるのは実は難しい ルールを強制してあげることで、新しいコードをキレイな状態に保ちな がら、負債を返済していくことができる
  7. 02 依存の方向を強制することによるその他のメリット ©NewsPicks Inc. All Rights Reserved.
 • 何でも屋クラスが作られづらくなり、各クラスの責務が明確になる。さらに、その状 態を維持しやすい

    • ライブラリへの依存がモジュールに閉じるので、ライブラリを使ったコードが散らば らないし、ライブラリの更新、差し替えもしやすくなる 負債が生まれにくく、かつ生まれても返済可能な状態を維持できる!
  8. 02 どうしても古いコードを使いたいときは ©NewsPicks Inc. All Rights Reserved.
 • Adapterパターンを使って古いコードを参照する(後述) ◦

    戻り値の型を新しいコードのものに変換するなどして、新しいコードの都合に 合わせるようにする • 利用は最低限にすること
  9. 02 Adapterパターンを使った古いコードの利用方法 ©NewsPicks Inc. All Rights Reserved.
 • 利用したいクラス(例: SelfLogic)がLegacyモジュールにあるとする

    • Domainモジュールに利用したい機能のインタフェースを定義したプロトコル(例: SeflLogicAdapter)を作成する • SelfLogicをSelfLogicAdapterに準拠させる • DIコンテナがPresentationモジュールのクラスにSelfLogicをインジェクトする
  10. 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 } } • インジェクションをどうやるかはプロ ジェクトによって異なる
  11. 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をインジェクトしている
  12. 02 なぜユニットテストの実装を強制するのか? ©NewsPicks Inc. All Rights Reserved.
 • ユニットテストを実装するためには、テスタブルな設計にしなければならない。その結 果、ロジックがシンプルで、可読性が高くなりやすい

    ◦ 何でも屋クラスや、複雑過ぎるメソッドが作られづらくなる(負債化しにくくな る) • ユニットテストの実装がしづらいと感じたら、プロダクションコードを見直すことにな り、より良い設計にしようという意識が働く ◦ どうすれば良い設計になるかをチームで議論する機会が明らかに増えた • ユニットテストがあると、リファクタしやすくなる ◦ 負債を継続的に返済していくための環境ができる 負債が生まれにくく、かつ生まれても返済可能な状態を維持できる!
  13. 02 ユニットテストはバランスが大事 ©NewsPicks Inc. All Rights Reserved.
 • マルチモジュール化して依存の方向を強制したり、テスタブルにした結果、テストする までもないシンプルなコードが多くなった

    ◦ ロジックがほとんどないシンプルなコード、変わることがほとんどないコードにつ いては、テストを書いてもコスパが悪い • 比較的変更の多いプレゼンテーションロジックを中心にテストを書くのが良い
  14. 03 新しく作ったコードもすぐに負債になり得る ©NewsPicks Inc. All Rights Reserved.
 • 新しく作ったコードが完璧なものとは限らない •

    設計に不備があったり、納期を優先しなければならない状況は常に発生する 技術的負債を返済可能な状態を維持していることが重要! 技術的負債解消プロジェクトを何度もやることにならないように 最初にしっかり準備をしよう!