77
Copyright © DeNA Co.,Ltd. All Rights Reserved. レレレレレ Perl レレレレレ DDD( レレレレレレレレ ) レレレレレ レレレレ DeNA Games Osaka レレ レ レ レレ 西 [email protected]

レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Embed Size (px)

Citation preview

Page 1: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

レガシーな Perl システムに DDD( ドメイン駆動設計 ) を取り入れる

株式会社 DeNA Games Osaka 技術部 人西 聖樹 [email protected]

Page 2: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

YAPC !

Page 3: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Kansai !

Page 4: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

めでたい !

Page 5: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

自己紹介

人西 聖樹(ひとにし まさき)

Twitter: @sairoutine

株式会社 DeNA Games Osaka

Web アプリケーションエンジニア

生まれは京都、育ちは大阪

Page 6: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

関西以外から来られたかたどれくらいいます?

Page 7: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

突然ですが

Page 8: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

本セッションは全て関西弁でお送りします。

Page 9: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

それではやっていきまんねん

Page 10: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

ウソです

Page 11: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

関西人は「〜まんねん」使いません

※ 独自調査

Page 12: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

でも飴のことを「あめちゃん」って言う人は多いです

※ 独自調査

Page 13: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

改めてよろしくお願いします。

Page 14: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Page 15: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

ご当地スポンサー枠

Page 16: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Mobage

Page 17: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Mobage 10 周年

Page 18: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

実はもう 11 周年 !

Page 19: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Page 20: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Page 21: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

まだまだ1000 タイトル以上が稼働中

Page 22: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

DeNA 2016 年度 第 3 四半期決算説明会資料より引用

126億

56 億

Page 23: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

まだまだ日本最大規模のプラットフォームであることに変わりはありません

Page 24: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

そんな Mobage は、Perl で作られています

Page 25: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Perl 5.8.8

Page 26: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

独自フレームワーク MobaSiF

Page 27: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

今日はなすこと

僕らが開発・運用しているシステムについて

レガシーコード改善の歴史

ドメイン駆動設計の導入

学び

Page 28: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

今日はなすこと

僕らが開発・運用しているシステムについて

レガシーコード改善の歴史

ドメイン駆動設計の導入

学び

Page 29: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Mobage の 1 ブラウザゲームタイトル

いわゆる「ソーシャルゲーム」

システムとしては、 LAMP(Linux, Apache, MySQL, Perl) + Memcached etc…

Page 30: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

通常の機能に加えて、期間限定のイベントを月に 4 回開催してます。

イベント自体は、前月のシステムを使いまわしていますが、毎月何かしらの機能追加/改修を行ってます。

たまに新規イベントとかも作ったりします。

新規イベントは、開発期間 3 ヶ月〜 6 ヶ月と結構長い

通常のゲームの機能をあまり流用しないことが多く、 1 からゲームを作る感覚。

Page 31: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

アーキテクチャ

Page 32: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

MVC

Page 33: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Model

情報を扱うクラス O/R マッパー RDBMS の 1 テーブル 1 クラス フレームワーク or ライブラリが提供してない 独自実装 Rails の Active Record に影響受けてそうな API

# 1 行取得my $record = Class->find($pk);# 1 行 UPDATE$record->hp(100);$record->save();

Page 34: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

View

Mobasif 付属のテンプレートエンジン「 Mtemplate 」 ガラケー 3 キャリアに対応する HTML を 1 つのテンプ

レートで記載可能 事前コンパイルにより、リクエストごとのテンプレートの

パースを省略 主要な部分は XS で書かれており、高速

<!-- 条件分岐 -->$ if (condition) { $ <div> hoge </div>$ } elsif (conditions) { $ <div>fuga</div>$ } else { $ <div>piyo</div>$ } $

Page 35: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Controller

開発者内では、 Page 層と呼称されることが多い

Conf ファイルに、 URL と、 URL に該当するクラス/メソッドを記載する

入力値の validation

Page 36: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

5 年くらい運用してくると出て来る課題

人の入れ替わり

→実装した人が既に退職してる。 5 年も運用してると、現在のチームメンバーが書いたコードは、システムの 10% くらいとか。

知識の継承

知識の継承が出来ておらず、追加実装/変更に対して、いちいち既存の実装の調査に工数がかかる。既存の実装を弄ると、あらぬところにエンバグする。

仕様の肥大化

そもそも実装だけでなくシステムの仕様も肥大化していて、新規仕様を追加するに当たって、既存仕様との不整合による考慮漏れが発生する。

Page 37: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

今日はなすこと

僕らが開発・運用しているシステムについて

レガシーコード改善の歴史

ドメイン駆動設計の導入

学び

Page 38: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

レガシー Perl 特有の辛さ

Page 39: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

EUC-JP

Page 40: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Shift_JIS

Page 41: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

データベースは Shift_JIS

プログラムは EUC-JP

スマートフォン向け出力は UTF-8

ガラケー向け出力は Shift_JIS

Page 42: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

連想配列リファレンスによる引数の受け渡し

→連想配列の作成元までコードを読まないとどういう挙動の コードかわからない。

# 例sub getEquipmentsString { my ($items) = @_;

if ( scalar(@$items) ) { my @strings = ();

for my $rhItem (@$items) { push(@strings, "$rhItem->{name}x$rhItem->{num}"); }

return join('/', @strings); } else { return undef; }}

Page 43: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

その他、個人的に辛いなぁと思ったこと

全てを管理する神クラス

引数の連想配列リファレンスを変更する addXXXInfo 的なメソッド

超巨大な if 文 (30 回以上 if ~ elsif し続ける )

値が変更されうるグローバル変数 (!) プラットフォーム側と 1枚岩の超モノリ

シックなシステムなところとか

Page 44: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

むむ、ちゃんとオブジェクト指向やれば解決しそう感

Page 45: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

これまでもオブジェクト指向はちょっとずつ取り入れてきました

Page 46: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

DAO 層の追加

Data Access Object RDBMS のデータをオブジェクトとして扱える

Mobasif には DA (DBI クラスのラッパー ) しかなかった

オブジェクトを扱うだけで、 SQL を発行できるので、 SQL 関係のバグが減る

SQL をコントローラーなどに書かずに済む

共通で使われるような SQL を一箇所に集約できる

ゲームロジックについては引き続き Controller 側あった

→ Fat Controller になる問題

Page 47: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Model 層の追加

RDBMS との連携だけでなく、状態を操作する処理も担当する

get_group_info メソッドとか increment_user_num メソッドとか

そのうち、他の Model を操作するコードとかも増える

長大なゲームロジックのコードも増えだす

今度は Fat Model になってくる問題が

Page 48: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Logic 層の追加

Model からゲームロジックに関する部分を切り出す

複数の Model の操作や、処理順序通りの実行などを行う

Page 49: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

残る課題感

インスタンス化してるけど結局 Func っぽい使い方のクラス

→ クラスメソッドで良いのでは

→ むしろ状態を持つと、状態の遷移を考慮しないといけなくなる

せっかくオブジェクト指向で書いてるのに if文がたくさん!

→ ポリモーフィズムとは

new に連想配列リファレンスを渡して、外から編集したり参照したり

→ カプセル化したい

Page 50: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

もうちょっとオブジェクト指向における指針が欲しい

Page 51: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

特にビジネスロジックに焦点を当てた ...

Page 52: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

今日はなすこと

僕らが開発・運用しているシステムについて

レガシーコード改善の歴史

ドメイン駆動設計の導入

学び

Page 53: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

ドメイン駆動設計とは

厳しい現実の中で、ソフトウェア設計を習得しようと奮闘してきた技術者の物語。不完全な状況の中で、抽象的な設計原則を、現実のソフトウェアに適用するための助言。

日本語版への序文 by エリック・エヴァンス

Page 54: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

バイブル

Page 55: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

より実践的な方

Page 56: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

哲学と戦術

Page 57: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

ドメイン駆動設計とは哲学ドメインモデルユビキタス言語戦術エンティティ値オブジェクトサービスレイヤー化アーキテクチャ

Page 58: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

ドメインモデルとレイヤ化アーキテクチャにフォーカスする

Page 59: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

レイヤ化アーキテクチャ

『レイヤ化アーキテクチャ』による『ドメイン層の隔離』

ドメイン層を他階層と分ける事により、各層の責務を明確化する。

特にドメイン層が隔離されることで、後のビジネスロジックの進化に実装がついていきやすくなる。

ドメイン層にミドルウェアのためのコードやユーザーの入力のためのコードを入れない

Page 60: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

レイヤー化アーキテクチャ

ユーザインターフェース層 ユーザに情報を表示し、ユーザの入力を認識

→ View, Controller アプリケーション層 ドメイン層のオブジェクトを協調させ、作業

の調整を行う

→ Controller, Service ドメイン層 ロジックの表現

→ Domain インフラ層 上位レイヤを支える

→ DAO 。 MySQL, Memcached のスキーマと、ドメインモデルの差異を吸収する。

Page 61: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

やったこと

Domain と Service 層の追加

Domain はドメインモデルを表す

オブジェクト指向におけるオブジェクト (語弊を怖れず言うと )

世界を抽象化した際の物体

Service はドメイン同士を組み合わせた処理

及びそのワークフローを組み立てる

Service は状態を持たない

→既存の Logic 層を Domain と Service に分解していく

Page 62: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

ロジックをDomain と Service に分解していく

Page 63: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

ボスへの攻撃の処理を考えてみる

Page 64: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

ドメインモデルの抽出

「『ユーザー』が『ボス』に攻撃する」 →Domain::User, Domain::Boss の発見 「『アイテム』を使って攻撃する」 Domain::UserItem の発見 「バトルに参加して攻撃する」 →Domain::BattleField の発見

→5W1H でドメインモデルを発見していく

Page 65: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

ドメインモデルの発見

ユーザーとは?→ デッキを持つ→ デッキは 6枚のカードで構成される→ Domain::Deck の発見、 Domain::Card の発見

ボスとは?→期間限定ボス、シングルボス、マルチボスなど種類が存在

する→ Domain::Boss:Scheduled, Domain::Boss::Single,

Domain::Boss:Multi の発見

→ Domain をさらに分解していくと、さらに Domain を発見できる

Page 66: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

「攻撃する」処理

Service::Attack→ 各種ドメインを組み合わせて、「攻撃」時に起こる各ドメ

インの状態を操作する→ユーザーのデッキの HP, ボスの HP, 消費リソースの減少

etc…

サービスは状態を持たない→あくまで状態はドメインが持つ

Service::Attack->exec($user, $boss, $deck, $item, $battlefield etc..);

→サービスのメソッドは引数が長くなりがち…

Page 67: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Service

Service は処理の順番を担保する 攻撃ならば → アイテムの所持チェック → アイテムの消費 → デッキの攻撃力計算 → ボスの攻撃力計算 → デッキの HP減少 → ボスの HP減少 → ユーザーの行動ログの保存etc..

Page 68: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

機能追加の設計をする際にエンジニアが考えること

1. ドメインモデルの発見 →機能について関わる物体 (オブジェクト ) を洗

う。 →洗ったオブジェクトが持つと考えられるメソッ

ドを洗う →Domain::User なら reduce_item,

Domain::Card なら calc_attack 等

2. ドメイン同士の処理の順番を考える ( ワークフロー )

→アイテム消費→ボスの HP減少→味方の HP減少 etc..

Page 69: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

議論になったところ (抜粋 )

Page 70: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

古いコードとの接続をどうするか?

ゲーム共通で使用するアイテム等。

リファクタできる箇所はリファクタした。

できなければラッパークラスを作って隠蔽した(デザパタで言う Adaper )

Page 71: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

Service は状態を持つべきか否か

→今後の機能改修で、 Service が複雑な状態操作をするようになっていくことを怖れて、状態を持たせない

my $service = Service->new(%args); # 必要な User や Boss を渡す$service->exec(); # 実行

Page 72: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

チームメンバーへの理解 新規の機能追加にアサインされたので、まず僕がコードを書

くところから 事前の根回し (オブジェクト勉強会/別プロジェクトの勉強

会等の情報 ) 実装は、ドメイン駆動/実践ドメイン駆動読みつつサグりサグり

もう一人のアサインされたエンジニアには、合意だけ取って まず僕がコード書いて、相方にはコードベースで設計を共有 今思えばあまりよくなかった (口頭/レビューで設計をすり

あわせるべき ) 導入後は、社内勉強会で他のメンバーへ擦り合わせ 僕/相方が関わるプロジェクトでコードがどんどん増えて

いった コードを書く前の勉強会はピンとこない

Page 73: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

今日はなすこと

僕らが開発・運用しているシステムについて

レガシーコード改善の歴史

ドメイン駆動設計の導入

学び

Page 74: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

以下が解決

インスタンス化してるけど結局 Func っぽい使い方のクラス

→ ドメインモデルとして捉えられるものがインスタンス化できるクラス

→ むしろ状態を持つと、状態の遷移を考慮しないといけなくなる

せっかくオブジェクト指向で書いてるのに if文がたくさん!

→ ポリモーフィズムで if を排除 ( これはただのオブジェクト指向 )

new に連想配列リファレンスを渡して、外から編集したり参照したり

→ ドメインモデルをコードに落とし込み、メソッドとプロパティを定義することで、クラスの API が明確に。

Page 75: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

学び

あれ?これは結局ただのオーソドックスなオブジェクト指向じゃない?感

→戦術だけ見てドメイン駆動設計をやり始めると、そうなる→大切なことは哲学の方

ドメイン駆動設計の解釈は人それぞれ。チーム内で認識をすりあわせることが大切

→理論が正ではなく、チームで共有できた認識が最も正しい

Page 76: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

未来

新規機能でドメイン駆動設計を実践する知見は溜まったので、既存のコードも置き換えていっている

実践したことで、設計についてチームで共通認識があるのは良い

要件定義/仕様作成の段階で、ユビキタス言語も取り入れていきたい

Page 77: レガシーな Perl システムに DDD (ドメイン駆動設計)を取り入れる

Copyright © DeNA Co.,Ltd. All Rights Reserved.

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