潜在的にモノリシックなアプリケーションをいくつかの小さなアプリケーションに分割すると、バグを防ぐことができますか?[閉まっている]


48

これを求める別の方法は次のとおりです。なぜプログラムはモノリシックになる傾向があるのですか?

Mayaのようなアニメーションパッケージのようなものを考えています。人々はさまざまなワークフローに使用します。

アニメーション機能とモデリング機能を独自の個別のアプリケーションに分割し、それらの間でファイルをやり取りして個別に開発した場合、それらの保守は容易ではないでしょうか?


9
If the animation and modelling capabilities were split into their own separate application and developed separately, with files being passed between them, would they not be easier to maintain?簡単に拡張たり、保守やすいモジュール混在させたりしないでください。それ自体は、複雑さや疑わしい設計の自由ではありません。Mayaは、プラグインはそうではありませんが、維持すべき地獄になる可能性があります。またはその逆。
ライヴ

37
単一のモノリシックプログラムは販売しやすく、ほとんどの人が使いやすい傾向があると付け加えます
DarthFennec

2
@DarthFennec最高のアプリは、ユーザーにとっては1つのアプリのように見えますが、内部で必要なものは何でも利用します。訪問するさまざまなWebサイトを駆動するマイクロサービスはいくつですか?それらのほとんどはもはやモノリスではありません!
corsiKa

23
@corsiKa通常、複数のモジュール/ライブラリを記述し、それらをモノリシックバイナリにリンクするだけでは得られない、内部で通信する複数のプログラムとしてデスクトップアプリケーションを記述することで得られるものはありません。マイクロサービスは、単一のアプリケーションを複数の物理サーバーで実行でき、負荷に応じてパフォーマンスを拡張できるため、まったく異なる目的に使用されます。
DarthFennec

5
@corsiKa-私が使用しているWebサイトの圧倒的な数はまだモノリスだと思います。結局のところ、ほとんどのインターネットはWordpressで実行されています。
19:52のDavorŽdralo

回答:


94

はい。一般に、2つの小さく複雑でないアプリケーションは、1つの大きなアプリケーションよりも保守がはるかに簡単です。

ただし、アプリケーションがすべて連携して目標を達成すると、新しいタイプのバグが発生します。それらを連携させるには、メッセージを交換する必要があり、すべてのアプリケーションが完全に機能する場合でも、このオーケストレーションはさまざまな方法で失敗する可能性があります。100万個の小さなアプリケーションを持つことには、独自の問題があります。

モノリシックアプリケーションは、単一のアプリケーションにさらに多くの機能を追加する場合に実際に使用するデフォルトのオプションです。各機能を単独で検討する場合、これが最も簡単なアプローチです。全体が大きくなってから「XとYを分離すればうまくいく」と言うことができるのは一度だけです。


6
はい。また、ポインタを渡すコストとデータをシリアル化するコストなど、パフォーマンスに関する考慮事項もあります。
ジミージェームズ

65
「一般に、2つの小さく複雑でないアプリケーションは、1つの大きなアプリケーションよりも保守がはるかに簡単です。-そうでない場合を除き、それは本当です。これら2つのアプリケーションが相互に接続する場所と方法に大きく依存します。
ドックブラウン

10
「一般的に、2つの小さく複雑でないアプリケーションは、1つの大きなアプリケーションよりも保守がはるかに簡単です。」私はそれについてもう少し説明が必要だと思います。コードベースから1つの実行可能ファイルではなく2つの実行可能ファイルを生成するプロセスにより、コードが魔法のように簡単になるのはなぜですか?コードがいかに簡単であるかを決定するのは、それがどれほど緊密に結合されているか、および同様のものです。しかし、それは論理的な分離であり、物理的分離とは関係ありません。
Voo

11
@Ew物理的な分離は論理的な分離を強制しません。それが問題です。2つの別々のアプリケーションが密接に結合されたシステムを簡単に設計できます。確かに、アプリケーションを分離するために時間を費やす人は、これらのことを検討するのに十分な能力を持っている可能性が高いため、ここには何らかの相関関係がありますが、因果関係を仮定する理由はほとんどありません。同じロジックで、最新のC#バージョンを使用するとコードの保守がはるかに簡単になると主張できます。ツールを最新の状態に保つチームは、おそらくコードの保守も心配するからです。
Voo

9
ここでの議論は2つのステートメントで要約できると思います:1)アプリ自体を分割しても、アプリのメンテナンス性は向上しません-反対に、別の失敗の可能性のあるポイントを提供します2)アプリを分割すると、分割する場所を考えるように強制されますこれは、これまで行われたことのないモノリスに比べて利点があります。
R.シュミッツ

51

潜在的にモノリシックなアプリケーションをいくつかの小さなアプリケーションに分割すると、バグを防ぐことができますか

物事は現実にはめったにありません。

分割しても、そもそもこれらのバグを防ぐのに役立ちません。バグをより迅速に見つけるのに役立つ場合があります。小さく分離されたコンポーネントで構成されるアプリケーションでは、それらのコンポーネントに対してより個別の(「ユニット」のような)テストが可能になる場合があります。

しかしながら、

  • 外部からモノリシックに見えるアプリケーションでさえ、内部で多くのユニットテスト可能なコンポーネントで構成されている可能性があるため、モノリシックアプリのユニットテストは必ずしも難しくない

  • ユアンが既に述べたように、いくつかのコンポーネントの相互作用は、追加のリスクとバグをもたらします。また、複雑なプロセス間通信を使用したアプリケーションシステムのデバッグは、単一プロセスアプリケーションのデバッグよりも大幅に困難になる場合があります。

これは、より大きなアプリをコンポーネントに分割できる度合い、コンポーネント間のインターフェースの広さ、およびそれらのインターフェースの使用方法にも大きく依存します。

要するに、これはしばしばトレードオフであり、「はい」または「いいえ」の答えが一般的に正しい場合は何もありません。

なぜプログラムはモノリシックになる傾向があるのか

彼らですか?あなたの周りを見てください、私には非常にモノリシックに見えない、まったく逆の世界の膨大な数のWebアプリがあります。プラグインモデルを提供する多くのプログラムも利用可能です(言及したMayaソフトウェアでも提供されています)。

保守が簡単ではないでしょうか

ここでの「メンテナンスの容易化」は、多くの場合、アプリケーションのさまざまな部分をさまざまなチームがより簡単に開発できるため、分散ワークロードが改善され、より明確な焦点を当てた専門チームなどに起因します。


4
最後の文について、コンウェイの法則は、システム構造が組織を模倣する傾向があると述べています。構造:開発者/チームは他の部分よりも一部の部分に精通しているため、最も関連性の高い部分で修正/改善行われますが、開発者は(a)その方法を学ぶよりも他の部分が動作する、または(b)その部分に精通した誰かと動作する。これは、@ TKKが言及する「継ぎ目」に関連しており、「正しい」/単純なものを見つけて実施するのがどれだけ難しいかということです。
ワーボ

38

私はこれに関する大多数に反対する必要があります。アプリケーションを2つの別々のアプリケーションに分割しても、それだけではコードの保守や推論が容易になりません。

コードを2つの実行可能ファイルに分離すると、コードの物理構造が変更されるだけですが、それは重要ではありません。アプリケーションの複雑さを決定するのは、それを構成するさまざまな部分がどれほど緊密に結合されているかです。これは物理的な特性ではなく、論理的な特性です。

さまざまな懸念事項とシンプルなインターフェースを明確に分離したモノリシックアプリケーションを作成できます。他のマイクロサービスの実装の詳細に依存し、他のすべてのマイクロサービスと緊密に結合されたマイクロサービスアーキテクチャを持つことができます。

本当のことは、1つの大きなアプリケーションを小さなアプリケーションに分割するプロセスは、各パーツの明確なインターフェースと要件を確立しようとする場合に非常に役立ちます。DDDで言えば、境界のあるコンテキストが思い浮かぶでしょう。しかし、多数の小さなアプリケーションを作成する場合も、同じ論理構造を持つ1つの大きなアプリケーションを作成する場合も、技術的な決定になります。


しかし、複数の編集モードを備えたデスクトップアプリケーションを使用し、代わりに、ユーザーがインターフェイスを持たずに個別に開くモードごとに1つのデスクトップアプリケーションを作成するとどうなりますか。「ユーザーが編集モードを切り替えることができる」という「機能」を生成するための専用のコードが大量に排除されることはないでしょうか?
グレートダック

3
@TheGreatDuckそれはまた、異なるアプリケーションを切り替える必要がないという、些細でない量のユーザーを排除するように思えます。;)しかし、はい、機能を削除すると一般的にコードが簡単になります。スペルチェックを削除すると、スペルチェックのバグが発生する可能性がなくなります。誰かがそれを望んでいたために機能が追加されたため、それはめったに行われません。
オダリック

1
@TheGreatDuck確かに、UXの設計は、アーキテクチャを決定する前に行う必要があります。誰もあなたのプログラムを使用していなければ、最適に設計されたアーキテクチャを持つことは意味がありません。まず、構築するものを決定し、技術的な詳細に基づいて決定します。2つの個別のアプリケーションが望ましい場合は、それを選択してください。それでも、共有ライブラリを介して多くのコードを共有できます。
Voo

システムの複雑さは部品の密結合に起因すると言うのは本当ですか?特定の個々のコンポーネントの複雑さは、より限定された複雑さの制限された状態で分離されますが、インダイレクションと通信を導入するときにシステムを分割すると、全体の複雑さが増します。
アレックス

1
@TheGreatDuckここでの基本的な前提は、システムには共通の何かがあり、実際には何らかの方法で互いに通信する必要があるということでした。OPが、何らかの奇妙な理由で一緒にバンドルされている2つの完全に異なるアプリケーションを分離した場合に維持しやすいかどうかを尋ねていたとは思わない。実際には頻繁に出てこない奇妙なエッジケースのように思えます(誰かがそれをしたと確信していますが)。
Voo

15

はい。分割が完了したら、メンテナンスが簡単になります。しかし、それらを分割することは必ずしも簡単ではありません。プログラムの一部を再利用可能なライブラリに分割しようとすると、元の開発者が継ぎ目がどこにあるべきかを考えることができなかった場所が明らかになります。アプリケーションの一部がアプリケーションの別の部分に深く到達している場合、修正が難しい場合があります。継ぎ目をリッピングすると、内部APIをより明確に定義する必要があり、これが最終的にコードベースの保守を容易にします。再利用性と保守性は、どちらも明確に定義された継ぎ目の製品です。


素晴らしい投稿。あなたが話していることの古典的/標準的な例はGUIアプリケーションだと思います。多くの場合、GUIアプリケーションは1つのプログラムであり、バックエンド/フロントエンドは密結合されています。時間が経つにつれて問題が発生します...他の誰かがバックエンドを使用する必要がありますが、それはフロントエンドに結び付けられているため使用できません。または、バックエンドの処理に時間がかかりすぎて、フロントエンドが動かなくなる。多くの場合、1つの大きなGUIアプリケーションは2つのプログラムに分割されます。1つはフロントエンドGUI、もう1つはバックエンドです。
トレバーボイドスミス

13

相関関係は因果関係ではないことを覚えておくことが重要です。

大きなモノリスを構築し、それをいくつかの小さなパーツに分割すると、良いデザインになる場合とそうでない場合があります。(設計改善できますが、保証はされていません。)

しかし、優れた設計では、多くの場合、大きなモノリスではなく、いくつかの小さな部品としてシステムが構築されます。(モノリスができる最高のデザインも、それがあることをちょうどはるかに少ない可能性があります。)

なぜ小さな部品が優れているのですか?彼らが推論するのが簡単だからです。また、正確性について推論するのが簡単な場合は、正しい結果が得られる可能性が高くなります。

CAR Hoareを引用するには:

ソフトウェア設計を構築する方法は2つあります。一つの方法は存在しないこと、それは非常にシンプルにすることです、明らかに無欠陥、および他の方法は、それがそう全く存在しないことを複雑にすることです明白な欠陥が。

もしそうなら、なぜ誰かが不必要に複雑な、またはモノリシックなソリューションを構築するのでしょうか?ホアは次の文で答えを提供します。

最初の方法ははるかに困難です。

その後、同じソースで(1980年のチューリング賞講演):

信頼性の代償は、最大限のシンプルさを追求することです。それは、非常に金持ちが最も支払いが難しいと感じる価格です。


6

これは、「はい」または「いいえ」の回答を含む質問ではありません。問題はメンテナンスの容易さだけではなく、スキルの効率的な使用の問題でもあります。

一般に、適切に記述されたモノリシックアプリケーションは効率的です。プロセス間およびデバイス間の通信は安価ではありません。単一のプロセスを分割すると、効率が低下します。ただし、すべてを単一のプロセッサで実行すると、プロセッサが過負荷になり、パフォーマンスが低下する可能性があります。これが基本的なスケーラビリティの問題です。ネットワークが状況に入ると、問題はさらに複雑になります。

単一のサーバー上で単一のプロセスとして効率的に動作できる適切に作成されたモノリシックアプリケーションは、メンテナンスが容易で、欠陥がないように維持できますが、コーディングとアーキテクチャスキルを効率的に使用することはできません。最初のステップは、プロセスをライブラリに分割し、それらは同じプロセスとして実行されますが、結合と疎結合の規則に従って独立してコーディングされます。このレベルで良い仕事をすると、保守性が向上し、パフォーマンスにほとんど影響しません。

次の段階では、モノリスを個別のプロセスに分割します。難しい地域に入るため、これは難しくなります。競合状態エラーを導入するのは簡単です。通信のオーバーヘッドが増加するため、「チャットインターフェイス」に注意する必要があります。スケーラビリティの壁を破るので、見返りは大きいですが、欠陥の可能性も高まります。マルチプロセスアプリケーションはモジュールレベルでのメンテナンスが容易ですが、システム全体がより複雑でトラブルシューティングが困難です。修正は非常に複雑な場合があります。

プロセスが別々のサーバーまたはクラウドスタイルの実装に分散されると、問題はより困難になり、見返りは大きくなります。スケーラビリティが急上昇します。(スケーラビリティをもたらさないクラウド実装を検討している場合は、よく考えてください。)しかし、この段階で発生する問題は、特定して考え抜くことが非常に難しい場合があります。


4

いいえ。保守が容易になるわけではありません。何か問題があれば歓迎します。

どうして?

  • プログラムは直交しておらず、合理的な範囲でお互いの作業を維持する必要があり、これは共通の理解を意味します。
  • 両方のプログラムの多くのコードは同一です。共通の共有ライブラリを維持していますか、それとも2つの別々のコピーを維持していますか?
  • これで2つの開発チームができました。彼らはどのように通信していますか?
  • 次の2つの製品が必要です。

    • 共通のUIスタイル、相互作用メカニズムなどです。設計上の問題が発生しました。(開発チームはどのように再び通信していますか?)
    • 下位互換性(モデラーv1をアニメーターv3にインポートできますか?)
    • クラウド/ネットワーク統合(機能の場合)は、2倍の製品で更新する必要があります。
  • モデラー、アニメーター、モデラーアニメーターの3つの消費者市場があります。

    • 優先順位が相反する
    • 対立するサポートニーズがあります
    • 競合する使用スタイルがあります
  • Modeller Animatorsは、同じファイルで作業するために2つの別個のアプリケーションを開く必要がありますか?両方の機能を持つ3番目のアプリケーションがありますか。1つのアプリケーションが他のアプリケーションの機能をロードしますか?
  • 等...

より小さなコードベースはアプリケーションレベルでのメンテナンスが容易であると言われているので、無料のランチを手に入れることはできません。これは、Micro-Service / Any-Modular-Architectureの中心にある同じ問題です。万能薬ではなく、アプリケーションレベルでのメンテナンスの難易度は、オーケストレーションレベルでのメンテナンスの難易度と引き換えになります。これらの問題は依然として問題であり、もはやコードベースにないため、回避するか解決する必要があります。

オーケストレーションレベルで問題を解決する方が各アプリケーションレベルで解決する方が簡単な場合は、2つのコードベースに分けてオーケストレーションの問題に対処するのが理にかなっています。

そうでない場合は、それをしないでください。アプリケーション自体の内部モジュール性を改善することで、より良いサービスが得られます。アプリケーションがプラグインとして機能するライブラリを、まとまりのある保守しやすいライブラリにプッシュします。結局、モノリスは図書館のランドスケープのオーケストレーションレイヤーにすぎません。


3

たくさんの良い答えがありましたが、ほとんど死んだスプリットがあるので、リングにも帽子を投げます。

ソフトウェアエンジニアとしての経験では、これは単純な問題ではないことがわかりました。それは実際に依存する大きさ規模、および目的のアプリケーションの。それらを変更するために必要な慣性のおかげで古いアプリケーションは、これが長い間一般的な慣行であったため、一般にモノリシックです(Mayaはこのカテゴリに該当します)。あなたは一般的に新しいアプリケーションについて話していると思います。

多かれ少なかれ単一の懸念である十分に小さいアプリケーションでは、多くの別個の部品を維持するために必要なオーバーヘッドは、一般的に分離を持つことの有用性を超えています。1人で保守できる場合は、多くの問題を引き起こすことなくモノリシックにできます。このルールの例外は、多くの異なる部分(フロントエンド、バックエンド、おそらくその間のいくつかのデータ層)が(論理的に)便利に分離されている場合です。

非常に大規模な単一の懸念アプリケーションでも、それを分割することは私の経験では理にかなっています。他の(場合によっては簡単に解決できる)バグと引き換えに、可能なバグのクラスのサブセットを減らす利点があります。一般に、生産性を向上させるために、単独で作業する人々のチームを持つこともできます。しかし、最近の多くのアプリケーションは非常に細かく分割されており、場合によっては独自の損害が発生しています。私はまた、アプリケーションが不必要に多くのマイクロサービスに分割されているチームに参加していたため、物事が互いに話をやめたときに多くのオーバーヘッドが発生しました。さらに、各パーツが他のパーツとどのように通信するかに関するすべての知識を保持しなければならないことは、連続するスプリットごとに非常に難しくなります。バランスがあり、ここの答えからわかるように、その方法は非常に明確ではありませんが、


2
プログラマーとしての最初の仕事は、ミレニアムバグプログラマーとしてでした。私が取り組んでいたソフトウェアは、何百もの小さなプログラムに分割され、すべてが少しずつ機能し、バッチファイルとファイルを使用して状態を通信しました。コンピューターが遅く、メモリがほとんどなくストレージが高価だった時代に発明された大きな混乱でした。私がそれを使ったとき、コードはすでに10〜15歳でした。完了したら、彼らは私のアドバイスを求めました。私のアドバイスは、すべてを新しいモノリシックアプリケーションに変換することでした。彼らはそうし、1年後に私はあなたに大きな感謝をしました。
ピーターB

@PieterB同様の経験があります。「最先端」の技術は、残念ながら多くの点で非常に大きなカーゴカルトです。仕事に最適な方法を選択する代わりに、多くの企業は、FAANGがその時点で何をしているのかを何の質問もなく従います。
CL40

また、コンパイルされたモノリシックアプリケーションとして出てくる可能性のあるものは、コードに関しては非常にモジュール化されたアプリケーションかもしれません。
ピーターB

1

UIアプリの場合、バグの全体的な量を減らすことはまずありませんが、バグミックスのバランスをコミュニケーションに起因する問題にシフトします。

ユーザー向けのUIアプリケーション/サイトと言えば、ユーザーは非常に非患者であり、短い応答時間を要求します。これにより、通信の遅延がバグになります。結果として、単一のコンポーネントの複雑さの減少によるバグの潜在的な減少と、非常に難しいバグ、およびプロセス間/マシン間の通信のタイミング要件とを交換します。

プログラムが扱うデータの単位が大きい場合(画像など)、プロセス間の遅延は長くなり、排除するのが難しくなります-「10mb画像に変換を適用する」のようなものは、即座に+ 20mbのディスク/ネットワークIOを追加で獲得しますインメモリ形式からシリアル化形式への変換、およびその逆。ユーザーからそうするために必要な時間を隠すためにできることは本当に多くありません。

さらに、すべての通信、特にディスクIOは、ウイルス対策/ファイアウォールチェックの対象になります。これにより、再現が困難なバグや遅延がさらに増えることになります。

モノリシックな「プログラム」の分割は、通信の遅延が重大でないか、すでに避けられない場合に効果的です

  • 個々の手順を大幅に改善するためにわずかな余分な遅延を引き換えにできる情報の並列化可能な一括処理(市販の1回使用することでカスタムコンポーネントの必要性を排除することもあります)。個々のステップのフットプリントが小さいため、たとえば単一の高価なマシンではなく、複数の安価なマシンを使用できます。
  • モノリシックサービスを結合度の低いマイクロサービスに分割-おそらく1つではなく複数のサービスを並行して呼び出しても、余分な遅延は追加されません(個々のサービスが高速で依存関係がない場合、全体の時間を短縮することさえできます)
  • ユーザーが長時間かかると予想される操作を排除-複雑な3Dシーン/ムービーのレンダリング、データに関する複雑なメトリックの計算、...
  • あらゆる種類の「オートコンプリート」、「スペルチェック」、およびその他のオプションの補助機能を外部にすることができます-最も明らかな例は、入力が常に外部サービス(検索エンジン)に送信されるブラウザーのurl自動提案です。

これは、デスクトップアプリとWebサイトに適用されることに注意してください-プログラムのユーザー向け部分は「モノリシック」になる傾向があります-単一のデータに関連付けられたすべてのユーザーインタラクションコードは通常、単一のプロセスで実行されます(分割することは珍しくありません) HTMLページや画像などのデータ単位で処理しますが、この質問とは直交しています)。ユーザー入力のある最も基本的なサイトでも、サーバー側をよりモジュール化し、複雑さ/コードの重複を減らしても、クライアント側で検証ロジックが実行されていることがわかります。


0

バグの防止に役立ちますか?

防ぐ?まあ、いや、そうでもない。

  • バグの検出に役立ちます
    つまり、自分が持っていることすら知らなかったすべてのバグは、その混乱全体を小さな部分に分割しようとしたときに初めて発見したものです。そのため、ある意味では、これらのバグが本番環境で出現することを防ぎましたが、バグはすでに存在していました。
  • バグの影響軽減するのに役立ちます
    モノリシックアプリケーションのバグは、システム全体をダウンさせる可能性があり、ユーザーがアプリケーションとやり取りできないようにします。そのアプリケーションをコンポーネントに分割すると、ほとんどのバグは設計上、コンポーネントの1つにのみ影響します。
  • 新しいバグのシナリオを作成します
    ユーザーエクスペリエンスを同じ状態に保ちたい場合は、それらのすべてのコンポーネントが(RESTサービスを介して、OSシステムコールを介して、何を持っているか)通信する新しいロジックを含めて、ユーザーのPOVからシームレスに対話できるようにする必要があります。
    簡単な例として、モノリシックアプリを使用すると、ユーザーはアプリを離れることなくモデルを作成してアニメーション化できます。アプリを2つのコンポーネント(モデリングとアニメーション)に分割します。ユーザーはモデリングアプリのモデルをファイルにエクスポートしてから、ファイルを見つけてアニメーションアプリで開く必要があります...それに直面して、一部のユーザーはそのようなことをしないので、新しいロジックを含める必要がありますファイルをエクスポートするアプリをモデル化し、アニメーションアプリ自動的に起動し、ファイルを開きます。そして、この新しいロジックは、可能な限り単純ですが、データのシリアル化、ファイルのアクセスと許可、ユーザーがアプリのインストールパスを変更することなどに関して、多くのバグを抱えている可能性があります。
  • 多くの必要なリファクタリングを適用するのに最適な言い訳です。
    モノリシックアプリをより小さなコンポーネントに分割することを決定した場合、システムが最初に設計されたときよりも多くの知識と経験を使用して(できれば)分割します。そのおかげで、多くのリファクタリングを適用してコードを作成できますよりクリーンで、シンプルで、効率的で、回復力があり、安全です。そして、このリファクタリングは、ある意味で、バグの防止に役立ちます。もちろん、同じリファクタリングをモノリシックアプリに適用して同じバグを防ぐこともできますが、UIの何かに触れてビジネスロジックを壊すのが怖いほどモノリシックなので、そうではありません¯\ _(ツ) _ /¯

ですから、モノリシックなアプリを小さなコンポーネントに分割するだけでバグを防いでいるとは言いませんが、バグを簡単に防げるポイントに到達しやすくしているのです。

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