web-dev-qa-db-ja.com

DDDを使用するためのjQueryスパゲッティコードのリファクタリング

クライアント側のコードのほとんどは、1つのファイル内の長いスクリプトとして終了しますが、ほとんどは次のようになります。

<script>
function someFunction1(){/*...*/}
function someFunction2(){/*...*/}
...
var globalVariable1;
var globalVariable2;
...
$(function(){

$('selector1').click(function(){
    //get relevant data from various DOM elements

    //some business logic rules and validation

    //open dialog box

    //more business logic rules and more validation

    //post an ajax request

    //update the DOM    
});

//many other events

//many jQuery dialogs    
});
</script>

メンテナンスの悪夢です。私はDDDを使用して適切に設計されたサーバー側構造(アプリケーションサービス、ドメインサービス、値オブジェクトなど)を使用していますが、クライアントコードを構造化して問題をより適切に分離できていません。

クライアント側のアプリケーションを作成していません。私はクライアント側でjQueryを集中的に使用しています。

クライアント側にDDDを適用するには、コード構造にどのようにアプローチすればよいですか?

5
Songo

クライアント側のアプリケーションを作成していません。私はクライアント側でjQueryを集中的に使用しています。

あなたの目標が書き換えではなく段階的なリファクタリングである場合、 RequireJS をチェックします(他のすべての回答とは異なります) )はMVCフレームワークではありません

代わりに、コードをモジュールに分割し、それらの間の依存関係を処理するための方法にすぎません。このメカニズムは「非同期モジュール定義」またはAMDと呼ばれ、PHPまたはJavaのクラスが通常編成される方法と似ています。


これは途方もなく単純な例です:

myapp/quoteList.js

// Define a module with no dependencies that is an array
define([],function(){
    return(["Hello","World"]);
});

myapp/generateQuote.js

// Define a module with one dependency on another module and is a function
define(["./quoteList"],function(quoteList){
    var f = function(){
        var num = Math.floor(Math.random() * quotes.length);
        return quotes[num];
    };
    return f;
});

myapp/MyUtils.js

// Define a module which is an object. (Effectively a singleton)
define(["./generateQuote"],function(quotes){
    var o = {
        "getQuote" : generateQuote,
        "doPopup" : function(msg){alert(msg);}
    };
    return o;
});

page.html

<script>
// Load a module for use by plain old procedural code
require(["myapp/MyUtils"],function(MyUtils){
    MyUtils.doPopup(MyUtils.getQuote());
});
</script>

このようにして、既存のコードを最も意味のある組織にチャンク化し始めることができます。

1
Darien

MVVMフレームワーク(AngularJS、Knockoutなど)を使用できるように聞こえます。AngularJSにjQueryを含めると、AngularJSが持っているjQLiteの代わりにjQueryを使用するので、jQueryを使用できます。

これらの種類のフレームワークで実行できるのは、コントローラーメソッドを参照する要素のアクションを定義することです。たとえば、AngularSJにはng-clickディレクティブがあります。これは、jQueryで何かを選択してからイベントハンドラーを追加するのとは対照的です)

また、AngularJSを使用すると、コードをコントローラー、サービス、構成などに分離できます(Knockoutやその他の機能を使用していないため、ここではAngularJSのみを参照しています)。

1
Philipp Gayret

サイトがかなり基本的な場合は、独自のMVCを導入できます。 PureMVCを見て、そのモデルをエミュレートしてみてください。ラジオなどのpub/subシステムを取得して、次のように構築します。すべてのメディエーター、コントローラー、モデルを登録するファサード。最後の2つが何であるかを知っていれば、メディエーターは基本的にはビュー/ビューコンポーネントですが、それは抽象化するため、基になるhtmlについて心配する必要はありません。メディエーターはメッセージを送受信します。多くの場合、データチャンクがそれほど大きくない限り、未加工のモデルからメッセージを受信できます。また、物事を管理するためのコントローラが必要になる場合もあります。コントローラーはステートレスであり、特定のメッセージに対してアクションを実行します。モデルとビューの間の交換を管理します。あなたがすべてを正しく行うならば、コントローラは再利用に関して最も使い捨てです。他の2つは可能な限り馬鹿げています。

0
Mark

ある種のMV * JavaScriptフレームワークを使用することを強くお勧めします。それらはたくさんあります(AngularJS、KnockoutJS、Ember、Backbone)。 ここ は、いくつかの最も人気のあるものの素晴らしいレビューです。

一部の単純なページでは、JSフレームワークを使用すると、多くの対話性がない場合や、ページがサーバー側に大きく依存している場合に、やり過ぎになることがあります。これらの場合、JSフレームワークはおそらく適切ではありません。しかし、(クライアント側で)より複雑なものを構築し、(頻繁なDOM操作やルーティングなどの)対話性が必要な場合は、JavaScriptフレームワークが最適なソリューションです。

クライアント側フレームワークを使用すると、半分の作業が完了します。

  • データを表すモデル。
  • モデルを変更すると更新されるビュー。
  • ユーザー入力を処理する(およびモデルを変更する)コントローラー。

MV *フレームワークのほとんどは、単体テストとエンドツーエンドのテストもサポートしています(AngularJSでのテストのサポート方法が気に入っています)。フロントエンドのユニットテストでは、誰かが何かを変更したときに機能が壊れないようにします(たとえば、一部のクラスが削除または変更され、jQueryセレクターがclickイベントハンドラーを追加する要素を見つけられない)。

0
Christian P