リファクタリングしてもコードの質は改善されないという実験結果 83
ストーリー by hylom
動いているコードは触るなという教訓 部門より
動いているコードは触るなという教訓 部門より
eggy 曰く、
ソースコード中の記述を整理したり、変数名や関数名を分かりやすく書き換えることはリファクタリングと呼ばれているが、実験の結果、リファクタリングを行ったとしてもコードの質が格段に良くなるものでもないことが分かったそうだ(ITWorld、Slashdot)。
調査を行ったのはスリランカの研究チーム。リファクタリングによりソフトウェアの品質が外部的・内部的にどれほど向上するのかを調べたそうだ。実験には、オンラインドキュメント評価のスケジューリングおよび管理を行う小規模のアプリケーション(4,500行ほどのC#コード)が用いられ、10個の一般的なリファクタリング技術が適用された。
実験の結果、実際の統計では大きな差はみられなかったもの、参加者らの採点によればリファクタリングされたコードの方が解析性が劣り、コードのバグ修正と実行にはより時間がかかるようになったという。また、リファクタリングしたからといってリソース使用量が減るという結果も得られなかったという。唯一、リファクタリングすることの利点として保守性指数が僅かに高かったものの、品質を測るほかの内部測定では、リファクタリングしたからといってパフォーマンスが上がるわけでもないことが分かったとのこと。
小規模のアプリケーションを用いた実験であるため、この結果に対する懐疑的な見方もあるだろうが、リファクタリングが嫌だと感じている人にとっては、わざわざリファクタリングしないことの十分な理由となるだろうとのこと。
正論だな (スコア:4, おもしろおかしい)
スリランカだけに。
Re: (スコア:0)
昔の話だ、今は違うね。
そもそも手を入れる必要が無いのなら・・・ (スコア:1)
今の一般的なソフトウェアの製作過程でみれば、何らかの問題があるからリファクタリングするのであって、問題の出ていないソースコードに集中的なリファクタリングしても効果が見られないのは当然だという気がする。
もっとも、地道な研究というのも必要だとは思うし、将来的にはこういう技術の延長でプログラマがまだ気付いていない問題を顕在化する前に知らせるとか取り除いてくれるとかなら嬉しい。
Re:そもそも手を入れる必要が無いのなら・・・ (スコア:2, すばらしい洞察)
いやあ、違うんじゃないですかね。
リファクタリングは「動いているコードを触る」ということであって、基本的に挙動は変化しちゃいかんのですよ。
挙動が変化するようなものはもはやリファクタリングじゃなく普通の修正です。
なので、リファクタリングにパフォーマンス向上を求めることが筋違いではないかと。
ついでに言えば、コンピューターサイエンスの学生に評価をさせたようですけど、学生に「保守性」が本当に認識できるのか、という疑問が……。
Re:そもそも手を入れる必要が無いのなら・・・ (スコア:1)
問題というとやっぱり、ソフトウェアのバグみたいに聞こえてしまいますね。
ここで言いたいのは、機能拡張をしたいけれど、既にやっつけの拡張が多数集積していて見通しが悪すぎるとか。そういう問題です。
それから単純なものだと、ほぼ全ての変数や関数が英数字二文字以内というソースコードは、余程短くない限り問題ありです。
一息にコーディングするとき余計なことに気を散らしたくないのは判るけれど、関数名がすべて f0 とか f4 とかだったりは受け取れません。
Re: (スコア:0)
ここに一票。
つまり、更なる機能追加の土台均しだから、リファクタリングそのものでコードが複雑になったとしても、その後の機能追加と併せて整合性がとれるなら意味があるはず。
Re: (スコア:0)
最後のくだりだけについて反応。
関数名については 全く同意しますが、
最近 golang さんとかだと、変数名はなるべく短く、かつすぐ使い終わるように、
というような方針が推奨されているようですよ。
Re:そもそも手を入れる必要が無いのなら・・・ (スコア:3)
>最近 golang さんとかだと、変数名はなるべく短く、かつすぐ使い終わるように、
これは変数のスコープは最小にしろ。スコープが十分小さければ変数は短くてもOK。
っていう、昔から言われていることを言い換えているだけでは。
Re: (スコア:0)
昔はスコープ長かったけどね。初期のCは関数の先頭に全部書かなきゃいけなかったし、互換性のために長い間その方式を踏襲してたから。
むしろ名前の拒否反応は命名規則と習慣からくるんじゃないかな。以前、他人が書いたコードに
ってのに手を入れてた時にiiをiにしたくてしょうがなかったもの。頭でわかったつもりになってても、途中から
「iiってなんだっけ?ああ、ループ回してるんだったな。…(ちょっと先)…ところで、このii*iiってどういう意味だ?あ、あー、ループカウントを2乗してるのか、i * iのことだな。…(さらに先)…あれ、ptrからii引くのはいいけど、このiiってどっから出てきたんだよ。あー、わかった!くそ、思い出した!」
って感じになったから。jとかkとかnとかlだと全然気にならないんだけど、iiは生理的に受け付けないと自覚してしまった。
Re:そもそも手を入れる必要が無いのなら・・・ (スコア:3, おもしろおかしい)
Re: (スコア:0)
パフのプロジェクトではデバッグと称してリファクタリングしていたパフ
Re:そもそも手を入れる必要が無いのなら・・・ (スコア:1)
リファクタリングの定義はマーティン・ファウラーによって明確に決められていると思っていたが。
この件については、「挙動を変えないで、改善を図る」、という最低ラインについては共通認識として
あるのではないか。
立場によってリファクタリングが違う、とするのは我田引水に聞こえてしまう。
リファクタリングは、仕様書云々とは全く別のフェーズの話でしょう。
十分なユニットテスト・結合テストを準備すれば、根拠をもった改善が可能だ、とする
話であって、ここからずれたらやはりそれはただの「根拠のない修正」「仕様変更」
に過ぎません。
リファクタリングを考え始める規模 (スコア:1)
リファクタリングを考え始める規模がこの実験の10倍程度以上くらいかなというのが、個人的な経験則です。
みなさんはどれくらい??
他の方も述べてますが、こういった実験は非常に重要で、定量的に評価される実験が重なることで着実に開発の世界が進歩するのだと思います。
速度向上を目的とするときも、手を入れる際には必ず計測を行います。リファクタリングにも計測できる手法が開発されたらいいなと思います。
Re: (スコア:0)
>みなさんはどれくらい??
量じゃなくて自分の書くコードから放たれる異臭に耐え切れなくなったら始めてる。
臭いが我慢できる程度になったら止める。
機能実装優先で書いた自分のコードの臭いこと臭いこと・・・
asdf()なんて関数見つけてセルフ悶絶。
Re: (スコア:0)
静的チェックしてると、たまに complexity がでかいよ!ってチェックされたりしますよね。
あれってリファクタリングさぼるんじゃないよ!って意味なのかなと思うのですが。
Re: (スコア:0)
理想論で言えば常に。
即ち、常にリファクタリングがされているので、瞬間瞬間での効果は少なくても構わないと思います。
リファクタリングして大幅に改善出来る状況って、要はかなり酷い状態ってことでしょ?
えっ? (スコア:1)
その程度のことをリファクタリングって言うんだっけ?
Re:えっ? (スコア:2)
リファクタリングはメソッド抽出など大きな変更もあれば、変数名変更のような小さい変更もあります。
例えばEclipseでは変数名を変えるコマンドがメニューの「リファクタリング」の中に入っている。
ただ、厳密な定義があるわけではないので、スリランカの研究チームでは変数名変更も含めている、という認識で十分かと。
Re: (スコア:0)
なんか根本的に間違えているというか勘違いしている感じよね。
「新しいソフトウェア作るには、まず既存の似たようなソフトのソースを探してきてCopyright表記をすべて自社名義に書き換える」くらいの斬新さ。
Re: (スコア:0)
某漫画ではチ○チ○をいじくりまわすことをリファクタリングと呼んでたぞ
Re: (スコア:0)
マイクロでソフトなゲイツのはよく動かないのでリファクタリングしていいの?
ジレンマだかパラドックスだか (スコア:1)
リファクタリング可能なコードはリファクタリング前から既に十分な解析性と変更しやすさを備えている疑惑。
解析困難で変更困難なコードはリファクタリング困難だろう。
あとリファクタリングは動作を変える作業ではないから実行時間やリソース使用量が大きく変化されても困る。
短すぎる (スコア:0)
4,500行程度だと、勢いでかける、ちょっと時間かければ全部読んで内容を把握できる、という程度だと思いますので、効果が出づらいのではないでしょうか。
#とはいえ1か月前に書いた 4500 行のコードは脳 RAM から内容が(ものによっては書いた記憶さえ)消え去っているので、やる意味があるかも。
Re: (スコア:0)
だよねぇ、タレコミ元はリファクタリングの意味わかってんのかなという印象。
リファクタリングはパフォーマンス向上のためにする物でも無いし。
リファクタリング後の方がコード量増えるのもザラ。
たかだか4500行程度のコード捏ね繰り回しただけで何寝言言ってんのかと。
先週自作ドライバのコードをリファクタリングしてたけど主目的は脱臭。
やっつけで書いた処理の書き直しやコピペでできた重複の除去ばっかやってた。
流石に異臭を放ち始めた食材で調理を続行する気にはなれなかったから。
#リファクタリング中に仕様変更もしてしまい泥沼になりかけたのはお約束。
保守性≒解析性だと思ってた (スコア:0)
タイトルどおりなんだけど、3段落目の
リファクタリングされたコードの方が解析性が劣り
と
リファクタリングすることの利点として保守性指数が僅かに高かった
が、矛盾してない?
俺の思っている保守性とは、また違うものなのかしらん?
Re: (スコア:0)
矛盾しないように解釈するなら、コードを理解するコストと、問題発生時に修正するコストの違いじゃねぇの。
Re: (スコア:0)
この論文では
解析性(人間がコードを評価した結果)
保守性指数(ツールがコードを評価した結果)
なのでツールは人間の感覚を再現するものではない、ということかと。
Re: (スコア:0)
「解析性」は「可読性」と読み替えるとして、
「バグが出て修正に時間がかかっている」らしい記述からすると、
リファクタリングに失敗して保守性は低下しているようですから、
「保守性指数」の算定アルゴリズムが現実の「保守性」を表していないということでしょうか…
Re: (スコア:0)
バグが出て修正に時間がかかったのに保守性は改善したとか、いろいろ矛盾していますね。
可能性
・統計情報を適切に読み解けてない
・記事(あるいは翻訳)が傾向と事例を区別できていない
・まともにできる人がいなくて、「失敗することが多かった」と言っているだけ
:
Re: (スコア:0)
元の論文を読めばわかることだけど、適用したリファクタリングは以下のようなもの。特にR3~R6を無分別に適用したせいで、コーディングのミスや漏れを防げるようになった代わりに、処理の具体的内容が読みづらくなったということだと思う。
Re:保守性≒解析性だと思ってた (スコア:1)
その操作を個々の状況、条件から適切なものを選んで適用するのがリファクタリングなんだから、無分別に適用したらリファクタリングじゃない。
情報不足 (スコア:0)
これ、変更前 変更後のソース見せてもらえないとなんとも言えないよね?
そもそもリファクタリングの定義ってナニ?
微妙な匂いがする (スコア:1)
「10個の一般的なリファクタリング技術」という表現から、何か微妙な匂いがする。
文字通り、10種の施策を徹底的に(≒闇雲に)適用したのだとすると、それはリファクタリングじゃなくただのトランスレート作業をやっちまったんではなかろうか。
リファクタリングで改悪されるのは (スコア:0)
手段と目的を取り違えてるのじゃないか?
動いているコードは触るなという教訓(キリッ (スコア:0)
そうか、そうか、つまり君はそういうやつなんだな。>hylom
Re: (スコア:0)
ビルゲイツが言ったことで有名なフレーズなんですがそれは
Re: (スコア:0)
ゲイツが言うからリファクタリングは不要ってことですね、わかります
Re: (スコア:0)
hylomがどうであれ、こういうもの言いをする奴って、そういう奴だよな。
http://ja.m.wikipedia.org/wiki/ [wikipedia.org]人身攻撃
そもそも性能上げるための作業じゃないでしょう。 (スコア:0)
>パフォーマンスが上がるわけでもないことが分かったとのこと。
代表的な10の方法ってものが、Wikipediaのリファクタリングの項目にのっているものだとすると、
そもそもパフォーマンスが向上するような手法は無いと思うのですけど。
あくまで保守性を上げるぐらいでしょう。
Re: (スコア:0)
むしろ、関数が分割されて呼び出しコストがかかりそう...
Re:そもそも性能上げるための作業じゃないでしょう。 (スコア:1)
ある分野においてはそうかもしれないけど、PC用のアプリケーションなら小さい関数に分割することで速くなることも多い。逆にインライン化して「確実に」速くなるのはアクセサ相当のものぐらい。
もちろん、「小さい処理」であれば速くなるだろうけど、その「小さい処理」の線引きが難しいから、関数に関しては可読性重視で書いておくのがいい。高速化のテクニックはいろいろあるけど、呼び出す関数が静的に決定できる限りにおいては、簡素になる方向で書いておけば、ほぼ間違いはない。
そもそも、高速化が必要なのかと言うのも問題だし、高速化するにしても、関数呼び出しにかかわる部分をいじるのは割と後の方。まずは余計な重い処理を減らすことが先決で、そういう処理を探し出すためにも長い関数は分割しておいた方がいい。
Re: (スコア:0)
実験データが4500行のコードといっているので、
分割されても複数箇所から呼び出されることも無さそうですね。
そもそもタイトルにある「コードの質」って何をもっていっているのだろうか。
コードの質が高い≒パフォーマンスでしょう。
Re: (スコア:0)
そうそう。 ソースにドキュメントを書き入れるのもリファクタリングだよね?
関数の機能を確認し、インターフェース(引数と戻り値と大域変数との関わりなど)を
詳細に説明する説明文をコメントとして入れる。 各処理のコメントも充実させるなどな。
論文自体から (スコア:0)
- http://arxiv.org/ftp/arxiv/papers/1502/1502.03526.pdf [arxiv.org]
3.1で「先行研究で高いインパクトがあった10リファクタリング手法を使いました」的なことがあり、
このリストの10個のほとんどがコード(とくにclass)を増やすリファクタリングである以上、
リファクタリング手法の適用によって評価指標が下がるのは当然なのでは。
リファクタリングする/しないの後に、関連する部分にコードを追加したり単純化したりしたものを
評価したら、だいぶ違ってくるのではないでしょうか。
Re: (スコア:0)
この論文自体は、2にあるように先行研究が欠いたことを補完することが主な動機であり、
結論も、未熟者がやろうがリファクタリングそれ自体が効果がある、というものではないよね、的な話でした。
タレコミの元になったメディア記事のように拡大解釈して、
リファクタリング活動そのものをDISるようなものではないと思います。
関数名 "func1" だの変数名 "hensuu0" だの (スコア:0)
リファクタしようと言う気力すらなくなるソースコードがこれで正当化されそうだ
パフォーマンスのミスリード (スコア:0)
「パフォーマンス=性能」の主語を勘違いしていませんか?
この記事に登場するパフォーマンスの主語はすべて「保守性」であって、
実行速度等のプログラムのブラックボックスな意味のパフォーマンスではないと思われます。
# リファクタリングの主旨を理解していればミスリードしない、はず?
# 理解を先回りして訳ができるというのは、実際翻訳を体験してみると難しさがわかります。
Re: (スコア:0)
>唯一、リファクタリングすることの利点として保守性指数が僅かに高かったものの、品質を測るほかの内部測定では、リファクタリングしたからといってパフォーマンスが上がるわけでもないことが分かったとのこと
ここにパフォーマンスという言葉が出てきて保守性指数がわずかに高いのにパフォーマンスが上がるわけでもないと言っているので、「保守性」ではなく「(コードの)品質」では?
Re: (スコア:0)
品質ならQualityを使いそうだけどなぁ...
Re: (スコア:0)
ずばり
> Refactoring code doesn’t make it run faster
と書いてあるパフ
> Internal measure of software quality were calculated for the refactored and un-refactored code using Visual Studio. These metrics were: Maintainability Index, Cyclomatic Complexity, Depth of Inheritance, Class Coupling, and Line of Code.
品質は速度とぜんぜん関係ないパフ
eggyはなぜくっつけたのか理解に苦しむパフ