コアポイント
最新のフレームワークMVCモデルの特定の実装方法を決定します。すべての説明が異なる場合、これは混乱を招く可能性があり、それによりノイズと混乱を加えます。いずれかのコードベースが複数のフレームワークを採用すると、イライラする混乱が発生します。私の心の問題は、より良い方法があるかということです。
MVCパターンはクライアントフレームワークに適していますが、最新のフレームワークは変更されます。今日の近代化は時間とともに死にます。この場合、私は代替案を探求し、ちょっとした規律が私たちを連れて行くことができる場所を見たいと思います。
現代のjavascriptを読んで、javascriptの絶えず変化する世界に遅れないようにしてください!この本を読むMVCモデル自体は数十年前にさかのぼることができます。これにより、プログラミングスキルへの投資に値するデザインパターンになります。 MVCモードは、独立して存在できるモードです。問題は、これがどこまで私たちを連れて行くことができるかということです。
待って、これは別のフレームワークですか?
フレームは、デザインパターンに従う必要がないため、異なります。フレームワークとパターンを区別する1つの方法は、ハリウッドの原則を探すことです。ハリウッドの原則は、「私たちに電話しないでください、あなたがそれを使用することを決定するためにいつでも依存しています。フレームワークはハリウッドによく似ており、何をすべきか、どうすればよいかを決めることはできません。実際、開発者は俳優のようで、行動を求められたときにスクリプトに従っています。
クライアントフレームワークを避けるための多くの正当な理由があります:
そのコアは、MVC設計パターンが懸念の明確な分離についてであることです。目的は、ソリューションを明確で理解しやすくすることです。特定の変更を行いたいプログラマは、適切な場所を簡単に見つけることができます。
ペンギンデモ
ペンギンのデモを作る時が来ました!ページにいくつかの種を示すデッキを見せます。このために、MVCデザインパターンと少し規律を使用したいと思います。極端なプログラミング方法を使用して、ユニットテストと簡単な方法を使用して、手元の問題を解決します。最後に、それぞれが独自のデータとプロフィール写真を備えたいくつかのペンギンを閲覧できるはずです。
この例の終わりまでに、純粋なJavaScriptでMVCデザインパターンを使用するのに十分なことを学ぶべきでした。パターン自体はテストが非常に簡単であるため、優れたユニットテストが予想されます。
クロスブラウザーの互換性の理由については、このデモでES5に固執します。実証済みの言語機能をこの永続的なデザインパターンと組み合わせて使用することは理にかなっています。
準備はできていますか?待って見てみましょう。
skeleton
以下は、その外観の視覚化です:
Penguincontrollerはイベントを処理し、ビューとモデルの間の仲介者です。ユーザーがアクションを実行したときに何が起こるかを計算します(たとえば、ボタンをクリックしたり、キーを押したりします)。クライアント固有のロジックをコントローラーに配置できます。やるべきことがたくさんある大規模なシステムでは、モジュールに分解できます。コントローラーは、イベントのエントリポイントであり、ビューとデータの間の唯一のメディエーターです。
ペンギンビューはdomを気にします。 DOMは、HTML操作を実行するために使用するブラウザAPIです。 MVCでは、ビューを除いて変更domの一部はありません。ビューはユーザーイベントを添付できますが、イベントの処理問題をコントローラーに残します。ビューの主なコマンドは、ユーザーが画面に表示するステータスを変更することです。このデモンストレーションでは、ViewはDOM操作に純粋なJavaScriptを使用します。
PenguinModelはデータを気にします。クライアントJavaScriptでは、これはAjaxを意味します。 MVCパターンの利点の1つは、サーバー側のAjaxコール用の単一の場所があることです。これにより、ソリューションに精通していない他のプログラマーが開始することが容易になります。この設計パターンのモデルは、サーバーのJSONまたはオブジェクトのみを気にしています。
1つのアンチパターンは、この懸念のこの固有の分離に反しています。たとえば、モデルはHTMLを気にしてはなりません。ビューはAjaxを気にしてはなりません。コントローラーは、実装の詳細を心配することなく、メディエーターとして機能する必要があります。
このパターンを使用すると、開発者は最初は善意を持っていますが、懸念を漏らします。すべてをWebコンポーネントに変えて混乱に陥るのは魅力的です。機能とユーザー指向の懸念に焦点を当てます。ただし、機能的な懸念は機能的な懸念とは異なります。
プログラミングで私が気に入っているのは、機能的な懸念を明確に分離することです。個々のプログラミングの問題は一貫して解決されます。これにより、コードを読むときに理解しやすくなります。目的は、他の人がプラスの貢献をすることができるように、わかりやすいコードを書くことです。
あなたが見て触れることができる本当の例がなければ、それは良いデモではありません。言うまでもなく、ここにペンギンのデモを示すCodepenがあります:
SitePoint(@SitePoint)を表示すると、CodePenでペンギンのデモをペンします。
私は十分に言った、今度はコードを書く時が来た。
ビューとモデルは、コントローラーが使用する2つのコンポーネントです。コントローラーには、コンストラクターでジョブを行うために必要なすべてのコンポーネントが含まれています。
<code>var PenguinController = function PenguinController(penguinView, penguinModel) { this.penguinView = penguinView; this.penguinModel = penguinModel; }; </code>
ユーザーイベントは接続され、この方法で処理されます。
このイベントは、現在のターゲットを使用して、国家をDOMに保存することに注意してください。この場合、DOMはその現在のステータスについてすべてを教えてくれます。 DOMの現在のステータスは、ユーザーがブラウザで見るものです。コントローラーがステータスを変更しない限り、ステータスデータをDOM自体に保存できます。
<code>PenguinController.prototype.initialize = function initialize() { this.penguinView.onClickGetPenguin = this.onClickGetPenguin.bind(this); }; PenguinController.prototype.onClickGetPenguin = function onClickGetPenguin(e) { var target = e.currentTarget; var index = parseInt(target.dataset.penguinIndex, 10); this.penguinModel.getPenguin(index, this.showPenguin.bind(this)); }; </code>
イベントがトリガーされた後、コントローラーはデータを取得し、次に何が起こるかを説明します。 this.showpenguin()コールバックは興味深いものです:
コントローラーは各ペンギンのインデックスを計算し、それをレンダリングするビューを伝えます。モデルからデータを取得し、ビューが理解し、気にかけているオブジェクトに変換します。
<code>PenguinController.prototype.showPenguin = function showPenguin(penguinModelData) { var penguinViewModel = { name: penguinModelData.name, imageUrl: penguinModelData.imageUrl, size: penguinModelData.size, favoriteFood: penguinModelData.favoriteFood }; penguinViewModel.previousIndex = penguinModelData.index - 1; penguinViewModel.nextIndex = penguinModelData.index + 1; if (penguinModelData.index === 0) { penguinViewModel.previousIndex = penguinModelData.count - 1; } if (penguinModelData.index === penguinModelData.count - 1) { penguinViewModel.nextIndex = 0; } this.penguinView.render(penguinViewModel); }; </code>
以下は、ペンギンのときの幸せな道を示すユニットテストです。
<code>var PenguinController = function PenguinController(penguinView, penguinModel) { this.penguinView = penguinView; this.penguinModel = penguinModel; }; </code>
PenguinviewMockは、実際の実装と同じ契約を結んでいます。これにより、ユニットテストを作成してアサーションを作成できます。アサーションはノードアサーションから来ており、チャイアサーションにも存在します。これにより、ノードおよびブラウザで実行できるテストを作成できます。
コントローラーは実装の詳細を気にしないことに注意してください。 This.render()など、ビューが提供する契約を使用します。それは、クリーンコードを書くために必要な規律です。コントローラーは、すべてのコンポーネントがそれが言うことを行うことができると信頼することができます。これにより、透明性が向上し、コードの読み取りが容易になります。
ビューは、DOM要素と接続イベントのみを気にしています。
<code>PenguinController.prototype.initialize = function initialize() { this.penguinView.onClickGetPenguin = this.onClickGetPenguin.bind(this); }; PenguinController.prototype.onClickGetPenguin = function onClickGetPenguin(e) { var target = e.currentTarget; var index = parseInt(target.dataset.penguinIndex, 10); this.penguinModel.getPenguin(index, this.showPenguin.bind(this)); }; </code>
その主な関心事は、ビューモデルデータをHTMLに変換し、状態を変更することであることに注意してください。 2つ目は、クリックイベントを接続し、コントローラーをエントリポイントとして機能させることです。ステータスが変更された後、イベントハンドラーがDOMに接続されます。このテクノロジーは、一度にイベント管理を処理します。
<code>PenguinController.prototype.showPenguin = function showPenguin(penguinModelData) { var penguinViewModel = { name: penguinModelData.name, imageUrl: penguinModelData.imageUrl, size: penguinModelData.size, favoriteFood: penguinModelData.favoriteFood }; penguinViewModel.previousIndex = penguinModelData.index - 1; penguinViewModel.nextIndex = penguinModelData.index + 1; if (penguinModelData.index === 0) { penguinViewModel.previousIndex = penguinModelData.count - 1; } if (penguinModelData.index === penguinModelData.count - 1) { penguinViewModel.nextIndex = 0; } this.penguinView.render(penguinViewModel); }; </code>
これは、すべての主要な問題、状態の変更、および接続イベントを解決します。しかし、データはどこから来るのでしょうか?
モデル
<code>var PenguinViewMock = function PenguinViewMock() { this.calledRenderWith = null; }; PenguinViewMock.prototype.render = function render(penguinViewModel) { this.calledRenderWith = penguinViewModel; }; // Arrange var penguinViewMock = new PenguinViewMock(); var controller = new PenguinController(penguinViewMock, null); var penguinModelData = { name: 'Chinstrap', imageUrl: 'http://chinstrapl.jpg', size: '5.0kg (m), 4.8kg (f)', favoriteFood: 'krill', index: 2, count: 5 }; // Act controller.showPenguin(penguinModelData); // Assert assert.strictEqual(penguinViewMock.calledRenderWith.name, 'Chinstrap'); assert.strictEqual(penguinViewMock.calledRenderWith.imageUrl, 'http://chinstrapl.jpg'); assert.strictEqual(penguinViewMock.calledRenderWith.size, '5.0kg (m), 4.8kg (f)'); assert.strictEqual(penguinViewMock.calledRenderWith.favoriteFood, 'krill'); assert.strictEqual(penguinViewMock.calledRenderWith.previousIndex, 1); assert.strictEqual(penguinViewMock.calledRenderWith.nextIndex, 3); </code>
インデックスに基づいてペンギンを取得する時が来ました:
<code>var PenguinView = function PenguinView(element) { this.element = element; this.onClickGetPenguin = null; }; </code>
これはエンドポイントを指し、サーバーからデータを取得します。ユニットテストでデータをock笑することでこれをテストできます:
ご覧のとおり、モデルは元のデータのみを気にします。これは、AJAXおよびJavaScriptオブジェクトを使用することを意味します。純粋なJavaScriptのAjaxを知っていない場合は、詳細な記事があります。
<code>PenguinView.prototype.render = function render(viewModel) { this.element.innerHTML = '<h3>' + viewModel.name + '</h3>' + '<img alt="' + viewModel.name + '" src="'%20+%20viewModel.imageUrl%20+%0A%20%20%20%20%20%20'">' + '<p><b>Size:</b> ' + viewModel.size + '</p>' + '<p><b>Favorite food:</b> ' + viewModel.favoriteFood + '</p>' + '<a href="https://www.php.cn/link/f0b875eb6cff6fd5f491e6b6521c7510"> ' data-penguin-index="' + viewModel.previousIndex + '">Previous</a> ' + '<a href="https://www.php.cn/link/f0b875eb6cff6fd5f491e6b6521c7510"> ' data-penguin-index="' + viewModel.nextIndex + '">Next</a>'; this.previousIndex = viewModel.previousIndex; this.nextIndex = viewModel.nextIndex; // Wire up click events, and let the controller handle events var previousPenguin = this.element.querySelector('#previousPenguin'); previousPenguin.addEventListener('click', this.onClickGetPenguin); var nextPenguin = this.element.querySelector('#nextPenguin'); nextPenguin.addEventListener('click', this.onClickGetPenguin); nextPenguin.focus(); }; </code>
単位テスト
<code>var ElementMock = function ElementMock() { this.innerHTML = null; }; // Stub functions, so we can pass the test ElementMock.prototype.querySelector = function querySelector() { }; ElementMock.prototype.addEventListener = function addEventListener() { }; ElementMock.prototype.focus = function focus() { }; // Arrange var elementMock = new ElementMock(); var view = new PenguinView(elementMock); var viewModel = { name: 'Chinstrap', imageUrl: 'http://chinstrap1.jpg', size: '5.0kg (m), 4.8kg (f)', favoriteFood: 'krill', previousIndex: 1, nextIndex: 2 }; // Act view.render(viewModel); // Assert assert(elementMock.innerHTML.indexOf(viewModel.name) > 0); assert(elementMock.innerHTML.indexOf(viewModel.imageUrl) > 0); assert(elementMock.innerHTML.indexOf(viewModel.size) > 0); assert(elementMock.innerHTML.indexOf(viewModel.favoriteFood) > 0); assert(elementMock.innerHTML.indexOf(viewModel.previousIndex) > 0); assert(elementMock.innerHTML.indexOf(viewModel.nextIndex) > 0); </code>
私にとって、これは、各ユースケースに完全な一連のユニットテストを提供することを意味します。テストは、コードがどのように役立つかについてのガイダンスを提供します。これにより、特定の変更を行いたいプログラマーに開いて魅力的になります。
楽しみにしています ペンギンのデモンストレーションには、MVCがどれほど有用であるかを示す基本的な実行可能な概念のみが含まれています。ただし、多くの改善点を反復させることができます:
もちろん、私の読者、あなたはこのデモをさらに改善することができます。これらは、このデザインパターンの力を紹介できるアイデアにすぎません。
MVCの設計パターンと少しの規律があなたを連れて行く場所を見ることができることを願っています。優れたデザインパターンは、邪魔にならずにクリーンコードを書くことを容易にします。手元の問題を解決するとき、タスクに集中し続けます。それはあなたをより良く、より効率的なプログラマにするでしょう。
プログラミングでは、目的は、冗長性を排除しながら、手元の問題に密接に焦点を当てることです。プログラミングの技術は、一度に1つの問題を解決することです。 MVCでは、これは一度に機能的な問題を解決することを意味します。
開発者として、あなたが論理的であり、感情に対処しないと信じるのは簡単です。真実は、一度に問題が多すぎるとイライラすることです。これは、私たち全員が対処しなければならない通常の人間の反応です。実際、フラストレーションはコードの品質に悪影響を与える可能性があります。この気持ちがあなたを捕らえてあなたの仕事をリードするとき、それはもはや論理に関するものではありません。ソリューションがより多くのリスクと複雑な依存関係をとるため、これはイライラする可能性があります。
私が好きなのは、単一の焦点に焦点を当てることです。一度に1つの問題を解決し、肯定的なフィードバックを取得します。このようにして、集中力を維持し、効率的に保ち、意味のないことを避けることができます。
この記事は、Vildan Softicによって査読されました。 SitePointコンテンツを最高の状態にしてくれたすべてのSitePointピアレビューアに感謝します!
MVCパターンは、コードの読みやすさと保守性をどのように改善しますか?
MVCパターンにおけるモデルの役割を説明できますか?
コントローラーはMVCモードをどのように宣伝していますか?
MVCモードはスケーラビリティをどのように強化しますか?
MVCパターンは他のJavaScriptフレームワークで使用できますか?
JavaScriptにMVCパターンを実装することの課題は何ですか?
MVCモデルはチームの開発をどのようにサポートしていますか?
MVCモードを使用してモバイルアプリケーションを開発できますか?
以上がVanilla JavaScriptのMVC設計パターンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。