「マキンは建築家です。」 パート1:ソフトウェアエンジニアリングの浮き沈み

こんにちは、Habrの読者の皆さん。 一連の記事「Mamkin Architect」をご紹介します。 この一連の記事は、Eric Evansの著書、Object Oriented Design(DDD)から着想を得ています。 複雑なソフトウェアシステムの構築。」 その中で、柔軟なアーキテクチャの構築に関する私の個人的な意見を反映しようとします。 途中で、これが管理者にとってどのように役立つかを説明し、開発者が基本概念を強化するのを助けます。



画像






この記事では、「創造性の上昇」、「創造性の低下」、および「傾斜」のポーカー概念について説明します。 後者は、ソフトウェアアーキテクチャのコンテキストでの対象モデルのさまざまな状態における開発者の状態を完全に反映しています。 オーパスは便利です:



  1. 「すべて埋めてやり直しましょう」などの開発者からの問題を解決するマネージャー。
  2. 慎重に構築された(または家の)オブジェクトモデルのカプセル化装甲をその概念的な形で見ることに興味がある開発者。
  3. アーキテクトまたはシステム設計者は、概念モデルで対象モデルを実装、サポート、保持する私の経験に興味を持ちます。


それでは、創造的な盛り上がりとは何ですか?



創造的な成長は心理的な概念であり、主にプログラムの質的な飛躍に関連しています。 簡単に言えば、これは行われた仕事からの波のような満足感です。 リファクタリングにより、飛躍的な進歩が実現します。 「リファクタリングの必要性」の定義によって開発者が具体的に何を意味するかを、非技術専門家に説明します。



まず、Martin Fowlerの本「リファクタリング。 既存のコードの改善 ":
「リファクタリングとは、コードの外部動作は変わらないが、内部構造は改善されるソフトウェアシステムを変更するプロセスです。 これは体系的にコードを整理する方法であり、新しいエラーの可能性は最小限です。 実際、コードをリファクタリングするときは、コードの作成後にデザインを改善します。


難しいですか? 次に、リファクタリングを次の3つの主要な亜種に分割します。



  1. ナノリファクタリングが進行中です。 すべての開発者が使用するわけではない最も一般的な形式。 しかし、非常に高いレベルでプログラムを変更できる人はかなりの割合です。 ほとんどの場合、ナノリファクタリングは、対象モデルにとってあまり価値のないメソッド/機能の変更を目的としています。 例:大きなメソッドを副作用のない小さな関数に分割します。
  2. システムオブジェクト内の論理構造の変更を目的としたマイクロリファクタリング。 これは、対象モデルに関する新しい知識の出現でより頻繁に使用されますが、動機は単に読み取り可能なコードを作成するよりも深い場合があります。 一般的な意味は次のとおりです。段階で意味のある詳細なモデルに移行するプロセスを断片化すること。 このようなリファクタリングは、開発プロセスを「凍結」しないため便利です。 その主な目標は、開発者が特定のオブジェクトの動作原理だけでなく、オブジェクトがそれを行う理由を理解するのを支援することです。 同時に、この理解は応用分野の専門家によっても目覚め、チーム内で単一の言語を生成します。
  3. 詳細なリファクタリングは最も複雑で、対象モデルの根本的な変更を目的としています。 対象モデルの深い理解が動機となっています。 ソフトウェア製品全体に根本的な影響を与えるため、その方向は最も危険です。 実生活からの例は、モーターがロケットエンジンに変更された通常の車です。 このようなマシンを単純なマシンと呼ぶことはできません。また、その主な機能は果たせません。


ご想像のとおり、リファクタリングの1つのタイプは、通信する通信の原則に従って別のタイプから行われます。 しかし、最後の容器がいっぱいになるとどうなりますか? たとえば、液体がこぼれた場合など、システム全体のいくつかの基本的な変化を想像できます。 実際、最後の容器のオーバーフローは、詳細なリファクタリングの推進力です。 概念モデルは変化していますが、プロジェクトのアーキテクチャは変化していません。 この時点で、ソフトウェア製品に深刻な問題が発生し始めます。 システムモデルは、アーキテクチャのプログラム的な表現に対応しなくなりました。 多くの企業がこの瞬間を延期しようとし、定期的に高レベルのリファクタリングを適用しています。 戦術の理由は単純です:徹底的なリファクタリングは、単にプラントを停止します。



より高いレベルのリファクタリングを使用して、架空の容器の下にバケツを入れたり、袋に入れたりすることができます。 これらのすべての「ギャグ」を取得し、専門家の時間と分類を掛けると、管理されていないシステムになります。 後者は、開発チームの複数のメンバーで終了します。 これらの微妙さを知っていれば、解雇を恐れることなく妨害行為を手配することさえできます。 これらのパッケージ、チューインガム、ランチャーなどすべてでシステムがどのように機能するかを理解している開始者もいます。 間違いなく、地獄のボイラーはそのような人々のために準備ができていますが、私たちはこれに戻ります。



遅かれ早かれ、最後の船の臨界質量が船自体の極限強度に達し、それが破裂することを認めることは残念です。 そのような場合、リファクタリングは通常そこで終わりません。 すべてをゼロから書き直す方が簡単で安価です。 したがって、より楽観的なモデルに戻りましょう。



創造的な成長は、ソフトウェア製品の質的な飛躍に先行しています。 ソフトウェア製品が質的に飛躍する前に、ナノリファクタリングまでの徹底的なリファクタリングなどが行われます。



実際のプロジェクトの例



プロジェクトの1つに参加して、人と人との間の会議を作成するシステムのリファクタリングに約2か月を費やしました。 それは表面的なものであり、アウトソーシングの悲惨な結果のみを排除しました。 システムをさらに開発する準備ができているかどうかを決定すると、多くの問題に直面しました。 レコメンダーシステムの複雑なアルゴリズムを少し誇張しますが、意味は変わりません。



実際、推奨システムは、森でのハイキング、飲酒施設での散歩などをユーザーに提供することになっています。 私がこの分野の専門家ではないことは注目に値します。 追加の基準を追加してシステムを改善するタスクがありました。 推奨システムはドメインモデルの一部であるため、適切な専門家を迅速に見つけることができました。 数回の会議で、彼はシステムの複雑さを見つけるのを助け、未解決の問題はありませんでした。



開発したモデルは良かったのですが...



最初は楽観的でした。 3か月以上にわたって、ソフトウェア製品のアーキテクチャをうまく管理しました。 次に、対象モデルと「同期」しました。



選択のルールを明確にし、現在のモードの問題を解決する変更を加えました。 しかし、新しい選択基準が追加されるたびに、アーキテクチャの複雑さが増しました。 安定した信頼性の高い機能にすばやく到達できませんでした。



さらに、計算を四捨五入する際のエラーについて心配し始めました。 これにより、関連付けられていないグループ内のユーザーを識別できます。 もちろん、これらのエラーは1つの観点からは重要ではありません。 しかし、「推奨システム」の精度の観点から、彼らは特定の疑問を提起しました。 この時点で、これらの不正確さは単なる見た目の問題ではなく、基本的なアーキテクチャの問題の症状であると疑い始めました。



ジャンプ



突然、問題とその解決策を理解することができました。 このモデルでは、ユーザーとグループは実際の状況に対応しない方法で接続されていました。 そのような発見には、幅広い反響がありました。 私たちは、ドメインの専門家に任命し、その支援を得て、新しいモデルをボードに描きました。 この詳細はまだ具体化されていないことは注目に値しますが、どの新機能がモデルにとって重要であるかはすでにわかっています。 ユーザーグループの定義は、ユーザーの好みに関係なく行われます。 面白いですが、このソフトウェア製品のフレームワークでは-当然です。 同様の結論を出した後、このモデルの動作とその脆弱性のさまざまなシナリオを検討しました。



グループが共有で形成されたので、共通言語で「共有」の概念を導入しました。 「グループ」という概念の必要性は、ユーザーの関心の分担に従って形成が既に行われているため、消滅しました。 用語の共通言語の開発を開始しました。これにより、ドメインスペシャリストとの会議でのコミュニケーションが容易になりました。 対象モデルの条件に基づいて操作したため、誰もが会話の本質を明確に理解していました。 また、アプリケーションアーキテクチャに完全に準拠しています。



物事を冷静に見る



この瞬間、私たちは素晴らしいと感じたと思いますか? ほぼ。 はい、ドメインモデルの仮想的な実装は、新しいアーキテクチャに完全に適合します。 しかし、このプロジェクトでは、厳しい時間枠が設定されていたため、ほとんど適合しませんでした。 その時私が個人的に経験した主な感覚は恐怖でした。



リファクタリングのパラダイムは、小さなステップでの移動と、ソフトウェア製品を常に動作状態に維持する必要性です。 しかし、コードをリファクタリングするには、深いリファクタリングが必要です。 ソフトウェア製品は一時的に無効にするだけでなく、リリースを延期する必要があります。 また、作業中の中間状態も失われます。 製品の歴史は「前」と「後」に分けられます。 私たちのチームは、特定の肯定的な結果につながる小さな改善を見ました。 しかし、これはシステムの概念的な整合性に私たちを近づけませんでした。 数回の技術会議の後、新しい概念モデルへの移行に向けてモジュールを準備できる一連の手順が特定されました。 しかし、効率を維持することはほとんどできませんでした。 言うまでもなく、重度の遺伝では自動テストはありませんでしたか? 新しいオブジェクトモデルと古いオブジェクトモデルに対応するモジュールの下位互換性は保証できませんでした。 失敗とエラーは明白です。 途中で、このモデルを導入するために新たな努力が必要になりましたが、私たちはすでにマウスの大騒ぎに疲れていました。



ゆっくりと、プロジェクトに対する私の態度が平凡になりつつあることに気づき始めました。 古いモデルの枠組みの中で私が推論することは難しくなりました。 後になって、私は傾いた状態にあることが判明しました。 この用語は、ポーカーを積極的にプレイし、トーナメントで賞品を受け取る友人によって私の日常生活に導入されました。 彼は私に次のように説明しました。「傾斜中、あなたはもはや理性によって導かれるのではなく、感情によって導かれます。 これは、単にポーカープレーヤーに受け入れられません。」 類推を描くと、グローバルな変化について余分な感情をどれだけ示しているかを実感しました。



開発チームがリーダーと会ったのはこの瞬間でしたが、これは決して忘れません。 私たちのリーダーは賢く、自信を持った人でした。 彼は私たちにいくつか質問をしました。 Pがリーダー、Kがチーム、Tがチームリーダーであるダイアログの例を示します。



R:現在の機能に戻すために、新しいモデルはどれくらい導入されますか?

K。:約6週間。

R:そのようなグローバルな変更なしで問題を解決することは可能ですか?

K。:可能ですが、保証はありません。

R:これらの変更を今すぐ実装しない場合、プログラムの次のバージョンをリリースすることは可能ですか?

K。:変更を導入しないと、前方への動きが大幅に遅くなり、新しい調整を行うことがますます難しくなります。 プロジェクトは、コードベース全体をインストールした後に移動を停止します。

R:個人的に、すべてをやり直すことは正しいと確信していますか?

T。:プログラムがゆるくなり、そのパフォーマンスがスレッドにかかっていることがわかりました。 必要であれば、私たちは疲れているので、私たちは昔ながらの方法を扱うことができます。 しかし、プロジェクトの目標により適した、よりシンプルなソリューションを主張して、「はい」と言う方が良いでしょう。 プロジェクトの開発の見通しについて話す場合、新しいモデルを導入することはそれほど危険ではありません。



その後、リーダーは私たちの行動を承認し、顧客からのすべての攻撃から私たちを閉鎖することに気付きました。 5週間で袖をまくり、すべてを仕上げました。 不均衡な仕事がありましたが、私たちは本当の家族になりました。 実装は非常にスムーズに進み、おそらくモジュラー戦略が影響を受けました。



報復



この瞬間、私たちは本当のリフトを感じました。 私の神経衰弱は無期限に延期されました。 実装はより意味のある完全なものになり、推奨システムに問題はありませんでした。 他にもすべて。 すべてのモジュールは1つのアーキテクチャで機能し、対象モデルを反映していました。 最初のバージョンをリリースし、ユーザーから非常に温かく迎えられました。 それ以降のバージョンは問題ではなくなったため、私たちはしっかりと立ちました。 モデルの開発には、単一の言語の開発が伴いました。 プログラムの3番目のバージョンまでに、全員が「私たちの」言語という用語を積極的に適用しました。 マーケティング担当者は、潜在的な投資家とのコミュニケーションに幅広く活用し、プログラムの機能を説明しています。



コインの裏側



途中、リーダーが「未知の世界に足を踏み入れる」勇気に欠けるプロジェクトがありました。 動機は異なり、不信から始まり「後回しに」で終わる。 しかし、ロープがいくらカールしても、臨界質量は増加します。 Tiltに付属し、サポートされていないプログラムが続きます。 これらは、常に快適で痛みがないとは限らない世界的な変化の兆候です。



結論として



何かをアドバイスすることは非常に困難です。なぜなら、それはすべてプロジェクトに依存しているからです。 人為的に飛躍を引き起こそうとしないでください。これは作業を凍結するだけです。 通常、潜在的なジャンプは、リファクタリングのカスケード後に発生します。 次に、洞察、モデルの新しいビジョン、およびソフトウェアアーキテクチャでのその表示があります。 ほとんどの時間は、小さな変化、ジャークへの準備、一連のクリティカルマスによって占められています。



飛躍への道を開き、主題モデルに関する知識を習得し、単一の言語を育成することに焦点を合わせます。 サブジェクトエリアの概念を「感じて」、最も明確な形式でモデルで表現します。 プログラムのアーキテクチャを改善し、より柔軟にします。 モデルの知識を抽出し、最も重要な論争を強調します。 理解と可視性を向上させます。 これらの要因は、飛躍に貢献します。 飛躍は、ソフトウェア開発のすべてのブランチに有益な効果をもたらします。 開発者はプログラムに自信を持つようになり、マネージャーはタスクを賢明に評価します。 平和、友情のチューインガム!



All Articles