Webサービスの成長を止めずに リファクタリングする技術 / web-refactoring

Webサービスの成長を止めずに リファクタリングする技術 / web-refactoring

PHPカンファレンス福岡 2019
- https://phpcon.fukuoka.jp/2019/

■参考資料
https://oso.connpass.com/event/53811/presentation/

88f4e84b94fe07cddbd9e6479d689192?s=128

soudai sone

June 25, 2019
Tweet

Transcript

  1. Webサービスの成長を止めずに
 リファクタリングする技術
 PHPカンファレンス福岡2019

  2. What is it?
 リファクタリングしてますか?


  3. What is it?
 • サービス開発が優先…
 • 技術的負債の返済に理解が無い…
 • どこからやればいいかわからない…
 現場の声


  4. What is it?
 これは全部、言い訳です


  5. What is it?
 今日は実際に
 どのようにやったらいいか
 どのようにやってきたか
 
 


  6. What is it?
 余すことなく、お伝えします


  7. あじぇんだ
 1. 自己紹介
 2. Webサービスを止めない工夫
 3. リファクタリングとテスト
 4. 新規開発とリファクタリングの共存
 5.

    実際にリファクタリングした例
 6. まとめ

  8. あじぇんだ
 1. 自己紹介
 2. Webサービスを止めない工夫
 3. リファクタリングとテスト
 4. 新規開発とリファクタリングの共存
 5.

    実際にリファクタリングした例
 6. まとめ

  9. 自己紹介
 曽根 壮大(34歳)
 株式会社 オミカレ 副社長 CTO
 
 そ  ね  

    たけ とも
 • 日本PostgreSQLユーザ会 勉強会分科会 担当
 • 3人の子供がいます(長女、次女、長男)
 • 技術的にはWeb/LL言語/RDBMSが好きです
 • コミュニティが好き
  10. 婚活といえばオミカレ
 https://party-calendar.net/

  11. あじぇんだ
 1. 自己紹介
 2. Webサービスを止めない工夫
 3. リファクタリングとテスト
 4. 新規開発とリファクタリングの共存
 5.

    実際にリファクタリングした例
 6. まとめ

  12. Webサービスを止めない工夫
 Webサービスは止められない


  13. Webサービスを止めない工夫
 • 365日/24時間、稼働している
 • サービスの停止=ビジネスの停止
 • 複雑な依存関係があり、単純に1つだ け止めれば良いとならない
 止められない理由


  14. Webサービスを止めない工夫
 Webサービス、止めないとは?


  15. Webサービスを止めない工夫
 Webサービス、止めないとは?
 ↓
 Webサービスの稼働を止めない?


  16. Webサービスを止めない工夫
 Webサービス、稼働と進化を止めない


  17. Webサービスを止めない工夫
 リファクタリング戦略と戦術が大切


  18. Webサービスを止めない工夫
 戦略→目的を達成するためのシナリオ
 戦術→目的を達成するための手段・手法


  19. Webサービスを止めない工夫
 • 目的と効果の判断をする
 • ゴールを決める
 • 方針を決める
 リファクタリング戦略


  20. Webサービスを止めない工夫
 • 目的と効果の判断をする
 • ゴールを決める
 • 方針を決める
 リファクタリング戦略


  21. Webサービスを止めない工夫
 チーズと腐った牛乳の違い


  22. Webサービスを止めない工夫
 何を変更するのか?


  23. Webサービスを止めない工夫
 • 機能追加
 • バグ修正
 • 最適化
 • リファクタリング
 それぞれの目的が違う


  24. Webサービスを止めない工夫
 機能追加とバグ修正
 ↓
 振る舞いが変わる


  25. Webサービスを止めない工夫
 最適化とリファクタリング
 ↓
 振る舞いが変わらない


  26. Webサービスを止めない工夫


  27. Webサービスを止めない工夫
 目的 / 対象
 新機能
 機能
 リソース
 構造
 要件追加
 変化する


    ー
 ー
 変化する
 バグ修正
 ー
 変化する
 ー
 変化する
 最適化
 ー
 ー
 変化する
 ー
 リファクタリング
 ー
 ー
 ー
 変化する
 引用:レガシーコード改善ガイド 第1章 ソフトウェアの変更 P7
  28. Webサービスを止めない工夫
 複数の目的を一つのチケットにしない
 


  29. Webサービスを止めない工夫
 複数の目的を一つのチケットにしない
 ↓
 目的を単純化して小さいチケットにする


  30. Webサービスを止めない工夫
 機能追加のためにリファクタリングが必要


  31. Webサービスを止めない工夫
 テストの内容が変わる


  32. Webサービスを止めない工夫
 機能追加のためにリファクタリングが必要
 ↓
 それぞれ別のPRにする


  33. Webサービスを止めない工夫
 • 目的と効果の判断をする
 • ゴールを決める
 • 方針を決める
 リファクタリング戦略


  34. Webサービスを止めない工夫
 ゴールを決める
 


  35. Webサービスを止めない工夫
 ゴールを決める
 ↓
 期間と目的を決める


  36. Webサービスを止めない工夫
 1回で終わらないタスクもある
 数ヶ月単位のリファクタリングもある
 


  37. Webサービスを止めない工夫
 ゴールを決める
 ↓
 スケジュールを設計する


  38. Webサービスを止めない工夫
 1. 第1法則
 仕事の量は、完成のために与えられた時間を
 すべて満たすまで膨張する
 2. 第2法則
 支出の額は、収入の額に達するまで膨張する
 パーキンソンの法則


  39. Webサービスを止めない工夫
 リファクタリングの完成は無い


  40. Webサービスを止めない工夫
 だからこそ、ゴールを決めることが大切


  41. Webサービスを止めない工夫
 • 目的と効果の判断をする
 • ゴールを決める
 • 方針を決める
 リファクタリング戦略


  42. Webサービスを止めない工夫
 どのようにリファクタリングするか


  43. Webサービスを止めない工夫
 Webサービス、稼働と進化を止めない


  44. Webサービスを止めない工夫
 • 新機能とコンフリクトしない
 • 振る舞い(既存機能)を壊さない
 • サービス停止を伴わない
 • 新たな負債を作らない
 要件


  45. Webサービスを止めない工夫
 • 新機能とコンフリクトしない
 • 振る舞い(既存機能)を壊さない
 • サービス停止を伴わない
 • 新たな負債を作らない
 要件


  46. Webサービスを止めない工夫
 改善と新機能追加を
 明確に分ける


  47. Webサービスを止めない工夫
 新機能→ユーザ画面
 改善→管理画面
 これはコンフリクトする場合がある
 


  48. Webサービスを止めない工夫
 ユーザ機能は管理画面と
 依存関係がある


  49. Webサービスを止めない工夫
 依存関係の例
 ユーザ画面
 管理画面
 ユーザ
 ① 予約アクション
 ② 予約情報の確認
 ④

    予約情報の確認
 管理者
 ③ 予約情報の変更

  50. Webサービスを止めない工夫
 機能で分ける


  51. Webサービスを止めない工夫
 ???「既存機能は密結合してる」
 


  52. Webサービスを止めない工夫
 機能で分ける
 ↓
 機能別に分割することが
 リファクタリングの最初


  53. Webサービスを止めない工夫
 • 新機能とコンフリクトしない
 • 振る舞い(既存機能)を壊さない
 • サービス停止を伴わない
 • 新たな負債を作らない
 要件


  54. Webサービスを止めない工夫
 目的 / 対象
 新機能
 機能
 リソース
 構造
 要件追加
 変化する


    ー
 ー
 変化する
 バグ修正
 ー
 変化する
 ー
 変化する
 最適化
 ー
 ー
 変化する
 ー
 リファクタリング
 ー
 ー
 ー
 変化する
 引用:レガシーコード改善ガイド 第1章 ソフトウェアの変更 P7
  55. Webサービスを止めない工夫
 壊さないための工夫


  56. Webサービスを止めない工夫
 壊れてないことの証明
 


  57. Webサービスを止めない工夫
 壊れてないことの証明
 ↓
 テストコード


  58. Webサービスを止めない工夫
 壊さないリファクタリング
 


  59. Webサービスを止めない工夫
 壊さないリファクタリング
 ↓
 デザインパターンを活用する


  60. Webサービスを止めない工夫
 例えばDecoratorパターン
 (GoFデザインパターン)


  61. Webサービスを止めない工夫
 ルーク、Do You PHPを読め
 http://shimooka.hateblo.jp/entry/20141217/1418788239 


  62. Webサービスを止めない工夫
 • 新機能とコンフリクトしない
 • 振る舞い(既存機能)を壊さない
 • サービス停止を伴わない
 • 新たな負債を作らない
 要件


  63. Webサービスを止めない工夫
 変更の影響を小さくする


  64. Webサービスを止めない工夫
 • データストアとアプリケーションを
 できるだけ一緒に変更しない
 • 変更前と変更後でも同じ振る舞いをする
 • テスト項目が現実的なサイズに留める
 変更の影響を小さくする


  65. Webサービスを止めない工夫
 リファクタリングの場合は満たしやすい
 機能追加の場合は腕の見せ所


  66. Webサービスを止めない工夫
 • 新機能とコンフリクトしない
 • 振る舞い(既存機能)を壊さない
 • サービス停止を伴わない
 • 新たな負債を作らない
 要件


  67. Webサービスを止めない工夫
 目的がブレると陥りやすい


  68. Webサービスを止めない工夫
 納期のために…
 良い方法が思いつかない…
 やりたい事の問題が大きい…


  69. Webサービスを止めない工夫
 こうなったらリファクタリングしない


  70. Webサービスを止めない工夫
 良い解決策がない場合
 それは時期早々


  71. Webサービスを止めない工夫
 リファクタリングは機能追加ではない
 


  72. Webサービスを止めない工夫
 リファクタリングは機能追加ではない
 ↓
 必ず必要ではない


  73. Webサービスを止めない工夫
 目的を明確に、小さくやる


  74. あじぇんだ
 1. 自己紹介
 2. Webサービスを止めない工夫
 3. リファクタリングとテスト
 4. 新規開発とリファクタリングの共存
 5.

    実際にリファクタリングした例
 6. まとめ

  75. リファクタリングとテスト
 実際にリファクタリングしましょう


  76. リファクタリングとテスト
 実際にリファクタリングしましょう
 ↓
 テストはありません


  77. リファクタリングとテスト
 ???「わかるぅ〜〜〜」
 (CV:そーだい)


  78. リファクタリングとテスト
 テストを書きましょう


  79. リファクタリングとテスト
 テストを書きましょう
 ↓
 責務が多くてテストが書けません


  80. リファクタリングとテスト
 ???「わかるぅ〜〜〜」
 (CV:そーだい)


  81. リファクタリングとテスト
 まずはテストできる状況を目指す


  82. リファクタリングとテスト
 • 機能が疎結合
 • テストの実行環境がある
 • 振る舞いが明確である
 テストができる状態


  83. リファクタリングとテスト
 状況に合わせてテストを使い分ける


  84. リファクタリングとテスト
 • ユニットテスト
 • インテグレーションテスト
 • シナリオテスト
 etc...テストは奥が深く他にも色々
 主なテストの種類


  85. リファクタリングとテスト
 何をテストしたいのか


  86. リファクタリングとテスト
 機能要件ベースならシナリオテスト
 コードベースならユニットテスト
 自動化はとても大切だけど全てではない


  87. リファクタリングとテスト
 責務が多すぎてユニットテストが出来ない
 ↓
 まずはシナリオテストを用意する


  88. リファクタリングとテスト
 • 本番相当のテストデータ
 • 本番相当のテスト環境(staging)
 • 明確な機能要件
 シナリオテストに必要なこと


  89. リファクタリングとテスト
 いきなりシナリオテストを自動化しない
 (例えばSeleniumとかで)


  90. リファクタリングとテスト
 シナリオ(機能要件)は変化しやすい
 ↓
 Viewに近いところは
 ビジネスの変化を受けやすい


  91. リファクタリングとテスト
 要件を絞る
 ↓
 フルテストみたいなシナリオを書かない


  92. リファクタリングとテスト
 シナリオテストが出来たら?
 ↓
 シナリオテストが通るように機能を分解
 


  93. リファクタリングとテスト
 機能を分解するとき
 ユニットテストは最初から書く


  94. リファクタリングとテスト
 テストが出来ないコードを防ぐ
 


  95. リファクタリングとテスト
 テストが出来ないコードを防ぐ
 ↓
 TDDでなくてもいいけど、テストは書く


  96. リファクタリングとテスト
 Viewから遠いところからテストを書く


  97. リファクタリングとテスト
 Viewから遠いところからテストを書く
 ↓
 例えばドメイン層


  98. リファクタリングとテスト
 データソース層 Table Data Gateway ActiveRecord DataMapper など データストア ドメイン層 プレゼンテーション層

    View Controller ビジネスロジック Service Entity Repository ドメイン層から着手する 
 目指すアーキテクチャに合わせてリファクタリング 
 ※左記の例は一例でドメインの分割は多種多様 
 (フレームワークの制約も受ける) 

  99. リファクタリングとテスト
 • 責務の分割
 • ロジックの整理
 • 不要なコードの削除
 etc...
 ドメイン層のリファクタリング例


  100. リファクタリングとテスト
 何年も稼働しているサービスなら
 ビジネスロジックのコアが見えてるはず


  101. リファクタリングとテスト
 ビジネスロジックのコアを整理する
 ↓
 変化のインパクトが大きいからこそ
 リファクタリングとテストが活きる


  102. あじぇんだ
 1. 自己紹介
 2. Webサービスを止めない工夫
 3. リファクタリングとテスト
 4. 新規開発とリファクタリングの共存
 5.

    実際にリファクタリングした例
 6. まとめ

  103. 新規開発とリファクタリングの共存
 偉い人「新規開発は止めないで」


  104. 新規開発とリファクタリングの共存
 Webサービス、稼働と進化を止めない


  105. 新規開発とリファクタリングの共存
 新規開発は既存部分と分ける


  106. 新規開発とリファクタリングの共存
 ???「fileやコンポーネント増えません?」
 


  107. 新規開発とリファクタリングの共存
 ???「fileやコンポーネント増えません?」
 ↓
 増えます


  108. 新規開発とリファクタリングの共存
 サービスレイヤが無いなら導入する
 


  109. 新規開発とリファクタリングの共存
 サービスレイヤが無いなら導入する
 ↓
 既存は少しづつリファクタリングで
 サービスレイヤに移行する


  110. 新規開発とリファクタリングの共存
 サービスレイヤが無いなら導入する
 ↓
 既存は少しづつリファクタリングで
 サービスレイヤに移行する
 新規は最初から利用する


  111. 新規開発とリファクタリングの共存
 モック化しやすいように変更する
 ↓
 例えばAPI経由にする


  112. 新規開発とリファクタリングの共存
 
 データソース層 Table Data Gateway ActiveRecord DataMapper など データストア ドメイン層

    プレゼンテーション層 View Controller ビジネスロジック Service Entity Repository API層 新たなロジック
  113. 新規開発とリファクタリングの共存
 新規開発はリファクタリング後の姿で
 最初から開発する


  114. 新規開発とリファクタリングの共存
 リファクタリング 新規開発 理想の状態 両軸から理想を目指す


  115. 1. 自己紹介
 2. Webサービスを止めない工夫
 3. リファクタリングとテスト
 4. 新規開発とリファクタリングの共存
 5. 実際にリファクタリングした例


    6. まとめ
 あじぇんだ

  116. 実際にリファクタリングした例
 オミカレのフルリニューアル
 (なんと6/25にリリースしたばかり!)


  117. 実際にリファクタリングした例
 • テーブル設計に不備がある
 • 一つのモデルの責務が大きい
 • FatController
 • Viewにロジックが含まれている
 今までのオミカレ


  118. 実際にリファクタリングした例
 • テーブル設計に不備がある
 • 一つのモデルの責務が大きい
 • FatController
 • Viewにロジックが含まれている
 今までのオミカレ


  119. 実際にリファクタリングした例
 一つ一つ改善してきた


  120. 実際にリファクタリングした例
 https://employment.en-japan.com/engineerhub/entry/2018/12/11/110000

  121. 実際にリファクタリングした例
 https://speakerdeck.com/soudai/aws-dms

  122. 実際にリファクタリングした例
 https://speakerdeck.com/soudai/kichijojipm

  123. 実際にリファクタリングした例
 細かく知りたい人は
 資料を見てください


  124. 実際にリファクタリングした例
 エンジニアHubから引用

  125. 新規開発とリファクタリングの共存
 
 データソース層 Table Data Gateway ActiveRecord DataMapper など データストア ドメイン層

    プレゼンテーション層 View Controller ビジネスロジック Service Entity Repository API層 新たなロジック まさにこれ!

  126. 実際にリファクタリングした例
 APIとRDBMSの機能を使って
 データ構造を変える


  127. 実際にリファクタリングした例
 APIはINとOUTが明確
 ↓
 テストコードが書きやすい!


  128. 実際にリファクタリングした例
 • テーブル設計に不備がある
 • 一つのモデルの責務が大きい
 • FatController
 • Viewにロジックが含まれている
 今までのオミカレ


  129. 既存のオミカレ
 データストア ドメイン層 プレゼンテーション層 View Controller モデルクラス - データアクセスと ロジックが同じクラスにか

    かれている - Controllerに一部の ロジックが漏れている(書 かれている)
  130. 実際にリファクタリングした例
 エンジニアHubから引用

  131. 実際にリファクタリングした例
 APIを経由することで
 ロジックの責務を分解する
 APIがドメイン層とも言える


  132. 実際にリファクタリングした例
 リファクタリングの例
 例えばpartyの取得


  133. 実際にリファクタリングした例
 REST API(/api/public/party)を作る
 


  134. 実際にリファクタリングした例
 APIを呼び出すRepository(PartySearch)を作る
 パラメータをSetして呼び出すだけ
 


  135. 実際にリファクタリングした例
 PartySearchを使って情報を取得する
 Presenter(SearchPartyPresenter)を作る


  136. 実際にリファクタリングした例


  137. 実際にリファクタリングした例
 検索条件は複雑だから、PresenterからRepositoryを 呼び出すパターンが無限にある


  138. 実際にリファクタリングした例
 PresenterとRepositoryをつなぐ
 Model(SearchModel)を作る
 Presenter ↔ Model ↔ Repository


  139. 新規開発とリファクタリングの共存
 
 データストア ドメイン層 プレゼンテーション層 View Controller Presenter ビジネスロジックを書く Repository

    適切なデータに アクセスする API層 データの取得と調整 まさにこれ!
 キャッシュ Model データの取得 と加工する
  140. 実際にリファクタリングした例
 Modelの責務を分ける
 ↓
 Controllerが呼び出す
 get_party()の振る舞いは変わらない
 get_party()はPresenterに実装する


  141. 実際にリファクタリングした例
 Presenterはデータの保存先を知らない
 ↓
 ビジネスロジックだけに注力する
 NoSQLでもRDBMSでもキャッシュでも良い


  142. 実際にリファクタリングした例
 Modelはビジネスロジックに
 必要なお膳立てをする
 振る舞いの例
 1. PresenterがSetした条件に合わせてPartyを取得する
 2. 与えられた条件から参加可否を加工する
 3. 不要な情報をフィルタする …など


  143. 実際にリファクタリングした例
 RepositoryはModelが必要な
 データアクセスを提供する
 RDBMSもキャッシュも同じフォーマット(オブジェクト)で返ってきて ほしい


  144. 実際にリファクタリングした例
 責務を分けるとモック化やテストが楽


  145. 実際にリファクタリングした例
 • テーブル設計に不備がある
 • 一つのモデルの責務が大きい
 • FatController
 • Viewにロジックが含まれている
 今までのオミカレ


  146. 実際にリファクタリングした例
 controllers ❯❯❯ wc -l area.php
 5124 area.php


  147. 実際にリファクタリングした例
 5000行超えのController、趣がありますね


  148. 実際にリファクタリングした例
 SEOのために必要な
 パンくずやキーワードの取得を書いてしまう


  149. 実際にリファクタリングした例
 AパターンのときとBパターンの時に
 パンくずの出力を分けてください
 ↓
 Controllerにif文が生える


  150. 実際にリファクタリングした例
 どんどんControllerがロジックを持つ
 


  151. 実際にリファクタリングした例
 どんどんControllerがロジックを持つ
 ↓
 無限に増える行数


  152. 実際にリファクタリングした例
 ロジックがControllerに漏れているのが原因
 


  153. 実際にリファクタリングした例
 ロジックがControllerに漏れているのが原因
 ↓
 Presenterに責務を移していく
 データアクセスがない部分でもしっかりPresenterにする


  154. 実際にリファクタリングした例
 Presenterは先に作れる
 ↓
 他の開発の邪魔をしない


  155. 実際にリファクタリングした例
 controllers ❯❯❯ wc -l Area.php
 542 Area.php
 同等の機能が約1/10の行数になった!


  156. 実際にリファクタリングした例
 Controllerの行数は
 メンテナンス工数に直撃する


  157. 実際にリファクタリングした例
 Controllerが小さくなることで
 影響範囲が明確になった


  158. 実際にリファクタリングした例
 • テーブル設計に不備がある
 • 一つのモデルの責務が大きい
 • FatController
 • Viewにロジックが含まれている
 今までのオミカレ


  159. 実際にリファクタリングした例
 Viewにif文を書いてませんか?


  160. 実際にリファクタリングした例
 <?php if($header) : ?> <?= $this->load->view('/parts/header'); ?> <?php else:

    ?> // headerがいらないときの処理 <?php endif; ?>
  161. 実際にリファクタリングした例
 ???「1行だけだし、これでいっか」
 


  162. 実際にリファクタリングした例
 ???「1行だけだし、これでいっか」
 ↓
 良くない!!!!
 


  163. 実際にリファクタリングした例
 ???「PCとSPでheaderを分けてほしい」
 


  164. 実際にリファクタリングした例
 <?php if($header && $is_pc) : ?> <?= $this->load->view('pc/parts/header'); ?>

    <?php elseif($header && !$is_pc) : ?> <?= $this->load->view('sp/parts/header'); ?> <?php else: ?> // headerがいらないときの処理 <?php endif; ?>
  165. 実際にリファクタリングした例
 ???「AMPもやりたい」
 ↓
 こうやって無限に増える
 


  166. 実際にリファクタリングした例
 Viewにifがある=状態を持っている
 ↓
 状態を持っているとテストが難しい


  167. 実際にリファクタリングした例
 • 見た目のテストは成否が難しい
 • ブラウザなど依存環境が多い
 • テストの自動化のコストが高い
 • テスト項目が多いと時間がかかる
 そもそもViewのテストは難しい


  168. 実際にリファクタリングした例
 できるだけテストしたくない
 


  169. 実際にリファクタリングした例
 できるだけテストしたくない
 ↓
 Viewにif文を書かない
 


  170. 実際にリファクタリングした例
 とある日のCTO
 「突然ですがViewでif文を禁止にします」


  171. 実際にリファクタリングした例
 どうやって実現するか


  172. 実際にリファクタリングした例
 どうやって実現するか
 ↓
 出力するデータをPresenterで事前に用意する
 Viewは出力するだけ


  173. 実際にリファクタリングした例
 100文字以上は末尾を…にしたい
 ↓
 Helperで吸収してViewはechoするだけ


  174. 実際にリファクタリングした例
 Viewのif文が無くなるとデバッグが楽になる
 Presenterだけに注力すれば良い
 そしてPresenterにはテストが書ける!


  175. 実際にリファクタリングした例
 現状に合わせて1つ1つ積み重ねる
 オミカレも1年以上かかった
 
 この他にもFWやPHPのバージョンアップなどもした


  176. あじぇんだ
 1. 自己紹介
 2. Webサービスを止めない工夫
 3. リファクタリングとテスト
 4. 新規開発とリファクタリングの共存
 5.

    実際にリファクタリングした例
 6. まとめ

  177. まとめ
 リファクタリングの戦略を決める


  178. まとめ
 リファクタリングの戦略を決める
 ↓
 どこからやるか、どのようにやるか


  179. まとめ
 https://speakerdeck.com/naoya/ji-shu-de-fu-zhai-toxiang-kihe-u

  180. まとめ
 [オープンセミナー岡山 2017] [検索]

  181. まとめ
 優先順位は大切
 小さく始める


  182. まとめ
 まずはテストをできる状態にする
 
 


  183. まとめ
 まずはテストをできる状態にする
 ↓
 自動化じゃなくてもテストはできる


  184. まとめ
 分割してからテストの自動化を目指す


  185. まとめ
 分割ができれば新規機能追加と衝突しない


  186. まとめ
 分割ができれば新規機能追加と衝突しない
 ↓
 新規とリファクタリングの両輪で
 理想を目指す


  187. まとめ
 技術で課題を解決する


  188. まとめ
 テストを工夫したり
 監視をすることでテストの代用をしたり
 デザインパターンを活用したり


  189. まとめ
 リファクタリングはできる!


  190. まとめ
 理想への一歩目を踏み出すのは
 自分自身


  191. まとめ
 ご清聴ありがとうございました