私は ボーイスカウトのルール を信じています。
モジュールをチェックアウトするときよりも常にきれいにチェックしてください。」元の作者が誰であったとしても、モジュールを改善するためにどんなに小さなことでも常に努力した場合はどうなりますか。結果はどうなるでしょうか。すべてがその単純なルールに従っていると、ソフトウェアシステムの容赦ない劣化の終わりが見えます。代わりに、システムは進化するにつれて次第に良くなっていきます。システム全体を管理しているチームも見るでしょう。自分の小さな部分を気遣うだけの個人よりも。
私はまた、関連するアイデア Opportunistic Refactoring を信じています。
いくつかの予定されたリファクタリング作業の場所がありますが、コードをクリーンアップする必要があるときはいつでも、どこでも、誰でも、リファクタリングを日和見的な活動として奨励したいと思います。これが意味することは、誰かがあるべきほど明確でないコードを見たときはいつでも、その場でそれを修正する機会を得る-あるいは少なくとも数分以内に
特に、リファクタリング記事からの次の抜粋に注意してください。
私は、日和見主義リファクタリングの摩擦を引き起こす開発慣行には警戒しています...私の感覚では、ほとんどのチームは十分なリファクタリングを行っていないため、人々がそうすることを妨げていることに注意を払うことが重要です。これをフラッシュするのを助けるために、小さなリファクタリングをやる気がなくなったときはいつでも気をつけてください。そのような障壁は、会話を促すべき臭いです。そのため、落胆を記録し、チームに提示します。少なくとも、次の回顧展で話し合う必要があります。
私が働いているところでは、重い摩擦を引き起こす開発慣行があります-コードレビュー(CR)。 「割り当て」の範囲外の何かを変更するたびに、レビュー担当者から、変更をレビューするのが難しくなっていると非難されます。これは、リファクタリングが含まれる場合に特に当てはまります。これは、「行ごと」の差分比較が困難になるためです。このアプローチはここでの標準です。つまり、日和見主義リファクタリングはめったに行われず、「計画された」リファクタリング(通常は少なすぎ、遅すぎる)が行われるとしても、行われるだけです。
メリットはそれだけの価値があると私は主張し、3人のレビュアーは少し変更して(変更された行の狭い範囲を見るのではなく、実際にコードを理解するために)、レビュー自体はそれだけでより良いでしょう)コードを読んで維持する次の100人の開発者が利益を得られるようにします。私がこの議論を私のレビュアーに提示すると、同じCRにない限り、彼らは私のリファクタリングに問題はないと言います。しかし、私はこれが神話だと主張します:
(1)ほとんどの場合、割り当ての最中にリファクタリングしたいものと方法を理解するだけです。マーティン・ファウラーが言うように:
機能を追加すると、追加するコードの一部に既存のコードとの重複が含まれていることに気づくので、クリーンアップするために既存のコードをリファクタリングする必要があります...何か機能するかもしれませんが、既存のクラスとの相互作用が変更された場合、より良い。自分が終わったと考える前に、その機会にそれを実行してください。
(2)本来想定されていなかった「リファクタリング」CRのリリースを好意的に検討する人は誰もいません。 CRには一定のオーバーヘッドがあり、マネージャーはリファクタリングに「時間を浪費する」ことを望んでいません。予定されている変更にバンドルされている場合、この問題は最小限に抑えられます。
Resharperはこの問題を悪化させます。変更に追加する新しいファイルごとに(どのファイルが最終的に変更されるかを正確に事前に知ることはできません)、通常はlitteredエラーと提案-ほとんどのこれらは完全に修正に値するものです。
その結果、恐ろしいコードが表示され、そのまま残しておきます。皮肉なことに、そのようなコードを修正することは私の立場を改善するだけでなく、実際にそれらを低下させ、仕事をする代わりに誰も気にしないものを修正する時間を無駄にする「焦点の外れた」男として私を描くと感じます。私は本当に悪いコードを軽蔑し、それを監視するのに我慢できず、自分のメソッドからそれを呼び出すことはできないので、私はそれについて気分が悪くなります!
この状況をどのように解決できるかについての考えはありますか?
OK、これでコメントに適したものよりも多くのものがここにあります。
あなたが何をすべきかについてのあなたの直感すべき(あなたが行くにつれてリファクタリング)は正しいです。
これを実装する難しさ-不十分なコードレビューシステムを回避する必要がある場合-は、ソースコードとVCSを操作する難しさに帰着します。複数の人があなたがcanおよびshould変更を(はい、ファイル内でも)複数のコミットに分割すると言っていますが、これを信じるのは難しいようです。
あなたは本当にできますこれを行います。それは本当に私たちが提案していることです。あなた本当にすべき編集、ソース操作、バージョン管理ツールを最大限に活用する方法を学びます。それらを上手に使用する方法を学ぶことに時間を費やせば、それは人生をずっと簡単にします。
基本的には、GlenH7と同じように、2つのコミットを作成することをお勧めします。1つはリファクタリングのみで、(明示的または明らかに)機能的な変更はありません。
ただし、エラーのlotsが見つかった場合は、単一のCR内で修正するエラーの単一のカテゴリを選択すると便利です。次に、「重複コード」、「type-Xエラーの修正」などのコメント付きのコミットが1つあります。これにより、おそらく複数の場所で単一のタイプの変更が行われるため、確認するにはtrivialにする必要があります。それはあなたが見つけたすべてのエラーを修正することができないことを意味しますが、密輸することの苦痛を少なくするかもしれません。
作業ソースに加えられた変更を複数のコミットに分割することは難しいことではありません。何を使っているかは言っていませんが、可能なワークフローは次のとおりです。
gitを使用している場合、このための優れたツールがあります
git add -i
を使用できますgit gui
を使用して、個別のハンクと行を選択してステージすることができます(これは、コマンドラインよりも実際に私が好むいくつかのVCS関連のGUIツールの1つで、もう1つは優れた3ウェイマージエディターです)rebase -i
で分割したりできます。gitを使用していない場合でも、VCSはこの種のツールを備えている可能性がありますが、使用しているシステムがわからない場合はアドバイスできません
TFSを使用しているとのことですが、TFS2013以降、gitと互換性があると思います。リポジトリのローカルgitクローンを使用して作業することは実験に値するかもしれません。これが無効になっているか、機能しない場合でも、ソースをローカルgitリポジトリにインポートして、そこで作業し、それを使用することができます。最終コミットをエクスポートします。
diff
やpatch
などの基本的なツールにアクセスできる場合は、任意のVCSで手動で実行できます。それはもっと痛いですが、確かに可能です。基本的なワークフローは次のとおりです。
diff
を使用して、最後のコミット以降のすべての変更を含む(コンテキストまたは統合)パッチファイルを作成しますpatch
を使用してパッチファイルの1つを再生し、それらの変更をコミットしますこれで2つのコミットがあり、変更が適切にパーティション分割されました。
このパッチ管理を容易にするツールがおそらくあることに注意してください-gitが私のためにそれを行うので、私はそれらを使用しません。
私は、変更要求があなたの会社で大きく正式であると仮定します。そうでない場合は、変更を(可能な場合) 多くの小さなコミット に変更します(想定どおり)。
この状況を改善するにはどうすればよいですか?
あなたがしていることを続けますか?
つまり、あなたの考えや控除はすべて完全に正しいです。目にしたものを修正する必要があります。計画的なリファクタリングは十分に行われていません。そして、グループ全体へのその利益は、いくつかを不便にするよりも重要です。
助けになるのは、戦闘力を減らすことです。コードレビューは「なぜあなたはそれをしたのですか?」という格闘的なものであってはならず、彼らは共同で「こんにちは。その文化を変えるために(可能であればあなたのリード/マネージャーと一緒に)働くことは難しいですが、高機能の開発チームを作るにはかなり重要です。
また、可能であればリード/マネージャーと協力して、これらのアイデアの重要性を同僚と進めることができます。 「なぜ品質を気にしないの?」彼らが「なぜあなたはいつもこれらの役に立たないことをしているのですか?」と尋ねるのではなく。
私はあなたの状況に同情していますが、具体的な提案はほとんどありません。他に何もない場合は、状況と同じくらいひどい場合は、もっと悪い可能性があると私はあなたに納得させます。それは常に悪化する可能性があります。 :-)
まず、私はあなたの文化には(少なくとも)1つではなく2つの問題があると思います。 1つの問題はリファクタリングへのアプローチですが、コードレビューは別の問題のようです。私は私の考えを分離しようとします。
コードレビュー
私はコードレビューを嫌いなグループにいました。グループは、会社の別々の部分からの2つのグループをマージすることによって形成されました。私は数年前からコードレビューを行っていたグループの出身で、概ね良好な結果が得られました。私たちのほとんどは、コードレビューは私たちの時間の有効な利用だと信じていました。私たちはより大きなグループに統合しましたが、私たちが知る限りでは、「他の」グループはコードレビューさえ聞いたことがありませんでした。今、私たちは皆「彼らの」コードベースに取り組んでいました。
私たちが合併したとき、物事はよくありませんでした。新機能は毎年6〜12か月遅れでした。バグのバックログは巨大で、増大し、生命を浪費していました。特に最上級の「教祖」の間で、コードの所有権は強力でした。 「機能ブランチ」は数年続くこともあり、いくつかのリリースにまたがっていました。時にはNOBODYですが、メインブランチに到達する前に1人の開発者がコードを見ました。実際、「機能ブランチ」は、コードがリポジトリのどこかにあることを示唆しているため、誤解を招く可能性があります。多くの場合、それは開発者の個々のシステムのみにありました。
経営陣は、品質が許容できないほど低くなる前に「何かをする」必要があることに同意しました。 :-)彼らの答えはコードレビューでした。コードレビューは、すべてのチェックインの前に公式の「Thou Shalt」アイテムになりました。私たちが使用したツールはレビュー委員会でした。
私が説明した文化ではどのように機能しましたか?何もないよりはましですが、苦痛であり、一種の最小レベルのコンプライアンスに到達するのに1年以上かかりました。私たちが観察したいくつかのこと:
コードレビューについていくつかの段落を書こうと思っていましたが、主に文化について書いていることがわかりました。結局のところ、コードレビューはプロジェクトに役立つ可能性がありますが、チームは得るに値するメリットしか得られません。
リファクタリング
私のグループは、コードレビューを嫌う以上にリファクタリングを軽視しましたか?もちろん!すでに言及されているすべての明白な理由のため。おかしなコードレビューで私の時間を無駄にしており、機能を追加したり、バグを修正したりすることすらありません。
しかし、コードは依然としてリファクタリングの必需品でした。どうやって進める?
なぜ両方を行わないのですか?別々のコミットで?
あなたの仲間はポイントを持っています。コードレビューでは、他の誰かによって変更されたコードを評価する必要があります。 あなたは、他の誰かのためにレビューしているコードに触れてはいけません。
ただし、いくつかの重大な問題が発生した場合は、2つの方法があります。
コードレビューに問題がなければ、レビューした部分をコミットして、2回目のチェックインでコードをリファクタリングできるようにします。
コードレビューに修正が必要な問題があった場合は、Resharperの推奨事項に基づいてリファクタリングするよう開発者に依頼してください。
私は個人的に、コミット後のコードレビューのアイデアを嫌っています。コードを変更すると、コードレビューが行われます。もちろんここで話しているのはペアプログラミングです。ペアリングすると、無料でレビューが提供され、より優れたコードレビューが得られます。今、私はここで私の意見を表明しています。他の人がこれを共有していることを知っています。おそらくこれを証明する研究があるでしょう。
コードレビュー担当者とペアを組めるようになれば、コードレビューの闘争的な要素がなくなるはずです。理解できない変更を加え始めると、変更の時点で問題が提起され、議論され、代替案が検討されるため、より良いリファクタリングにつながる可能性があります。ペアは変更のより広い範囲を理解でき、コードを並べて比較することで得られる行ごとの変更にそれほど重点を置かないため、より高品質のコードレビューが得られます。
もちろん、これは作業中の変更の範囲外にあるリファクタリングの問題に対する直接の答えではありませんが、変更を加えたときにそこにいる場合は、変更の背後にある理由を同僚がよりよく理解できると思います。
余談ですが、TDDまたは何らかの形式の赤と緑のリファクタリングを実行している場合、ピアから確実にエンゲージメントを得る1つの方法は、ピンポンペアリング手法を使用することです。ドライバーがRGRサイクルの各ステップでローテーションされると簡単に説明されます。つまり、ペア1は失敗したテストを書き込み、ペア2はそれを修正し、ペア1はリファクタリングし、ペア2は失敗したテストを書き込みます。
おそらくこの問題は、組織の文化に関するはるかに大きな問題を反映しています。人々は製品をより良くするよりも「仕事」に興味を持っているようです。おそらくこの会社には協調文化ではなく「責任」の文化があり、人々は製品/会社全体のビジョンを持つよりも自分自身をカバーすることに関心があるようです。
私の意見では、あなたは完全に正しいです。あなたのコードをレビューする人々は、あなたが「あなたの割り当て」以外のものに「触れる」ために不満を持っている場合、それらの人々を説得しようとしますが、あなたの原則に決して決して反対しないので、私にとってこれは完全に間違っています。真のプロフェッショナルの最も重要な品質。
そして、あなたの作品を評価する愚かな企業のやり方で正しいことがあなたに悪い数字を与えた場合、何が問題なのでしょうか?誰がこの評価ゲームを狂った会社で「勝ち取りたい」のか、それを変えようとします!あなたは疲れていて、別の場所を見つけますが、決してあなたの原則に反することはありません、あなたが持っている最高のものです。
時々、リファクタリングは悪いことです。しかし、コードレビューアが与えている理由のためではありません。彼らは実際にはコードの品質を気にしていないようですが、あなたはdo気にかけており、それは素晴らしいことです。しかしリファクタリングを妨げる2つの理由:1。自動テスト(単体テストなど)で行った変更をテストすることはできません2。よく理解していないコードに変更を加えています。つまり、変更によってどのような変更が必要かを知るためのドメイン固有の知識がありません。
コードレビューを行う人は、あなたが行った変更が、以前は機能していたものを壊していないことを確認できる必要があります。これが、作業コードをそのままにする最大の理由です。はい、間違いなく1000行の長い関数(これは本当に忌まわしいです!)を一連の関数にリファクタリングすることをお勧めしますが、テストを自動化できない場合、すべてのことを他の人に納得させることは非常に困難です。正しい。私は間違いなく以前にこの間違いを犯したことがあります。
リファクタリングの前に、単体テストがあることを確認してください。単体テストがない場合は、いくつか書いてください!次に、リファクタリングします。コードレビューアは、動揺する(正当な)言い訳はありません。
私が働いている場所には、化学工学に重いコードがたくさんあります。コードベースは、化学エンジニアに共通のイディオムを使用しています。 フィールドに慣用的な変更を加えないでください。x
と呼ばれる変数の名前をmolarConcentration
に変更するのは良い考えのように思えるかもしれませんが、どうでしょうか? all化学テキストでは、モル濃度はx
で表されます。名前を変更すると、そのフィールドの人々のコードで実際に何が行われているのかを知ることが難しくなります。
慣用的な変数の名前を変更する代わりに、それらが何であるかを説明するコメントを入れてください。それらが慣用的である場合ない慣用的な場合、それらの名前を変更してください。より適切な名前が機能する場合は、i
、j
、k
、x
、y
などをそのままにしないでください。
略語の経験則:人々が話しているときに略語を使用する場合、コードでその略語を使用しても問題ありません。作業中のコードベースの例:
「Area of Concern」は「AOC」になり、「Vapor cloud explosion」はVCEになるなど、次のような概念があります。私たちのコードベースでは、誰かがaocと呼ばれるすべてのインスタンスをAreaOfConcernに、VCEをvaporCloudExplosionに、nPlanesをconfiningPlanesCountにリファクタリングしました...これにより、ドメイン固有の知識を持つ人々にとってコードが実際に読みにくくなりました。私もこのようなことをすることに罪を犯しています。
これは実際にはあなたの状況にまったく当てはまらないかもしれませんが、この問題について私の考えがあります。
この質問には2つの異なる問題があります。コードレビューでの変更のレビューのしやすさ、およびリファクタリングに費やされた時間です。
私が働いている場所では、激しい摩擦を引き起こす1つの開発方法-コードレビュー(CR)があります。 「割り当て」の範囲外の何かを変更するときはいつでも、レビュー担当者から、変更をレビューするのが難しくなっていると非難されます。
他の答えが言ったように-リファクタリングチェックインをコード変更チェックインから分離できますか(必ずしも個別のレビューとしてではありません)?コードレビューを行うために使用しているツールによっては、特定のリビジョン間の差分のみを表示できるはずです(AtlassianのCrucibleは間違いなくこれを行います)。
(2)本来想定されていなかった「リファクタリング」CRのリリースを好意的に検討する人は誰もいません。 CRには一定のオーバーヘッドがあり、マネージャーはリファクタリングに「時間を浪費する」ことを望んでいません。予定されている変更にバンドルされている場合、この問題は最小限に抑えられます。
リファクタリングが簡単で、コードを理解しやすくする場合(これがリファクタリングだけの場合は、これで十分です)、コードレビューの完了に時間がかかりません。将来再びコードを確認する必要があります。上司がこれを理解できない場合は、ボーイスカウトルールによってコードとの生産性が向上する理由を説明するリソースに向けて、上司をそっと微調整する必要がある場合があります。 「あなたの時間の無駄」が、あなたや他の誰かがそのコードに対してさらに作業を行うために戻ってきたときに、2、5、または10倍節約できることを彼らに納得させることができれば、問題は解消するはずです。
Resharperは問題を悪化させます。変更に追加する新しいファイルごとに(どのファイルが変更されるか正確に前もって知ることはできません)、通常、エラーや提案が散らばっています。修正。
これらの問題を同僚の注意を引き、修正する価値がある理由について話し合ったことがありますか?そして、それらのいずれかを自動的に修正できますか(自動リファクタリングで問題が発生していないことを確認するのに十分なテストカバレッジがあると仮定します)?本当に気の毒なものである場合、リファクタリングを実行することは「あなたの時間に値する」とは限りません。チーム全体でReSharperを使用していますか?もしそうなら、あなたはどの警告/ルールが施行されているかについての共有ポリシーを持っていますか?そうでない場合でも、おそらく、将来の痛みの原因となる可能性のあるコードの領域を特定するためにツールがどこで役立つかを示す必要があります。
私もボーイスカウトのルールと日和見主義的リファクタリングを信じています。多くの場合、問題は経営陣の賛同を得ることです。リファクタリングにはリスクとコストの両方が伴います。経営陣が見落としがちなのは、技術的負債も同様に見落としていることです。
それは人間の本性です。私たちは本当の問題に対処することに慣れており、それを防止しようとはしていません。私たちは積極的ではなく、積極的です。
ソフトウェアは無形であり、車のように修理が必要であることを理解するのは困難です。道理にかなった人が車を買ってそれを修理することは決してないでしょう。そのような過失があると、その寿命が短くなり、長期的にはコストが高くなります。
多くのマネージャがこれを理解しているという事実にもかかわらず、彼らは本番コードへの変更に対して責任を負います。一人で十分に離れることを容易にする政治があります。多くの場合、説得力を必要とする人は実際にはあなたのマネージャーよりも上であり、彼は単にあなたの「素晴らしいアイデア」を生産に取り入れるために戦いたくありません。
正直に言うと、あなたのマネージャーはあなたの救済策が実際にはあなたが思っているほど優れていると常に確信しているわけではありません。 (ヘビ油?)セールスマンシップがあります。彼がメリットを理解できるようにするのはあなたの仕事です。
経営陣はあなたの優先事項を共有しません。管理用の帽子をかぶって、管理の目で見てください。あなたはおそらく正しい角度を見つけるでしょう。しつこい。最初の否定的な応答があなたを抑止しないようにすることで、より多くの変化をもたらすでしょう。
25年ほど前に他の目的でたまたま作業していたコードを「クリーンアップ」したことを覚えています。ほとんどの場合、コメントブロックとタブ/列の配置を再フォーマットして、コードをきちんと整理して理解しやすくしています(実際の機能変更はありません)。 。たまたまlike整然とした整然としたコードです。さて、上級開発者たちは激怒しました。ある種のファイル比較(diff)を使用して、ファイルの個人用コピーと比較して何が変更されたかを確認しましたが、今ではあらゆる種類の誤検知が発生しています。私たちのコードライブラリはメインフレーム上にあり、バージョンコントロールがありませんでした-基本的に、そこにあるものは何でも上書きしました。
物語の教訓?私は知らないよ。たぶん、自分以外は誰も喜ばせられないのではないでしょうか。時間を無駄にしていませんでした(私の目では)-クリーンアップされたコードだった読みやすく、理解しやすくなりました。他の人が使用するプリミティブな変更管理ツールが、追加のワンショット作業を追加するだけです。ツールはあまりにも原始的すぎて、スペース/タブやリフローされたコメントを無視できませんでした。
@ Useless、@ Telastynなどで指摘されているように、要求された変更と要求されていないリファクタリングを(多数の)個別のコミットに分割できる場合、それが最善の方法です。 「リファクタリング」CRを作成するという管理上のオーバーヘッドなしに、単一のCRで作業します。コミットを小さく集中してください。
それを行う方法についていくつかアドバイスを与えるのではなく、専門家からのより大きな説明(実際には本)を紹介することをお勧めします。これにより、さらに多くのことを学ぶことができます。 Michael Feathersによるレガシーコードの効果的な使用をお読みください。この本は、機能の変更をインターリーブしてリファクタリングを行う方法を教えることができます。
取り上げるトピックは次のとおりです。
この本には、プログラム要素を分離して操作し、より安全な変更を行うのに役立つ24の依存関係をなくす技法のカタログも含まれています。
@ GlenH7で示されているように、リクエストされた変更とリクエストされていないリファクタリングを2つの個別の変更リクエストに分割できる場合、それが最善の方法です。あなたは「時間を無駄にする男」ではなく、「2倍の努力をする男」です。
要求された作業をコンパイルするために要求されていないリファクタリングが必要になったため、分割できない状況に頻繁に遭遇する場合は、コーディング標準を自動的にチェックするツールを使用することを強くお勧めします 概説した引数を使用)ここに (Resharperの警告自体は良い候補かもしれませんが、私はそれに精通していません)。これらの引数はすべて有効ですが、利点を生かすことができるもう1つの点があります。これらのテストを行うことで、テストを渡すdutyになります。各コミット。
あなたの会社が「リファクタリングに無駄な時間を費やす」ことを望まない場合(彼らの側の悪い兆候)、彼らはあなたに「警告抑制」ファイル(各ツールは独自のメカニズムを持っています)を提供して、もう煩わされないようにする必要がありますそのような警告。これは、最悪の場合でも、さまざまなシナリオのオプションを提供するためです。また、双方の暗黙の仮定よりも、予想されるコード品質に関して、あなたとあなたの会社との間の合意を明確に示すことをお勧めします。