テストを書いてからリファクタリングなんてのは幻想

このエントリーをはてなブックマークに追加
1デフォルトの名無しさん
テストを書いてからリファクタリングするというけれど、
コードの内容によっては、それが現実的に不可能な場合がある。

汚いコードであればあるほど、リファクタリングの前に
テストを書くのは難しくなる。

テストが書けるのは、単機能の関数になっているものだけ。
1000行以上からなる複数の処理を行う関数などテストを先に書くなんてまず不可能。

テストを書くためには、コードの再配置を先にやらなくてはいけない。
コードの順番を変えたりモジュールに分離するなどして、小さな処理にまとめて関数化する。
そこまでやってやっとテストが書ける。

現実的な修正の順番としては

コード再配置 → テストコード記述 → リファクタリング

にならざるをえない。

コード再配置はテストがない状態で行うから非常に神経を使う。
ミスを起こさないような再配置しかやってはいけない。
2デフォルトの名無しさん:2012/10/03(水) 00:29:16.55
See: Working Effectively with Legacy Code
3デフォルトの名無しさん:2012/10/03(水) 03:59:19.12
このスレッドは天才チンパンジー「アイちゃん」が
言語訓練のために立てたものです。

アイと研究員とのやり取りに利用するスレッドなので、
関係者以外は書きこまないで下さい。

                  京都大学霊長類研究所
4デフォルトの名無しさん:2012/10/03(水) 14:23:07.28
>>1
> 1000行以上からなる複数の処理を行う関数などテストを先に書くなんてまず不可能。

そうでもないよ。


================================== 終了 ===============================
5デフォルトの名無しさん:2012/10/14(日) 16:37:35.20
関数をリファクタリングするのは簡単だが、
明らかに関数になってない処理、
つまりいろんな手続きのあつまりを修正するのは難しい。

なぜなら、その処理の集まりを実行すると
何十もある状態(データベースなどの値)が一気に変化するから。

関数に値を数個入れて、一個の値を返すのではなく
何十個も値を入れて、何十個も値を返すという状態になってる。
そんなものにどうやってテストコードを書くのか。

こういうのはテストコードを書く前に、処理の集まりの中から
関数になる部分を抜き取るという作業になる。

抜き出した部分にテスト書くことはできるが、
処理の集まりの方に、テストを書くのはまず不可能。
6デフォルトの名無しさん:2012/10/14(日) 17:42:49.53
関数 {

 ここからAの処理
   :
   :

 ここからBの処理
   :
   :

 ここからCの処理
   :
   :

}
こういうのはリファクタリングしやすい。
7デフォルトの名無しさん:2012/10/14(日) 17:44:07.73
でも実際には、こうなっている。

関数 {
 Aの処理その1
 Bの処理その1
 Cの処理その1

 Cの処理その2
 Aの処理その2
 Bの処理その2

 Bの処理その3
 Aの処理その3
 Cの処理その3
}
8デフォルトの名無しさん:2012/10/14(日) 17:49:11.03
もちろん、どの行がどの処理かってのはわからないから
見た目にはこう見える。

関数 {
 処理そのa
 処理そのb
 処理そのc

 処理そのd
 処理そのe
 処理そのf

 処理そのg
 処理そのh
 処理そのi
}

9デフォルトの名無しさん:2012/10/14(日) 17:49:52.99
>>8のような感じのコードが数千行になっており
仕様も存在しない、書き方も冗長でよくわからないコード

それを綺麗に処理ごとに関数にリファクタリングするのは
すごく大変だということがわかるだろう?

テストを書く前に>>8の状態から>>6の状態に
する必要がある。そうしないと何を関数に分離できるかわからない。
10デフォルトの名無しさん:2012/10/14(日) 17:53:01.93
>>8の「関数」のテストを書けばいいだけと思うかもれないが、

「関数」がどんな処理を行なっているかは明確に書かれていない。
データベースの何かの値を読んで、なんかの値を返す。
そしてその他のサーバーとも通信している。
ファイルにも保存する。

徐々に機能が追加されてしまっており仕様がない。
入力となる組み合わせもデータベースのいろんな状態を考慮するために
こんなので全体が何をしているかのテストを書くのは不可能。

11デフォルトの名無しさん:2012/10/15(月) 11:19:25.44
>>10
> こんなので全体が何をしているかのテストを書くのは不可能。

そうでもないよ。


================================== 終了 ===============================
12デフォルトの名無しさん:2012/10/15(月) 11:24:01.39
反論できないのを見るとすっきりするなw
13デフォルトの名無しさん:2012/10/15(月) 13:05:35.58
>>12
キミがテストなんか書けないと思ってる関数さらしてごらん。
俺がテスト書いてやるから。
14デフォルトの名無しさん:2012/10/15(月) 15:10:45.67
>>13
じゃ、これ
http://www.pro.or.jp/~fuji/mybooks/cdiag/cdiag.10.1.list

テスト書く前に修正はしないようにねw
15デフォルトの名無しさん:2012/10/15(月) 15:22:46.82
>>14
マジで、この関数のテストどう書けばいいかわかんないの?
超簡単じゃん、これ。書き方が下手なだけで、記述が冗長になってるだけ。

・システムコール以外の関数のスタブを準備する
・扱うファイルのフォーマットがわかるなら、そのファイルを準備する
・フォーマットがわからないなら、システムコールと同名のスタブを準備する
・コンパイルして実行できるmainあるいはxUnitのコードを書く
・全部の(をめざして)return文を実行するようなテストを書く
・全部の(をめざして)if-elseを分岐するようなテストを書く
16デフォルトの名無しさん:2012/10/15(月) 15:23:43.32
>>15
口より手を動かす。

自分で書いてやるといったのだから、
言い訳せずに書け。
17デフォルトの名無しさん:2012/10/15(月) 15:25:16.96
言っとくが修正が終わったものを持ってくるだけじゃだめだぞ。
ちゃんと先にテストを書いたことがわかるように、
修正前のコード+テストの状態のものを持ってくること。
18デフォルトの名無しさん:2012/10/15(月) 15:26:01.91
つか、まさかとは思うけど、『レガシーコード改善ガイド』読んでないとか?

読めよw
19デフォルトの名無しさん:2012/10/15(月) 15:27:04.34
>>16
ヘッダファイル準備しろよ。そしたら実コード書いてやる。
20デフォルトの名無しさん:2012/10/15(月) 15:34:36.31
>>16
このコードが意味不明なのだから
先にヘッダファイルが用意できるわけがない。

リファクタリングしなければ、ヘッダファイル
(何を関数にするか)判断できないだろ。

今お前はテストの前にリファクタリングを要求したんだよ。
21デフォルトの名無しさん:2012/10/15(月) 15:35:18.81
>>16
というかさぁ、キミは>>15の6つのステップを実行できると思うの?思えないの?
実行できないと思えないのはどのステップ?
それはなんで実行できないの?
22デフォルトの名無しさん:2012/10/15(月) 15:38:07.18
>>20
> このコードが意味不明なのだから
> 先にヘッダファイルが用意できるわけがない。

ちょっと何言ってるかわからないよ。
リファクタリングの定義知ってる?
動作するものを、その振る舞いを変えずに構造を変えることだよ。
つまり、ビルドできるものが前提。

ヘッダファイルが用意できないのなら、リファクタリングはおろか、ビルドもできないよ。

> リファクタリングしなければ、ヘッダファイル
> (何を関数にするか)判断できないだろ。

ヘッダファイルがなんなのかも知らないの?

関数宣言が入ってたり、構造体の定義が入ってたりする奴だよ?
23デフォルトの名無しさん:2012/10/15(月) 15:41:19.98
もっと具体的に書かないとわからいのかな。

PSEND_CONDITIONとかSYS_PAGE_HEADの定義や、MakeSendMountDevice()の宣言が書かれたヘッダが必要。
じゃないとコンパイルできないじゃん。
24デフォルトの名無しさん:2012/10/15(月) 15:41:21.69
> それはなんで実行できないの?

テストを書くと時間がかかるので、メリットが
相殺またはマイナスになってしまうから。

たとえば数値を+1する関数にいちいちテストは書かない。
これを間違える可能性は極めて少ないから。

本気でやるのならテスト項目は無限にある。
極端な例で言えば、全パターンの組み合わせテストを
行うと何千年もかかることもある。

すべてにテストを書くのが愚かであるのと同じように
間違いの可能性が少ない修正にテストは不要。
そのようなテスト不要な場所を見つけ、テストを書く前に
ある程度コードをリファクタリングするのが効率が良い。
25デフォルトの名無しさん:2012/10/15(月) 15:42:52.44
あと、多分知らないと思うから、StubやMockやxUnitについて調べた方が良いよ。
26デフォルトの名無しさん:2012/10/15(月) 15:44:16.59
>>23
> PSEND_CONDITIONとかSYS_PAGE_HEADの定義や、MakeSendMountDevice()の宣言が書かれたヘッダが必要。
> じゃないとコンパイルできないじゃん。

それこそ、スタブ書けって話だなw
27デフォルトの名無しさん:2012/10/15(月) 15:45:18.08
>>24
安心してリファクタリングができるだけのテストがあれば十分。
誰もC0/C1カバレッジ100%のテストを書けとか言ってないよ?

> 本気でやるのならテスト項目は無限にある。
> 極端な例で言えば、全パターンの組み合わせテストを
> 行うと何千年もかかることもある。

循環的複雑度って知ってるかな。
上のURLのコードは「簡単」な部類だよ。全然「複雑」じゃない。
28デフォルトの名無しさん:2012/10/15(月) 15:46:00.22
>>26
> >>23
> > PSEND_CONDITIONとかSYS_PAGE_HEADの定義や、MakeSendMountDevice()の宣言が書かれたヘッダが必要。
> > じゃないとコンパイルできないじゃん。
>
> それこそ、スタブ書けって話だなw

スタブが何か知らないんですね。
29デフォルトの名無しさん:2012/10/15(月) 15:47:31.99
今俺が話してるのが>>1なのか違うのかしらないけど、俺は

>>1
> 1000行以上からなる複数の処理を行う関数などテストを先に書くなんてまず不可能。

が違うよって言いたいだけなんだよね。
書き方を知らないだけなんじゃ無いのってことで。
30デフォルトの名無しさん:2012/10/21(日) 00:18:34.09
変数名とか関数名、型名とかプログラマが自由に付けられるものは、一度
AとかBとかの短い名前に置き換えてみると、>>6 >>7 >>8 の作業がやり易い。
長い名前のままだとそれを目で追って一致しているかどうかを判断するの
が面倒だし、間違いやすい。

ところで、
 コード再配置 → テストコード記述 → リファクタリング
のコード再配置っていうのはリファクタリングの一部ではないの?
つまりスレ主が言いたいのは、
 テストコード記述 → リファクタリング
は不可能で、
 リファクタリング → テストコード記述
しかない、ってことなんじゃないの?

おれもそうだと思うけど。
31デフォルトの名無しさん:2012/10/22(月) 11:16:06.10
>>30
何度も言わせないでくれよ。
まず『レガシーコード改善ガイド』を読めよ。
32デフォルトの名無しさん:2012/10/22(月) 14:56:28.67
事前にテストなんか書けない、ということにしたい人達って何が目的なんだろうか。
事前にテストを書かないことの理論武装をしたくて、同調者を探してるのか?
33デフォルトの名無しさん:2012/10/22(月) 20:18:22.95
事前にテストを書くのは不可能ではないが、
事前にテストを書くとコストが高くなることがある。
レガシーなコードがそう。

ある程度片付けてからテストコードを
書いたほうが効率がいい。
34デフォルトの名無しさん:2012/10/22(月) 22:55:12.15
どうやって振る舞いが変わってないことを
証明すんの?
35デフォルトの名無しさん:2012/10/23(火) 00:03:06.37
test
36デフォルトの名無しさん:2012/10/23(火) 00:08:10.16
変更前のテストが無いと
振るまいが変わってない保証がないよね
37デフォルトの名無しさん:2012/10/23(火) 03:07:20.45
テストがあったからって
振る舞いが変わってないという
保証はないよ。

なぜなら、そのテストが完璧なテストであるという
保証がないから。
38デフォルトの名無しさん:2012/10/23(火) 03:18:27.38
簡単な処理に対するテストは簡単にかける。

だけど、リファクタリングをしたい = コードが汚い = 複雑な処理をしている
このテストを書くのは、すごく大変になる。

仮にリファクタリング対象の関数が、10の処理をしていたとしよう。
これが内部で綺麗に分かれていれば、10の処理に対するテストを書いて、10の関数に分ければいい
だけど、10の処理が内部で複雑に絡み合っていたら10乗のテストを書かなければいけない。

これだけテストの数が違うわけで、先にプチリファクタリングを行なって
内部で処理を分解したほうがはるかにコストが低いというのがわかるだろう。
39デフォルトの名無しさん:2012/10/23(火) 03:29:50.21
そうだね。恥をかいたのは女性だけど
40デフォルトの名無しさん:2012/10/23(火) 03:36:13.09
先にテストをやれば〜とか
テストがあれば〜とか
言ってる人って、テストの作成・修正のコストを
無視してるんだよねw
41デフォルトの名無しさん:2012/10/23(火) 06:09:57.99
あまりにひどけりゃリファクタリングよりも書きなおす方を選ぼう。
42デフォルトの名無しさん:2012/10/23(火) 06:27:51.93
仕様が完全にわかっていれば
それも出来るだろうけどな。
43デフォルトの名無しさん:2012/10/23(火) 06:45:06.99
レガシーコード改善ガイドにも

コードの中の一部分を取り出して、
他のクラスに移動する。

新しいコードのテストは書くが
古いコードのテストは書かないって
よく読めばかいてあるよ。
44デフォルトの名無しさん:2012/10/23(火) 10:43:00.90
動いてるソースをいじるなよ
45デフォルトの名無しさん:2012/10/23(火) 19:25:45.13
機能追加とバグ改修の要求が一つもなけりゃいじらないよ
46デフォルトの名無しさん:2012/10/24(水) 09:50:26.74
リファクタリングに必要なのは結局は説得力だからな
「コードの見かけは変わったけどこの機能は変わってません」ということを報らせることができれば妥協、でいいんじゃないか
必須の機能についてのテストが書かれてなかったのなら、そりゃモトモト足りなかったってことで事前に書いとくのがいいだろう
47デフォルトの名無しさん:2012/10/24(水) 16:51:24.57
オリジナルを作ったときのテストなら信じられるが
後から作ったテストは信用ならないな。
48デフォルトの名無しさん:2012/10/24(水) 17:07:38.54
>>43
> 新しいコードのテストは書くが
> 古いコードのテストは書かないって
> よく読めばかいてあるよ。

そもそも「レガシーコード」とは、「テストの無いコード」のことであって、それに対して
どう対処していくか、どうテストを書いていけば良いのかが『レガシーコード改善ガイド』なんだけど。

どこをどうよく読んだの?
49デフォルトの名無しさん:2012/12/19(水) 01:23:05.20
結論から言うと、素人がやる上から下へのベタ書きの方が理解しやすい
50デフォルトの名無しさん:2012/12/19(水) 11:00:58.54
小規模ならね
51デフォルトの名無しさん:2012/12/30(日) 00:02:34.08
上から下へのベタ書きが理解しやすいのは
ifとforがほとんどないコードで100行まで。
52デフォルトの名無しさん:2013/01/02(水) 11:19:49.01
クローズドな黎明期ならCプログラミング診断室のような糞本でも商売が出来た
53デフォルトの名無しさん:2013/01/27(日) 00:48:54.78
ぶっちゃけテストユニット作ってリファクタリングとかより
仕様理解してクソコードは全捨て&全書き直し
その後、人力デバッグした方が手っ取り早い
54デフォルトの名無しさん:2013/01/27(日) 00:56:19.75
さんざん言われてるが、どんだけコストをかけるか、かけたコストは回収できるのか、ということでしかないからな
無限の時間と無限のコストと無限の人員と仏の顧客がいるのなら、そりゃあねえ
55デフォルトの名無しさん:2013/01/27(日) 14:10:54.08
>仕様理解して

テストコード(あるだけましorソース)が仕様書です。(キリッ
56デフォルトの名無しさん:2013/01/28(月) 11:11:45.51
仕様書はウソをつくがテストコードはウソをつかない
客の目に触れない部分は極力無駄なドキュメントを書かない
57デフォルトの名無しさん:2013/01/28(月) 13:46:04.77
仕様書の厚さが請求金額に比例します!(キリッ
58デフォルトの名無しさん:2013/02/06(水) 22:51:21.05
                       ヘ(^o^)ヘ いいぜ
                         |∧  
                     /  /
                 (^o^)/ てめえが何でも
                /(  )    思い通りに出来るってなら
       (^o^) 三  / / >
 \     (\\ 三
 (/o^)  < \ 三 
 ( /
 / く  まずはそのふざけた
       幻想をぶち殺す

スレタイみたら、このAA貼られまくってんだろうな、と思っていたんだが…
59 ◆ahSvoMzzMtg3 :2013/06/15(土) 23:55:59.85
そげぶ
60デフォルトの名無しさん:2014/02/27(木) 22:28:26.67
設計せずにテスト書くから>>1みたいになるんだろ
61デフォルトの名無しさん:2014/03/01(土) 05:02:58.30
「テスト」って「とりあえず作ってみる」ってことで合ってる?
62デフォルトの名無しさん:2014/03/01(土) 05:43:48.56
合ってない
63デフォルトの名無しさん:2014/03/02(日) 10:27:27.27
じゃぁなんだよ
64デフォルトの名無しさん:2014/03/02(日) 11:48:58.69
COBOLの悲劇史を繰り返さないための手段であって
TESTでバグ出しするのは副次的な作業なんだけどな
仕様書や設計書に出てこない後から外から見るとナゾな挙動を説明するための
65デフォルトの名無しさん:2014/03/04(火) 02:47:44.08
テストって結局何よ?
66デフォルトの名無しさん:2014/03/04(火) 11:53:44.72
Test存在意義がわからない
Testの為に機能を細切れにするの嫌だ
プロジェクトとTestの親和性に問題がある

そんな主張をするヤツを効率的に排除するツール
67 忍法帖【Lv=7,xxxP】(1+0:5) :2014/03/06(木) 16:46:28.44
'
てすと
68デフォルトの名無しさん:2014/03/07(金) 22:19:35.78
テスト開発駆動
69デフォルトの名無しさん:2014/03/10(月) 17:37:30.97
きっちり設計していればテストは不要
70デフォルトの名無しさん:2014/03/10(月) 18:43:43.35
自動化できる部分を自動化できることをきっちりという
71 忍法帖【Lv=10,xxTP】(2+0:5) :2014/05/24(土) 00:41:48.50 ID:cnUjpUj/ BE:261546113-2BP(1000)
テスト
72デフォルトの名無しさん:2014/07/29(火) 23:13:43.20 ID:Lzz8ZlFD
テストドリブンって生産性悪いよな?
73デフォルトの名無しさん:2014/07/30(水) 11:48:15.62 ID:X0HdXrVF
コード量の生産性は悪い
中長期的および小中規模における保守改良を含めると生産性は結果的に高くなる

それだけの話
一人で書く・短期で書く・大人数で分担製作する・顔も知らない人が長期保守する等の場合は大きな障害になりうる
そういうプログラミングしかしないのなら最終証明書的なテスト以外はやらないほうがいいことが多い
74デフォルトの名無しさん:2014/10/25(土) 15:43:01.88 ID:2HGeWB2j
>一人で書く・短期で書く・大人数で分担製作する・顔も知らない人が長期保守する等の場合は

どこかの警視庁プロファイリングを思い出した
75デフォルトの名無しさん:2014/11/08(土) 14:04:15.77 ID:UfN+T2xC
設計できるレベルのエンジニアが少ないのでしかたない
76デフォルトの名無しさん:2014/12/02(火) 21:54:52.49 ID:Emi9Jogj
テスト ドリチン
77デフォルトの名無しさん:2014/12/07(日) 09:17:55.92 ID:Y58/hvmd
1 デフォルトの名無しさん sage 2012/10/03(水) 00:24:26.88
テストを書いてからリファクタリングするというけれど

テストとリファクタリングは関係無くね?
78デフォルトの名無しさん:2014/12/17(水) 21:46:46.06 ID:KocJU1bl
アホには関係
79デフォルトの名無しさん:2015/02/14(土) 07:54:44.64 ID:SarccncW
>>1 は正しい指摘をしてるのに

知識もない奴が難癖つけて
糞スレにしてしまった
悲しいことですね
80デフォルトの名無しさん:2015/02/14(土) 10:03:56.04 ID:5BqTjtvr
>テストを書いてからリファクタリングするというけれど

どこでそんなこと言われてるんだよ
81デフォルトの名無しさん:2015/02/21(土) 05:55:05.56 ID:RdZxGcLP
てすてす。
82デフォルトの名無しさん:2015/02/24(火) 06:35:08.88 ID:xl3zgpOz
>>80
世のあちこちで

テスト書かなかったら動作が変わってないってどうやって保証すんのさ
83デフォルトの名無しさん
てすと