はてなキーワード: リファクタリングとは
端的に言えば、「やり方が変わったらミスが増えるし覚えるまでの仕事が遅くなるから」以外にないですよ。
新しいやり方になって大幅スピードアップならともかく、仕事のスピード自体はおおむね一緒だけどやり方だけは変わるってパターンの場合は現場の負担が半端ない。
現場が死ぬ気でやれば解決するわけでもなく、人員を一時的に増やした所で初心者ばかり集めては結局ミスが増える。
「リファクタリングの方が安く仕上がりると勘違いしてるから目指してるんだろうな」と思ってる人、ただのバカです。
発注側も一次請けも現場もみんな「いっそ根本から作り直したほうがシステム屋さん的には楽なんだろう」ってことは分かってる。
でも作り直してしまった場合に生じる現場の混乱とリファクタリングのコストを天秤にかけて現場のやり方を変えないことを選んでるわけ。
そこが分かってないで「まーたアホな仕様でシステム更新しようとしたんでしょー。学習しないね―」みたいなこと言ってるのいい加減見飽きたよ。
去年から稼働している現場で、以前からあったReact Nativeの面倒を見ているんだがまあこれがひどい出来なんだ。
jQuery時代に見かけたようなコードをやたら見かけたので思わず懐かしくなってしまった。
リファクタリングしようとしたけど直す範囲が広すぎてアプリを壊しかねなかったので、早々に諦めてだましだまし保守をしていた。
そんな中今年に入ってアプリのリニューアルの話が出てきた。React Native捨ててSwift/KotlinやらFlutterに書き換えるとかそういうのではなく、デザインの刷新といくつかの機能改修。
このままだとアプリが更に魔窟化するので、マネージャーに色々相談したところいくつかの事実がわかった。
ということだった。
結局現状のまま進めるわけにはいかず、要件定義の傍らリファクタリング作業をしている。
そういう経緯もあったので、リファクタリングとテストの工数も積んだ上で見積もりだしてもらってる。
「レガシーアーキテクチャをモダンアーキテクチャに刷新」なんてよく聞く話しだけど、
実態は「長年の増改築とだましだましのリフォームが限界になってきたので新築で建て替えます」何だと思う。
最近は「Vue.jsからRemixにマイグレーション」なんて見かけるけど、悪いのはVue.jsじゃなくて禄に設計しないでコード書いてるエンジニアと、
リファクタリングには予算でないけどマイグレーションなら予算取れるという悪しき風習。
年がら年中フロントエンド刷新しているような会社は地雷なので行かないほうがいい。
「この関数にこういうパラメータを使ったこういう処理を追加してくれ」などと言われたら、コードは複雑化するのは当然だろう。
かといってこういう要求が来た時に、コード全体を一から作り直して簡潔にしようと思うのはナンセンスだ。
コードの量にもよるが、一定程度の量のコードがそこにあるときは、やはりリファクタリングの方が効率よく進められる。
「僕はリファクタリングなんてしませぇん、一から書いた方がいいでぇす」というのは、特定の現場・状況だけにあてはまるものだと認識しておこう。
確かに「コード全体をリファクタリング」なんてしようと思ったら大変すぎるが、通常は「修正を担当する部分をついでにリファクタリングする」でOKだ。
ユニットテストさえかけていれば、そのリファクタリングによって、バグが見つかりやすくなるだろうし、保守性も上がるのである。
なお、本当にコードベースが酷いカオス状態で、ゴッドオブジェクトを使っているような状況になったら、「書き直す」という利点が少しはあるかもしれないが、そういう場合は関係各位に同意を取らなければやってはいけない。
そういったカオスな状況でさえ、平均的なプログラマーは「良いコード」よりも「慣れているコード」に愛着を持つ傾向にある。
もしあなたが「コードを綺麗にするためにすべてを一から書き直そう」と、無断でそのようなことをやったら、彼らが慣れていないという理由で批判の嵐が殺到するだろう。
プログラマーの三代美徳は、怠惰でもなければ傲慢でもない。本能、感情、混乱である。
本能とは、モチベーションの本質的部分である。エロいdeepfakeを作りたい、頭よく見られたい、金儲けしたいといった動機によってプログラマーは手を動かす。
本能がなければドーパミンも存在しない。コードを書く誘因は本能的衝動によって生み出されている。
感情とは、要するに好き嫌いのことだ。たくさんの経験を積み重ねてセンスを獲得するには、好き嫌いに敏感でなければならない。
なぜvscodeがクソで、emacsが素晴らしいのか。なぜマイクロサービスアーキテクチャに強い疑念があるのか。なぜベンダーロックインが金の浪費に繋がるのか。
そういったことは、経験から学び、そして感情という次元に落とし込まれる。感情は少数の次元で美的感覚を得るための優れたセンサーである。
混乱とは、人生である。混乱したことのないものはエントロピーを操ることはできない。
コードは常にエントロピー増大の法則に晒されている。高エントロピーの乱雑的コードを読んで混乱したことがなければ、リファクタリングもできないだろう。
誰にも相談せずに
コードを書く上で重要なことは?という質問に対して、アスペならば「実行できること」と答えるだろう。
当たり前なことしか言っていない。「実行できること」という文からは全く有益な知見を得られない。
実行できることは重要性ではなく、必要性である。重要性とは、必要なことをすべてやった上でなおやる価値のあることを意味する。
そう考えた時に私がよく思うのは「最短時間で理解可能」であることが重要であると思うわけである。
しかしここに宗教がある。そもそも、人間が物事を理解するプロセスは人それぞれである。
私は一度、関数やモジュールで適切に分離するためのリファクタリングというものを行ったことがある。
というのも、一つの関数に万を超える行が書かれていたため、上司がリファクタリングを命令したためである。
具体的詳細はprivateメソッドに、公開する必要のあるものはpublicメソッドに移した。
そして当初働いていた職場での反応はどうだったかというと、「スパゲッティコード」だというのだ。
スパゲッティコード?一つの関数に万を超える行があるほうがスパゲッティだと普通は思うだろう。
ところが、彼らの脳内では、「常にコードの詳細が見えていなければ気がすまない」という、カプセル化を無視する思想で動いていたため、関数化すると関数の最下層まで辿らないと気がすまないらしかったのである。
このようにして、教育の無い人間はコードの読み方もカプセル化も知らないので、非生産的な方法が最短の方法になってしまうのである。
コードを最短で理解するためにはどうするのか。基礎知識を教育された集団の中に身を置くのがまず先決である。
例えばcalc_monthly_salary_yen(Person p)という行が存在した時、いちいちcalc_monthly_salary_yenの中身を常に見に行くような人たちはダメだ。
「人間のデータを入力すれば円単位で月の給料を計算してくれるんだろう」とざっくりと自然言語的に読み進められる人たちでなければ「最短理解」は難しい。
開発手法でしっくり来てるのがAndy HuntさんのTracer Bullet Developmentで、開発の方向性を示すのに試作を作る方法。
1. 主要なシステム オブジェクトを定義。UI、サーバー、ロジックビット、データベース抽象化レイヤー等。
3. データフローを実現するために API とその戻り値をコーディング。
4. 単体テストを使用して API の予想される使用法を文書化。
5. 各 API に必要な量の既定のデータ (別名、ダミー データ、偽のデータ、ハードコーディングされたデータ) を追加して、API が「実行」されるようにする。
6. あらかじめ用意されたデータを実際の機能に段階的に置き換える。
プログラミングの話題と相性がいいんじゃないかと思って、昔読んだことがある達人プログラマー (1999年に出版された第1版の方、2019年に出版された第2版ではない) をぱらぱら見返してみた。プログラマーとしての姿勢やプラクティスなどは一般に普及したかどうかの判断が難しい。間違いなく一般的になったなと思えるものに絞って書く。インフラ面の進化が大きいと言えそう。
フリーレン「わずか数年で人類の開発方法論に組み込まれ、新しいインフラによってシステム開発の生産性を向上させた。」
でも今のチームはソースコード管理システムを使っていないんだけど……
恥ずかしいと思ってください! そして、これが伝道師となる機会だと受け止めてほしいのです。しかし、彼らが自ら進むべき道を見つける時まで、あなた一人ぼっちであってもソース管理を使うようにしてください。
フェルン「いまのはバージョン管理システムです。」
いつリファクタリングを行うべきなのか?
コードがうまくなじんでいないと感じたり、まとめるべき 2 つの事柄を見つけたりといった何か「おかしなもの」に遭遇した場合、手を入れることを躊躇してはいけません。
テストの文化
あなたの記述したソフトウェアはすべてテストの対象になります。あなたやあなたのチームの人間がテストをしなければ、最終的にユーザーがテストを強いられるのです。このため、テスト計画を徹底的に練る必要があります。しかし、事前にものごとを少し考えるだけでメンテナンス費とヘルプデスクへの呼び出しを大幅に削減できます。
(中略)
テストは技術というよりは文化なのです。こういったテスト文化は、使用する言語に関係なくプロジェクトに植え付けることが可能なのです。
フェルン「いまのはテスト駆動開発です。」
多くのプロジェクトでは、こういったレベルのビルドは毎晩自動的に実行されています。つまり、プロジェクトの特定部分を夜間ビルドで作成すると同時に、個別のテストよりも完全なテストを実行できるのです。これによって、完全なビルド実行時に行うテストをすべて実行させることも可能になります。結果として、その日のうちに回帰テストの問題を見つけられるようになるわけです。ソースの変更後、できるだけ早い時点で問題を検出できれば、バグの検出と修正を円滑に進められるようになるはずです。