DRYはソフトウェアプロジェクト管理の敵ですか?


83

ソフトウェア開発の最も基本的で広く受け入れられている原則の1つはDRYです(繰り返してはいけません)。また、ほとんどのソフトウェアプロジェクトには何らかの管理が必要であることも明らかです。

では、管理が簡単なタスク(見積もり、スケジュール、制御)は何ですか?正しい反復タスク、DRYに従って回避すべきタスク。

そのため、プロジェクト管理の観点からは、既存のコードを100回コピーしてタスクを解決し、必要に応じて各コピーに若干の修正を加えることは素晴らしいことです。常に、あなたが行った仕事の量と残っている量を正確に知っています。すべてのマネージャーはあなたを愛します。

代わりに、DRYの原則を適用して、重複するコードを多かれ少なかれ除去する抽象化を見つけようとすると、状況は異なります。通常、多くの可能性があります、あなたは決定を下し、研究を行い、創造的でなければなりません。短い時間でより良いソリューションを思いつくかもしれませんが、失敗することもあります。ほとんどの場合、どれだけの作業が残っているかを実際に言うことはできません。あなたはプロジェクトマネージャーにとって最悪の悪夢です。

もちろん大げさですが、明らかにジレンマがあります。私の質問は次のとおりです。開発者がDRYをやりすぎているかどうかを判断する基準は何ですか?どうすれば良い妥協点を見つけることができますか?または、妥協を見つけるだけでなく、このジレンマを完全に克服する方法はありますか?

注:この質問は、前の質問「ソフトウェア開発における日常作業の量と推定への影響」と同じ考えに基づいていますが、それが私のポイントをより明確にするので、繰り返して申し訳ありません:)。


96
これらの100個すべてのコピーアンドペーストされたインスタンスで何かを探し、変更し、テストするときが来たら、プロジェクト管理がどのように感じているかを教えてください。実際に変更されたのはそのうちの98だけであるため、なぜ壊れてしまうのかを突き止めるために費やされる追加の時間を忘れないでください。
Blrfl

16
一方、@ Blrflでは、共有された抽象化は共有された依存関係であるため、適切な抽象化が明確になる前にコードを時期尚早にDRYしてしまうと、生産性も低下します。ちなみに、私は反対していません。ただ、バランスが取れていることを指摘するだけです。
GoatInTheMachine

16
DRYが制御不能になるのを防ぐ原則は、YAGNI(あなたは必要ではない)原則です。
フィリップ

88
ジレンマはありません。見積もりが簡単であるためにプロジェクトマネージャーが多くの余分な手動作業を行うことを望んでいる場合、明らかな解決策はプロジェクトマネージャーを解雇することです。
ジャックB

10
繰り返しますが、それでも見積もりが難しい他のすべての作業に加えて、余分な無意味な作業を行う必要があります。それはプロジェクトにどのように役立ちますか?
user253751

回答:


134

プロジェクト管理の主な目的は、正確な見積もりを作成することだと思われるようです。これはそうではありません。プロジェクト管理の主な目的は、開発者と同じです。製品所有者に価値を提供することです。

理論上、自動化ではなく低速の多くの手動プロセスを使用する製品は、推定しやすいかもしれませんが(疑いはありますが)、顧客に価値を提供するわけではないため、単に悪いプロジェクト管理です。ジレンマはありません。

ソフトウェアプロジェクトの見積もりは困難であり、それを管理するために多数の書籍が執筆され、さまざまなプロセスが開発されていることはよく知られています。

PMの唯一の目的が正確な推定値を作成することであれば、それは簡単です。見積もりを10倍に詰め込み、開発者が残りのゲームを早めに終わらせることができるようにします。ゲームをプレイしても製品の保守性が低下することはないので、これは実際に時間を埋めるためにコピーアンドペーストビジーワークを使用する提案よりも優れています。

しかし、実際には、製品の所有者は有用な見積もり高品質の製品を可能な限り迅速かつ安価に提供することを望んでいます。これらは、PMがナビゲートしなければならない実際の制約です。

いずれにせよ、手作業の繰り返しは自動化よりも予測しやすいという前提に異議を唱えます。すべての経験は、反復的な手作業がよりエラーを起こしやすいことを示しています。また、コピーアンドペーストされたコードにバグが見つかった場合はどうなりますか?突然、バグを修正するコストに繰り返しの量が乗じられ、不確実性が爆発します。


21
ここでのあなたの主張には完全に同意しますが、スピードや品質よりも予測可能性を本当に好むプロジェクトマネージャーがたくさんいることに注意する必要があると思います。プロジェクト管理のトレーニングを受けていないほとんどの人は、見たことからそれについて知っていることを学びます。私の経験では、落ち着いた合理的な方法で不確実性に対処できるプロジェクトマネージャーはほとんどいません。
ジミージェームズ

5
@FrankPuffer行ったことあります。どのくらい時間がかかりますか?ここでの1つのオプションは、範囲を提供することです。特に3点の見積もりについては、PERTを読んでください。完了率?これは最も厄介です。無視してみてください。ただし、コード化された行の割合などではなく、時間の割合であることを思い出せない場合。彼らが本当に知りたいのは、いつ完成するのかということです。早い段階で、各タスクについて控えめな予測を行い、進むにつれて改善します。最後の最後まで待って、もっと時間をかけると、人々は夢中になります。
ジミージェームズ

11
どのくらい時間がかかりますか?私はそれをxで終えることができると確信していますが、5倍の時間がかかる可能性は10%です。
デビッド

18
@David:経験から、この10%の確率が実際に80%の確率で起こることを知っているので、これはおそらくPMを狂わせるでしょう:)
フランクパファー

7
現実には、多くの場所がプロジェクトを地面に追跡したいと思っていて、予想外に成功します。PMは、正確な予測をしたことで報われることが多いため、逆のインセンティブがあります。これは、プリンシパルエージェントの問題です。
そり

39

あなたは正しいです-コピーと貼り付けはうまく機能し、DRYは、コピーされたテンプレートまたはコピーのいずれかを将来維持または進化させる必要のないプログラムを作成することがあなたの仕事であるときに意味がありません。これらの2つのソフトウェアコンポーネントのライフサイクルが完全に異なる場合、共通のコードをリファクタリングして相互に結合し、それ自体が開発中の共通ライブラリに統合されると、実際に予測できない効果が生じる可能性があります。一方、1つのプログラムまたはプログラムシステム内でコードセクションをコピーする場合、これらの部分はすべて通常同じライフサイクルを持ちます。これがDRYとプロジェクト管理にとって何を意味するかを以下に説明します。

真剣に、そのようなプログラムがたくさんあります:たとえば、コンピューターゲーム業界は、最大で数ヶ月または1年の短い期間にわたって維持しなければならない多くのプログラムを生成し、その時間が終わったら、コピー&ペーストメンテナンス期間を超過した以前のゲームの古いコードを、新しいゲームのコードベースに完全に入れると、速度が向上する可能性があります。

残念ながら、私が過去数年間に対処しなければならなかったほとんどのプログラムのライフサイクルは、それとは非常に異なっています。私に届いた要件またはバグ修正リクエストの98%は変更リクエストでした既存のプログラム用。既存のソフトウェアの一部を変更する必要がある場合は、テストとデバッグの作業が非常に少ないときに「プロジェクト管理」または計画が最適に機能します。 -貼り付けられたビジネスロジックは、コードベースの他の12の場所も変更する必要があることを簡単に忘れてしまいます。そして、それらすべての場所を見つけることができたとしても、それらをすべて変更する(そして変更をテストする)時間は、たぶん、変更する場所が1つしかないかのようにはるかに長くなります。そのため、変更の正確な見積もりを行うこともできます。必要なコストよりも数十倍高いコストを設定すると、プロジェクトの予算と簡単に衝突する可能性があります。

TLDR-オリジナルまたはコピーのバグ修正とメンテナンスの必要性または責任がないプログラムを開発する場合は、いつでもコピーしてください。しかし、あなた、あなたのチーム、またはあなたの会社が責任がある、またはそうなる可能性がある場合は、できる限りDRYを適用してください。

補遺として、「バグ修正とメンテナンス」が何を意味するのか、そして実際の例を挙げて、特に1つの製品の内部で、これが計画の予測不能性にどのようにつながるかを説明します。実際、このような種類の問題は、おそらく100インスタンスではなく、実際に発生しますが、重複インスタンスが1つしかない場合でも問題が発生する可能性があります。

タスク:アプリケーションごとに100の異なるレポートを作成します。各レポートは非​​常に似ており、レポート間の要件の違い、異なるロジックがありますが、全体としては多くの違いはありません。

このタスクを取得した開発者は最初のタスクを作成し(3日かかると言います)、QAと顧客検査によるいくつかの変更またはマイナーなバグ修正が完了した後、正常に実行されるようです。その後、彼はすべてをコピー&ペーストして次のレポートを作成し、次に次のレポートを作成し始めました。新しいレポートごとに、平均で約1日必要です。一目で非常に予測可能...

現在、100のレポートが「準備完了」になった後、プログラムは実際の生産に移行し、QA中に見落とされていたいくつかの問題が発生します。パフォーマンスに問題がある可能性があります。レポートが定期的にクラッシュする可能性があり、意図したとおりに機能しない可能性があります。現在、DRYの原則が適用されたとき、これらの問題の90%は、コードベースを1か所で変更することで解決できました。ただし、コピーと貼り付けのアプローチにより、問題は1回ではなく100回解決する必要があります。また、あるレポートから別のレポートに既に適用された変更のため、開発者は最初のレポートの修正を他の99にすばやくコピーアンドペーストできません。100個すべてのレポートを調べ、それらを読み、変更を修正済みに変換する必要があります報告、テスト、そして多分それを個々にデバッグします。PMの場合、これは本当に難しくなり始めます-もちろん、彼は「通常の」バグ修正に時間をかけ(3時間と言います)、これに100を掛けることができますが、実際には、これはおそらく間違った推定であり、修正の一部は他の人より作るのが簡単で、他の人はもっと難しいかもしれません。また、この見積もりが正しい場合でも、必要なデバッグ費用が100倍になると、会社に多額の費用がかかります。

次回、顧客がすべてのレポートで会社のエンブレムの色を変更したり、ページサイズを構成可能にしたり、同様の方法ですべてのレポートに影響する他の新しい要件を要求したときにも同じことが起こります。その場合、コストを見積もって、コードがDRYであったときに支払う必要がある価格の100倍を顧客に請求できます。ただし、これを数回試してみると、顧客はプロジェクトをキャンセルすることになります。なぜなら、彼はおそらくあなたの法外な進化費用を支払う気がないからです。そして多分その時点で誰かがなぜこれが起こったのかという質問をし、このコピー・ペースト・プログラミングの決定をした人を指で指し示すでしょう。

私のポイントは、他の人のためにソフトウェアを作成するとき、少なくとも短期間、常に動作させる、バグを修正する、プログラムを変化する要件に適応させるなどの責任を負っていることです。部品は、当初計画されていた開発作業よりもはるかに多くを迅速に追加できます。特に、すべてのコピーペーストされたコードが1つの製品内にある場合、責任期間はすべての部分で同じです。これは、もはやなくなったプロジェクトから古いコードをコピーペーストした状況とはまったく異なります。アクティブなメンテナンス中。


4
おそらく良い答えですが、他の良い答えと比べて冗長すぎます。
ビンスオサリバン

4
「将来、コピーを維持または進化させる必要がない」場合は、DRYを無視できますが、二度と使用されないコードは、とにかく再び使用されることになります。
アンディレスター

「コピーと貼り付けはすばらしい...」-同意しない!プログラムが1回限りであり、初期リリース以降に進化しないことが保証されている場合でも、コピーアンドペーストコードにより、プログラムの初期バージョンの開発中に見つかったバグを修正するための作業とリスクが大幅に増えます。間違いを犯さない限り、あなたは神です。
ジャックB

1
@JacquesB:あなたは私の答えをもっと注意深く読むべきです、私は別の何かを書いていません。
ドックブラウン

コンピュータープログラミングは、組立ラインで同一のマシンを構築することとはまったく異なります。ほら 誰がそれをサンクしたでしょうか?たぶん、PMとして働くプログラマがいるはずです。しかし、その後、マネージャーとしてプログラマーが必要になります。株主としてのプログラマー。顧客としてのプログラマー...撮影して、プログラミングとそれを行う方法をみんなに教えてください。(言い換えれば、非専門家は決して専門家によって知られている変遷を理解するつもりはありません。)

19

そのため、プロジェクト管理の観点からは、既存のコードを100回コピーしてタスクを解決し、必要に応じて各コピーに若干の修正を加えることは素晴らしいことです。常に、あなたが行った仕事の量と残っている量を正確に知っています。すべてのマネージャーはあなたを愛します。

ベースアサーションが正しくありません。

ソフトウェアを他の職業と異なるものにしているのは、毎日新しいものを作っているということです。結局のところ、他の誰かがすでに作成したものを構築するために顧客があなたに支払うつもりはありません。プロジェクトマネージャーは予測可能性を好むかもしれませんが上司は価値を好むでしょう。わずかなバリエーションのあるコードをコピーアンドペーストするだけの場合、会社にとって大きな価値はありません。

最終的に会社は、優秀なプログラマーを雇うことで、ほんの少しの時間で同じ仕事をすることができることに気付くでしょう。そして、そうでない場合、彼らの競争相手はそうするでしょう。


2
ほとんどのエンジニアリングの専門家は「毎日新しいものを作る」ことだと主張するだろう
BlueRaja-ダニーPflughoeft

12
@ BlueRaja-DannyPflughoeft:そうでもない。電子工学/電気工学のエンジニアとして働いたことがあるので、ほとんどの大規模な工学の専門職(船や発電所の建設などの試運転を必要とするプロジェクト)は、試されてテストされた人々がそれを適切に行うことを確認することについて証言できます。それがビジネスが「エンジニアリング」と考えるものです。新しいものを作ることは「R&D」
-slebetman

3
@slebetman経営陣が行っているすべての作業に気付いていないかもしれません。同じことを何度も繰り返している場合でも、環境は毎回変化します。顧客に提供してそれを行うだけの発電所のテンプレートはないため、調査を行う必要があります。工場に原材料を供給し、製品を持ち帰り、建設用のすべての原材料を管理し、供給の問題や作業不足、その他数百万の問題に対処する方法を見つけます。(多くのソフトウェアの取り組みと同様に)テンプレート作業のように見えますが、実際はそうではありません。
ルアーン

1
@Luaan:はい。しかし、そのどれもが新しいものを生み出しているわけではありません。それらのすべては「私たちが行う方法を知っていることをしている」。ソフトウェア開発は異なります。主にソフトウェアでは、物理的なエンジニアリングプロジェクトとは異なり、ライブラリで行う方法を既に知っていることをカプセル化する傾向があるため、手動で「調査を行う」などする必要はありません。そのためにライブラリをインポートして使用するだけです。
スリーブマン

2
@slebetman書かれているソフトウェアのほとんどすべては、「方法を知っている何か」です。図書館はまた、常に変化する環境に住んでいます。また、ライブラリ全体、およびそのライブラリのすべての依存関係、および他の依存関係に関する100%の知識と経験はなく、合理的なシステムの動作を拒否する奇妙なシステムとハードウェア構成がたくさんあります。作業。カプセル化は優れていますが、それでも地獄のように高価であり、大量の調査が必要です。また、エンジニアリングにはカプセル化もあります-プレハブブロック、ICなど
-Luaan

12

カットアンドペーストプログラミングは、最終的には放棄されたソフトウェアにつながります。私は、非常に大きな電話会社に有線サービスを注文するシステムの請負業者でした。すべてのテストは手動で行われ、動作するコードを変更する必要はなかったため、システムはカットされて貼り付けられた悪心でした。最も小さな機能強化により、数百行のコードの新しいコピーが作成される可能性があります。もともと、アプリケーションは最大12の物理回線のアカウントを処理するように作成されていました。もちろん、この制限はコード内の数百の場所で行われました。約4年後、ビジネスはより大きなアカウントを処理するために何が必要かをチームに尋ねました。彼らは約1800万ドルを見積もった。その時点で、プロジェクトは最小限のメンテナンスでオフショアチームに引き継がれました。既存のチームは全員解雇されました。

このように考える組織は、より優れた技術を持つ企業に押しつぶされています。


優れた技術よりも優れた脳だと考えています。テクノロジーは脳から生まれますよね?「より賢く、難しくはない」とはどうなりましたか?

10

ここで当てはまる忘れがちな格言は3のルールです。これは、一度コードをコピーしても問題ありませんが、それを超えて汎用コードに置き換える必要があることを示しています。

3は任意の数字のように見えますが、一般的なシナリオは、アプリケーションとデータベースでデータとロジックが複製される場合です。よく引用される例は、データベースと列挙クライアント側にルックアップテーブルがある場合です。パラダイムの違いにより、これを単一の場所に簡単に保存することはできないため、情報はしばしば両方の場所に表示されます。

DRYコードがあると便利ですが、ビジネスロジックが例外を指示する場合があるため、以前は汎用だったソースから2ビット以上のコードを作成する必要があります。

じゃあ何をすればいいの?現状のコード(やっぱりYAGNI)。変更を容易にするためにコードを作成する必要がありますが、必要のないもののためにたくさんのベルやホイッスルを作成することは、ただお金を燃やすだけです。


6
これは、コードを(両方の場所で)コピーしたことをコメントする必要があることを意味しているので、再度コピーしようとしているかどうかを確認する必要があることに注意してください。
マークハード

3
これは、2つのクラスが同じメソッドを必要としているが、ほとんど関連していない場合(遠い従兄弟のようなもの)で実行しました。実際にコードを共有するには、ほぼ12個のクラスに依存関係を追加する必要がありました。だから私はマークが提案したものが好きだった-メソッドをコピー&ペーストし、またそのメソッドの他の場所を指摘する大きな明白なコメントを残した。
ジュトナルグ

@MarkHurdうん- ...素晴らしいポイント
ロビーディー

8

質問では、プロジェクト管理の3つの機能(見積もり、スケジュール、および制御)のみをリストします。プロジェクト管理とは、プロジェクトの制約内で目標を達成することです。プロジェクトの制約内で目標を達成するために使用される方法は、ソフトウェアプロジェクトでは他の多くのタイプのプロジェクトとは異なります。たとえば、製造プロセスの再現性と理解度を高めたいと考えています。ただし、ソフトウェア開発は主に知識作業です-それは非定型であり、厳格な指示や手順に従うのではなく、考える必要があります。ソフトウェアプロジェクトの開始、計画、実行、監視、制御、およびクローズに使用される手法では、ソフトウェアプロジェクトで実行する必要がある作業の種類、具体的には実行できない非日常的な作業を考慮する必要があります。特定の指示と手順に。

もう1つの問題は、情報の繰り返しに関連する概念であるDRYを使用して、それをタスクの管理に適用しようとしていることだと思います。DRYは、情報の信頼できる表現は1つだけにする必要があると単純に述べています。プロジェクトマネージャーはこれを採用する必要があります。これは、誰もが情報の入手先を知っているため、変更の伝達が容易になり、変更を適切に制御および管理できるためです。DRYは、再利用可能な部品を通じて、長期的なコストを抑え、長期的なスケジュールを維持し、品質を向上させるのに役立ちます- プロジェクト管理トライアングルの 3つの部品。物事を効果的にDRYにするために費やした時間とお金をいくらか投資する必要がありますが、プロジェクトマネージャーの仕事は時間、コスト、スケジュール、品質のトレードオフをすることです。


確かに、ソフトウェア開発は知識の仕事です。実際、最初の例(コピー/貼り付け)を厳密な意味でのソフトウェア開発であるとは考えていません。それでも、この種の作業の管理ははるかに困難であるため、PMは、開発のバックグラウンドを持ち、このすべてを知っていても、PMとしての役割においてそれを無視する傾向があります。(私はこれが良いことだとは言いません、それは私が何度も観察したことです。また、それらのPMが愚かで無能だとは思いません。役割が時々このような行動を強制するようです。 )
フランクパファー

3
@FrankPufferプロジェクトマネージャーの役​​割が、特定の決定を下すことを強制することに同意しません。それはおそらく教育的または組織的な力です。私が見たところから、ほとんどのプロジェクト管理教育は、ソフトウェアプロジェクト管理技術よりも従来のプロジェクト管理技術に焦点を当てています(おそらく、より多くのプロジェクトに適用される可能性が高いためです)。これは、これを期待し、ソフトウェア開発などのナレッジワークプロジェクトを管理するための他の手法を検討しない組織に流出する可能性があります。
トーマスオーエンズ

2
@FrankPuffer確かにタフですが、より多くの価値を提供します。あなたの上司が十分に賢い場合、彼は「自分のために物事を簡単にする」ことを試み、実際に彼の仕事をすることができる誰かを見つけようとするマネージャーを取り除きます。作るものより簡単に価値を提供する場合、誤解しないで、それのために行く-しかし、あなたが記述するもので、これはほぼ確実にある損害終了値の。
ルアーン

4

新しいコードを書くことはタスクのほんの一部です

あなたの提案は、最初に新しいコードを書く部分を簡単に見積もることができるでしょう。ただし、実際に新しいものを導入するには(新しいシステム、機能の追加、機能の変更に関係なく)、これを行うだけでは不十分であり、作業はごくわずかです。一部は総作業量の20%〜40%のようなものです。

そのため、作業の大部分(最初の開発を実際に必要なものに適合させること、統合、テスト、書き換え、再テストなど)を簡単に見積もることができません。逆に、意図的にDRYを回避すると、その部分が大きく、難しく、変数の推定値が大きくなります-クローンされた部分をすべて変更する必要があるバグまたは変更の必要性が発生しない場合があります完全に間違っているでしょう。

仕事の小さな部分の推定品質を改善しても、仕事の大部分でそれを悪化させることによって、より良い推定を得ることはできません。したがって、実際にはトレードオフではなく、生産性が低下するだけでなく、推定値も低下する負けの状況です。


それは良い点です。ただし、DRYまたは同様の原則は、テストや統合などの他のタスクにも適用されます。ほとんどのことは、あまり考えずに、またはよりインテリジェントな方法で、機械的な方法で実行できます。多くの場合、インテリジェントソリューションははるかに高速ですが、障害のリスクが伴います。さらに、結果を得る前にかなりの量の作業を行わなければなりません。
フランクパファー

「失敗のリスク」はなく、失敗の確実性があります。すべては遅かれ早かれ失敗します。あなたはただ、霊expensive車がどれくらい高価で、どれだけ速く運転するかを選択しています。

4

DRYは便利ですが、過大評価されています。一部の人々はそれをやりすぎます。多くの開発者が気付かないのは、DRYを実装して同じメソッドを2つの(わずかに)異なる目的に使用すると、さまざまな用途間で非常に緊密な結合が発生するということです。これで、最初のユースケースのコードを変更するたびに、2番目のユースケースに回帰するかどうかも確認する必要があります。これらが広く独立したユースケースである場合、それらを密結合する必要があるかどうかは非常に疑わしいです。

また、DRYの過剰使用は、コードを複製するより小さなアトミックメソッドがはるかに保守性が高い場合に、複雑に爆発して、使用されるすべての異なるユースケースを処理するGodメソッドにつながる可能性があります。

ただし、この質問はプロジェクト管理レベルにはあま​​り関係ないことをお勧めします。プロジェクトマネージャーは、このレベルの実装の詳細に関心を持ちたくないでしょう。もしそうなら、それはおそらくマイクロ管理です。本当に... 実装方法は、開発者と技術リーダーの責任です。プロジェクトマネジメントは、いつ行うにより関心があります。

編集:コメントごとに、開発時間を簡単に見積もることができる限り、DRYを回避することで不確実性の量を減らすことができることに同意します。しかし、これは、(1)ビジネス要件が満たされるまでの期間、(2)プロセスでどのような技術的負債が発生するか、(3)総コストに対するリスクといった、より差し迫った問題に関連する重要でない問題だと思います。行われたアーキテクチャの選択の所有権-多くの場合、DRYを行うかどうかは、プロジェクトマネージャーにより正確な情報を提供するのが少し簡単になるかどうかよりも、それらの要因に対するリスク/報酬に基づいて設計する必要があります。


もちろん、プロジェクトマネージャーは実装の詳細を扱うべきではありません。それは私のポイントではありません。私のポイントは、開発者が何かを実装する方法に応じて、プロジェクト管理に必要な情報を多かれ少なかれ提供できるということです。
フランクパファー

製品をより良く報告できるようにするためだけに、製品を損傷/制約したり、技術的な負債を組み込んだりするのは理にかなっていない。報告書の価値は、確かに質の高い仕事の価値よりも桁違いに低くなければなりません。しかし、YMMV
ブラッド・トーマス

たぶんプログラマーはマネージャーよりも桁違いに支払われるべきでしょうか?

2

DRYを誤解していると思います。

例を使用してみましょう:

public Class A
{
    public int Multiply(int x, int y)
    {
        return x * y;
    }
}

public Class B
{
    public int Multiply(int x, int y)
    {
        return x * y;
    }

    public int Add(int x, int y)
    {
        return x + y;
    }
}

public Class C : A
{
    public int Add(int x, int y)
    {
        return x + y;
    }
}

クラスBをCに置き換えることにより、DRY原則に従い、コードの重複を減らしました。ただし、未知の要素やプロジェクトへのリスクは増加していません(以前に継承を行ったことがない場合を除きます)。

DRYについて話すとき、あなたが言うことは、デザインタスクに似ていると思います。すなわち:

public Class A
{
    public int Multiply(int x, int y)
    {
        return x * y;
    }
}

!!!新しい要件!一部のクライアントは、倍を増やす必要があります!!

// Use class B for new clients!!
public Class B
{
    public int Multiply(double x, double y)
    {
        return x * y;
    }
}

public Class A // Version 2
{
    public int Multiply(int x, int y)
    {
        return Multiply(x as double, y as double);
    }

    public int Multiply(double x, double y)
    {
        return x * y;
    }
}

ここでは(動作すると仮定して)、実際の問題やビジネスルールの数学モデルを作成しようとして、古い要件と新しい要件の両方に対処できるソリューションを設計しました。実際には、モデリングしているシステムは明らかにはるかに複雑であり、そのモデルは正確には適合せず、エッジケースと予期しない結果を見つけて修正するには時間がかかります。

この場合、BまたはAバージョン2を使用する必要がありますか?

  • Bは、実際の要求された変更に対してより具体的になり、副作用が少なくなり、推定がより簡単になり、より迅速になります。

  • バージョン2では、今後の全体的なコードが少なくなり、よりエレガントなソリューションになります

繰り返しますが、それは仕様と要件の品質にかかっています。

エッジケースと下位互換性をカバーする非常に明確な仕様がある場合、バグを生成せずにモデルをリファクタリングするのに十分なシステムを十分に理解していると確信できます。

システム全体を考慮せずに、その顧客の行動が変わるという唯一の要件がある単一の顧客に緊急の要求がある場合。次に、リファクタリングAによってモデルを「改善」することは、かなりのリスクを伴います。ソリューションの設計とテストに余分な時間が必要なため、他の顧客を破ったり、期限を超過したりします。


7
私は同意しません。継承は、一度行ってからマスターするものではありません。落とし穴はたくさんあります。継承よりも合成が優先されるべき理由があります。だから私たちは決断をしなければなりません:継承?構成?他に何か?この決定は現実の世界ではおそらく難しいでしょう。2番目の例には、多くの選択肢もあります。ジェネリック/テンプレートはどうですか?ラムダを使用した機能的なアプローチでしょうか?繰り返しますが、それぞれに特定の意味がある可能性がたくさんあります。
フランクパファー

4
ポイントは、最初の例では、どのような方法でも文字通り重複コードを削除することです。ただし、まったく同じコードがどちらの方法でも実行されます。したがって、機能の変更はありません。2番目の例では、あなたがfunctionaly eqivilantですが、actualy異なるコードであると思います何かへのアプローチに変更
ユアン

1
私はあなたの「緊急要請」が当たり前の状況にありました。私が働いていた会社は、多くの異なる顧客向けにカスタマイズされたデータシステムを作成しました。最初に、Cobolを使用して1つのシステムを作成し、次に顧客が100人になるまでそれを次の顧客などにコピーしました。現在、彼らは体系的な改善と更新を行うために仕事をしていました。単一のソースコードセットを使用してこれらのシステムのほとんどの動作を再現できるシステムで作業していましたが、カスタマイズは構成データに保存されていました。私たちはすべてをすることはできませんでしたし、いくつかのことを追加できませんでした。

1

段落ごとの段落

ソフトウェア開発の最も基本的で広く受け入れられている原則の1つはDRYです(繰り返してはいけません)。また、ほとんどのソフトウェアプロジェクトには何らかの管理が必要であることも明らかです。

正しい。

では、管理が簡単なタスク(見積もり、スケジュール、制御)は何ですか?正しい反復タスク、DRYに従って回避すべきタスク。

繰り返しタスクは自動化する必要があり、必須です。手作業で作成すると、退屈でエラーが発生しやすくなります。

そのため、プロジェクト管理の観点からは、既存のコードを100回コピーしてタスクを解決し、必要に応じて各コピーに若干の修正を加えることは素晴らしいことです。常に、あなたが行った仕事の量と残っている量を正確に知っています。すべてのマネージャーはあなたを愛します。

「適応」という言葉は「構成」で変更できると思います。コピーされることになっているこのコード部分にバグがあると考えてください。特定の条件下で表示されるバグ。元のソースで修正されておらず、コピーされる場合、修正する場所がたくさんあります。これは悪いかもしれませんが、誰かがする必要があります:

  • 最初に元のソースのコードを修正します。
  • 他のすべての場所でコードを修正します。
  • それらがすべての場所であることを確認してください。あなたがこれをマネージャーに行わなければならないと言うとき、彼はおそらく少なくとも誰かを憎むでしょう。

代わりに、DRYの原則を適用して、重複するコードを多かれ少なかれ除去する抽象化を見つけようとすると、状況は異なります。通常、多くの可能性があります、あなたは決定を下し、研究を行い、創造的でなければなりません。短い時間でより良いソリューションを思いつくかもしれませんが、失敗することもあります。ほとんどの場合、どれだけの作業が残っているかを実際に言うことはできません。あなたはプロジェクトマネージャーにとって最悪の悪夢です。

重複を削除すると、単一障害点になります。何かが失敗した場合、これがどこで起こるかをかなり確信で​​きます。SOLIDとDesign Patternsは、まさにその問題を修正するのに役立ちます。期限が短すぎると、手続き型の「コーディング」を引き起こす傾向があります。再利用可能な何かを作成するために1つのプロジェクトにより多くの時間を費やすことは、機能が再利用されるときに次のプロジェクトで費やす時間を最小限に抑える必要があることを意味します

もちろん大げさですが、明らかにジレンマがあります。私の質問は次のとおりです。開発者がDRYをやりすぎているかどうかを判断する基準は何ですか?どうすれば良い妥協点を見つけることができますか?または、妥協を見つけるだけでなく、このジレンマを完全に克服する方法はありますか?

多くの人がここにジレンマはないと指摘しました。はいといいえ。

かつてないほど高度に実験的なものがある場合-ジレンマはありません。さもなければ、すでに抽象化されている新しい予約システムのように、やり直さなければならないことがある場合、必要なものに依存します。

ジレンマは、要求される可能性が低い場合、機能に何かを実装する必要があると思います。要求されたときに何かを実装します。誰も使用されない巨大なインフラストラクチャを必要としません。


それが要求されたので、今、シンプルで速い方法で何かを実装してください。後で、複雑な方法が必要になったとき、元の努力は何の役にも立たず、最初からやり直す必要があります。マネージャーはこれを好まない。あなたが言ったように、「今、私たちが東に行く必要があるならば、西を運転するのに費やす時間は役に立たなかった」しかし、初めて東に行くことができるように初めて世界を一周するのも無駄な時間です。

1

これは将来の再利用のための設計やYAGNIの原則に関するものではありません。現在の作業パッケージでコードを繰り返すことです。

それは絶対にデザインです。それ自体は再利用できないかもしれませんが、それでもデザインは変わりません。

開発者がDRYをやりすぎているかどうかを判断する基準は何ですか?

経験と既存の環境/状況。与えられた問題に対して、より高い程度の乾燥を試みると、プラドの原理の強い感覚が得られます。その後、管理上の考慮事項が突然現れます。時間、目標、顧客、長期的なコード管理(誰かが技術的負債と言った)などが攻撃の計画を知らせてくれます。

どうすれば良い妥協点を見つけることができますか?

えっと…デザイン?リファクタリングはデザインであり、そうであるはずです。DRYingのスコープは、ループからメソッド、クラスまで、超新星のように簡単に拡張できます。そこに行って、それをやった。しかし、あなたは問題を研究するまで本当に知ることはできません-これは設計です。

設計上の問題にならないのはどうしてですか?問題は、当面の重複コードよりも広く考慮する必要があります。これは、既存のコードでも空白のシートでも、設計アクティビティです。「抽出メソッド」であるか、新しいクラスとモジュールを作成するか。

エピローグ

...参照されている質問とその回答は、プロジェクト管理の側面をカバーしていません。

設計時間を無視した典型的な管理。理想的には、コーディングの前に余分な冗長性を設計する必要があります。代わりに、管理者は開発(およびバグ修正)が単一のオリンピックイベント(コーディング)であり、実際には十種競技であると考えています。そして、彼らはそれがすべてアナログだと思うので、彼らは1/1000秒まで測定します。

代わりに、DRYの原則を適用して、重複するコードを多かれ少なかれ除去する抽象化を見つけようとすると、状況は異なります。

「GUIフォームのこの行を書くのに2日間、残りのフォームを書くのに2時間を費やした」という経験がありました。私は、再利用可能なクラスを特定するために時間をかけたことを意味します-DRYは自然な副作用です-GUIフォームの行と他のいくつかのw / in。これらをデバッグすると、フォーム全体で個別におよび構成で使用され、非常に高速にコーディングされ、ビルドの複雑さにもかかわらずテストは非常に迅速でした。また、驚くほど低いバグ率で正式なテストを実施しました。

ほとんどの場合、どれだけの作業が残っているかを実際に言うことはできません。あなたはプロジェクトマネージャーにとって最悪の悪夢です。

私も知りませんでしたが、前もって設計する努力が報われると信じていました。私たちは皆これを言いますが、特に経営陣はそれを信用していません。経営陣は私がうんざりしていると思っていただろう。「2日間で、まだ2%のコーディングもありません!」

あるケースでは、経営陣が「設計に時間を費やしすぎているので、始めてください」と言ったとき、私たちは銃に固執しました。そして同僚は「クラスが多すぎる」と言っています。さて、はるかに複雑ではないサブプロジェクトは約1か月かかると想定されていましたが(大まかな推測だと思いました)、5か月かかりました。その3か月はPOSであったため、テスト/修正に費やされました。「しかし、設計する時間がありませんでした!」。彼らは実際にそう言った。

私の質問は次のとおりです。開発者がDRYをやりすぎているかどうかを判断する基準は何ですか?どうすれば良い妥協点を見つけることができますか?または、妥協を見つけるだけでなく、このジレンマを完全に克服する方法はありますか?

管理者にその仕組みを示します。いくつかのデータをキャプチャします。他の仕事、特に平手打ちダッシュの仕事をしている同僚の仕事と比較してください。失敗の山は常にレースに負けてしまい、テストでスタックしてしまい、リリース後にバグを修正するために何度も戻ってきました。


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