24

私は定期的に、実際のロケット外科医によって構築されたシステムの保守作業を行うよう求められます。どこから始めればよいか分からないほど、多くの間違いがあります。

いいえ、待ってください。最初から始めましょう。プロジェクトの初期の段階で、設計者はシステムをスケーリングする必要があると言われており、スケーラビリティの問題の原因はアプリケーションとデータベース間のトラフィックであると読みました。このトラフィックを最小限に抑えるようにしました。どのように?すべてのアプリケーション ロジックを SQL Server ストアド プロシージャに配置します。

真剣に。アプリケーションの大部分は、XML メッセージを作成する HTML フロント エンドによって機能します。中間層が XML メッセージを受信すると、ドキュメント要素のタグ名を呼び出すストアド プロシージャの名前として使用し、SP を呼び出して、XML メッセージ全体をパラメータとして渡します。SP が返す XML メッセージを受け取り、フロントエンドに直接返します。 アプリケーション層には他のロジックはありません。

(スキーマのライブラリに対して受信 XML メッセージを検証するためのコードが中間層いくつかありました。しかし、1) 少数のメッセージのみが対応するスキーマを持っていること、2) メッセージが実際には準拠していないことを確認した後、それを削除しました。 3) メッセージを検証した後、エラーが発生した場合、メソッドはメッセージを破棄しました。「このヒューズボックスは本当に時間の節約になります - 工場でペニーがプリインストールされています!」)

以前、間違ったことをするソフトウェアを見たことがあります。たくさん。かなり書いてきました。しかし、このシステムの設計とプログラミングに具現化されている、あらゆる可能なターンで間違ったことをするという冷徹な決意のようなものを見たことがありません。

まあ、少なくとも彼は自分が知っていることで行きましたよね?うーん。どうやら、彼が知っていたのはアクセスだったようだ。そして、彼はAccessを本当に理解していませんでした。またはデータベース。

このコードの一般的なパターンは次のとおりです。

SELECT @TestCodeID FROM TestCode WHERE TestCode = @TestCode

SELECT @CountryID FROM Country WHERE CountryAbbr = @CountryAbbr

Invoice.*、TestCode.*、Country.* を選択
   FROM 請求書
   JOIN TestCode ON Invoice.TestCodeID = TestCode.ID
   JOIN Country ON Invoice.CountryID = Country.ID
   WHERE Invoice.TestCodeID = @TestCodeID AND Invoice.CountryID = @CountryID

じゃ、いいよ。クエリオプティマイザーも信頼していません。しかし、これはどうですか?(もともと、これは「これまでに遭遇したソース コードで最高のコメントは何ですか?」に投稿する予定でしたが、この 1 つのコメントだけでなく、書くべきことがたくさんあることに気付き、事態は手に負えなくなりました。)多くのユーティリティ ストアド プロシージャの最後に、次のようなコードが表示されます。

-- NULL を修正
SET @TargetValue = ISNULL(@TargetValue, -9999)

はい、そのコードは、あなたが気が狂わないように、それが行っているとは信じられないことを正確に行っています。変数に NULL が含まれている場合は、その値を -9999 に変更して呼び出し元に警告しています。この番号が一般的にどのように使用されるかを次に示します。

-- 目標値を取得
EXEC ap_GetTargetValue @Param1、@Param2、OUTPUT @TargetValue
-- NULL 値のターゲット値を確認します
IF @TargetValue = -9999
    ...

本当。

このシステムの別の側面については、thedailywtf.com のI Think I'll Call Them "Transactions"というタイトルの記事を参照してください。私はこれを作り上げているわけではありません。私は誓います。

このシステムに取り組んでいると、ある学生に対する Wolfgang Pauli の有名な応答をよく思い出します。

これは、これまでで最悪のプログラムではありません。これは間違いなく、私の 30 年間のキャリア全体で取り組んできた中で最悪のものです。しかし、私はすべてを見たわけではありません。何を見た?

4

14 に答える 14

42

私はかつてMP3デコーダーを書き込もうとしました。うまくいきませんでした。

于 2008-10-18T10:33:32.787 に答える
19

ExtUtils::MakeMakerを維持しました。MakeMakerは確かに私が維持しなければならなかった最悪のコードではありません。それは実際にはエンジニアリングの驚異です。ただし、最もミッションクリティカルなコードが最も恐ろしいのは、そのユニークなクラスのコーディングホラーです。

MakeMakerは、ほとんどのPerlモジュールのインストーラーです。「Makefile.PL」を実行すると、MakeMakerが呼び出されます。MakeMakerが壊れると、Perlも壊れます。Perlはすべてで実行されるため、MakeMakerはすべてで実行する必要があります。私がすべてを言うとき、私はすべてを意味します。すべての奇妙なUnixバリアント。Windows95以降。そしてVMS。はい、VMSです。

MakeMakerは何をしますか?Makefile.PLは、PerlモジュールをビルドおよびインストールするためにPerlを実行することが多いシェルコマンドを含むMakefileを作成するPerlプログラムです。繰り返しますが、Perlを実行するためのシェルコマンドを記述します。Perl、シェルスクリプトを置き換える言語。

ああ、Cコードをコンパイルしてリンクすることもできます。また、Perlモジュールをperlに静的にリンクすることもできます。ああ、それはRCSチェックアウトを管理することができます。ああ、そしてあなたのディストリビューションのtarballを転がして...そしてzipファイル。そして、モジュールのインストールに漠然と関連する他のすべてのことを行います。

そして、これらすべてをポータブルで下位互換性のある方法で実行する必要があります。の亜種やバグに対処する必要があります...

  • make(GNU make、BSD make、nmake、dmake、mms、mmkなど)
  • シェル
  • Perl
  • ファイルシステム(大したことではないと思われる場合は、VMSを試してください)
  • Cコンパイラとリンカー

絶対に、確実に失敗することはなく、100%下位互換性を維持する必要があります。

ああ、それは実際の拡張APIの邪魔になるものがほとんどないので、それを拡張するために人々がしなければならないアドホックなMakefileハッカーとの互換性を維持する必要があります。

なぜそれがすべてこれを行うのですか?15年前にPerlがUnixでしか実行されなかったとき、これは素晴らしいアイデアのように思えました。makeだけを使用できるのに、なぜビルドシステム全体を作成するのですか?Perlはテキスト処理言語です。これを使用してMakefileを作成します。

幸い、代替のModule :: Buildがあり、MakeMakerがすぐに終了することを期待しています。しかし、その取り込みは遅く、コミュニティは変更に対して非常に抵抗力があるため、MakeMakerの保守に行き詰まっています。

于 2008-10-20T00:56:44.230 に答える
12

あなたが維持しなければならなかった最も不健全なプログラムは何ですか?

今まで書いたもの全部!

真剣に。ブログを読んだり、ポッドキャストを聴いたり、このようなサイトをフォローすればするほど、毎日より多くのことを学びます. そして毎日、基本的に昨日書いたことはすべて何らかの形で間違っていることに気づきます. キャリアの早い段階で書いたものを維持している貧弱な樹液に同情します。

于 2008-10-20T02:04:21.380 に答える
7

私が始めたばかりのもの。

  1. ソース管理なし。
  2. すべてのソースはライブで編集されます。間違いを防ぐために、db-access.php.070821のようなバックアップファイルがソースツリーに散らばっています。
  3. コードは非常に脆弱です。エラーチェックの方法はほとんどなく、フォールバックが発生してもまったくフォールバックしません。
于 2008-10-18T10:44:16.043 に答える
5

私はかつて、プログラミングの意志を失った(そしておそらく生きている)一部のプログラマーによって以前に作成および保守されていたレガシーCアプリケーションを保守する必要がありました。WTFが多すぎて言及できませんでしたが、さまざまな特殊なケースでTRUE + 1、TRUE+2などを返すブール関数を覚えています。

それから私はRoedyGreenのエッセイを読み、たくさん笑いました。それが面白いと思った理由は、私が維持しているコードからほとんどの例を認識したからだと気付くまでです。(そのエッセイは、何年にもわたる追加で少し肥大化していますが、それでも一見の価値があります。)

于 2008-10-22T10:04:30.660 に答える
2

Lucent の大学院を卒業した直後に、PL/I で書かれたコンパイラとインタープリタを管理するように与えられました。コンパイルされた言語は複雑な整合性制約のセットを記述し、インタープリターはこれらの制約を大規模なデータ セットに対して実行しました。このデータ セットは、後に 4ESS スイッチを制御する初期データベースに形成されます。4ESS は長距離音声トラフィック用の回線交換機であり、現在もそうです。

コードはごちゃ混ぜでした。「NORTH40」という分岐先のレーベルがありました。元の開発者にそれが何を意味するのか尋ねました。

「ここで範囲チェックが行われます。各フィールドの値が正しいことを確認するためのチェックです。」

「でもなんで『NORTH40』なの?」

「ほら、『ホーム、レンジのホーム』」

"は?"

'NORTH40' は農場の北 40 エーカーを意味し、都会で育った彼の頭の中では牧場とのあいまいなつながりを持っていました。

別のモジュールには、TORY と DIREC と呼ばれる 2 つの並列配列があり、これらは並列に更新されたため、データのペアを含む単一の配列をモデル化するという明らかに誤った試みでした。名前が分からず、開発者に聞いてみました。それらは一緒に読むことを意図していたことが判明しました:「ディレクトリ」。偉大な。

整合性制約を作成しなければならなかったかわいそうな連中には、手引きとなるユーザー マニュアルがなく、口頭の伝統と手書きのメモだけでした。さらに悪いことに、コンパイラは構文チェックを行わず、多くの場合、間違ったロジックに静かにマップされた制約を指定してしまい、多くの場合、非常に悪い結果をもたらしました。

さらに悪いことは来ていました。インタープリターの内部を掘り下げていくと、それが巨大なソート プロセスを中心に構築されていることがわかりました。ソート前は、生データと整合性制約からソート入力データを生成する入力プロセスでした。したがって、5,000 のトランク定義を含むテーブルがあり、各トランク レコードに、入力データ セット全体で一意である必要がある 3 つのフィールド値がある場合、入力プロセスは 3 * 5,000 = 15,000 の並べ替え入力レコードを作成し、それぞれが raw整合性制約番号がプレフィックスとして付けられたデータ レコードと、並べ替えられるフィールド値のコピー。5,000 レコードのソートを 3 回行う代わりに、15,000 レコードのソートを 1 回実行しました。何百ものテーブル内およびテーブル間の整合性制約、およびいくつかの非常に大きなテーブルを考慮に入れる頃には、組み合わせの悪夢に見舞われていました。

少しリファクタリングし、言語を文書化し、構文チェックを追加してわかりやすいエラー メッセージを表示することができましたが、数か月後、新しいグループへの異動に飛びつきました。

于 2009-06-01T01:43:45.200 に答える
2

私は以前、COBOLプログラマーでした(戦慄)。私たちのコードはすべて「不健全」なカテゴリに分類されました。COBOL では、名前空間がなく、すべての変数がグローバルであり、ファイル名やその他のリソースの重複が必須です。プロシージャを呼び出すには、グローバル変数を設定し、プロシージャを呼び出してから、それらのグローバル変数 (または設定される可能性のある他の変数) の内容を調べます。

しかし、最悪だったのは、私が生まれる前 (私は 1967 年生まれ) に書かれた COBOL プログラムを維持することであり、そのフロー制御の唯一の方法は GOTO でした。それは絶対的な混乱であり、従うことは不可能でした。変数タイプへの小さな変更は、解決するのに数日かかる場合があります。自動化されたテストはなく、手動のテスト計画は保存されませんでした。そのため、すべての変更は、新しい手動のテスト計画を作成し、徹底的に追跡し、コードとともに提出する必要がありました。

皮肉なことに、これが COBOL の成功の理由です。COBOL は多くの場合、ジョブ制御言語 (JCL) によって実行されます。COBOLは非常に弱いため、プログラムは多くのことを行うわけではありません。そのため、JCLはディスクスペースを割り当て(多くの場合、シリンダーレベルまで)、小さなCOBOLプログラムを実行してデータを読み取り、必要なデータだけを書き出します。次に、JCL はソート プログラムを呼び出して、結果のファイルをソートします。次に、別の COBOL プログラムが呼び出されて、ソートされたファイルが読み取られ、データが要約され、場合によっては必要な結果が再抽出されます。また、JCL を使用してファイルを別の場所に移動したり、別の COBOL プログラムを呼び出して結果を読み取ったり、データベースに保存したりすることもできます。各 COBOL プログラムは 1 つのことだけを行う傾向があり、Unix パイプライン モデルの原始的なバージョンが作成されました。これはすべて、COBOL は保守や複雑なことを行うのが難しすぎるためです。他の方法で COBOL を記述することはほとんど不可能だったため、疎結合と緊密な結束 (プログラム内ではなくプログラム間) がありました。

于 2008-10-22T09:07:25.237 に答える
1

PHP/MySQL 駆動のオンライン連絡先管理システムで、連絡先テーブルに自然キーがありませんでした。区切られた文字列の形式で複合データを含むデータベース フィールドのインスタンスが多数あり、後でアプリケーション コードで解析する必要がありました。

HTML とロジックが絡み合っており、関数はほとんど使用されておらず、代わりにコードが切り取られて数十のソース コード ファイルに貼り付けられていました。データがサニタイズされていなかったため、(たとえば) 垂直タブが埋め込まれたフィールドが原因で、Ajax 呼び出しによって返された XML が誤動作し、さらに、数百とは言わないまでも数十の空のステートメントを含むファイルで、右中括弧の直後にセミコロンが続きます。 : "};"

于 2008-11-22T02:59:57.617 に答える
1

私は以前、BASIC で書かれた CAD アプリケーションに取り組んでいました。会社のポリシーでは、すべてのプログラムは次のステートメントで始めなければならないというものでした。

エラー再開時

jMM

于 2009-07-13T17:45:04.570 に答える
1

私は、イントラネットで使用するスケジューリング Web アプリケーションを保守しています。スケジューラーからエージェントを削除できるかどうか尋ねられたとき、私はその理由を確信しました。ソース コードを調べたところ、このエージェントの 1 日のすべての時間が個別にコーディングされていることがわかりました。彼の毎日もそうでした。そして、この地域のすべてのエージェントの毎週がそうでした. そして、約5地域のすべての地域がそうでした. asp コードをあちこちに保持する HTML ファイル。

ある日、これらのさまざまなファイルに含まれるコードの行数を推測するのに時間がかかり、約 300000 行と見積もった.30 万行のコードは、一度手書きでコピーして貼り付けたコードです。

しかし、この数字はすぐに私のマネージャーに、新しいスケジューリング アプリがすぐに必要になることを確信させました。

于 2008-10-20T01:13:31.450 に答える
0

私がこれまでに書いたものは、もともと簡単なプロトタイプであるはずだったもので、しばらくそのままになります。私の問題領域は、その性質上、多くの使い捨てのプロトタイピングが必要です。これらのプロトタイプの場合、すべてのベスト プラクティスと優れたスタイルのルールに違反することが合理的な場合があります。ただし、これらのプロトタイプを適切に動作させるのが非常に難しく、最終的にキーパーになってしまうことがあります。このような場合、私は通常、リファクタリング/リライトを無期限に延期することになります。私のモチベーションをさらに低下させているのは、上司がドメインの専門家であり、プログラミングをまったく行っていないことです。

于 2008-11-22T02:31:17.253 に答える
0

以前の雇用を維持するために開発者を雇っている特定の会社の ASP アプリケーションを維持しています... これらのアプリケーションはすべて文書化されておらず、コメントもありません。

すべての関数は、すべての ASP ページにコピー アンド ペーストされます。そのため、関数は定義されていません... DMZをバイパスするために、最初にサーバーにリモートする必要があるため、毎日私は彼らの環境に不自由です。その後、変更を加える必要がある本番サーバーにリモート接続する必要があります。

于 2008-10-22T09:16:39.057 に答える
0

CAD/CAM ジオメトリ処理言語 (P1 = 10,10; P2 = 20,20; L1 = P1,P2; - そのようなもの) のインタプリタ。Microsoft BASIC Professional Development System (PDS) で記述され、最小限の長さ変数名 (1 文字がすぐになくなったので、2 文字に変更しました。PP、PQ、PR、誰?)。そして、公平を期すために、いくつかのコメント。イタリア語で。

おかしなことに、それは実際に機能し、いくつかの機能を追加することはできましたが、アマチュア歯科のようでした-痛みがあり、お勧めできません...

于 2009-01-10T09:27:57.117 に答える
0

私はかつて、EDIF リーダーの定期的なクラッシュを追跡するために呼び出されました。ほとんどすぐに頭が痛くなり始めました。元の作者は、 Yaccがホワイトスペースで罰せられると感じていたようで、彼の Yacc 文法は密集していて読めない混乱でした。私はそれをフォーマットし、欠落している端末が出現したときにルールを追加し、スタックの成長を回避するように宣言を構造化するのに数時間を費やしました.ほら、クラッシュは消えました.

したがって、Yacc が文法を処理するのを待つたびに、生成されたパーサーが何千回も実行されることを覚えておいてください。空白で安くしないでください!

于 2008-10-24T19:25:34.553 に答える