web-dev-qa-db-ja.com

プログラムを最初から完全に再構築した場合に、どうすればそれをはるかに改善できるのかを常に回避するにはどうすればよいですか?

私はかなりの量のコーディングを学びましたが、それは常に科学環境(コンピューターサイエンスではない)で行われており、正しい方向に導くための誰もなしで完全に独学で学びました。したがって、私のコーディングの旅は...厄介でした。ある種のプログラムを構築するときはいつでも、最終的には、それをはるかにエレガントに、はるかに効率的に、さらに柔軟で、今後の管理が簡単な方法で実現できることに気づきました。一部の状況では、私は実際に戻って物事を一から作り直しましたが、通常これは実際的に実現可能ではありません。これまでの私のプログラムのほとんどは比較的小規模でしたが、何かを作成するたびに大きなプログラムを完全に書き直すのはかなり扱いにくいようです。

私はただ疑問に思っています、これは通常の経験ですか?そうでない場合、これを防ぐにはどうすればよいですか?事前に計画を立ててみましたが、コードの作成に取り掛かるまで、すべてを実際に予測することはできません。

92
Ashish

この感覚は完全に正常で、期待されています。それはあなたが学んでいることを意味します。ほとんどの場合、新しいプロジェクトを開始するたびに、一方向から始め、最終的には別の方法で設計します。

実際の作業を始める前に、まずprototypeを開発するのが一般的な方法です。古いコードに再度アクセスしてrefactorとすることも一般的です。これは、デザインがmodularの場合に簡単です。古いデザインを完全に破棄する必要なく、ビットとピースを一度に簡単に再デザインできます。

一部の人にとっては、最初にpseudo-codeと書くと役立ちます。 commentsの記述から始めて、コードの機能を説明し、一般的な構造が記述されたらコードを記述することもできます。これら2つのことは、設計をよりよく計画するのに役立ち、書き直しの必要性を回避する可能性があります。

チームの一員である場合、レビュープロセスを持つことは設計プロセスにとって非常に重要です。デザインを改善する方法を学ぶことができるように、誰かにコードをレビューしてもらいます。

4
asrjarratt

これは非常に一般的な経験です

私が交流するほとんどの人、そして私自身も、このように感じています。その理由の1つは、コードを記述するときに使用するドメインとツールについて詳しく知ることができることです。これにより、プログラムを記述した後に、多くの改善の機会を認識することができます。

もう1つの理由は、理想的なクリーンなコードソリューションについて頭の中で考えていると、現実世界とその厄介な制限が邪魔になり、不満を残す可能性のある不完全な回避策とハックを書くように強いられることです。

「誰もが顔を殴られるまでの計画を持っています。」

それについて何をすべきか

ある程度までは、コードが完璧になることはないことを受け入れることを学ぶ必要があります。それを助けてくれたのは、「1か月前に書いたコードが嫌いなら、それは私が学んでより優れたプログラマーになったことを意味する」という考え方です。

この問題を緩和する方法は、継続的に作業し、リファクタリングするときに、潜在的な改善点を常に見張っていることです。リファクタリングと新機能の追加/バグの修正のバランスが取れていることを確認してください。これは大きな設計の問題には役立ちませんが、一般に、誇りにできるより洗練されたコードベースを手に入れます。

100

リファクタリングを学ぶ-段階的に改善するコードの芸術。私たちは皆常に学んでいるので、自分で書いたコードはもっと良い方法で書けるかもしれないということを理解することは非常に一般的です。

ただし、既存のコードを変換して、最初からやり直すことなくこれらの改善を適用できるはずです。

45
JacquesB

優れた静的要件があり、それらを十分に理解し、詳細な分析の時間がある場合は、完了しても満足できる優れた設計を思い付く可能性があります。

その至福の場合でも、デザインの改善に役立つ新しい言語機能を学ぶことができます。

ただし、通常、それほど幸運になることはありません。要件は非常に少なく、不完全であり、理解したと思っていても、無効な仮定をした領域があることがわかります。

その後、ユーザーが最初の成果物を確認すると、要件が変化します。次に、ユーザーが制御しないものは変更されます。税法。

物事が変わると想定して、あなたができることはデザインだけです。可能な場合はリファクタリングしますが、多くの場合、時間と予算によって、最終的に得られる成果物は、最初に現在わかっていることを知っていた場合ほど洗練されていないことになります。

時間が経つにつれて、受け取った要件を掘り下げることができるようになり、変更を吸収するために設計の一部に柔軟性が必要になる可能性が高いと思われる部分を理解することができます。

しかし、結局のところ、変化は一定であることを受け入れ、「もっと上手くできたはずだ」と言っていることは無視してください。ソリューションを提供したことを誇りに思い、満足してください。

9
Wildbill

プログラムを最初から完全に再構築した場合に、どうすればそれをはるかに改善できるのかを常に回避するにはどうすればよいですか?

あなたができることは、「実際の」プロジェクトを始める前に使い捨てのプロトタイプを作成することです。早くて汚い。次に、概念を証明するためのプロトタイプを入手すると、システムと、物事を適切に行う方法を知ることができます。

しかし、N年後にこのコードに戻って「なんてめちゃくちゃだ」と思っても驚かないでください。

3
BЈовић

このマントラを覚えておいてください:

完璧は善の敵です

perfectソリューションは、必ずしもidealソリューションであるとは限りません。 idealソリューションは、最小の作業で「十分に良い」ステータスを達成するソリューションです。

  • 機能とパフォーマンスに関するすべての要件を満たしていますか?
  • 現在のアーキテクチャでは修正できない重大なバグはありませんか?
  • 将来このアプリケーションを維持するためにどれだけの作業を投入するかを見積もります。書き換えの労力は、それが節約する長期的な労力よりも多いのでしょうか?
  • 新しいデザインが実際に事態を悪化させる可能性はありますか?

これらすべての質問に「はい」と答えた場合、ソフトウェアは「十分に良好」であり、ゼロから書き直す正当な理由はありません。代わりに、学習した設計レッスンを次のプロジェクトに適用してください。

すべてのプログラマーが過去にいくつかの厄介なプログラムを持っていることは完全に正常です。ソフトウェア開発者としてのキャリアの中で何度かコードを見て「バカがこの混乱を書いたのは何だろう?」.

3
Philipp

事前に計画を立ててみましたが、コードの作成に取り掛からない限り、すべてを実際に予測することはできません。

完璧な計画が完璧なソフトウェアの設計/アーキテクチャを提供すると考えるのは魅力的ですが、それは明らかに間違っていることがわかります。これには2つの大きな問題があります。 。まず、「紙の上」と「コード」が一致することはほとんどありません。その理由は、実際にそれを行うとは対照的に、say方法を簡単に実行できるためです。第2に、要件の予期しない変更は、開発プロセスの後半で明らかになり、当初からは推論できませんでした。

アジャイルの動きをご存知ですか?これは、「計画に従う」ではなく「変化に対応する」ことを重視する考え方です物)。これが manifesto です(簡単に読むことができます)。また、Big Design Up Front(BDUF)とその落とし穴についても読むことができます。

残念ながら、「アジャイル」のコーポレートバージョンは、一連の偽物(認定されたスクラムマスター、「アジャイル」の名前での重いプロセス、スクラムの強制、100%のコードカバレッジの強制など)であり、通常、マネージャーがアジャイルはプロセスであり、特効薬であると考えてください(どちらでもありません)。アジャイルマニフェストを読み、人々の声に耳を傾けてください開始した人ボブおじさんやマーティンファウラーのようなこの運動、そして「企業アジャイル」のナンセンスバージョンに夢中にならないでください。

特に、通常は科学的コードでTDD(テスト駆動開発)を実行するだけで済むため、ソフトウェアプロジェクトが判明する可能性が高くなります。かなりまあまあ。これは、成功した科学的コードが、非常に使いやすいインターフェースを備えており、パフォーマンスが二次的な(場合によっては競合する)懸念事項であるため、より「貪欲な」設計を回避できるためです。 TDDは、ソフトウェアをultra-usableにすることを強制します。なぜなら、あなたはwant呼び出されるもの(理想的に)実際に実装する前に。また、小さな関数を強制的に小さなインターフェイスですばやく呼び出すことができます単純な「入力」/「出力」の方法で、要件が変更された場合にリファクタリングするための適切な位置に配置します。

numpyが成功した科学計算ソフトウェアであることに、私たちは皆同意できると思います。それらのインターフェースは小さく、非常に使いやすく、すべてがうまく連携しています。 numpyのリファレンスガイドではTDDを明示的に推奨しています:https://docs.scipy.org/doc/numpy- 1.15.1/reference/testing.html 。過去にTDDをSAR(合成開口レーダー)イメージングソフトウェアに使用したことがあります。また、その特定のドメインでTDDが非常にうまく機能していると主張することもできます。

警告:TDDの設計部分は、基本的なリファクタリング(ソフトウェアに高度な並行性が必要であると判断するなど)が難しいシステムではうまく機能しません、分散システムのように。たとえば、数百万の同時ユーザーがいるFacebookのようなものを設計する必要がある場合、TDD(設計を推進するため)を実行するのは誤りです(-afterを使用しても問題ありません暫定設計し、「最初の開発をテスト」するだけです)。アプリケーションのリソースと構造について考えることが重要ですbeforeコードにジャンプします。 TDDが高可用性の分散システムにつながることは決してありません。

自分のプログラムを最初から完全に再構築した場合に、どうすればそれをはるかに効率よく実行できるのかを常に回避するにはどうすればよいですか?

上記のことを考えると、完璧なデザインを実現することは実際には不可能であることはある程度明白であるため、完璧なデザインを追いかけることは愚かなゲームです。近づくだけ。 考える最初から再設計できる場合でも、おそらくまだ自分自身を示していない隠された要件があります。さらに、書き換えには、元のコードの開発にかかったのと同じ少なくとも同じくらいかかります。 new設計には予期しない問題が発生する可能性が高く、古いシステムのすべての機能を再実装する必要があるため、これはほぼ確実に短くなることはありません。

もう1つの考慮事項は、設計が本当に重要であることだけです要件が変更された場合設計がどれほど悪いかは関係ありません何も変更されない場合(現在のユースケースで完全に機能している場合)。 22,000行の切り替えステートメントが含まれるベースラインに取り組みました(関数はさらに長くなりました)。ひどいデザインでしたか?いや、それはひどかった。修正しましたか?いいえ、問題なく機能し、システムのその部分がクラッシュやバグを引き起こすことはありませんでした。私がプロジェクトに参加していた2年間に1度しか触れられませんでした。誰かが推測したとおり、別のケースがスイッチに挿入されました。しかし、あまり頻繁に触れられないものを修正するために時間をかける価値はありません。そうではありません。不完全な設計をそのままにし、それが壊れた(または常に壊れた)場合は、修正しないでください。 それであなたは多分あなたすることができましたよりよくする...しかしそれは書き直す価値があるでしょうか?あなたは何を得ますか?

HTH。

3

Andreas Kammerloherの回答に完全に同意しますが、コーディングのベストプラクティスの学習と適用を提案した人がまだいないことに驚いています。もちろん、これは特効薬ではありませんが、オープン指向のアプローチ、デザインパターン、コードの匂いがするタイミングなどを理解することで、より優れたプログラマーになります。ライブラリ、フレームワークなどの最適な使用方法を調べてください。確かに他にもたくさんあります。表面をなぞっただけです。

それはあなたが古いコードを完全なゴミとして見ないことを意味するわけではありません(実際には、最も古いプログラムはこの知識がない場合よりもさらにゴミが多く表示されます)。しかし、新しいソフトウェアを書くたびに、あなたが向上します。また、コーディングのベストプラクティスの数は時間の経過とともに増加し、一部は単純に変更されるため、実際に完璧に到達することはありません。これまたはかなりのパスを受け入れます。

もう1つの良い点は、コードリビジョンを作成することです。一人で作業するときは、簡単に手抜きができます。 2人目のユーザーがコードをレビューしている場合、彼らはあなたがこれらのベストプラクティスに従っていない場所を指摘することができます。このようにして、より良いコードを生成し、何かを学びます。

2
Ister

ここで他の優れた答えに追加するために、私が役立つと思う1つのことはどこに到達したいかを知るです。

それ自体でリファクタリングの大部分が許可されることはまれです。ただし、コードベースの各領域で作業しているとき、「レーダーの下」で進むにつれて、小さなリファクタリングを実行できることがよくあります。そして、もしあなたがゴールを念頭に置いているなら、あなたはこれらの機会を利用して、正しい方向に一歩一歩前進することができます。

時間がかかる可能性がありますが、ほとんどのステップでコードが改善され、最終的な結果は価値があります。

また、上手くできる気分は良い兆候です!それはあなたがあなたの仕事の質を気にしていること、そしてあなたがそれを批判的に評価していることを示しています。おそらくあなたは学び、改善しているでしょう。これらのことであなたを心配させないでください—しかし、それをやめないでください!

1
gidds

人類の最大の課題(冒険)の1つである人と機械の架け橋に偶然偶然に遭遇しました。人と物理的構造、たとえば土木工学との間の架け橋は、約200年以上にわたって進行中です。

ソフトウェア開発は本当に90年代に主流になっただけなので、それは約30年前のものです。社会科学ほどエンジニアリングの分野ではないことを学びました。まだ始まったばかりです。

はい、TDD、リファクタリング、関数型プログラミング、リポジトリパターン、イベントソーシング、MV何か、Javaスクリプト(<-これを実行すると、クレイジーです)、モデルバインディング、SQLなし、コンテナを試す、アジャイル、SQL(<-これは強力です)。

修正はありません。専門家でさえもストローを把握しています。

ようこそ、警告されます。孤独な場所です。しかし、本当に魅力的です。

1
Marius

私は穀物に少し対抗します。これは信じられないほどcommonですが、acceptableではありません。これが示していることは、コードを書いているときにコードを整理する良い方法を認識していないということです。感じはあなたのコードから来ます簡単ではありません

あなたの経験も長い間私のものでしたが、最近(ここ数年)、私はしないではないコードをさらに作成しています私はすべてを捨てる必要があるように感じます。これが私がおおよそしたことです:

  1. 特定のコードブロックがどのような仮定をしているのかを明確にします。満たされていない場合はエラーをスローします。残りのソフトウェアの動作に関する詳細に依存せずに、これについて単独で考えます。 (ソフトウェアの残りの部分が実行していることは、適用する仮定とサポートするユースケースに影響しますが、仮定に違反したときにエラーをスローするかどうかには影響しません。)
  2. ルール、パターン、および慣習に従うことは良いコードを生成すると信じて停止します。明白ではない簡単な考え方や実践を捨てます。これは巨大でした。 OOおよびTDDは通常、コードを書くときに従うべき一連の抽象的な原則として、実際の考慮事項に基づいていない方法で教えられます。しかし、これは実際に優れたコードを開発するためにはまったく役に立ちません。OOまたはTDDを使用する場合は、理解している問題の解決策として使用する必要があります。つまり、問題を見て「わかりました、これは完全に理にかなっており、優れたソリューションとして非常に明白です」と考える場合にのみ使用してください。
  3. コードを書くときは、2つの質問に焦点を当てます。
    • 機能とライブラリを使用するように設計された方法で使用していますか?これには、解決しようとした種類の問題、または少なくとも非常に類似した問題に使用することが含まれます。
    • それはsimpleですか?同僚も私も、後で簡単にロジックをたどることができますか?コードからすぐにわかりにくいものはありますか?

私のコードはより「手続き型」になりました。つまり、使用するデータ構造ではなく、どのようなアクションを実行するかによって編成されています。スタンドアロン関数をその場で置き換えることができない言語でオブジェクトを使用しています(C#およびJava関数をその場で置き換えることはできません、Pythonできます)。私は今、より多くのutility関数を作成する傾向があります。これにより、迷惑なボイラープレートが邪魔にならなくなり、実際にコードのロジックを読み取ることができます。 (たとえば、リスト内の項目のすべての組み合わせを処理する必要がある場合、元の関数がそれらの実装の詳細で乱雑にならないように、Tuplesを返す拡張メソッドにループするインデックスを押し込みました。 )関数を他のオブジェクトに到達させてフェッチするのではなく、関数にパラメーターとしてより多くのものを渡します(呼び出し側が代わりにそれをフェッチまたは作成して、それを渡します)。これはコードを見るだけでは明らかではないため、メソッドのロジックをたどるのが簡単になります。テストを書くのは、 mが心配私が作ったものの論理であり、モックの使用は避けます。 (私は孤立したロジックの部分でより多くの入出力テストを行います。)結果はperfectではないコードですが、実際には大丈夫、2年か3年後でさえ。変更にかなりよく反応するのはコードです。システム全体がばらばらになることなく、細かいことを追加、削除、変更できます。

ある程度、あなたは物事が混乱している期間を経験するため、経験を積むことができます。しかし、物事がめちゃくちゃになっていて、すべて捨ててやり直したい場合は、何かがおかしいです。あなたは学んでいない。

1
jpmc26

あなたの時間は限られていることを思い出すことによって。そして、あなたの未来の時間も限られています。仕事でも学校でも個人プロジェクトでも、workingコードに関しては、「これを書き換えることは私の限られた貴重な時間の最善の使い方ですか?」と自問する必要があります。それとも、「これは最も責任がある限られた時間の使用ですか?」

時々答えは明確にyesになります。通常はありません。時々それは柵の上にあり、あなたはあなたの裁量を使わなければならないでしょう。時々それはあなたがそれを行うことによって学ぶことのために単にあなたの時間の良い使い方です。

仕事と個人の両方で、移植/書き換えの恩恵を受けるプロジェクトがたくさんあります。他にもやることがあります。

0
Jared Smith

それは完全に正常な学習の一部です。行くにつれて間違いに気づきます。

それはあなたが良くなる方法であり、それはあなたが避けたくないものではありません。

0
mathreadler

あなたは自分自身に経験を与えて、書き直そうとする誘惑的な衝動が通常非生産的であることを知ることができます。適度に複雑な、古くて毛深い、エレガンスのないオープンソースプロジェクトを見つけてください。ゼロから書き直してみて、その方法を確認してください。

  • ゼロからのデザインは、希望どおりにエレガントになりましたか?
  • あなたの解決策は本当にまったく同じ問題の解決策ですか?除外した機能は何ですか?どのEdgeケースを見逃しましたか?
  • エレガンスを追求するために、元のプロジェクトで苦労して学んだ教訓は何ですか?
  • これらの欠落している部分をデザインに戻した後、それらがない場合と同じようにきれいですか?

やがて、あなたの本能は「このシステムをもっと上手く書き直すことができる」という考えから「このシステムの扱いづらさはすぐには明らかにならない複雑さを示しているのかもしれない」という考えに変わります。

0
Maxpm