品質の改善を期待してコードをミニリファクタリングすることは有用ですか、それとも単に「コードを移動する」だけのメリットがありますか?


12

データベースからデータをロードし、HTMLマークアップを表示し、ルーター/コントローラー/アクションとして機能する「すべて」を行うモノリシックコードに出会いました。データベースコードを独自のファイルに移動するSRPを適用し始め、物事の命名を改善しましたが、すべてが見栄えが良かったのですが、なぜこれを行っているのか疑問に思い始めました。

リファクタリングする理由 目的は何ですか?役に立たない?利点は何ですか?モノリシックファイルはほとんどそのままにしておきましたが、作業を行う必要がある領域に関連する小さな部分のみをリファクタリングしたことに注意してください。

元のコード:

具体的な例を挙げると、このコードスニペットに出会いました。既知の製品IDまたはユーザーが選択したバージョンIDのいずれかで製品仕様を読み込みます。

if ($verid)
    $sql1 = "SELECT * FROM product_spec WHERE id = " . clean_input($verid);
else
    $sql1 = "SELECT * FROM product_spec WHERE product_id = " . clean_input($productid) ;
$result1 = query($sql1);
$row1 = fetch_array($result1);
/* html markup follows */

リファクタリング:

この特定のコード部分を変更する必要がある作業を行っているため、リポジトリパターンを使用するように変更し、オブジェクト指向のMySQL機能を使用するようにアップグレードしました。

//some implementation details omitted 
$this->repository = new SpecRepository($mysql);
if ($verid)
    $row1 = $this->repository->getSpecByVersion($verid);
else 
    $row1 = $this->repository->getSpecByProductId($productid);
/* html markup follows to be refactored or left alone till another time*/

//added new class:
class SpecRepository extends MySqlRepository
{

    function getSpecByVersion(int $verid)
    {
        return $this->getMySql()->paramQuery("
            SELECT * FROM product_spec WHERE id = ?
        ", $verid)->getSingleArray();
    }

    function getSpecByProductId(int $productid)
    {
        return $this->getMySql()->paramQuery("
            SELECT * FROM product_spec WHERE product_id = ?
        ", $productid)->getSingleArray();
    }
}

これをすべきですか?

変更を振り返ると、コードは同じ機能を備えていますが、異なるファイル、異なる名前、場所にあり、手続き型ではなくよりオブジェクト指向のスタイルを使用しています。実際、リファクタリングされたコードは、同じ機能を持っているにもかかわらず、はるかに肥大化したように見えることに注意してください。

「リファクタリングの理由が分からない場合は、リファクタリングしないでください」と答えるのを予見し、おそらく同意するかもしれません。私の理由は、時間の経過とともにコードの品質を改善することです(そして、私の希望は、SRPおよび他の原則に従うことでそうすることです)。

これらの十分な理由か、このように「コードの再配置」に時間を無駄にしているのでしょうか?全体的なリファクタリングは、正直言って水を踏むように感じます。時間がかかり、SRPに関する限り「分離」されますが、私の善意にもかかわらず、私は驚くべき改善を行っているとは感じません。したがって、コードを以前のままにしてリファクタリングしないことが最善かどうかを議論します。

そもそもなぜリファクタリングしたのですか?

私の場合、新しい製品ラインに新しい機能を追加するため、同様の製品ラインの既存のコード構造に従うか、独自のコード構造を作成する必要があります。


OTしかし、考慮すSelect * from ..べきことは、アンチパターンと見なすことができるということです。参照してくださいstackoverflow.com/q/3639861/31326
ピーター・M

1
@PeterM:ORMを書いている場合を除き、その場合select *は「ベストプラクティス」になります。
ロバートハーベイ

なぜ私が疑問頂く場合@RobertHarveyにあなたが D:自分のORMを書いている
ピーター・M

より関連のない原因のリファクタリングを行いました。技術的な負債を削減することは、利益がコストを上回るとすぐに効果があります。これはあなたの場合のように見えます。問題は、コードが期待どおりに動作することを確認するための適切なテストがありますか?
ライヴ

1
IMOをリファクタリングするときは、変更性に関連する保守性ではなく、信頼性が主要なメトリックである必要があります。安定性が向上し、完全に安定して信頼性があり、必要なすべての条件を満たすコードは、変更する必要がほとんどないため、メンテナンスコストがほとんどかかりません。できるだけ簡単に変更できるようにするのではなく、変更する理由を減らすように努めてください。前者を探すことは、後者のいくつかを与える傾向があります。

回答:


13

あなたが与えた具体的な例では、少なくともまだ、リファクタリングは必要なかったかもしれません。しかし、あなたは、より長くて退屈なリファクタリングにつながる、より厄介なコードの可能性があることを見たので、あなたは今イニシアチブを取り、物事を整理しました。

また、ここで得られた利点は、少なくとも私の観点からは、コードベースを知らない人として理解しやすいコードだったと思います。


一般に:

リファクタリングにより、他の開発者がコードを理解しやすくなりますか?

リファクタリングにより、コードの強化が容易になりますか?

リファクタリングにより、コードの保守が容易になりますか?

リファクタリングはデバッグを容易にしますか?

これらのいずれかの答えが「はい」である場合、それは価値があり、それは単なる「コードの移動」以上のものでした。

これらすべての答えが「いいえ」であった場合、リファクタリングする必要はないかもしれません。

コードベースの最終サイズは、LoCの観点からは大きくなる可能性あります(ただし、一部のリファクタリングは、冗長コードを合理化することでコードベースを縮小できます)。


9

モノリスを分解する場合、リファクタリングは膨張します。

しかし、あなたはすでに利点を見つけました。

「私の場合、新しい製品ラインに新しい機能を追加しています。」

モノリスに機能を追加することは、物事を壊さずに簡単に行うことはできません。

同じコードがデータを取得してマークアップを実行していると言っていました。特定の条件で表示するように選択および操作している列を変更するまでは、すばらしいです。突然、特定のケースでマークアップコードが機能しなくなり、リファクタリングする必要あります。


はい、しかし、新しい機能でもモノリスに追加し続けることができます:)つまり、新しいif/elseブロックを追加し、元のスタイルのコードに従ってSQLステートメントを追加し、同じHTMLマークアップを同じモノリスファイルに配置します。また、列を変更するには、SQL行を格納するif / elseブロックを見つけ、そのSQLを編集して、そのファイルを分割せずに列を変更します。
デニス

リファクタリングされたアプローチでは、最初にモノリスのif / elseブロックに移動して、SQLを変更するために別のリポジトリファイルに移動する必要があることを確認します。または、そのモノリスに最近取り組んだ場合、代わりにモノリスをバイパスしてリポジトリファイルに直接移動することを知っています。または私は特定のSQLのための私のコードベースを検索した場合、検索にもモノリスをバイパスして新しいリポジトリファイルに私を置く
デニス・

2

そのプロジェクトで数ヶ月、さらには何年も働かなければならないことがわかっている場合は、リファクタリングを検討します。あちこちで変更を行う必要がある場合、コードを移動したいという衝動に抵抗するよりも。

リファクタリングを行う好ましい方法は、ある種の自動化されたテストを含む基本コードがある場合です。それでも、以前と同じように機能するように、変更内容には非常に注意する必要があります。動作するはずの領域以外の領域にバグを配信すると、すぐに信頼を失います。

私は次の理由でリファクタリングを大切にしています:

  • コードをよく理解している
  • 重複したコードを削除するので、1つの場所にバグがある場合、コードがコピーされた場所をすべて探し回る必要はありません。
  • 明確に定義された役割を持つクラスを作成します。たとえば、同じリポジトリを再利用して、HTMLページ、XMLフィード、またはバックグラウンドジョブをハイドレートできます。データベースアクセスコードがHTMLクラスにのみ存在する場合、これは不可能でした。
  • 変数、メソッド、クラス、モジュール、フォルダーが現在の現実と一致しない場合、それらの名前を変更します。I comment変数名、メソッド名を介したコード
  • 単体テストとリファクタリングの組み合わせで複雑なバグを解決します
  • モジュール全体、パッケージ全体を交換できる柔軟性があります。現在のORMが古くなったり、バグがあったり、メンテナンスされていない場合、プロジェクト全体に分散していなければ、簡単に交換できます。
  • 顧客への提案につながる新しい機能や改善点を発見しました。
  • 再利用可能なコンポーネントを作成しました。これは、そのプロジェクトで行われた作業を別のクライアント/プロジェクトに再利用できるため、最大の利点の1つでした。
  • 私はしばしば、最も馬鹿げた、ハードコードされた、奇抜なソリューションから始めます。詳細がわかったら、後でそれをリファクタリングします。この後の瞬間は、今日か、数日後かもしれません。architectソリューションにあまり時間をかけたくありません。これは、書き込み中に発生します-コードを前後に書き換えます。

完全な世界では、リファクタリングは単体テスト、統合テストなどによって検証される必要があります。ない場合は、追加してみてください。また、いくつかのIDEが大いに役立つかもしれません。私は通常お金がかかるプラグインを使用します。リファクタリングに少し時間を費やし、それについて非常に効率的になりたいです。

バグも紹介しました。一部のQAがare you guys doing refactoring? because everything stopped working!これを求めている理由がわかります。これはチームが受け入れる必要があるリスクであり、常に透明性を保つ必要があります。

何年もの間、継続的なリファクタリングによって生産性が向上することがわかりました。新しい機能を追加するのがはるかに簡単でした。また、コードベースが製品の進化に適合しなかった場合によくあったように、大規模な再構築では全体の書き換えは必要ありませんでした。また、楽しいです。


これは非常に近い投票です。「コンピュータープログラマー」には「私」はいません。「私」とは、「私」(反対票)ですか?それとも、開発者が現在および将来のコードに取り組んでいるということですか?
マッテンツ

私もそれに気づきましたが、言葉遣いにそれを置きました。また、私は長年ソロ開発者として働いていましたが、この答えを書いたとき、私はその経験からほとんど繰り返しました。私は置き換えることができItoいるが。
エイドリアンイフトデ

1

あなたが自問しなければならない質問は、それほど「利益はありますか?」ではないと思います。しかし、「誰がこの仕事にお金を払うのですか?」

認識されている利点については、何日も終わるまで議論することができますが、それらの利点を信じて、それを行ってはいけない変更に対して十分な価値を与える顧客がいない限りは。

コードを見るために開発チームのどこかにいて、それをリファクタリングして「より良い」ものにしたいときは、とても簡単です。しかし、製品がすでに動作しているときに「より良いコード」に価値を置くことは本当に難しいです。

「新機能のより速い開発」のようなものは、単にコストが削減されるため、それを削減しません。売上を生み出す必要があります。


1

私の意見では、リファクタリングは良い投資です。

そうしないと、すぐに技術的な負債(未解決の問題、特定の条件下でのみ機能する不良コードなど)が発生します。ソフトウェアがメンテナンスできなくなるまで、技術的な負債はまもなく大きくなります。

しかし、リファクタリングを機能させるには、テストにも投資する必要があります。自動テストを作成する必要があります。理想的には、単体テストと統合テストが必要です。これにより、既存のコードを壊すことがなくなります。

上司や同僚を説得する必要がある場合は、アジャイル手法(SCRUMなど)とテスト駆動開発に関する本を読む必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.