どのような設計上の決定を下し、どのようにして裏目に出たのでしょうか。設計上の決定に誤りがあったため、結局その悪い決定を永遠にサポートしなければならなくなりました(私もその一部でした)。これにより、1つの設計ミスが永遠にあなたを悩ませることがあることに気付きました。私は経験豊富な人々からどのような失敗を経験し、彼らから何を学んだのかを学びたいです。
これは、他のプログラマーがそれらの決定を繰り返さないようにするのを助けることによって、多くの助けになると確信しています。
あなたの経験を共有してくれてありがとう。
[〜#〜] yagni [〜#〜] を無視して、何度も...
「後でやります」
「後で」来ることはありません。
C++、 ひし形の複数の仮想継承 。あなたはアイデアを得ます。
アプリケーションの構成可能性は素晴らしいです。構成可能性が高すぎると、使用や維持が困難になります。
私の過ちの1つから、DBの正規化を盲目的に追跡するべきではないことを学びました。できます。状況によっては、テーブルをフラット化する必要があります。
私は(モデルを介して)テーブルの負荷を管理することになり、パフォーマンスはテーブルを少し平坦化した場合ほど良くはありませんでした。
ステータスなどのデータベースで単一の文字を使用します。これにはまったく意味がありません。長いchar()またはnvarchar2()を使用するオーバーヘッドは、ネットワークと比較してごくわずかであり、SQL呼び出しによって発生する解析ですが、文字は常に終了しますかなり難読化されているか、または不足しています(ステータスではなく、他のもの)。人間が読めるバージョンを置くだけでなく、Javaモデル(私の場合)に、値が一致する列挙型も含める)の方がはるかに優れています。
これは時期尚早で不必要な盲目的な最適化の形だと思います。単一のcharを使用することで、最近の世界を救うかのように。ブール値/ビットをサポートしないデータベースのY/Nブール値は別として。
適切な Data Access Layer を開発せず、コード内のどこにでもsqlを使用して、何かを「すばやく」実行できるようにします。その後、プロジェクトが拡大し始め、要件が変更されると、悪夢になりました。当時、DALが何であるかは知りませんでした。
...私はそれを過ぎてうれしいですが、20年以上の「経験」を持つプログラマーがこれをやっているのを見ています。
私が建築家、開発者、PMのすべてが同じプロジェクトに参加する可能性があると考える。
1泊3時間の2ヶ月の睡眠は、あなたにはそれができないと教えてくれました。
Java IDEを作成するためのMicrosoft Foundation Classes(IFC)の選択。
それはmyの決定ではありませんでしたが(後で入社しました)、どこかで作業を行ったところ、すべてのログメッセージの翻訳を含め、i18nが少し長すぎました。
結果:
おっとっと。
車輪の再発明
設計しすぎ。多数のUML図、特にすべての単一操作のシーケンス図を作成すると、その多くは結局役に立たないことが判明しました。最後に、不必要に詳細な設計/図をスキップして直接コーディングを開始することで、かなりの時間を節約できることがわかりました。
顧客が何を求めているかを理解していると信じ、確認する前にやりすぎている。
私の単一の最悪の設計決定? 1980年代に戻って、実行時に解釈されるデータ入力画面の一種のテンプレートを作成するという優れたアイデアを得たプロジェクトに取り組んでいました。悪い決定ではありません。入力画面の設計が簡単になりました。基本的には、データ入力画面に似たファイルを作成するだけです。ラベルと入力フィールドの違いを識別し、入力フィールドが英数字か数値かを識別するための特別なコードを使用します。次に、これらのファイルにいくつかの特別なコードを追加して、実行する必要がある検証を特定することにしました。次に、画面の条件付き構築を許可するためのコードを追加しました。フィールドXは、一部の条件がtrueの場合にのみ含まれます。その後、コードを追加して、入力の簡単な処理を行います。などなど最終的には、画面テンプレートを新しいプログラミング言語に変え、式、制御構造、I/Oライブラリを完備させました。そして何のために? FORTRANを再発明するために私たちはたくさんの仕事をしました。私たちは、より適切に設計およびテストされた言語用のコンパイラでいっぱいの棚を用意しました。私たちが実際にある程度の専門知識を持っている製品を構築するためにその多くの努力を費やしたなら、その会社は今日でもビジネスをしているかもしれません。
オブジェクト指向開発の落とし穴 で列挙(---)によってDesign by Enumerationと呼ばれる熱心なアプリケーションは、賢明な人が要件は間違いなく変更される予定でした。そして、繰り返し変更します。
現在の要件にすべて正確に(---)を(ハード)コーディングした場合-「これはもっと一般的ではないでしょうか?」 YAGNIマレットを使用すると、要件が大幅に変化します(ただし、合理的に予想される方法で変化します)。これにより、適応に2週間かかる場合と20分かかる場合の違いが生じます。
更新:明確にするために、ここで、起こったことからそれほど遠くない架空の例を示します。 Stack Overflowはバッジをサポートするように設計されていますが、最初は4つのバッジしか考えられなかったとします。サイト内のすべてのロジック全体で正確に4つのバッジのサポートをハードコード化した、わずか4つです。データベース、ユーザー情報、すべての表示コード。 「そうじゃない」なんて考えられないバッジがあるからね?次に、サイトが稼働し、人々が新しいバッジを提案し始めたとします。 各場所にTweakへのハードコーディングが非常に多いため、各バッジの追加には最大2週間かかります。しかし、それでも、今日のリストよりも多くのバッジが「必要ない」ので、バッジの一般的なコレクションをサポートするためのリファクタリングはありません。そのような一般的なコレクションは、前もってもう時間がかかるでしょうか?あれば、それほど多くありません。
YAGNIは価値のある原則ですが、貧弱な設計や不適切なハードコーディングを許すために使用するべきではありません。バランスがあり、経験から、私はそれに近づいていると信じています。
間違った人と一緒に何かを正しく、素晴らしいものにしようとしています!
彼らが過剰な自我の役割を果たしている場合でも、PM(これは、彼らの無能さがより長く耐えられる大企業では特にあまりに一般的です)。
私は急いでいるので、技術的な負債を生み出すたびに、手続き型コードを書き、テストの記述をスキップします。ほとんど必然的に、これは将来私に苦痛をもたらすことがわかります。
最悪の敵には望みません。
過去2か月間にいくつかのSSISパッケージをビルドした後、私が開発したパッケージが配布可能ではなく、かつ展開不可能であることが判明した。具体的には、非Web、非SQL Serverライセンス環境。
純粋な.NET POCOコードでSSISパッケージを書き直す時間が48時間未満であるか、目標とする期限に間に合わない場合は、非常に悪い状況です。
OLEDBアダプターとSQLアダプターを使用して、純粋な.NETコードで12時間以内に3つのSSISパッケージ(テストと開発に2か月かかった)を書き直すことができたことに驚かされます。
SSISは配布可能ではなく、SQL Serverライセンス(具体的にはDTSPipeline.dll)がインストールされていない場合、クライアントマシンからパッケージを実行しません。これは、事前に知っておくと便利です。 MSDNに免責事項(細字)が表示されます。 SQL-LICENSEDマシンのみのコードを使用してインターネット全体にサンプルコードがある場合、これはうまくいきません。基本的に、SSISパッケージをプログラムで実行するには、SQLサーバーと通信するWebサービスを作成する必要があります。実行中のマシンにSQLライセンスがインストールされていない限り、純粋な.NETコードからそれらを実行することはできません。それはどれほど非現実的ですか?マイクロソフトは、SQLサーバーのインストールを必要とするマシンからSSISが使用されることを本当に期待していますか?なんと2か月の完全な無駄。
私の会社では、この小さな活字の「問題」のため、SSISを再び使用することはありません。
できるだけ早く展開メカニズム/モデルを定義しない。
2週間の休暇に行く前に書いたコードに「面白い」イースターエッグを投げ入れました。私が戻ったときにそれを読むのは自分だけだと思っていたので、笑って再コーディングする準備ができました。
言うまでもなく、私が不在の間に上司がレビューしたとき、上司は感銘を受けなかったし、「イースターエッグ」の1つがASCIIでおかしに漫画化された彼の顔を含んでいたとき、彼はさらにそれほど感銘を受けなかった。
うーん...
通常の旧式のCSSフォルダーだけで十分な場合に、ASP.Netテーマを使用します。
正しい道ではなく、いくつかのコードを機能させるための短い道のり(少し一般的ですが、これを抽象化と呼び、したがって「正しい」答えと呼びます)。
私の会社には滝のような開発モデルがあり、ビジネスユーザーとビジネスアナリストがプロジェクトの要件を定義します。私たちの「大きな」プロジェクトの1つで、要件のスタックを取得しました。具体的には、多数の要件の実装の詳細、具体的には、会計処理で使用されるデータベーススキーマに関連する情報が含まれていることに気付きましたシステム。
実装はmyドメインであり、要件に含めるべきではないとビジネスユーザーにコメントしました。結局のところ、彼らはビジネスであり、会計士が会計ソフトウェアを設計することは理にかなっているからです。トーテム世論調査をはるかに下回っている卑劣な開発者として、私はthinkではなくdoを支払われています。私がそれと戦っただけで、私は彼らに要件を書き直すように説得することができませんでした-変更の周りにあまりにも多くの書類と赤いテープがありすぎて、それはあまりに面倒です。
それで、私は彼らが望んだものを彼らに与えました。少なくとも、それはsorta worksですが、データベースは奇妙に設計されています:
不要な正規化がたくさんあります。 5または10のフィールドを含む単一のレコードは、3または4つのテーブルに分割されます。私はそれを扱うことができますが、個人的にはすべての1:1フィールドを単一のテーブルにプルしたいです。
多くの不適切な非正規化。請求書データ以外のデータを格納する請求書データを格納するテーブルがあります。フラグが論理的にInvoiceDataテーブルに関連付けられていない場合でも、InvoiceDataテーブルにさまざまなフラグを格納します。これにより、各フラグにはマジックのハードコードされた主キー値があり、他のすべてのフィールドはInvoiceDataテーブルでnullになります。フラグはテーブル内のレコードとして表されるため、フラグを独自のテーブルにプルすることをお勧めします。
より多くの不適切な非正規化。特定のアプリ全体のフラグは、不適切なテーブルに列として格納されているため、アプリのフラグを変更すると、テーブル内のすべてのレコードを更新する必要があります。
主キーにはメタデータが含まれているため、varchar主キーが「D」で終わる場合は、1つの値のセットを使用して請求書を計算し、そうでない場合は別のセットで計算します。このメタデータを別の列にプルするか、値のセットをプルして別のテーブルに計算するほうが理にかなっています。
外部キーは多くの場合、複数のテーブルに移動します。たとえば、「M」で終わる外部キーは住宅ローン勘定テーブルにリンクし、「A」で終わる外部キーは自動勘定テーブルにリンクする場合があります。データをMortageDataとAutoInsuranceDataの2つのテーブルに分割する方が簡単です。
私の提案はすべて、多くの嘆きと歯ぎしりで撃ち落とされました。アプリは設計どおりに機能し、泥の大球ですが、厄介なハッキング、特別なケース、および奇妙なビジネスルールはすべて、皮肉にもユーモラスにソースコードに文書化されています。
クライアントを新しい.NETフレームワークバージョンにアップグレードするのは面倒すぎるように見えるため、古いテクノロジーに固執しますが、ソフトウェアの一部の(時間を節約する)コンポーネントを利用できないため、ソフトウェアの作成には実際にはより多くの開発時間がかかります。新しいフレームワークバージョン。
大学に戻って、私はシニアデザインプロジェクトに取り組んでいました。別の男と私は、Webベースのバグ追跡システムを作成していました。 (画期的なことは何もありませんでしたが、私たちは両方ともWeb体験を得たいと思っていました。)私たちは、Javaサーブレットを使用してそれを行いました。エラー処理メカニズムとして、エラーコードの使用を選択しました。
ある学年のプロジェクトを発表したとき、教員の1人が必然的に「もう一度やり直さなければならなかった場合、どうしますか」と尋ねました。私はすぐに答えを知りました。「私は例外を使用します、それが彼らがそこにあるためのものです。」
私が選択した方法ではありませんが、行ベースのXMLファイルを列ベースのHTMLレポートに変換するXSLTを作成しました。
これはIEでのみ機能し、機能をデコードすることは完全に不可能でした。それを拡張する必要があるたびに、信じられないほど困難で、時代を経ました。
最後に、同じことを行う小さなC#スクリプトに置き換えました。
たとえそれさえ必要としないとしても、(新しいテクノロジーを学ぶために)すべての新しいテクノロジーを使用しようとすること。
ビジネスモデルを評価するのに十分な時間がかかりませんでした。私はクライアントが求めたことを行いましたが、6〜12か月後、両者は異なる方法で行うべきであるという結論に達しました。
仕様なしで設計。
要件に従ってアプリケーションのサブセクションを実装しました。
要件が肥大化し、金メッキされていることがわかり、私のコードは過剰に設計されました。サブセクションは、そのときに追加していたものだけで機能するように設計する必要がありましたが、最初から一般的なサポートを含めずに、他のすべてのものを追加することを計画しています。
作業コードを書き換えます。地獄の結果はうまくいき、バグが減り、メンテナンス性が向上しました。
しかし、顧客はそれほど気にする必要がなく、私の開発時間を費やしました...
2つのプロセッサ間で循環バッファ[N-deep]のN番目の要素を利用しようとしています。シンプルで信頼性を保つために、N-1を超える要素を使用することはありません。
問題:N-1個以下の要素を含む循環バッファーは、完全にスレッドセーフに実現できます(純粋なプロデューサー/コンシューマー)。 N個の要素用に最適化すると、キューが完全から空(データ損失)または空から完全(無効なデータ)に切り替わることがあります。
これを複雑なシステム(100Mバイトのデータ転送ごとに1つの破損)で見つけようとすることは、干し草の山で針を見つけるよりも困難です。
「デザイナー」が写真のカルーセルを望んでいたため、フラッシュを使用してサイトを構築しました(それは数年前、jQueryは存在しませんでした)。その後、彼は設計についての考えを変えたので、設計者はすべてを週に1回変更したいと思ったことがわかりました...なんとメンテナンスの悪夢。
私の最後の仕事で、クラス、リストをサポートしていない社内スクリプト言語を使用して、いくつかの大きなプロジェクトを書きました。唯一の「インクルード」メカニズムは、あるファイルを別のファイルに含めることでした。
後から考えて、.netまたはpythonでそれを書くことができ、拡張性の問題の半分が消えていただろう。
以前、クライアントサーバーアプリケーションのビジネス層を設計して、すべての呼び出しが非同期になるようにしました。サーバー側で不足しているリソースを管理しやすくなると思いました(1997年で、帯域幅に大きな制約がありました)。サーバーの管理方法には大きな違いはありませんでしたが、クライアントは非常に複雑になりました。
言うまでもなく、プロジェクトには約4か月の非常に迅速なリファクタリングがありました。そして、あなたのツールの強みを発揮するシンプルなアーキテクチャが常に最高であることを学びました。
後から見ると、互いにほとんど関係のないコンポーネントの密結合。これらのコンポーネントは、機能のごく一部のみを使用したい他の開発者によって、コピーパスタによって忘却に移されました。 :-(
Joelの話を聞いて、ソフトウェアを書き直す代わりに拡張しようとしています。
クライアントのサーバーでプロジェクトを開始する前に、仕様を完全に決定することに失敗しました。私はPHP(つまり> = 5.2)と言った、PHP 4、私は「データベースが必要だ」と言った(最終的に回答したとき) 、彼らは言った、「テーブルを作成したら、データベースに入れます...」(IIではなく、Apacheへの欲求についても言及していませんでした)。夜、これは私がこれまでに作った中で最悪の糞の1つです。私が得た唯一の利点は、PHP 4、理解したくないこと、と。
私が戻ってそれをもう一度やることができれば...私はそうしません。
OOと、手続き型アプローチの方が効果的だった場合の多態性の使用。
これ以外に何が悪い
は問題のある行をコメントアウトし、それがログイン呼び出しになった。 :(
前職では、自動テストフレームワークの構築を担当していました。 Background:すでにかなり良い「プロトタイプ」があり、多くのテストが書かれていました。 TCLで書かれています。
新しいプロジェクトでは、新しいプロジェクトに合うようにプロトタイプを調整することになっていた。私はTCLが本当に嫌いで、Pythonを習ったばかりなので、その新しい知識をどこかに適用するように強く要求していました。したがって、もちろん、プロトタイプをPythonで書き直すことにしました。私たちはたくさんの本当にクールな新しいことをしたかったので(階層テストをより良くサポートし、新しいテストを簡単に作成するためのあらゆる種類の追加メカニズムを持っています)、私はTCLでこれらすべての新しいものを書くことは悪夢になると言って私の決定を正当化しました。
結局、(wayとにかく難しすぎた)新機能のほとんどは使用されませんでした。プロトタイプ全体を最初から再実装して、ほとんど報酬を得ていませんでした。
最良の部分?約1年半後、古いプロトタイプを試して、古いプロジェクトでいくつかのテストを実行する必要がありました(これが起こることが予測されます)。新しいツールのいくつかにそれを適応させなければならないのではないかと心配していました(Pythonで再実装することを選択した理由の1つ)。約2時間の作業が必要であることがわかりました。
シングルトンパターンの使いすぎ
これは私がキャリアのかなり前にやったことです。特にTDDとユニットテストについて詳しく学ぶ前に、論理的に1か所にしか存在しないほとんどすべてのものをシングルトンにしました。多くの場合、そのコードベースが単体テストで改造される必要がない限り、それほど悪くはありませんでしたが、それは潜在的な技術的負債の大きな影響です。
また、このスタイルのコーディングでは、これらのシングルトンの一部が God Objects の種類になることがよくありました。多くの場合、アプリケーションのその領域に関連するほぼすべてを行う一種のユーティリティクラスとして。