複雑なデザインで本当に得られるものはありますか?


8

私は以前から、さまざまな規模のクライアントを抱えるコンサルティング会社で働いており、非常に単純なものから複雑なものまで、さまざまなWebアプリケーションを見てきました。

  • MVC
  • サービス層
  • EF
  • DB

本当に複雑に:

  • MVC
  • うわー
  • DI / IoC
  • リポジトリー
  • サービス
  • UIテスト
  • ユニットテスト
  • 統合テスト

しかし、スペクトルの両端で、品質要件はほぼ同じです。単純なプロジェクトでは、新しい開発者/コンサルタントは、何が起こっているのかを理解するために6層の抽象化をたどる必要がなく、複雑な抽象化を誤解し、コストを下げるリスクを冒すことなく、期待に応え、変更を加え、すぐに貢献できます。

すべての場合において、実際にコードをスワップ可能または再利用可能にする必要はありませんでした。また、要件が変更されたため、テストが実際に最初の反復を超えて維持されることはありませんでした。

だから-最終的に-

  • テストとインターフェースは使用されません
  • 迅速な開発(読み取り:コスト削減)が優先事項
  • プロジェクトの要件は開発中に大きく変化します

...エンタープライズクライアントに複雑な問題を解決するためであっても、超シンプルなアーキテクチャを推奨するのは間違っているでしょうか?エンタープライズソリューションを定義するのは複雑ですか、それとも信頼性、同時ユーザー数、保守の容易さ、またはこれらすべてですか。

私はこれが非常に曖昧な質問であることを知っており、どの回答もすべてのケースに当てはまるわけではありませんが、私はしばらくの間ビジネスに携わっており、これらのさまざまな程度の複雑さで機能している開発者/コンサルタントからの連絡に興味があります、少なくともプロジェクトの開発中は、クールだが高価な抽象化が全体的なコストに見合うかどうかを聞くため。


10
Xmlが唯一の適切な答えです。
Wyatt Barnett

2
その答えは、まさにエンタープライズソフトウェアについて私が言ったことだと思います。しかし、ここにはより深い質問があります。「高度なソフトウェアアーキテクチャとデザインのポイントは何ですか?」
マイケルブラウン

4
自動化されたテストなしで保守可能で重要なソフトウェアを作成できるというあなたの主張に挑戦します。さらに、なんらかのインターフェースがなくても、急速に変化する要件に対応できるようになることをお勧めします。
Telastyn 2013年

@MikeBrown-編集ありがとう-そんなばかげた質問のように思えますが、ええ、それは私が求めていることです。
SB2055 2013年

3
@BrianDHall:プロセスでチューリングを完了させようとする限り。
Wyatt Barnett

回答:


11

...エンタープライズクライアントに複雑な問題を解決するためであっても、超シンプルなアーキテクチャを推奨するのは間違っているでしょうか?

それはクライアントに依存します。多くの場合、より簡単なアプローチで問題ありません。単純なアプローチでは問題を解決できないため、自分は無能だと考える人もいます。「全体的に、ある理由で超低価格である必要があります...」という理由で、一部のものは作成にかかるコストよりもはるかに高価になります。

テストとインターフェースは使用されません

私は、これらのいずれかを使わずに費用効果の高い重要なソフトウェアを作成できる方法はあり得ないと主張します。会社として、あなたがそれらなしで私に何かを売ろうとした場合、私はあなたが完全に柔軟性がなく、維持不可能な蒸し犬のうんちの山で私を抱き締めることを恐れるでしょう。(編集:明確にするために、ここではインターフェイスについて話しているのですinterfaces。Java形式のインターフェイスがなくても、手続き型プログラムや関数型プログラムはすべてがらくたの山ではありません。)

クールだが高価な抽象化が全体的なコストに見合うかどうか

プログラムの設計者として、私たちは物事がどこで変化するかについて教育を受けた推測を行い、そこに線を引くことで、変化する物事が素早く、簡単に、そして正しく行われるようにする必要があります。避けられない変更が安くなるため、優れた抽象化は時間をかけてお金を節約します。

しかし、間違いなく、「建築宇宙飛行士」という用語が存在するのには理由があります。あなたはいつもスペースシャトルを作っているわけではありません。変更が必要なものの真ん中に存在するか、存在しない変更をサポートするために存在する不良な抽象化を追加すると、コストがかかる可能性があります。

しかし、私の経験では、抽象化されたコードの過剰について不満を言うのを聞いたことがありますが、抽象化されていないコードが原因でプロジェクトが失敗するのを見ただけです。


情報ありがとうございます。私はインターフェースなしで自分のアプリを構築しましたが、まだそれらの価値を見ていません...いくつかの抽象化を利用する複雑であると考えられる完全なサンプルアプリを知っていますか、それとも本を勧められますかWebアプリケーション開発のこの側面をカバーしていますか?私はスキートの本を注文したばかりですが、それは建築よりも言語に重点を置いていると思います。
SB2055 2013年

3
スパゲッティとラザニアの混合が多すぎてプロジェクトが失敗するのを見てきました。常に物事を可能な限りシンプルかつ正直に保つ必要があります。優れたアーキテクチャは鋭敏で経験豊富な目にはシンプルですが、n00bsは理解しません。優れたアーキテクチャでは、逆に遅くなることはありません。
Falcon

5
過度に複雑なコードが原因で多くのプロジェクトが失敗するのを見てきました。単純な設計では制限が見られる場合がありますが、少なくとも問題は確認できます。複雑な設計は、何かを修正または変更する必要があるまで、その制限を隠します。
Michael Shopsin 2013年

1
@MichaelShopsin同意します。実際、これは通常、彼らが失敗した場合にも当てはまります。ただし、私の経験では、抽象化されていないコードが失敗するのと同じ方法で失敗することはありません。隠された制限を克服するために多くの研究と作業が行われた後、開発者は失敗します。少なくとも、抽象化されていないプロジェクトでは、コードがニーズに適合しているかどうか、そして何を実行する必要があるかがすぐにわかります。
Fuzzical Logic 2013

1
@MichaelShopsin-過度に複雑なコードが原因でプロジェクトが失敗する可能性があることを無視しませんが、それらは複雑さの負担の下でかなり長い間動き続ける傾向があります。デザインが不十分なプロジェクトは、全体を書き直さないと必要なことを実行できないと、急速に死んでしまいます。
Telastyn 2013年

4

建築家に、または建築家に

アインシュタインを言い換えると、「物事は可能な限り単純でなければならない-しかし、より単純ではない」。一部のアーキテクチャの真の使用方法を理解することが重要です。これらのアーキテクチャは必ずしも個々のパフォーマンスのためではなく、多くの場合、仕事の満足のためでもありません。

エンタープライズプロジェクトは非常に大規模であり、非常に多くの人が働いているため、アーキテクチャーが非常に複雑になる場合があります。このアーキテクチャーは、誰もが他の人につまずくことなく、非常に多くの人が何かに向かって取り組むことを可能にするものです。時には、個人の生産性を低下させ、仕事を難しくする複雑さを加えただけですが、多くの人々が働くことができます。これは、追加された努力が個人の減少した意欲を上回った場合に機能します。

これはあなたのクライアントの状況ですか?まあ、彼らの予算がこのプロジェクトの何百万ドルにない場合、多分そうではありません。100k未満であれば、ほぼ間違いなくそうです。薪ストーブではなく、原子炉用のコンクリートバンカーを建てます:)

それが状況で必要とされるものであるならば、それがあなたのクライアントのために「たぶん働くことができる最も単純なもの」を提案することは必ずしも間違っていません。それはそれを処理する最良の方法かもしれません。確認する最も簡単な方法は、同様のタスクを実行するように設計された市販/オープンソースプロジェクト(これはとにかくデューデリジェンスの市場調査です)と比較して、彼らが何をするために彼らが何をしたかを確認することです。

もちろん、数百万ドルを使って作業しているときは、悪質なインセンティブがあることに注意してください。要するに、「お尻を覆う」:PhDが正しく理解する必要がある超複雑なアーキテクチャシステムを推奨する場合、それが地獄に行くとき、それは誰のせいでしたか?もちろんあなたのものではない-あなたは誰もが最高だと言う洗練された技術の中で最高のものだけを提案しました-しかし、それらは「複雑」で「難​​しい」ので、責任はそれを実装しようとした人々にあります。彼らは十分に賢くも、十分に熟練もしていないに違いありません...つまり、すべてのプロジェクトが成功するわけではないため、プロジェクトが失敗したときに見栄えが悪くならないように、多くのアドバイスが与えられます。それは悪いジュジュですが、それは私たちの現実の事実です。

フォロースルーの失敗

テストの継続的な更新とアーキテクチャーの決定のフォロースルー(更新ではなく変更時に計画を投げるなど)に失敗すると、多くのシステムが廃棄され、ゼロから書き直されたり、新しいものに置き換えられたりするので、ソリューション」は数年後のことです。

便宜上、明快さと一貫性を強制するものが放り出されると、あなたが非常にずるくると思って、実際に将来の変更をより難しく複雑にしたときに、本当に「やり遂げている」と考えるのは簡単です。すぐに利益を得るために将来の生産性を盗むことは非常に一般的です。具体的には、それが起こっていることに誰も気付いていない場合は特に悪いことです。

たとえば、テストは物事が変化したときに特に最適です。新しい方向性を反映するようにテストを変更してから、人々が考えを変えた、または前回何かを見落としたことに気付いたために、現在「壊れている」ものすべてを修正します。今週はやることがたくさんあるので、これは睡眠をあきらめるようなものです。

結論として、「それは依存する」(役に立つでしょうね)

アーキテクチャの複雑さは、実店舗でのビジネスのためにより大きなスペースを借りるようなオーバーヘッドコストです。管理する必要がある実際の複雑さがある場合にのみ意味があります。それが比較的一般的なソリューションに取り組んでいる3人のチームの場合、おそらく単純なMVCと最小限のツールで十分です。

それが複雑なマルチサブシステムのエンタープライズソフトウェアソリューションであり、予算に数百万もの予算があり、3から5のチームが少なくとも6ダースある場合、オブジェクト指向のプログラム分析とそのすべてのチャート、ダイアグラム、モデルでの往復エンジニアリングだけが与えることのできる、甘くて甘い愛を乞うでしょう。何十、何百もの目がまばたきなくあなたを見つめるのを防ぎ、彼らが今日何をすることになっているのか、どうやって何かを成し遂げるのだろうと思っているのを助ける何か。


2

コンサルティングへようこそ。

大量のお金を稼ぎ、機能をクライアントにすばやく提供するのに最適な場所です。

現在将来の両方でうまく機能する、保守可能で順応性のある美しいソフトウェアの作成に取り組む場合は、ヘルスケアや政府などの特定の業界で働き、質の高い仕事のためのより優れたニッチを切り開くことをお勧めします。


1
ちょうど好奇心から、なぜヘルスケアと政府を選び出すのですか?これらのフィールドは、特に保守可能/適応可能/美しい/高品質/ <形容詞>ソフトウェアで知られていますか?

2

堅実な設計から得られるのは、長期にわたる信頼性の高い変更サイクルです。適切にトレーニングされたプログラマーと適切な設計が必要なため、最初はコストが高くなりますが、意図するところは、後の変更によるコストが急上昇しないようにすることです。

確かなアーキテクチャがなければ、変更は最初から安くなるだけです。プロジェクトが進化するにつれて、変更はますますコストがかかります。これは、より安価な労働力とより速い反復への欲求と相まって、変更は最終的に会社が支払うこといとわない以上の費用がかかり、会社が待つことができるよりも多くの時間要するため、プロジェクトを中止する可能性があります。平均的なチームと平均的な時間がかかる可能性のあるその後の変更では、代わりに、超人的なチームと、何年ものコードをふるいにかけて、安全に変更を行うのに十分なリファクタリングに長い時間が必要になります。

クライアントがこの犠牲を理解し、それを犠牲にしたい場合は、最も速い方法で必要な変更を行います。しかし、これらのトレードオフを彼らのために行うことは賢明ではありません(そしておそらく不正直です)。このプロセスは彼らのビジネス上の決定に影響を与えるからです。


仕事の一部は、「これらは必要ですか?」と尋ねるだけでなく、リストしたすべての抽象概念を理解することです。しかし、それらがいつ、なぜ必要なのかを理解し、ソフトウェアの操作の一部としてそれらのパターンを適用する方法を理解する必要があります。

仕事のもう1つの部分は、クライアントが表示できるもの(UI、機能)によって作業を判断することが多く、表示できないもの(コードベースの状態)について教育を受ける必要があることを理解することです。

  • 時間の経過に伴う貧弱な設計のコストについては、この講演を参照してください
  • 安定した生産性に関するこの講演をご覧ください
  • 単体テストの価値については、このSOの回答を参照してください

2

複雑なのは相対的です。ポインタの概念、特にリンクリストのプログラミングを最初に学習したときは複雑でした( "フィールドとして機能するものをどのように持つことができますか?")。

関数型プログラミングの学習を始めたとき、ラムダの概念は複雑に見えました。しかし、それをC ++からの関数ポインターのアイデアに関連付けましたが、それは簡単でした。カレー、そして完成などのように。

最初にTDDの学習を始めたとき、それは複雑であるか、開発プロセスにオーバーヘッドがかかると思いました。現在、少なくともハッピーパスをカバーするテストがない限り、コードが完全だとは感じません。依存性注入と具象クラスの代わりにインターフェースを使用することは、最初は複雑に見えます。ただし、依存関係の詳細を理解し、より高いレベルの構造に最初に焦点を当てることを前提として、コードをビルドできます。

"Uncle Bob" MartinによるClean CodeとThe Clean Coderをチェックしてください。最初は、より良いコーディング方法について話します。2番目は、より良いコーダーになる方法について話します。2つの間に違いがあります。

たとえを言えば、私はギターを学んでいます。簡単なメロディーやコードを弾くことができる段階です。コードとポジションの間の移行は難しいです。もっと練習することで、それらのトランジションを簡単にヒットできるようになり、それが私にとって第二の性質になります。

リポジトリ/作業ユニットパターンを使用して、基本的な機能を構築しているときにインメモリリポジトリを使用し、納品に近づいたときに「sql lite」または「odata」リポジトリに変換します。これにより、最終的なインフラストラクチャが整う前(または決定する前)でも、より多くの機能を完了することができます。抽象化により、モックとスタブをより簡単に作成できるため、抽象化に依存するコードが期待どおりに機能することを確認できます。繰り返しますが、私は機能をトップダウンで完成させることができます。

最初にインフラストラクチャを作成するのは間違っていると思います。単純な事実は、それが反俊敏であることです。「インフラストラクチャ」にスプリントを費やすと、最終的に必要になるかどうかさえわからないものを構築し、ユーザーはフィードバックを提供するために何も見る必要がなくなります。

それが抽象化によって提供されるものです。それらを使用して練習すればするほど、それらは第二の性質になり、この議論を振り返って、あなたがどこまで開発したか驚嘆するでしょう。うまくいけば、数年のうちに、コードの切り替えがこれまで私にとってどのように挑戦されたのかと思います。


1

抽象化によって自動的に複雑さが増すというあなたの発言には完全に同意しません。抽象化は、今日ではマシンコードに解決する必要がない主な理由です。

抽象化に伴う問題は、エンドユーザーに複雑さを隠すのではなく、内部の仕組みに焦点を合わせる傾向があることです。抽象化はロジックを分離し、再利用性を促進する必要があります。さらに、テストは建築設計に挑戦する優れた方法だと思います。これは主に、ユーザーの視点からコードを見る必要があるためです。

時間の不足についてあなたが言及した問題は、悪いデザインの主な原因です。通常、優れた設計はすぐには実現されませんが、反復と改良によって実現されます。通常、お客様から要件を抽出する方法は、ユーザーストーリーです。このようにして、顧客はシステムを何にどのように使用したいのかを考えることができます。さらに、アーキテクトがシステムの意図を認識している場合は、適切な設計決定または抽象化手法を選択して、システムに柔軟性を追加できます。彼らがクールでいいからではありません。


1

質問に対処しています...

...エンタープライズクライアントに複雑な問題を解決するためであっても、超シンプルなアーキテクチャを推奨するのは間違っているでしょうか?

絶対違う。

クライアントの視点から

上記のように、それはクライアントに大きく依存します。また、どのソリューションがクライアントに適しているかを正確に判断する能力にも依存します。常に望ましい値に達すると認識されるコストが存在しますが、コンサルタントとして、クライアントの適切な期待を設定するのはあなたの仕事です。場合によっては、その認識を満たす必要があります。他では、それらを修正することがあなたの最善の利益になります。結局のところ、あなたはあなたのクライアントの専門家でなければなりません。そうでない場合は、その専門家になるための知識が必要です。それは彼らがあなたに支払うものです。

開発者の観点から

使用するアーキテクチャを選択する上で最も難しいのは、多くの場合、特定のニーズを満たすためにテクノロジを利用するために必要な作業量を正確に見積もることです。これは、クライアントの期待に応えられないプロジェクトにすぐにつながる可能性があります。あなたが言及しているこれらの「複雑な」コードの断片を使用すると、一部のプロジェクトが実際に高速化されることを理解してください。一部はそうではないことも理解されています。あなたまたはあなたのチームが知っていることに基づいて、その測定値を提供する必要があります。

エンタープライズソリューションを定義するのは複雑ですか、それとも信頼性、同時ユーザー数、保守の容易さ、またはこれらすべてですか。

詳細は異なる場合がありますが、一般的に、エンタープライズソリューションは、幅広い混合対象ユーザーに適用されるソフトウェアソリューションです。同時使用ユーザーの数は、要因である場合もあればそうでない場合もあります。ユーザーの総数は、多くの場合さまざまなビジネスロールに属しますが、ソリューションが「エンタープライズ」であるかどうかに関する最大の決定要因の1つです。

多くのエンタープライズソリューションは非常に複雑ですが、非常にシンプルなものもあります。企業は信頼性の空気を提供しますが(確かに特定の基準を維持する必要があります)、ソリューションごとに信頼性のレベルは異なります。

メンテナンスのしやすさは、すべての開発者(独立者またはチームメンバー)が努力することだと私は思うが、必ずしも簡単に達成できるとは限らない。重要なのは、「簡単」ではなく、しっかりとしたガイドラインのある保守手順があることです。異なるコードベースは、哲学、方法論、(ビジネス)環境活動、およびコードの複雑さに応じて、大幅に異なるレベルの容易さを持つことに注意してください。

他のステートメントに対応しています...

すべての場合において、コードを実際にスワップ可能または再利用可能にする必要はありませんでした

多くの場合、そうする必要は特にありません。ただし、これは常に目標です。これを検討してください... Webページからカレンダーにアクセスしたり、カレンダーを表示したりする機能を必要とするクライアントがあるかもしれません。独自のコードを再利用可能にすると、別のクライアントが同じことを要求したときに、すでにいくつかの作業が完了しています。そうしないと、もう一度やり直す必要があります。多くの場合、すべてのクライアントの問題は、将来別のクライアントが必要とする問題です。言い換えると、一緒に仕事をするすべてのクライアントは、将来のクライアントの仕事のコスト(必ずしも製品のコストではない)を削減できる可能性があるはずです。

要件が変更されたため、テストが実際に最初の反復を超えて維持されることはなく、時間がかかりすぎました。

ここでは、テスト方法論が十分に抽象化されていなかったと主張します。最近、独自の単体テストを直接実行するコードを使用しました。プロジェクトのニーズに対応するカスタムassertexpect機能が作成されました。ユニットテストが必要なときはいつでも、コードを調整することなく適用できます。実際、コードはアサートとともに積極的に配布され、まだそこにあることを期待しています。作業コードの一部としてこれらのチェックを行いました。

...締め切り、ビジネスのプレッシャーなど...

多くの場合、余分なビジネスプレッシャーとコーディングプロセスを妨げる期限が、クライアントではなく開発者の責任であることに気づきました。これは常に当てはまるわけではありませんが、多くの場合、ビジネスの圧力は、クライアントの期待に応えられないという認識によって引き起こされます。締め切りがコードの妨げになる場合、それは開発者が使用可能な機能コードに必要な作業量を正確に測定できなかったことが原因であることがよくあります。言い換えれば、それらをスケジュールし(クライアントはそれを期待する)、それらを測定し(将来のクライアントはそれを期待する)、それらを実行し(ユーザーはそれを必要とします)、それらに対して支払いを受けます(契約でそれを要求する必要があります)


1

この質問の多くは信じられないほど主観的なものであり、建築の複雑さの複合コストに関するデータを提示することが重要だと思います。MIT Sloanからの非常に興味深い事例研究があり、

  • 開発者の生産性の低下
  • 売上高の増加
  • そして、より複雑に起因する欠陥密度の増加。

基本的には、すべてのコードベースが(A)開発者の生産性を高めるためのシンプルさと(B)新しい機能が追加されたときに機能が損なわれないようにするための見通しとの間を行き来するために努力すべきいくつかの幸せな媒体があると思います。

ケーススタディは、複雑度の高いコア(ユーティリティや高度な抽象化など)と複雑度の低い周辺機器(依存関係の少ない新しい機能を考える)を備えたモノリシックコードベースを持つこの1社に関するものです。周辺とコアの間で、開発者の生産性は50%減少し(異常なもの)、欠陥は2.6倍に増加しました。


0

複雑なソフトウェア開発手法に関するあなたの疑問に関連することができます。あなたが挙げた理由から、できる人はたくさんいると思います:新しいシステムの最初の作成にオーバーヘッドを追加しますが、常に即座にそれらを表示するわけではありません利点。

それは明らかにそれらが存在しないことを意味しません、すべての概念には理由があり、ほとんどの場合は良いものです。全体として、プロジェクトを完成させるために必要な作業を削減し、後でそれを強化する必要があります。

もちろん、理論的には、これらすべての理論的なメリットを学んだことは間違いないでしょう。そして、それもまた正当な理由があるかもしれません。概念の権利を使用することは、それが使用される理由を理解することほど簡単ではありません。また、経験を持っているかもしれませんが、いつ抽象化すべきか、そうでないかを決めるのにクライアントがまだそうでないかもしれません。

プロジェクトのあらゆる可能な時点でコンセプトを使用すると、多くの時間がかかる可能性があり(Telatsynsの回答を参照して、その簡潔な文章を確認してください)、十分な経験がない場合は、適切な場所でコンセプトを使用してもコストがかかる可能性があります。 。あなたが言ったように、それらは単純な概念ではありませんが、あなたの状況に合わせる必要がある本当に複雑なものである場合があります、理論的理解はそれを速く正しく使うには十分ではありません。

そして、これらの理由から、クライアントが概念から離れることに気付かずにクライアントがテストと抽象化を放棄して、単純な作業を再開しても、驚くことではありません。

ソフトウェアエンジニアリングの大きな障壁について、この記事をお勧めします。ソフトウェアエンジニアリングの専門知識の7つの段階このページのどこかで偶然見つけましたが、非常に興味深い考えや経験を表しています。


-1

あなたが企業向けのアプリケーションを開発しているなら、あなたやあなたのプロジェクトを担当している人(Proj mgr)は、プロジェクトに入る必要がある仕事の量についてより良い感覚を持つべきだと私は言うでしょう。時間の無駄を感じている場合は、Proj mgrと意見を交換する必要があります。私が感じて操作する方法は、常に基本的な種類の判断に基づいていますが、私は常にあなたにカーブボールを投げるクライアントを探しています。私はあなたの私を点在させ、あなたのtを横切ることによって良い仕事をすることに誤りを犯すでしょう。また、適切なアプリケーションライフサイクル管理を実施して、ほとんどのオーバーヘッドが自動化され、時間の節約などにもなることを確認します。


1
この投稿は読みにくいです(テキストの壁)。より良い形に編集していただけませんか?
gnat 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.