私が数年間取り組んでいる大きなプロジェクトは、ファームウェアの中心である高度なデバイスの制御(およびすべて)アプリケーションです。
デバイスはかなり高度で、メモリから言うよりもさまざまな機能を備えており、それらの98%はこの1つの巨大な実行可能ファイルによって処理されます。一方で、プログラムは非常に保守可能で、モジュール化されており、適切に文書化されています。機能は、ディレクトリやファイルなどで合理的に分離されています。
しかし、最終的には、リモートデータベース通信、タッチスクリーン処理、さまざまな通信プロトコルの処理、測定、いくつかの制御アルゴリズム、ビデオキャプチャ、イースターの日の出時刻と日付(真剣に、非常に深刻な目的のために必要です!)...一般的に、非常に薄く関連しているもの、多くの場合、いくつかの遠いモジュール間で細流するいくつかのデータを通じてのみ関連しています。
たとえば、ソケットを介して、より具体的な目的で相互に通信するいくつかの個別の実行可能ファイルとして実行したり、必要に応じてロード/アンロードしたりすることができます。このように作成された特定の理由はありません。
一方で、それは機能し、それは大丈夫です。プロジェクトは、複数のバイナリのビルドを維持することなく、よりシンプルです。ソケットや共有メモリを介して通信する代わりに、メソッドを呼び出すか変数を読み取るだけでよい場合も、内部構造がより簡単になります。
しかし、一方で、このことのサイズ、スケールは私を忍び寄らせているだけで、タイタニック号を操縦しているように感じます。私はいつもモジュール化するように教えられました、そしてすべてを一つの巨大なファイルにまとめることは間違っていると感じます。私が知っている1つの問題は、1つの(重要ではない)モジュールの大クラッシュがすべてクラッシュすることです-しかし、コードの品質は、これがリリースバージョンでは実際に発生しないことを保証します。それ以外の場合は、内部の分離と防御プログラミングにより、何らかの理由で内部モジュールの半分が正常に機能しなくなった場合でも、ほぼ正しく実行されます。
他にどのような危険を見落としましたか?なぜこれは私を忍び寄らせるのですか?これは不明なだけの不合理な恐怖ですか?この方法で深刻な大きなプロジェクトを作ることは、受け入れられた慣行ですか?不安を和らげるか、バージョン2.0を複数の小さなバイナリにリファクタリングする十分な理由を教えてください。
最後の小さなコメント(2番目のCPUの監視)を除いて、あなたは私の会社を説明することができます。うん、イースターも必要だ。
さて、私たちは少し先に進んでいます。大きな実行可能ファイルを分割し、標準ビットに標準コンポーネントを使用しようとしました。期待したほどの大きな改善とは言えません。実際、ハードウェアが強化されていても、パフォーマンスは大きな問題になっています。また、狭いインターフェースを介してデータをシリアル化および同期化するための大量のコードがあるため、メンテナンスコストは実際には下がっていません。
私が学んだ教訓は?単一の実行可能ファイルを使用することは、小規模システムで十分に実証されたソリューションであり、その管理には数十年の経験があります。私たちのすべてのツールはそれをネイティブにサポートしています。モジュール化は単一の実行可能ファイル内でも行うことができ、他の理由でモジュール化を妥協する必要がある場合でも、ハックは小さいままです。
デバイスはかなり高度で、メモリから言うよりもさまざまな機能を備えており、それらの98%はこの1つの巨大な実行可能ファイルによって処理されます。一方で、プログラムは非常に保守可能で、モジュール化されており、適切に文書化されています。機能は、ディレクトリやファイルなどで合理的に分離されています。
あなたはそれを自分で言った-それはかなりメンテナンス可能で、よくモジュール化されている...
私の意見では、経営陣のほとんどはこれに同意しますが、変更のために変更を加えてはなりません。このプログラム(あなたの説明)には、最新のプログラミングの傾向(他の回答で言及されている)に従っていないこと以外は何も問題はありません。
はい、それはより大きなプログラムです...以前にも多くがそうでした。それも十分に文書化されているので、あなたがしなければならないのはその内部組織を研究することだけであり、その中に論理を見るでしょう。それを書いたあなたの前のすべての人が無能だったとは思えません。それで、少し調べて、それを学んでください...その後、書き直しの確かな理由が現れるまで、それをそのまま維持してください。あなたのマネージャーはあなたが良い費用対効果の比率を持っていることに対してあなたに感謝するでしょう。
他にどのような危険を見落としましたか?なぜこれは私を忍び寄らせるのですか?これは不明なだけの不合理な恐怖ですか?この方法で深刻な大きなプロジェクトを作ることは、受け入れられた慣行ですか?不安を和らげるか、バージョン2.0を複数の小さなバイナリにリファクタリングする十分な理由を教えてください。
それは大きいのであなたを忍び寄ります-しかし、繰り返しますが、誰もがあなたが一週間ですべてを暗記することを期待することはありません。だから、こつこつになるまで、少しずつ、少しずつ作業してください。最終的には、おそらくそれがそのままの形で編成されていることと、それがどのように編成されているかがわかります。
あなたがそれを書き直したなら、あなたは同じことを成し遂げるでしょうが、同時に、以前のコードの編成に慣れていたすべての人々のためにそれを台無しにしてしまいます。このように、あなただけが「適応」する必要があります。
単体テストにすべてを包み込んだと言ったら、私は気分が良くなるでしょう。そうでない場合は、アプリケーションの再設計を考える前に、テストスイートをビルドする必要があります。
テストスイートを用意することで、アプリケーションの理解が深まり、アプリケーションの変更によって何かが壊れたときに通知されます。
コードが適切にモジュール化され、結合度が低く凝集度が高い場合、コードは効果的に分割されます。 1つのプロセス内の通信オーバーヘッドは、複数のプロセスの場合よりも低くする必要があります。
組み込みシステムの場合、1つのプロセスで、作成するすべてのプロセスを実行するためにO/Sを実装する必要がなくなります。また、すべてのプロセスが実行されていることを確認し、可能であれば再起動するシステムを実装する必要もあります。それが不可能な場合は、それに応じて対応する必要があります。
モジュール間にすべてのクライアント/サーバーコードを実装する必要があるため、コードを個別の実行可能ファイルに分割すると、ソースコードの全体的なサイズも増加します。また、このコードを処理するためのテストケースと、サーバープロセスが存在しない場合のケースも必要になります。大きなプロジェクトは大きく、ここで行われたように見える不必要な複雑さを排除することで、プロジェクトをできるだけ小さく保つことができます。
テストは、テストの有無にかかわらず問題がまだ存在するため、ここでは一種の赤いニシンです。どちらかの設計を選択して適切なテストを行うことは確かに推奨されます。モノリシックコードを使用すると、テストがより簡単になると思います。
必要なときに強制的にクラッシュさせるのも、一体型の実行可能ファイルの方が簡単です。
このような大きなモノリシックアプリケーションで作業する場合、私を驚かせるのは、カプセル化の欠如、凝集度の低さ、結合の高さ、そしてこれらすべてをテストする方法です。大きなモノリスは、適切なアーキテクチャを放棄して 泥の大きなボール への降下を開始するための招待状であることがよくあります。
それが発生すると、テストは悪夢になり、陳腐化の兆しが見え始めます。
ただし、コードが適切に構成され、適切に維持されており、凝集度が高く、カップリングが低く、適切なカプセル化の原則が守られている場合、これを小さな単位にリファクタリングする理由はほとんどありません。
ただし、適切なテストを実施する必要があります。
単一のプロセスを使用している場合、サブモジュールの1つからのワイルドポインターがメモリの重要な部分を破壊する(そして全体をクラッシュさせる)可能性があります。
異なるプロセスを使用している場合は、少なくとも同じヒープまたはコールスタックを使用しておらず、単一のサブプロセスを再起動する方が簡単な場合もあります。
ソケットや共有メモリを介して話すのではなく、メソッドを呼び出すか変数を読み取るだけの場合、内部構造も簡単です。
すべてを複数のプロセスで再分配すると、設計をクリーンアップし、すべてのモジュールが他のモジュールの内部メソッドの使用を開始しないようにする必要もあります。
とはいえ、それはおそらく困難な作業です。
あなたが始めることができることは、すべての新しいモジュールが分離されたプロセスであるべきだと決定することです。
理想的には、答えはイエスです。複数のバイナリを持つことは、それをより安定させる可能性があります...
...しかし、モノリシックコードベース内のコードは適切に記述され、モジュール化されていることにも言及しました。
全体的に言えば、「完璧を善の敵にさせてはならない」ということわざは当てはまります。モノリシックなコードベースは悪いと言うのは正しいと思いますが、心配する価値はないと私は感じています。
新しいコードを独自のバイナリに配置して先に進むことは妥当ですが、戻ってリファクタリングすることは、おそらく価値がありません。
プロジェクトが大きすぎて一度にすべてを理解できない領域に入ると、すべての大きなセクションとそれらがどのように適合するかをレイアウトする壁に掛けるチャートを作成します。次に、作業しているときに、焦点を当てているモジュールを参照して、全体にどのように適合するかを視覚的に思い出させることができます。
切断された複数のバイナリのビルドとバージョン管理システムを維持することの複雑さと危険が、このような大規模で一体型のプロジェクトの不安をはるかに上回る可能性は十分にあります。