壊れていない場合は、修正しないでください。
これはよく知られているフレーズですが、私たちが知っているように、人間の技術的進歩のほとんどは、壊れていないものを修正することを決定した人々によってなされました。特にソフトウェア業界では、私たちが行っていることのほとんどは、壊れていないものを修正することであると主張することができます。
機能の修正、UIの改善、速度とメモリ効率の改善、機能の追加:これらはすべて、実行する価値があるかどうかを簡単に確認できるアクティビティです。 経験豊富なRails開発者 それらに私たちの時間を費やすことに賛成または反対を主張します。ただし、アクティビティがあり、ほとんどの場合、灰色の領域に分類されます。 標準のリファクタリング 、特に大規模なコードリファクタリング。
大規模リファクタリングという用語は、説明する価値があります。用語が少し曖昧であるため、「大規模」と見なすことができるものはケースごとに異なりますが、いくつかのクラスまたは複数のサブシステムに大きな影響を与えるものはすべて、そのインターフェイスは「大規模」であると考えています。 。」一方、単一のクラスのインターフェースの背後に隠れたままのRailsリファクタリングは、間違いなく「小さい」でしょう。もちろん、その間には灰色の領域がたくさんあります。最後に、あなたの腸を信頼してください。あなたがそれをすることを恐れるなら、それはおそらく「大きい」でしょう。
定義上、リファクタリングは目に見える機能を生み出さず、クライアントに見せることも、成果物も生み出しません。せいぜい、速度とメモリ使用量がわずかに改善される可能性がありますが、それは主要な目標ではありません。主な目標はあなたが満足しているコードであると言う人もいるかもしれません。しかし、コードベース全体に大きな影響を与えるような方法でコードを再配置しているため、すべての地獄が解き放たれ、問題が発生する可能性があります。もちろん、それは私たちが言及した恐怖が由来するところです。コードベースに新しい人を紹介し、彼らが特別に編成されたコードについて尋ねた後、次のような応答をしたことがありますか。
adobexdは何に使用されますか
ええ、これは当時は理にかなっていたレガシーコードですが、仕様が変更され、修正するにはコストがかかりすぎますか?
たぶん、あなたは彼らに非常に真面目な顔をして、そのままにして触れないように言ったのかもしれません。
「なぜ私たちはそれをやりたいのか」という質問。これは自然なことであり、リファクタリングに高価な時間を費やすことができるように説得しなければならない人が他にもいることが多いため、リファクタリングプロセスと同じくらい重要な場合があります。それでは、それを実行したい場合と、得られるメリットについて考えてみましょう。
保守性の観点からコードの現在の構成に満足していますが、それでもパフォーマンスに問題が発生しています。現在の設定方法を最適化するのは非常に難しく、変更は非常に脆弱です。
組織のゲシュタルト原則
ここで行うことは1つだけであり、それは広範囲にプロファイルすることです。ベンチマークを実行し、どれだけの利益が得られるかを見積もり、それが具体的な利益にどのように変換されるかを見積もります。提案されたコードリファクタリングは価値がないことに気付く場合もあります。また、ケースを裏付けるためのコールドハードデータがある場合もあります。
アーキテクチャは大丈夫ですが、やや時代遅れであるか、コードベースのその部分に触れるたびにうずくまるほどひどいのかもしれません。正常に高速に動作しますが、新しい機能を追加するのは面倒です。その痛みの中に、リファクタリングのビジネス価値があります。 「苦痛」はまた、リファクタリングプロセスが新しい機能を追加するのに時間がかかることを意味します。
そして、得られるメリットがあります。提案された大規模なリファクタリングがある場合とない場合のいくつかのサンプル機能のコスト/メリットを見積もります。同様の違いが、システムの開発中に現在および将来にわたってシステムのその部分に影響を与える今後の機能のほとんどに適用されることを説明します。彼らはしばしばソフトウェア開発にあるのであなたの見積もりは間違っているかもしれませんが、それらの比率はおそらく球場にあるでしょう。
時々、コードは最初はうまく書かれています。あなたはそれに非常に満足しています。高速で、メモリ効率が高く、保守が容易で、仕様に適合しています。最初は。しかし、その後、仕様が変更されたり、ビジネス目標が変化したり、エンドユーザーについて最初の仮定を無効にする新しいことを学んだりします。コードはまだうまく機能していて、あなたはまだそれについてかなり満足していますが、最終製品のコンテキストでそれを見ると何かが厄介です。物事がわずかに間違ったサブシステムに配置されているか、プロパティが間違ったクラスにあるか、または一部の名前が意味をなさなくなっている可能性があります。彼らは現在、まったく異なる名前のビジネス用語である役割を果たしています。ただし、関連する作業は他の例のいずれかと大規模になるため、大規模なRailsリファクタリングを正当化することは依然として非常に困難ですが、メリットはそれほど具体的ではありません。あなたがそれについて考えるとき、それを維持することさえそれほど難しいことではありません。いくつかのものは実際には別のものであることを覚えておく必要があります。 Aは実際にはBを意味し、AのプロパティYは実際にはCに関連していることを覚えておく必要があります。
そして、ここに本当のメリットがあります。神経心理学の分野では、私たちの短期記憶または作業記憶がわずか7 +/- 2の要素を保持できることを示唆する多くの実験があり、そのうちの1つは スターンバーグ実験 。私たちが主題を研究するとき、私たちは基本的な要素から始めます、そして最初に、私たちがより高いレベルの概念について考えるとき、私たちはそれらの定義について考えなければなりません。たとえば、「saltedSHA256password」という単純な用語について考えてみます。最初に、「salted」と「SHA256」の作業メモリー定義、さらには「ハッシュ関数」の定義を保持する必要があります。しかし、この用語を完全に理解すると、直感的に理解できるため、1つのメモリスロットしか占有しません。これが、高レベルの概念について推論できるようにするために、低レベルの概念を完全に理解する必要がある理由の1つです。私たちのプロジェクトに固有の用語や定義についても同じことが言えます。しかし、コードについて議論するたびに本当の意味への翻訳を覚えておく必要がある場合、その翻訳はそれらの貴重なワーキングメモリスロットのもう1つを占めています。それは認知的負荷を生み出し、コード内のロジックを介して推論することを困難にします。同様に、推論が難しい場合は、重要なポイントを見落とし、バグを導入する可能性が高くなります。
そして、より明白な副作用を忘れないでください。クライアントや正しいビジネス用語に精通している人と変更について話し合うと、混乱する可能性が高くなります。チームに参加する新しい人々は、ビジネス用語とコード内の対応する用語の両方に精通している必要があります。
これらの理由は非常に説得力があり、多くの場合、リファクタリングのコストを正当化すると思います。それでも、注意してください。リファクタリングの時期と方法を決定するために最善の判断を下さなければならないエッジケースがたくさんある可能性があります。
最終的に、大規模なリファクタリングは、私たちの多くが新しいプロジェクトの開始を楽しんでいるのと同じ理由で優れています。あなたはその空白のソースファイルを見ると、勇敢な新しい世界があなたの心の中を渦巻くようになります。今回は正しく実行します。コードはエレガントで、美しくレイアウトされているだけでなく、高速で堅牢で簡単に拡張できます。そして最も重要なことは、毎日作業するのが楽しいことです。小規模および大規模のリファクタリングにより、その感覚を取り戻し、古いコードベースに新しい命を吹き込み、その技術的負債を返済することができます。
kubernetesは、あらゆるコンテナ化製品で動作するように設計されています
最後に、リファクタリングが特定の新機能の実装を容易にする計画によって推進されている場合に最適です。その場合、リファクタリングはより集中的になり、リファクタリングに費やされた時間の多くは、機能自体のより迅速な実装によって即座に回収されます。
触れる可能性のあるコードベースのすべての領域で、テストカバレッジが非常に良好であることを確認してください。十分にカバーされていない特定の部分を見つけた場合は、最初にテストカバレッジを上げるために時間を費やしてください。テストがまったくない場合は、最初にそれらのテストの作成に時間を費やす必要があります。適切なテストスイートを作成できない場合は、受け入れテストに集中してできるだけ多くのテストを作成し、リファクタリング中に単体テストを作成するようにしてください。理論的には、適切なテストカバレッジがなくてもコードリファクタリングを実行できますが、多くの手動テストを実行する必要があり、頻繁に実行する必要があります。時間がかかり、エラーが発生しやすくなります。最終的に、テストカバレッジが十分でない場合、大規模なRailsリファクタリングを実行するコストが非常に高くなる可能性があるため、残念ながら、まったく実行しないことを検討する必要があります。私の意見では、それは十分に強調されていない自動テストの利点です。自動化されたテストにより、頻繁に、そしてより重要なことに、それについてより大胆にリファクタリングすることができます。
テストカバレッジが良好であることを確認したら、変更のマッピングを開始します。最初は、コーディングを行うべきではありません。関連するすべての変更を大まかにマップし、コードベースを介してすべての結果を追跡し、それらすべてに関する知識を頭の中にロードする必要があります。あなたの目標は、何かを変更する理由と、それがコードベースで果たす役割を正確に理解することです。変更が必要なように見える、または何かが壊れて問題が解決したように見えるという理由だけで、状況を変更することに遭遇した場合、おそらく死んだ路地になってしまうでしょう。新しいコードは機能しているように見えますが、正しくありません。今では、行ったすべての変更を思い出すことができません。この時点で、大規模なコードリファクタリングで行った作業を放棄する必要があり、本質的に時間を無駄にしています。したがって、時間をかけてコードを調べて、これから行う各変更の影響を理解してください。最終的には見事に報われるでしょう。
リファクタリングプロセスの支援が必要になります。あなたは何か他のものを好むかもしれませんが、私は単純な白紙とペンが好きです。まず、紙の左上に加えたい最初の変更を書きます。次に、変更の影響を受けるすべての場所を探し始め、最初の変更でそれらを書き留めます。ここであなたの判断を使うことが重要です。最終的には、紙のメモや図があなた自身のためにあるので、あなたの記憶に最も適したスタイルを選んでください。その下に箇条書きのマークが付いた短いコードスニペットと、それに直接(完全な矢印)または間接的に(破線の矢印)依存していることを示す他のそのようなメモにつながる多くの矢印を書きます。また、コードベースで気付いた特定のことを思い出させるために、矢印に省略記号で注釈を付けます。計画された変更を実行している間、これらのメモに戻るのは数日だけであることを忘れないでください。非常に短くて不可解なリマインダーを使用しても、スペースが少なくて済み、紙に簡単にレイアウトできます。 。 Railsのリファクタリングの数か月後に机を掃除していたときに、それらの論文の1つを見つけました。それは完全にぎこちないものでした、私はそれが狂った誰かによって書かれたかもしれないことを除いて、その紙の何が意味するのか全くわかりませんでした。しかし、私が問題に取り組んでいる間、一枚の紙が不可欠であったことを私は知っています。また、すべての変更を書き出す必要があるとは思わないでください。それらをグループ化し、別の方法で詳細を追跡できます。たとえば、メインペーパーでは、「A.bのすべてのオカレンスの名前をC.dに変更する」必要があることに注意してください。その後、いくつかの異なる方法で詳細を追跡できます。それらをすべて別の紙に書き出すか、すべての出現箇所をもう一度グローバル検索するように計画するか、選択したエディターで変更を開く必要があるすべてのソースファイルをそのままにしておくことができます。変更のマッピングが完了したら、それらに戻るように心に留めておきます。
最初の変更の結果を計画するとき、それが大規模であるという性質により、おそらくそれ自体がさらに結果をもたらす追加の変更を特定するでしょう。それらについても分析を繰り返し、依存するすべての変更に注意します。変更のサイズに応じて、同じ紙に書き出すか、新しい空白の紙を選ぶことができます。変更をマッピングする際に試行する非常に重要なことは、分岐する変更を実際に停止できる境界を特定することです。リファクタリングを、意味のある、丸められた、変更の最小のセットに制限する必要があります。停止して残りをそのままにしておくことができるポイントを見つけた場合は、概念的に他の変更に関連している場合でも、リファクタリングする必要があると思われる場合でもそうしてください。このラウンドのコードリファクタリングを終了し、徹底的にテスト、デプロイして、さらに戻ってきます。変更のサイズを管理しやすくするために、これらのポイントを積極的に探す必要があります。もちろん、いつものように、判断を呼びかけます。かなり頻繁に、いくつかのプロキシクラスを追加してインターフェイスの変換を少し行うことで、リファクタリングプロセスを中断できるようになりました。 「自然な停止」(つまり、プロキシコードがほとんど必要ない)ポイントになるまでリファクタリングを少し進めるのと同じくらいの作業になることに気付いたときに、実装を開始しました。その後、バックトラックし、最後の変更を元に戻し、リファクタリングしました。未知の領域をマッピングするように聞こえる場合は、領域マップが2次元しかないことを除けば、そう感じているからです。
リファクタリングの準備が完了したら、計画を実行します。集中力が高まっていることを確認し、気を散らすことのない環境を確保してください。この時点でインターネット接続が完全にオフになることもあります。問題は、準備が整っていれば、隣の紙に良いメモを書き、集中力を高めることです。多くの場合、この方法で変更を非常に速く進めることができます。理論的には、ほとんどの作業は準備中に事前に行われました。
カスタムフォントの作り方
実際にコードをリファクタリングしたら、非常に具体的なことを行い、悪いコードのように見える可能性のある奇妙なコードに注意してください。おそらくそれらは悪いコードですが、実際には、本番環境のバグを調査しているときに発見された奇妙なコーナーケースを処理しています。時間の経過とともに、ほとんどのRailsコードは、奇妙なコーナーケースのバグを処理する「髪の毛」または「いぼ」を成長させます。たとえば、IE6に必要な奇妙な応答コードや、奇妙なタイミングのバグを処理する条件などです。それらは全体像にとって重要ではありませんが、それでも重要な詳細です。理想的には、最初にそれらをカバーしようとしない場合でも、それらはユニットテストで明示的にカバーされます。私はかつて、中規模のアプリケーションをRails2からRails3に移植するという任務を負っていました。コードには非常に精通していましたが、少し面倒で、考慮すべき変更がたくさんあったため、再実装を選択しました。実際、これは実際の再実装ではありませんでした。これは決して賢明な動きではありませんでしたが、空のRails 3アプリから始めて、説明したプロセスを大まかに使用して、古いアプリの垂直スライスを新しいアプリにリファクタリングしました。垂直スライスを終了するたびに、古いRailsコードを調べ、各行を調べて、新しいコードに対応するものがあることを再確認しました。私は基本的に、古いコードの「髪の毛」をすべて選び、新しいコードベースに複製していました。結局、新しいコードベースでは、すべてのコーナーケースに対処しました。
手動テストを十分な頻度で実行するようにしてください。これにより、リファクタリングプロセスで自然な「中断」を探す必要が生じ、システムの一部をテストできるようになるだけでなく、自信を持てるようになります。 あなたが予期していなかったものを壊しませんでした プロセスを中断します。
Railsコードのリファクタリングが完了したら、最後にもう一度すべての変更を確認してください。差分全体を見て、それを調べます。リファクタリングの開始時に、現在の知識がなかったために見逃した微妙なことに気付くことがよくあります。これは、大規模なリファクタリングの優れた利点です。特に、最初にコードを記述していなかった場合は、コード編成のより明確なイメージを得ることができます。
可能であれば、同僚にもレビューしてもらいます。彼は、コードベースのその正確な部分に特に精通している必要はありませんが、プロジェクトとそのコードに一般的に精通している必要があります。変化に新たな目を向けることは、大いに役立つ可能性があります。他の開発者にそれらを見てもらうことが絶対にできない場合は、自分自身のふりをする必要があります。ぐっすり眠って、新鮮な心でそれを見直してください。
QAが不足している場合は、その帽子も着用する必要があります。繰り返しになりますが、休憩を取り、コードから離れてから、戻って手動テストを実行してください。たくさんの工具を使って雑然とした電気配線キャビネットに入って、すべてを整理し、場合によっては材料を切断して再配線するのと同じことを行ったばかりなので、通常よりも少し注意が必要です。
最後に、計画されているすべての変更を考慮して、作業の成果を楽しんでください。これにより、よりクリーンで実装が容易になります。
プロジェクトコードを最新かつ高品質に保つために大規模なリファクタリングを定期的に実行することには多くの利点がありますが、それでも非常にコストのかかる操作です。推奨されない場合もあります。
前述のように、テストカバレッジが非常に悪いと大きな問題になる可能性があります。自分の判断で判断してください。ただし、短期的には、新しい機能に取り組み、できるだけ多くのローカライズされた小規模なリファクタリングを実行しながら、カバレッジを上げることに集中する方がよい場合があります。思い切ってコードベースの大部分をソートすることにした場合、これは大いに役立ちます。
わざと「コードベースは変わらない」と言う代わりに過去形を使いました。経験から判断すると(そして経験によって私は何度も間違っていることを意味します)、コードベースの特定の部分をいつ変更する必要があるかについての予測に頼ることはほとんどできません。したがって、次善の策を実行します。過去に目を向け、過去が繰り返されると想定します。何かが長い間変更されていない場合は、おそらく今すぐ変更する必要はありません。その変化がやってくるのを待って、何か他のことに取り組んでください。
コンセプトの作り方
メンテナンスはプロジェクトのライフサイクルの中で最も費用のかかる部分であり、リファクタリングにより費用が安くなります。将来のメンテナンスをより安くするために、技術的負債を減らすためにリファクタリングを使用することは絶対に必要です。そうしないと、新しい機能を追加するのにますます費用がかかるという悪循環に陥る危険があります。それがなぜ悪いのかが自明であることを願っています。
とは言うものの、大規模なリファクタリングは、所要時間に関しては非常に予測不可能であり、途中で行うべきではありません。内的または外的な理由で時間に追われていて、その時間枠内に終了できるかどうか確信が持てない場合は、リファクタリングを中止する必要があるかもしれません。圧力とストレス、特に時間誘導型は、集中力のレベルを低下させます。これは、大規模なリファクタリングに絶対に必要です。チームからより多くの「バイイン」を取得して、その時間を確保し、時間がある期間のカレンダーを調べます。それが継続的な時間である必要はありません。もちろん、他にも解決すべき問題がありますが、それらの休憩は1日か2日を超えてはなりません。もしそうなら、コードベースについて学んだことと、正確にどこで停止したかを忘れ始めるので、自分の計画を思い出す必要があります。
いくつかの有用なガイドラインを提供し、特定の機会に大規模なリファクタリングを実行することの利点を確信させ、必要性をあえて言うことを願っています。トピックは非常にあいまいであり、もちろんここで述べられていることは明確な真実ではなく、詳細はプロジェクトごとに異なります。私の意見では一般的に当てはまるアドバイスを提供しようとしましたが、いつものように、あなたの特定のケースを考慮し、あなた自身の経験を使ってその特定の課題に適応してください。頑張ってリファクタリング!