00:00
ちょっと国明さんに聞きたいんですけど、
単体テストってどこまでモックすればいいかって、いつも迷うんですよね。
外部APIはもちろんモックするかなとは思うんですけど、
じゃあデータベースはとか、あとは他の関数はとか、どこまでモックしていくのかみたいなことが結構毎回迷ってて、
結局ですね、箇所によっては過剰なモックになってしまってないかなというのが若干不安なんですよね。
ここら辺国明さん、単体テストについてどう考えていたりします?
はい。単体テストっていうのはちょっといろいろ定義があるんですよ。
すごく定義が混乱しているので、これは私なりの理解で話すっていうふうな前置きをしておきます。
単体テストっていうのは原則的に全ての関節入出力っていうものをモックします。
この関節入出力っていうのは引数や戻り値以外で振る舞いを特徴づけるものです。
例えばグローバル変数とかファイルへの書き込みってよく皆さんコードで書きますよね。
それってグローバル変数が変われば振る舞いって変わるわけですよね。
例えば関数の戻り値が変わったりとかいろんなことが変わるわけです。
なのでこのテストするときにはその意図した入力によって意図した出力が出てくることを確認しているわけですから、
入力が変わっちゃうと出力が変わっちゃって大変なわけですよ。
グローバル変数とかだから大変なわけですよね。
なのでこういうときってグローバル変数をスタブっていうモックで置き換える必要があって、
例えばファイルへ書き込むときとかにはどんなものが書かれているのかなっていうのをスパイっていうので観測する必要がある。
基本的にはこの関節入出力っていうものを操作したり観測したり、
そのためにすべてモックをするっていうことが大原則です。
それはあれですかね、具体的に言うと副作用みたいな話なんですかね。
関数の副作用で発生する何らかだったり、あとは環境要因のところだったりっていうことなんですかね。
副作用は関節の出力の部分ですね。
グローバル変数とかが操作しちゃった、戻り値以外にその状態を変えちゃったとかっていうのが副作用って言われていて、
これが関節出力にあたります。
他の関数とかがグローバル変数書き換えちゃったって場合はこれ関節入力にあたりますね。
今まで期待していた状態が変わってしまったっていうのが起こってしまうので、
こういうものは大体全部単体テストではモックするということになります。
そう聞くとなんかもうほぼほぼ全てモックするんじゃないと思っちゃいますけど、
それは間違ってはないっていう話なんですかね。
これはちょっと面白いんですけど、例えばフィズバズ関数を例に話をしていきましょう。
フィズバズ関数のまず副作用がないバージョンから話をしていこうと思います。
フィズバズ関数っていうのは例えば1を与えると文字列で1が返ってくる。
2を与えると文字列Dで返ってくる。
3を与えるとフィズが返ってきて、5を与えるとバズが返ってくる。
そして15を与えるとフィズバズが返ってくる。
こんな感じの関数ですよね。
これって数字を与えると文字列が返ってくるっていう純粋な関数なわけです。
これってモックする余地がありますかね。関節入力が全くありません。
03:03
ないですよね。
そうなんですよ。なのでモックする余地ないんですよ。
これが一番テストが簡単な状態です。
単に呼び出すだけですから。
純粋な関数と呼ばれるものですかね。
そういうことです。
ここから例えばユーザーが入れた数字をコンソールに書き出す。
ユーザーが入れた数字をフィズバズ関数で通してコンソールに書き出すみたいなことを考えると
これがだんだんモックが必要になってきます。
っていうのはユーザーがどんな入力をするかってわからないですよね。
それを標準入力とかから受け取らなきゃいけない。
ここの標準入力に何を与えればいいのかっていうときに
だんだんと関節入力が見えてきます。引数じゃないですよね。
そうなるとここにスタブっていうものを用意して指してあげる必要がある。
問題なのは、じゃあフィズバズ関数がユーザー、お客様から入力を受け付けるバージョンにしたら
あっという間に関節輸出力が増えてしまったってことが今回の問題なわけで
ここからすごく大事なことが透けて見えます。
どうしても関節輸出力ってできちゃうんですよ。
できちゃうんだけど、これを持ってるオブジェクトと持ってないオブジェクトに分離するってことをすると
テストが簡単な部品とテストの難しい部品っていうのに分けることができますね。
なるほど。確かに。
一つだと全部テストが難しかったっていう状態だったのに
分けてあげるとテストが簡単な部品が出てくるっていうことが見えてくるわけです。
すごい雑な例を挙げると、メイン関数、多分これ聞いてる人たちの中でも
初心者の頃には絶対に書いたことあるだろうなと思うんですけど
メイン関数に全てをぶち込む。
あれっていうのは確実に複数作用もあるし
関節輸出力というのがいっぱいある関数なのですごくテストがしづらい。
モックをいっぱい書かないといけないというようなところですかね。
そうです。そういうふうな関数はよく最長不等関数とかって言い方をしますけど
そういうものっていうのはすごくテストが大変なので
モックがある時っていうのは、つまり実は設計、分割の仕方に問題があるってことを示唆してるんですね。
なるほど。単体テストの問題ではなくて
モックしづらいなというか、これモックめちゃくちゃ悩むんだけど
ここまでやっていいのかなみたいなのはそもそも設計が悪いですよっていう
警告信号が出てるよみたいな感じなんですね。
そうですね。よくスメルって言い方をしますけど、本当に設計のスメルが出てるというような状態ですね。
スメルは匂いってやつで、要するに臭いというわけですね。
めちゃくちゃわかりやすいですね。その信号。
基本的に何かモックがめちゃくちゃ必要だなっていう時は
自分の設計が間違ってるかもしれないってことを疑ってください。
これがすごく大事なコードからの助けてって声なんですよね。
何かモック必要になっちゃってるんだけど設計が間違ってないとかっていうのを
ここ本当は副作用を分離できるオブジェクトがあったりしていいっていう風なのが
コードが叫んでるわけです。それをよく聞いてあげて設計を分けてあげると
簡単にテストが簡単な部品とそうじゃない部品に分けることができるので
06:00
全体としてはテストが簡単になるわけです。
何かそのコードが叫んでるっていうのはちょっと面白い表現かなと思って
国分さんどういう立場で叫んでるんですよみたいなこと言ってんのかなっていうのを
若干面白かったなと思うんですけど
そういう3位を見逃さずにちゃんと分割しましょうねっていうようなお話ですね。
そうですね。ただ何でもかんでも分割すればいいっていうわけじゃないんですよ。
例えばさっきのメイン関数にいっぱい書いてるのを一行一行関数にして
LINE1関数、LINE2関数みたいなのをしたら別にそれは何も嬉しくないわけです。
そうですよね。
なのでちょうどいいところでちょうどモックが少なくなるようなところで分割してあげるってことが
すごく大事なポイントになってくるんですね。
なるほど。じゃあ分割にも思想というか設計があるよというようなお話で
その指針となるのがテストの書きやすさ
モックができる限り少ないような形で分割するとより良くなるよという話なのか
おっしゃる通りです。
なるほど。確かになんとなく経験則上もそんな気がするなという気がしますね。
なんかこの関数っていうかここの部分はすごい書きやすいんだけども
ここの部分はちょっと書きづらいなっていうのが設計から見て取れるみたいなのは
かなりわかりやすいところかなと思うんですけど
その時にじゃあどういう形で実際に具体的な
もし例があったらわかりやすいかなと思うんですけど
こういう分割方法あるよみたいなのあったりするんですか?
さっきのフィズバズ関数にしましょう
フィズバズ関数はユーザーから標準入力から何か数字を受け取って
標準出力にフィズバズなり数字なりを返すっていうふうなものがあったとします
こうするとこれ3つのパーツに分けることができます
一つはユーザーが入れた部分その数字なりは
ABCとか入れられたったら数字じゃないんで弾くとかっていう部分がありますね
これが入力を担当するコンポーネントです
こいつは関節入出力を直接出力に変えてあげるという役割を持ちます
そうするとユーザーが標準入力にAとかBとか打ったりとか
1とか2とか打った時にちゃんと数字だけが返ってくるよね
そうじゃないものはエラーで弾いて後ろに通さないよねっていうことを責任とする
まず入力部分になります
そしてその入力部分から受け取った数字っていうのをフィズバズ関数
さっきの整数を受け取って文字列を返す関数に組み合わせて
最後に標準出力に書き出す部分ですね
数字がもらったら標準出力に書き出す部分でこの3つのパーツに分けると
2つはそれぞれ関節入力が必要
もう1つは関節出力が必要なんだけど
真ん中のフィズバズ関数には関節入出力が全くないって状態を作れますね
なのでこれが嬉しい状態ということです
なるほどじゃあコンポーネント単位でちゃんと分けましょうねっていうのと
あとコンポーネント単位でちゃんと責務を分割しましょうという話ですね
設計原則としては
1つその責務の多さっていうのを見分ける指標があります
09:02
それはすごく簡単で直接入力出力の数と関節入出力の数
これを全部合算するっていうのが大体責務の大きさを示すパラメータになります
なるほどじゃあ依存しているものの数ですね
そうですね依存しているものの数もあるんですが
引数とか依存してないものとかの数も含まれているので
単純にその入出力の規模空間がどれくらい大きいかっていうことだと思う
なるほどじゃあそれを数え上げていって
ちょっと多すぎるよねみたいなのになったら責務として大きすぎるっていう話になる
それって見分けるツールとか実際あったりするんですかね
例えば前回話した林島だと言語によっては引数の数が多すぎると林島で起こるみたいな
あったりすると思うんですけどそれが該当するんですか
それも該当しますね引数の数もそうだし
あとはもう一つ今言ったのは一つ簡単な見分け方ですね
入出力の規模大きさを示すものもう一つはサイクロマティック複雑度と呼ばれているものがよく使われていて
サイクロマティック複雑度って要するに関数とかを一つ入れると数字がポッと出てくるんですね
これが大きいほど複雑であるってことを示すんですけど
この複雑であるっていうことは一体実はテストと関係があるのでこの話をしています
これ実はテストケース必要なテストケース数の条件を与えてるんですね
なるほどサイクロマティック何でしたっけ複雑度
これはC1っていうモーラ率があってこれは分岐モーラと呼ばれているものですね
ifの方前の部分を通るのとalesの部分を通る全部の通り方を取りました
そうすると100%になるのがC1と呼ばれているものです
このC1をモーラを達成するテストケース数ってのがありますね
例えばif文が中に1個だけある関数があったとしましょう
そうするとそこにifの部分とalesの部分があるからこれは2本テストケースが必要なわけです
なのでサイクロマティック複雑度は大体2ぐらいです
というふうにものがあってこれがあんまりに増えすぎるとテストの数が増えていくのがわかりますね
テストが大変になってくるわけです
そうするとやっぱり何かおかしいぞ設計おかしいぞもっと分割してっていう悲鳴が聞こえるってことなわけですね
それはあれですかねカバレッジ率でしたっけっていう単語でも表現されるというか
よくテストのレポートとかに書かれるやつあるかなと思うんですけどそれが該当思想なんですかね
そうですそれが該当します
カバレッジってすごく皆さん嫌な思い出がありませんか
カバレッジ80%達成しろって言われて
実装は1日で終わったのにテストに3日かかってるみたいなとかってありませんから
12:04
単純にテストコードの方が多くなる率高いので大変ですよね
大抵めっちゃモックしませんか
めっちゃモックする
これは実は何がいけなかったかっていうと本体の設計のまずさをテスト側でカバーしてあげようとするからこういうことが起こるんですね
ちょっといびつなんですねじゃあ本当は設計を直せばテストはもっと書きやすくなって
テストコード自体もスッキリするのに設計のところあの臭いところに蓋をしてテストで頑張って根性によるカバーをしようとしている状態
そうだからモックがめっちゃ必要でモックってそのモック準備するコードがいっぱい必要じゃないですか
例えばあのモックイットとか使った時とかってこれこれが与えられた時にこれをリターンするみたいなとか全部そのテストのセットアップ部分で入れますよね
あれめっちゃ大変ですよね
レール図とかだとRスペックのヘルパーとかにいっぱい書いてあるんですけど
モックの設定とかが大体どれが読み込まれているのかわからなくなるんですよね後々かなり大変です
Rスペックのヘルパーの悪いところですね全てを隠してしまう
RスペックRスペックなりの思想があるのでそればっかりが悪いばっかりじゃないんですけど
後から見た時の理解のしやすさって意味ではちょっと不利な選択ですね
ちなみにさっきちょっと話戻ってサイクロマティック複雑度ですかねそれって何か出すツールとかってあったりするんですか
はい例えば今話してたRubyだとRubocopっていう静的解析リントが有名だと思うんですけど
Rubocopは確かサイクロマティック複雑度でこれを超えると警告するみたいな感じの設定をかけたはずですよ
なるほどじゃあリントに組み込まれてるものなんですね
組み込まれてます
リントとテストとりわけその単体テストに関してはかなり密接というか結構関係する間側にありそうですね単体テストは
そうですねはい
ちなみにちょっと話変わってその単体テストってさっきのカバレッジの話にちょっと近しいんですけど
なんかいっぱい書けばいっぱいいいみたいないう世界線とちょっと違うなぁと思ってて
そのカバレッジを100%にたどり着ければいいっていう話じゃないかなとも若干思ってて
でいっぱい書けば書くほど次辛くなるのってリファクタリングした時になんかテストがいっぱい落ちてしまったとか
でこのテスト本当に意味があるのかなみたいなの結構経験則としてあって
このテスト落ちてるけど別にいいんじゃねみたいなじゃあ削除するかみたいなとか結構ありがちかなと思うんですけど
そこら辺との単体テストの関係性とかってなんかあったりするんですか
はいここはめちゃくちゃありますこれはですね
15:02
単体テストを消されちゃうんですけど消してるってことは既存の振る舞いのこの部分がいらなくなったよっていうことなんですよね
だから実はいろんなコンポーネントの部品の仕様コンポーネントに一個一個クラスとかに仕様って書きますよね
JavaDocみたいなのとかで書いたりとかあと例えばPythonとかのDocsRingっていうので
ちょっと上のところに3つこうダブルコート入れてなんかこの関西こんなことやる関西ですよみたいな書きますよね
あれが全部そのコンポーネントの仕様にあたるものであれが実はテストしているものなんですけど
それがいらなくなったそれをめちゃくちゃ変えたハチャメチャに変えたということなんですね
でそういう時にテストが真っ赤になるってのはその通りでそれだけ既存の振る舞いを壊しちゃったっていうことなんですね
これ自体は別に悪いことではないですちゃんと壊れてるってことを教えてくれてるわけですから
ただ問題なのは壊れちゃったなんでこんなに壊れちゃったの他に方法はなかったのっていうことが一番大事なわけです
実はここからもちょっと見えてくるものがありますね何かやっぱり分割の仕方を間違えてるんじゃないかっていうところに行き着くわけです
それはあの既存の設計側ですかねそれともリファクターした結果側ですかね
それは既存の設計ですねでこれはどう捉えたらいいかというとよくそのオブジェクト思考とかの原則で拡張に対して開き変更に対して閉じろっていうふうな格言がありますね
これはオープンクローズプリンシプルと言われてるやつで有名なオブジェクト思考の設計原則の一つです
これはテストから見るとすごくシンプルな原則になっていて何か変更したくなった時にテストケースをいっぱい変更したくなるような設計はダメだぞって言ってるんです
なるほど
これはテストケースを変えないで変更が振る舞いが変わるそしてでもそんなこと言ったら機能追加できないじゃないですか
あれ機能追加したいのに振る舞い変えちゃいけないってことはどうしたらいいんだってなっちゃいますよね
ここに面白いのがあって実は新しいコンポーネントを追加してそいつに差し替えるだけで動くっていうにしてあげれば既存のテストケース何も壊れないじゃんっていう考え方がこのオープンクローズプリンシプルなんです
なるほどじゃあもうガバッと変えちゃえばいいじゃないかという話なんですね
そのコンポーネントが振る舞いが変わるのであれば名前もちゃんと適するものをつけて設計し直して差し替えできるような形を保ってると一番健全だよというような話なんです
そういうことです
でよくこういうふうに言うと伝わりやすいかもしれませんね
あるオブジェクトの一部だけを変えたいってのは一体どういうことなのかってことだけですよ
例えばさっきのフィズバス関数の4の時だけ例えばホゲホゲみたいな感じにしたいっていうニーズがあるとすると一体これは何なんだって話なわけですね
それって実はこういうふうに変えたい部分が存在するってことは実はそこの部分を切り出していればそこの部分の交換で済んだわけですね
4って部分だけを判定して出力する関数が1個あったとしましょうそしたらそこの部品の交換だけで済んだはずですね
18:01
というふうに実は変更したい箇所が一部だけだってことはもっと分割できるよっていうスネルなんですよ
なるほど
とはいえあれですよね最初から1の関数2の関数3の関数4の関数みたいな形で最初から分割できているともあんまり思えないんですけど
無駄な分割かなと思うんですけどそこの辺の何かこう何でしょうね分岐みたいなのあったりするんですか
えっとこれがすごく難しくてえっとそうですね
仕様にいくつかのレイヤーがあるっていうのを意識すると伝わりやすいかもしれませんね
えっとこれちょっとすごく難しい話なのでちょっと丁寧に追っていきたいと思います
はいえっとまず仕様っていうのはレイヤーがあります
例えば我々が普段よくエンドツーエンテストとかで書いている仕様ってありますね何かユーザーがウェブ画面のどっかのボタンをクリックする
そうするとある画面が表示されてそこでまたそのボタンをクリックするとかっていう
こういう風な仕様のトップレベルの仕様って言い方をしていてこれは要するにユーザーに見える仕様です
でそれに比べると例えば先ほど言ったJavaDocとかPythonのDocstringとかに書いている
その小さなクラスの仕様とかっていうのはユーザーには見えてないわけですよね大抵
これはコンポーネント仕様ってなってる仕様一番下のレイヤーの仕様です
でこのコンポーネント仕様っていうのはちっちゃく仕様と思えばいくらでもちっちゃくできるわけですよ
例えばさっきのFizzBuzz関数で言うと1だけを扱う関数とか2だけを扱う関数っていうのが
でこういう関数をいっぱい作ることは全然できるんですね
ただそうすると仕様をこの1っていう関数を呼び出すだけのちょっとコンポーネントが何個かくっついた仕様っていうのも考えることができて
こういう風な仕様っていうのはいっぱい考えなきゃいけないですね中間の仕様っていうの
この中間の仕様がいっぱい出てくるとすごく大変になってくるわけです
その度に結合テストを書かなきゃいけなくなってしまう
なのであんまり変なくっつき方するようなのは作りたくないねっていうのがあって分けすぎるのもよくないねってことなんですね
なのでこのどれだけくっつけて意味のある仕様にできるかっていう部分のレイヤー数をある程度小さく保つってことがすごく大事です
なるほどもちろん現実世界何らかのプロダクトサービスを作る上での目的におけるプログラミング言語を使って実装してるわけですから
現実世界の何らかの課題を解決するサービスのそういった仕様っていうのももちろん紐づいてくるかなとは思うんですけど
そこが変わったら結構ガラッと変わりそうなのでね一番小さいところの仕様に関してもコンポーネントの仕様に関してもそういったところもあるが
そういったところを加味しつつちょっと未来見据えつつどういう分割方法がいいかなっていうのは
そのプロダクトごとサービスごとに適切なものを考えていくっていうのが重要だよねっていう
21:00
めちゃくちゃ重要で特に私が何かを設計するときに必ず聞くのは1年後の展望は何ですかとか3年後の展望は何ですか
どんな仕様を入れる可能性がありますかということを必ず聞きますそれによって拡張ポイントが変わってくるんですよ
全然違いますよね
でも結構よく設計を見ていると今の課題は何かってだけにフォーカスしちゃってる人たちがすごく多いと
そうするとやっぱり本当はこの部分だけ変わるかもしれないっていう部分の設計の築きっていうのを見逃してしまうんですね
なので未来にわたってこういう変更があるかもしれないっていうことのその精度を高めておくことってすごく大事ですね
いい設計をする上でそれが実は設計においてめちゃくちゃ重要な要素の一つなんです
一番最初開発を始める前もしくは新しい開発を始める前にどういう展望校のこれからの将来性のビジネスとしてこういうことをやっていきたいみたいなのが
おそらくそんな確実なものを求めているわけではないとは思うんですけど
こういうことを考えているフワットレベルでもいいのでそういうのがあると
本当に一番細かい例だと単体テストができる設計にまで影響を及ぼしかねないというようなことなんですねそこのビジネス要件が
これはすごく重要な原則なんですけど設計っていうのはいつだって賭けなんですよ
それは未来にこういうことがあると思うだからここに拡張ポイントを作っておこう
これは負ける時と勝つ時の両方がありますね
勝つ時は未来その予想が当たって確かにそこの仕様が変わったと時に部品の交換だけで済みましたこれは大勝利です
なんですけど負ける時あります実はお客様本当はこういうの必要だと思ってたんだけど実は違うのが必要だったんだよっていうことが後で分かっちゃって
賭けに負けることがありますつまり用意しておいた拡張ポイントが使われなかった
すると無駄な複雑性を持ち込むだけということになりますね
なのでこれは負けたということになります設計ってのはいつだってこういう博打なんですよ
なので一番大事なのは勝率を高めることですなのでいろんな良い情報その経営者がどういうことを考えているのかなとか
そういうところからここに拡張ポイント入れておいた方が良さそうだなっていうところを指して作っていくっていうのが実は設計ですごく重要な部分です
それが単体テストで色々真っ赤にしないための秘訣なんですね
なるほどちょっとかなり単体テストの話からすごいもう何でしょうね
エンジニアとしての在り方というか普通にビジネスマンとしての在り方みたいな話になってきたかなと思うんですけど
とりわけエンジニアとして責務を負ってるわけですよね我々は
そのプロダクトをより良いものを作っていくそして将来に渡ってセキュリティだったりとか拡張性も持たせる
24:02
技術的不採用をできる限り残さないように拡張できるようにしていくというのが我々エンジニアの責務だとしたら
ちゃんとそのビジネス要件的なところはなるだけ把握しておかないとそもそもお仕事できませんよねという提言でもありそうです
本当にその通りですだから実はそのリファクタリングというか機能追加とかで単体テストが真っ赤になってしまうってことは
あなたは賭けに負けてますってことを単体テストから突きつけられてしまってるんですね
いやなんかこれ聞いてる人の中でも耳痛い人いるんじゃないかなと思いますね本当に
いやさっき国明さんが言ってくれたその今のことにのみ集中してしまうというのは結構ありがちかなと思ってて
本当にこの案件をできる限り早く終わらせることに集中するみたいなのは穴がち間違いではないと思うんですけど
とはいえこれが2年3年続くサービスなのであれば絶対的に未来の設計みたいなところは絶対見ておかないといけないというところですね
はいおっしゃるとおりです
じゃあ今やっぱ単体テストを書いてて書きづらいなーっていうのは本当にもう設計が悪いよというような話なので
今すぐその設計のところから見直した方がいいよっていうお話ですね
そうですねでこういうふうなことを私はよくいろんな人に言ってですね単体テストつらいんだよって言われた時には設計がだいたいまずいんですよ
設計のスメルが見えてるんですよって話をよくするんですねこうすると必ず言われることがあります
じゃあどうやってそれを解消していけばいいんですかってことを必ず聞かれます
そうですよね
あれがですね遠い道のりなんですよ
なるほど
一度この状況になってしまうとすごく遠い道のりになるんです
でまず最初にやらなきゃいけないのはだいたいそういう現場ってその単体テストが不十分だったりだとかすることがあるんで
そして仕様もわかってないってことも結構あるんでまずは仕様化テストっていうのを書いてその仕様がどうなったのかってことを発掘してですね
そこの上にリファクタリングっていうのはちょっとずつかけていってっていうのをやっていくんですけど
リファクタリングするとさっき言ったように単体テスト最初はめっちゃ壊れちゃうわけですよ
だから最初は単体テストをほとんど消しちゃって結合レイヤーのテストだけ残してとかっていうのはなんかすごい遠い道のりが長い道のりがあるんですね
なのでこれを端的にこの30分間とかいう時間で説明しきることがなかなか難しくて
おすすめの本だけ紹介しておきます
おすすめの本はレガシーコード改善ガイドという本があります
レガシーコード改善ガイド
改善ガイド帯にすごくいいこと書いてあるんですよ
テストのないコードはレガシーコードだって書いてあってて実は隠れたテスト本なんです
なるほど
ちなみにその中ではどういった具体例なんですかねなんかここ良かったよポイントとかってあったりしますその本
一度テストとかに苦しんだことある人は目次だけでグッとくると思います
27:02
目次の中にもうどうしたらいいかわかりませんみたいなことが書いてあるんですよ
切実
そう切実もうこれ以上嫌だみたいなこととかが目次のどこら辺だったかなーにあって
それとか見るとこういう風にやっていくといいんだよっていう風なのがすごく親切にその道が書いてあるので
ぜひそのテストとかに悩んでる方はレガシーコード改善ガイド読んでみるといいと思います
これを聞きの方は概要欄の方にAmazonのリンク貼っておきますのでそちらからちょっと見てみてください
レガシーコード改善ガイドですね
そうです
ありがとうございます
ちなみに今の本の話でもあった通りテストがないコードっていうのはレガシーで全てレガシーであるという話である通り
テストって絶対書かないといけないものなんですかね
それはすごくいい質問ですね私はテストが書かない方がいいっていう状況はあると思ってます
例えば書き捨てのプロトタイプのプロジェクトを買っている時にそれもなるべく小さなものであればテストを書かない方がむしろ生産的だと思います
実際に動かして試してみる方が早いんですね
なんだけどそれが例えば長い間保守されるとかっていう時につまり書き捨てじゃなくなってしまった時とかは
ここの振る舞いってどうなんだっけとかって忘れちゃいますよね
そういう時にはテストがドキュメントとして残っていてほしいってことはあるんですけどすごく短期の寿命のプロダクトだったりする場合は
テストを書いてる時間があるんだったらその書き捨てのプロジェクトをプログラムをより良くしていく方に時間を使った方がきっといいでしょうね
そういうとさっきテストというのは設計が良い設計になってるかどうかっていうのを確認する術でもあるかなと
あれ聞いてて思ったんですけど書き捨ての場合は設計云々よりもそのプロダクトに価値があるかどうかの検証の方が最優先事項だから
設計よりかは作ってフィードバックをもらう方が重要だよねっていうようなところですかね書き捨ての場合は
そういうことです書き捨てのやつにプラグイン機構とか作るのってしょうがない なんかありえないじゃないですか
不意味わかんないですよ プラグイン作っていたら何するんだっていう話になるわけですね
そういうものは直接書いちゃった方が早いわけですよそういう風な設計して分割するポイントを作っておくってことはほとんど損なわけですね
無駄な複雑性を持ち込むことにしかなってないっていうのがあってでやっぱり設計ってその未来に向かってのその賭けっていう
未来に生きる生き物なんですよね設計って常にだから未来のないプロダクトって言い方変かなすごく短期でその寿命を終えるプロダクトっていうのは
やっぱり設計とかよりかはそのプロダクト自身の価値を磨くって方にきっとシフトした方が私は有益だと思っています
他にテストを書かない方が良さそうな例とかあったりするんですか
えっとですねちょっとそのバリエーションその短期のバリエーションなんですけど書き捨て以外にもありますえっと半死半生のプロジェクトで1ヶ月後にこのプロダクトが残ってるかわからないみたいな状況のプロジェクトってよくあるじゃないですか
30:12
ありますそういうところでいい設計を作ろう単体テストで住めるを築けるようになろうっていうことなんてしてる場合じゃないですよね
ないですね何とかしてお客様に少しでも喜ばれるそのコードを追加して多少バグがあったとしてもですね
追加してそれで収益を伸ばしてその生存ラインに生き延びるってことが大事になってくるわけです
その時にはテストとか設計とかそんなこと言ってる暇ではない暇ない感じになると思いますね
そこからじゃあそういったプロジェクトがあったとしてKPIとかを無事達成してその後も残り続けることになりましたと
でその時点ではテストももちろんないわけですよねでもちろんその設計も良くないというか最短経路でいったので
まあまあな歴として存在するとただ今後2,3年ぐらい続きそうという未来が確定した瞬間から
さっき言っていたそのじゃあどうしようか設計どうしようかというところの議論をしっかりしていかないといけないというフェーズに入っていくんですかね
その通りですこれをすごく良い言葉で表した人がいるんですね技術的負債っていう言葉でこれを表現しました
今のって先に前借りしたんですね未来の未来に苦しむかもしれないけれどお金を前借りしてプロジェクトを生き延びさせて
その間に一発当てるんだってことをやろうとしたわけですよ前借りなわけですよね
それで負債を積んでそれで生き延びたらラッキーなわけですよそうするしかね方法はなかったわけですから借金をして生き延びた
そうしたら借金返済が続いていくっていうのはその通りですねただその借金をしなければ生き延びられなかったわけだからそれは必要な経費だけですね
逆に言えばそうなったらちゃんと設計のことについて議論しましょうというお話でもありますよね
はいその通りですそこからだんだん始まっていきます
なるほどエンジニアリングが始まっていくんですねどんどんここから
そうやっぱり未来があるって分かった瞬間に設計が始まるんですよ
じゃあその未来に何を描くんだどこに拡張ポイントを入れるんだって話が出てくるわけですから
そして過去の負債ですね過去にペタッとモノリスみたいに作っちゃったそれをどうテストできる状態にしていくかってことが大事になってくるので
そこでやっと設計の話が始まるわけです
なるほどすごい単体テストそのお話というよりかはやはりもう本当にどれだけ未来性があるか未来が予測可能ではないからこそ不確実性が高いプロダクトこそできる限りの設計を頑張ってして
未来にも生き残りやすい単体テストを書きやすいものをやっていく設計にするのが一番プロダクトにとって重要っていう話ですね
かなり重要な話かなと思いました今全然こんな結論になるなぁとは全く思ってなかったので単体テストの話をした時には設計が重要という話です
33:08
ちなみにこのテストの話ってかなり膨大かなと思うんですけど何かこうまだ話し足りないところとかってあったりするんですか
いやー実はさっきスタブとかあのスパイって話をしましたよねでなんかあれスタブスパイそんな聞いたことないぞ
モックランじゃないの全部モックランじゃないとかっていう話あったと思うんですよ俺に実はこういうふうなものを定義も実はまた混乱していて
その中の定義の一つを私は取り上げたんですね他のやつとかもちょっと興味あったりしませんかっていうのは話し足りない部分ですかね
なるほどじゃあちょっとそういう細かい部分の話は次回ですかねちょっと3回目にちょっと取っておきたいなと思いますので
いい時間になりますのでちょっと今回ここまでにしたいなと思いますなんか最後国明さんの単体テストのここまでの話の中で最後に言いたいことありますか
そうですね私の今までの話の中に多分難しかったことがあると思います仕様とかの話はすごく難しかったんじゃないかなと思うので
ぜひあのここわかんないこれがどうなのとかってことはぜひお便りとして来ること私はすごく皆さんにお願いしたいです
ぜひあのわからないところとか仕様どうしたらいいのとかテストってどうなのとかって話をお便りとしていただければ私ぜひそれ回答したいのでよろしくお願いします
はいありがとうございますということで今回はここまでにしたいと思います
もっと詳しく教えてくださいラジオ略してクワラジではスーパーエンジニアである国明さんに一般エンジニアであるヘンテコが技術的な質問をしていく番組になっています
今後もですねいろいろなことをお聞きしたいなと思ってますのでお聞きのプラットフォームで高評価やフォローの方お願いします
また先ほど国明さんからあった通り国明さんにこんなことを聞いてほしいみたいなことがありましたらコメントいただけると取り上げたいなと思いますのでよろしくお願いします
Xなどでハッシュタグクワラジでつぶやいてもらって大丈夫ですので感想もぜひぜひお願いします
それでは今回もありがとうございましたありがとうございました