プログラムをゼロから完全に再構築した場合、ずっと改善したいという気持ちを常に避けることができますか?[閉まっている]


91

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

私はただこれが普通の経験なのだろうか?そうでない場合、これをどのように防止しますか?事前に計画を立ててみましたが、コードを打ち出すまですべてを実際に予測することはできません。


87
その通常のプログラムの詳細
ユアン



43
プログラミングへようこそ。古いコードに目を向けずに「非常に」と思う場合は、学習をやめたことを意味するため、心配し始める必要があります。
カルター

9
正直、この質問を見たとき、私は笑いました-私自身も含めて、私が話したことのある文字通りすべてのプログラマーは、常にこの感覚を常に持っているからです。あなたが作った最終製品に欠陥がないと感じた分野に行きたいなら、プログラミングは選択するのが間違った分野でした。
ジボブズ

回答:


4

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

本物から始める前に、まずプロトタイプを開発するのが一般的な方法です。古いコードを再検討してリファクタリングすることも一般的です。デザインがモジュール式の場合、これは簡単です。古いデザインを完全に廃棄することなく、一度に簡単にビットとピースを再設計できます。

一部の人にとっては、最初に擬似コードを書くと役立ちます。他の人は、コードが何をするかを説明するコメントを書くことから始め、一般的な構造ができたらコードを書くことが役立つと感じます。これらの2つのことは、設計をより良く計画するのに役立ち、書き換えの必要性を回避するかもしれません。

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


100

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

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

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

「顔をfaceられるまで、誰もが計画を立てています。」

それについてどうするか

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

問題を軽減する方法は、作業とリファクタリングを継続的に行う際に、潜在的な改善を常に注視することです。リファクタリングと新機能の追加/バグ修正のバランスが取れていることを確認してください。これは大きなデザインの問題には役立ちませんが、一般的には、より洗練されたコードベースが得られます。


18
この答えに追加する唯一のものは、コードを書くときにTDDの原則を学び、それに従うことです。これらのテストは、開発者として改善を続け、既存のコードを変更したい場合に、リファクタリングとリライトのための安全な環境を提供します。
デビッドアルノ

10
@DavidArnoテストを使用したリファクタリングのポイントは何ですか?それは、システムをアップグレードしてからバックアップをするようなものです... 0楽しい。
ジュリス

3
@Džuris、:)確かに、チャレンジが好きなら、テストを書かないでください
デビッドアルノ

6
@Džurisパラシュートを着て飛行機から飛び降りるようなものです!
JollyJoker

3
@jamesqf-それはTDDとユニットテストが行​​うことの誤った特徴です。例えば、彼らはあなたのモデルやアルゴリズムが正しく実装されており、リファクタリング時に何も壊していないことを教えてくれます。彼らはあなたのモデルが実際に有用であることをあなたに伝えることはできません。それは他の科学環境と同じように科学的環境でも同じです。
Ant P

46

リファクタリング- コードを徐々に改善する技術を学びます。私たちは常に学習しているので、自分で書いたコードをより良い方法で書くことができることを認識することは非常に一般的です。

ただし、ゼロから始めなくても、既存のコードを変換してこれらの改善を適用できる必要があります。


4
この方法は、モジュール化されたコードを書くことを学び、より簡単にリファクタリングすることもできます。世界のすべての講義では、古い習慣を扱いやすいチャンクに分割する必要があるので、この習慣を教えてくれなかったので、ゼロから書き直す必要はありません。すべての新しいプロジェクト、私はそれをうまくやっています。
JKreft

私の意見では、リファクタリングについて学ぶための最良の出発点は次のとおりです。リファクタリングは新しい機能についてです
ワイルドカード

9

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

その至福の場合でも、より良いデザインを作るのに役立つ新しい言語機能を学ぶかもしれません。

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

その後、ユーザーが最初の成果物を見ると、要件が変更されます。その場合、ユーザーが制御できないものは、たとえば税法を変更します。

できることは、物事が変化すると想定して設計することだけです。可能な場合はリファクタリングしますが、時間と予算は、最終的な成果物が最初に知っていることを最初に知っていた場合ほど洗練されていないことを意味することが多いことを理解してください。

時間が経つにつれて、受け取った要件を掘り下げ、デザインのどの部分が変化を吸収するために柔軟性を必要とする可能性が高いかを知ることができます。

しかし、最終的には、変化が一定であることを受け入れ、「もっとうまくやれた」と書かれているtwinを無視してください。ソリューションを提供したことを誇りに思い、喜んでください。


または、別の方法を使用します。不要なオーバーヘッドを発生させずに、最初から柔軟性考慮して設計する方法を学びます。理想的には、柔軟性は単純さに由来します。その後、設計は要件の変化のテストに合格する機会があります。
cmaster

3

プログラムをゼロから完全に再構築した場合、ずっと改善したいという気持ちを常に避けることができますか?

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

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


3
または、プロトタイプを上司に見せると、彼は「素晴らしい」と言います。別のプロジェクトに移動すると、プロトタイプが生産になります。
-RyanfaeScotland

2
このアドバイスは非常に一般的であるため、それに関することわざがあります。「捨てる1つを構築します」。そして、そのアドバイスは非常に誤用されているため、「捨てるために1つを構築すると、おそらく2つを捨てることになります」ということわざがあります。
エリックリッパー

2
@EricLippert私の経験は逆方向にひどいものでした-捨てるために1つを構築すると、必然的に顧客に出荷されます。
ジョン

2
@Jon:ええ、それは、特にコードが実際に存在する場合に管理ミスが「ユーザーインターフェイスが機能しているように見える」場合に起こります。そうは言っても、私の同僚は「間違って2回作成するのに十分な時間はありますが、一度だけ正しく作成するのに十分な時間はありません」と言っていました。:-)
エリックリッパー

@EricLippertそれがまさにGUIを最後に構築する理由であり、プロトタイプ用のGUIを構築するのではありません;)
BЈовић18年

3

このマントラを忘れないでください:

完璧は善の敵です

完璧な解決策は、常にではない理想的なソリューションです。理想的な解決策は、作業量が最も少ない「十分に良い」状態を実現するものです。

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

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

すべてのプログラマーが過去にいくつかの厄介なプログラムを持っていることは完全に普通です。ソフトウェア開発者としての私のキャリアの中で、コードを見て、「この馬鹿なことを書いたのはどんな馬鹿だろう?」


3

事前に計画を立ててみましたが、コードを打ち出すまですべてを実際に予測することはできません。

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

アジャイル運動について聞いたことがありますか?「計画に従う」こととは対照的に、「変化に反応すること」を重視する考え方です。これがマニフェストです(簡単に読むことができます)。また、Big Design Up Front(BDUF)とその落とし穴について読むこともできます。

残念なことに、「アジャイル」の企業版は偽の束(認定スクラムマスター、「アジャイル」という名の重いプロセス、スクラムの強制、100%のコードカバレッジの強制など)であり、通常はマネージャーがアジャイルはプロセスであり、特効薬だと思います(どちらでもありません)。アジャイルマニフェストを読んで、ボブおじさんやマーティンファウラーのようなこの運動を始めた人々の話を聞いてください。

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

numpy科学的なコンピューティングソフトウェアとして成功していることは、私たち全員が同意できると思います。インターフェースは小さく、非常に使いやすく、すべてがうまく連携しています。ことに注意してくださいnumpy:のリファレンスガイドは、明示的にTDDをお勧めします https://docs.scipy.org/doc/numpy-1.15.1/reference/testing.htmlを。過去にSAR(Synthetic Aperature Radar)イメージングソフトウェアにTDDを使用したことがあります。また、その特定のドメインで非常にうまく機能すると断言できます。

警告: TDDの設計部分は、分散システムのように基本的なリファクタリング(ソフトウェアの高度な同時実行が必要であると判断するなど)が難しいシステムではあまりうまく機能しません。たとえば、数百万人の同時ユーザーがいるFacebookのようなものを設計する必要がある場合、TDDを行う(設計を推進する)のは間違いです(予備設計を行った後で使用しても大丈夫です。")。コードジャンプするに、アプリケーションのリソースと構造について考えることが重要です。TDDが、高可用性の分散システムにつながることはありません。

プログラムをゼロから完全に再構築した場合、ずっと改善したいという気持ちを常に避けることができますか?

上記を考えると、完璧なデザインを実際に達成することは実際には不可能であることがある程度明らかであるはずです。そのため、完璧なデザインを追いかけるのは馬鹿げたゲームです。本当に近づくことができるだけです。ゼロから再設計できると思ったとしても、おそらくまだ見えていない隠された要件があります。さらに、書き換えには、少なくとも元のコードの開発にかかった時間を要します。新しい設計には予期しない問題が発生する可能性が高いため、ほとんど確実に短くなりません。さらに、古いシステムのすべての機能を再実装する必要があります。

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

HTH。


2

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

古いコードを完全なゴミとして見ないという意味ではありません(実際には、最も古いプログラムは、この知識なしで行うよりもさらにゴミを見ることになります)。改善します。また、コーディングのベストプラクティスの数は時間の経過とともに増加し、一部は単に変更されるため、実際には完璧にならないことにも注意してください。これまたは完全にパスを受け入れます。

もう1つの良い点は、コードを修正することです。一人で作業するときは、簡単に角を切ることができます。コードをレビューしている2人目の人がいる場合、それらのベストプラクティスに従っていない場所を指摘することができます。これにより、より良いコードを生成し、何かを学ぶことができます。


1

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

独自のリファクタリングの主要なビットのためにゴーサインを与えることはまれです。しかし、コードベースの各領域で作業する際に、「レーダーの下で」進むにつれて、より小さなリファクタリングを行うことができます。そして、目標を念頭に置いている場合、これらの機会を利用して、正しい方向に一歩ずつ移動することができます。

時間がかかる場合がありますが、ほとんどの手順でコードが改善され、最終結果に価値があります。

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


1

あなたは人類の最大の挑戦(冒険)の一つ、人と機械の間の橋に偶然につまずきました。たとえば土木工学など、人間と物理的構造の橋渡しは、約200年以上にわたって進められてきました。

ソフトウェア開発は実際に90年代にのみ主流になったため、約30年になります。私たちは、それが社会科学ほどエンジニアリングの専門分野ではないことを学び、まだ始まったばかりです。

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

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

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


1

私は穀物に少し反対するつもりです。これは非常に一般的ですが受け入れられません。これが示すのは、コードを記述するときにコードを整理する良い方法を認識していないということです。あなたのコードが簡単でないことから感じています。

あなたの経験も長い間私のものでしたが、最近(過去数年)、私はすべてを捨てる必要があると感じさせないコードをより多く生産しています。私がやったことはほぼ次のとおりです。

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

私のコードはより「手続き的」になりました。つまり、使用するデータ構造ではなく、実行するアクションによって編成されているということです。私は、スタンドアロン関数をその場で置き換えることができない言語でオブジェクトを使用します(C#とJavaは関数をその場で置き換えることができません、Pythonはできます)。私は今、より多くのユーティリティ関数を作成する傾向がありますが、それは邪魔なボイラープレートを邪魔にならないように押し出すだけなので、実際にコードのロジックを読み取ることができます。(たとえば、リスト内のアイテムのすべての組み合わせを処理する必要があるとき、返される拡張メソッドにインデックスをループアウトしましたTuple元の関数がそれらの実装の詳細で乱雑にならないようにするために)関数を取得するために他のオブジェクトに手を差し伸べるのではなく、関数にパラメータとしてより多くのものを渡します。(呼び出し側が代わりにそれをフェッチまたは作成し、渡します。)コードを見ただけでは明らかはないことを説明するコメントをさらに残します。これにより、メソッドのロジックを簡単にたどることができます。私は、たった今作ったもののロジックに関心がある限られたケースでのみテストを書き、モックの使用は避けています。(私はロジックの分離された部分でより多くの入力/出力テストを行います。)結果は完璧ではないコードですが、実際には問題ないようです、2、3年後でも。変更に対してかなりよく反応するのはコードです。システム全体をバラバラにすることなく、マイナーなものを追加、削除、または変更できます。

ある程度、あなたが持っているあなたはのオフに行くためのいくつかの経験を持っているように、物事が混乱している期間を経ます。しかし、物事がいまだにめちゃくちゃになっていて、それをすべて捨ててやり直したい場合は、何かが間違っています。あなたは学んでいません。


0

あなたの時間は限られていることを思い出してください。そして、あなたの将来の時間も限られています。仕事や学校や個人的なプロジェクトのためかどうか、それがに来るとき作業コード、あなたは「この私の限られた貴重な時間を最大限に活用を書き換えるのですか?」を自問する必要があります。または、「これが私の限られた時間の中で最も責任のある使用ですか?」

時には答えは明確にイエスになるでしょう。通常はありません。フェンスの上にあることもあり、あなたの裁量を使用する必要があります。それをすることであなたが学ぶことのために、それは単にあなたの時間をうまく利用することもあります。

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


0

それは学習の完全に正常な部分です。あなたが行くと、間違いに気づきます。

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


0

書き換えの誘惑的な衝動は通常非生産的であることを知るための経験をあなた自身に与えることができます。中程度の複雑さを持つ、古くて毛むくじゃらのエレガントなオープンソースプロジェクトを見つけてください。最初から書き直して、どのように実行するかを確認してください。

  • あなたの最初からのデザインは、あなたが望むほどエレガントになりましたか?
  • あなたの解決策は本当にまったく同じ問題に対するものですか?どの機能を省略しましたか?どのエッジケースを見逃しましたか?
  • オリジナルのプロジェクトで苦労して学んだ教訓を、エレガンスを追求して消去しましたか?
  • これらの不足している部分をデザインに追加し直した後、それらがない場合と同じくらいきれいですか?

最終的に、あなたの本能は、「このシステムを非常に良く書き直すことができる」という考えから、「このシステムの粗雑さは、すぐには明らかにならない複雑さを示しているかもしれない」と考えるようになります。

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