巨大なモノリシックアプリケーションの危険性


20

私がここ数年取り組んでいる大きなプロジェクトは、ファームウェアの心臓部である高度なデバイスの制御(およびすべて)アプリケーションです。

デバイスは非常に高度であり、メモリから言うことができるよりも多くの異なる機能を備えており、それらの98%はこの1つの巨大な実行可能ファイルによって処理されます。一方では、プログラムは非常に保守性が高く、内部で適切にモジュール化され、適切に文書化されており、ディレクトリやファイルなどによって機能が合理的に分離されています。

しかし、最終的には、リモートデータベース通信、タッチスクリーン処理、多数のさまざまな通信プロトコル、測定、いくつかの制御アルゴリズム、ビデオキャプチャ、イースターの日の出時刻と日付(真剣に、非常に深刻な目的のために必要です!)...一般に、非常に薄く関連しているもの、多くの場合、いくつかの遠いモジュール間で少しずつ流れるいくつかのデータを通してのみ関連するもの。

ソケットを介して、より具体的な目的で、必要に応じてロード/アンロードするなど、互いに通信する複数の個別の実行可能ファイルとして実行できます。この方法で作成された理由は特にありません。

片手で機能し、大丈夫です。プロジェクトは、複数のバイナリのビルドを維持することなく、よりシンプルです。内部構造も簡単です。ソケットや共有メモリを介して通信するのではなく、メソッドを呼び出すか、変数を読み取るだけです。

しかし、一方で、このことの大きさ、規模は私をゾッとさせるだけで、タイタニックを操縦しているように感じます。私は常にモジュール化することを教えられましたが、すべてを1つの巨大なファイルにまとめるのは間違っているように感じます。私が知っている問題の1つは、1つの(わずかな)モジュールがすべてクラッシュするという重大なクラッシュです。それ以外の場合、内部の分離と防御的なプログラミングにより、何らかの理由で内部モジュールの半分が正常に機能しなくなった場合でも、これがほとんど正しく実行されることが保証されます。

他にどんな危険を見落としましたか?なぜこれが私を怖がらせるのですか?これは単なる不合理な未知への恐怖ですか?このように深刻な大きなプロジェクトを作成することは、受け入れられている慣行ですか?不安を和らげるか、バージョン2.0を複数の小さなバイナリにリファクタリングする正当な理由を教えてください。


7
太陽の昇り方が早すぎると、イングランドは海に漂います。
Maxpm

1
または、地球の中心部の圧力がわずかに上昇します。
StuperUser

1
@Maxpmあなたがそこでしたことを見る... xkcd.com/687
テト

3
@Maxpm:幸いなことに、このアプリは日の出と日の入りを駆動しません。セレスティア王女は彼女の仕事に失敗しないと信じています。
SF。

1
@rwong:1.アップグレードのためにデバイスが停止します。その場で更新を生き延びますが、何らかの理由で更新が失敗した場合の予期しない結果は望みません。2. Linuxが組み込まれたシングルコアARM9。メインCPUが正常な出力を生成することを検証する、OSなしで実行される2番目の監視CPUがあります。
SF。

回答:


5

最後の小さなコメント(CPUを監視する2番目)を除いて、あなたは私の会社を説明することができます。はい、イースターも必要です。

さて、私たちはもう少し進んでいます。大きな実行可能ファイルを分割し、標準ビットに標準コンポーネントを使用しようとしました。期待するほどの大きな改善ではありません。実際、パフォーマンスは、より強力なハードウェアでも大きな痛みになりつつあります。また、狭いインターフェイスを介してデータをシリアル化および同期するためのコードが大量にあるため、メンテナンスコストが実際に下がっていません。

私が学んだ教訓は?単一の実行可能ファイルを持つことは、小規模システム向けの実績のあるソリューションであり、管理には数十年の経験があります。すべてのツールがネイティブにサポートしています。モジュール化は単一の実行可能ファイル内でも行うことができ、他の理由でモジュール性に妥協する必要がある場合、ハックは小さいままです。


感謝-「従うべき/犠牲にするべきベストプラクティス」および「潜在的なメリットと潜在的なデメリットの重み付け」エントリは、フェンスの反対側から直接の経験を持つ人ほど有用ではありません。
SF。

23

デバイスは非常に高度であり、メモリから言うことができるよりも多くの異なる機能を備えており、それらの98%はこの1つの巨大な実行可能ファイルによって処理されます。一方では、プログラムは非常に保守性が高く、内部で適切にモジュール化され、適切に文書化されており、ディレクトリやファイルなどによって機能が合理的に分離されています。

あなたはそれを自分で言いました-それは非常に保守可能で、十分にモジュール化されています...

私の意見では、ほとんどの経営陣はこの点について同意しますが、変更のために変更を加えることはできません。このプログラム(説明)に問題はありませんが、最新のプログラミングトレンド(他の回答で言及されている)に準拠していないことは別です。

はい、それは大きなプログラムです...多くの前にもされています。また、文書化されているので、あなたがしなければならないことは、その内部組織を研究することであり、その中の論理を見るでしょう。私はそれを書いたあなたの前のすべてが無能だったことを疑います。それで、それを少し探検し、それを学んでください...その後、それを書き換える確固たる理由が現れるまで、それをそのまま維持してください。上司は、費用対効果の比が良いことに感謝します。

他にどんな危険を見落としましたか?なぜこれが私を怖がらせるのですか?これは単なる不合理な未知への恐怖ですか?このように深刻な大きなプロジェクトを作成することは、受け入れられている慣行ですか?不安を和らげるか、バージョン2.0を複数の小さなバイナリにリファクタリングする正当な理由を教えてください。

それは大きいのであなたを忍び寄らせます-しかし、再び、誰もあなたが一週間ですべてを暗記することを期待していません。だから、少しずつ、あなたがそれに慣れるまで、少しずつ作業してください。最終的には、おそらくそれがそのままでうまく組織されていること、そしてそれがどのように組織されているかを学びます。

あなたがそれを書き直したなら、あなたは同じことを達成するでしょうが、同時にコードの以前の組織に慣れていたすべての人のためにそれを台無しにします。このように、あなただけが「適応」する必要があります。


16

あなたがすべてを単体テストでラップしたと言ったら、私は気分が良くなるでしょう。そうでない場合は、アプリケーションの再構築について考える前に、テストスイートを構築する必要があります。

テストスイートがあると、アプリケーションの理解が深まり、アプリケーションの変更が何かを壊したときに通知されます。


2
しかし、それは可能なアーキテクチャの両方に適用されます...
SF。

3
はい、それは...ない
ロバート・ハーヴェイ

10
...したがって、この回答は、単体テストを促進することを除いて、ディスカッションに何も追加しません。
ベンザド

2
@benzado:OPのシナリオでは、これは非常に重要です。
ロバートハーヴェイ

2
@ironcode:「レガシーコードを効果的に使用する」などの本をご覧ください。「あなたは、すでに高いコードカバレッジとのユニットテストスイートを持っていない場合、彼はその本の中で述べている最初のものであり、あなたが何かを行う前に、まずそれらを書く。」私はアドバイス以上の関連ここにあることを言うだろう、 OPが「私が見落とした他の危険は何か」と
ロバートハーヴェイ

8

コードが低結合および高凝集度で適切にモジュール化されている場合、コードは効果的に分割されます。1つのプロセス内の通信オーバーヘッドは、複数のプロセスの場合よりも低くなります。

組み込みシステムの場合、1つのプロセスで、作成するすべてのプロセスを実行するためにO / Sを実装する必要がなくなる場合があります。また、実行中のすべてのプロセスを確認するシステムを実装し、可能であればそれらを再起動する必要があります。それが可能でなかった場合、それに応じて対応する必要があります。

コードを別々の実行可能ファイルに分割すると、モジュール間にすべてのクライアント/サーバーコードを実装する必要があるため、ソースコードの全体サイズも大きくなります。また、このコードを処理するためのテストケースと、サーバープロセスが存在しないケースも必要になります。大きなプロジェクトは大きく、ここで行われたように見える不要な複雑さを排除することで、可能な限り小さく保つことができます。

テストは、テストの有無にかかわらず問題が残るため、ここでは一種のニシンです。どちらの設計を選択した場合でも、適切なテストを行うことをお勧めします。モノリシックコードを使用すると、テストが簡単になります。

モノリシック実行可能ファイルを使用すると、必要なときにクラッシュを強制することも簡単になります。


1
+1、エンジニアリングはトレードオフに関するものであり、小さなバイナリにもコストがかかります
ベンザド

+1私は心から同意します。複数の実行可能ファイルを保証する特定の理由はありません。実行可能ファイル間の通信と調整には代価があります。
エリックロバートソン

+1:壊れていない場合は、修正しないでください。
ボブマーフィー

1

このような大きなモノリシックアプリケーションで作業する場合、私を驚かせるのは、カプセル化の欠如、低凝集、高結合、およびこれらすべてをテストする方法です。大きなモノリスは、しばしば適切な建築を放棄し、泥の大きな塊への降下を開始するための招待状です。

それが起こると、テストは悪夢になり、陳腐化への道を順調に進んでいます。

ただし、コードが適切に構造化され、適切に管理されており、高い凝集度、低い結合、適切なカプセル化の原則が守られている場合、これを小さな単位にリファクタリングする理由はほとんどありません。

ただし、適切なテストを実施する必要があります。


1

理想的には、答えはイエスです。複数のバイナリがあると、より安定する可能性があります。

...しかし、モノリシックコードベース内のコードは適切に記述され、モジュール化されていることも言及しました。

全体として、適切なことわざは「完璧を善の敵にしないでください」と言うでしょう。モノリシックなコードベースは悪いと言っているのは正しいと思いますが、それを心配するだけの価値はないと思います。

独自のバイナリに新しいコードを配置して前進するのは合理的ですが、戻ってリファクタリングすることはおそらくあなたの価値がありません。


1

単一のプロセスを使用している場合、サブモジュールの1つからのワイルドポインタがメモリの重要な部分を破壊する(そしてすべてをクラッシュさせる)可能性があります。

異なるプロセスを使用している場合、少なくとも同じヒープまたは呼び出しスタックを使用していないため、単一のサブプロセスを再起動する方が簡単な場合もあります。

内部構造も簡単です。ソケットや共有メモリを介して通信するのではなく、メソッドを呼び出すか、変数を読み取るだけです。

すべてを複数のプロセスに再分割すると、設計をクリーンアップし、すべてのモジュールが他のモジュールの内部メソッドを使用し始めることを回避することも強制されます。

それは恐らく困難な作業だと言われています。

始めることができるのは、すべての新しいモジュールを独立したプロセスにすることです。


特にファーウェアや組み込みデバイスが関係している場合、ランタイムハードウェアとOS環境について非常に多くのことを想定しています。
パトリックヒューズ

0

プロジェクトが大きすぎてすべてを一度に理解できない領域に着くと、壁にぶら下がるチャートを作成して、すべての大きなセクションとそれらがどのように適合するかをレイアウトします。次に、作業中に焦点を合わせているモジュールを参照し、全体にどのように適合するかを視覚的に思い出させることができます。

複数の切断されたバイナリのビルドおよびバージョン管理システムを維持する複雑さと危険性が、このような大規模でモノリシックなプロジェクトの不安をはるかに上回る可能性は十分にあります。

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