AngularJS:サービスプロパティにバインドする正しい方法


162

AngularJSでサービスプロパティにバインドする方法のベストプラクティスを探しています。

AngularJSを使用して作成されたサービスのプロパティにバインドする方法を理解するために、複数の例に取り組みました。

以下に、サービスのプロパティにバインドする方法の2つの例を示します。どちらも機能します。最初の例では基本的なバインディングを使用し、2番目の例では$ scope。$ watchを使用してサービスプロパティにバインドしました

これらの例のいずれかがサービスのプロパティにバインドするときに推奨されますか、それとも私が知らない、推奨される別のオプションがありますか?

これらの例の前提は、サービスがそのプロパティを「lastUpdated」と「calls」を5秒ごとに更新する必要があることです。サービスのプロパティが更新されると、ビューにこれらの変更が反映されます。これらの例はどちらも正常に機能します。それを行うより良い方法があるのだろうか。

基本的なバインディング

次のコードは、ここで表示および実行できます。http//plnkr.co/edit/d3c16z

<html>
<body ng-app="ServiceNotification" >

    <div ng-controller="TimerCtrl1" style="border-style:dotted"> 
        TimerCtrl1 <br/>
        Last Updated: {{timerData.lastUpdated}}<br/>
        Last Updated: {{timerData.calls}}<br/>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
    <script type="text/javascript">
        var app = angular.module("ServiceNotification", []);

        function TimerCtrl1($scope, Timer) {
            $scope.timerData = Timer.data;
        };

        app.factory("Timer", function ($timeout) {
            var data = { lastUpdated: new Date(), calls: 0 };

            var updateTimer = function () {
                data.lastUpdated = new Date();
                data.calls += 1;
                console.log("updateTimer: " + data.lastUpdated);

                $timeout(updateTimer, 5000);
            };
            updateTimer();

            return {
                data: data
            };
        });
    </script>
</body>
</html>

サービスプロパティへのバインドを解決するもう1つの方法は、コントローラーで$ scope。$ watchを使用することです。

$ scope。$ watch

次のコードは、ここで表示および実行できます。http//plnkr.co/edit/dSBlC9

<html>
<body ng-app="ServiceNotification">
    <div style="border-style:dotted" ng-controller="TimerCtrl1">
        TimerCtrl1<br/>
        Last Updated: {{lastUpdated}}<br/>
        Last Updated: {{calls}}<br/>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
    <script type="text/javascript">
        var app = angular.module("ServiceNotification", []);

        function TimerCtrl1($scope, Timer) {
            $scope.$watch(function () { return Timer.data.lastUpdated; },
                function (value) {
                    console.log("In $watch - lastUpdated:" + value);
                    $scope.lastUpdated = value;
                }
            );

            $scope.$watch(function () { return Timer.data.calls; },
                function (value) {
                    console.log("In $watch - calls:" + value);
                    $scope.calls = value;
                }
            );
        };

        app.factory("Timer", function ($timeout) {
            var data = { lastUpdated: new Date(), calls: 0 };

            var updateTimer = function () {
                data.lastUpdated = new Date();
                data.calls += 1;
                console.log("updateTimer: " + data.lastUpdated);

                $timeout(updateTimer, 5000);
            };
            updateTimer();

            return {
                data: data
            };
        });
    </script>
</body>
</html>

$ rootscope。$ broadcastをサービスで使用でき、$ root。$ onをコントローラーで使用できることは知っていますが、私が作成した他の例では、$ broadcast / $ onを使用して最初のブロードキャストはコントローラーですが、ブロードキャストされる追加の呼び出しはコントローラーでトリガーされます。$ rootscope。$ broadcastの問題を解決する方法を知っている場合は、回答を提供してください。

しかし、先ほど述べたことを説明し直すために、サービスプロパティにバインドする方法のベストプラクティスを知りたいと思います。


更新

この質問は、元々2013年4月に質問され、回答されました。2014年5月に、Gil Birmanが新しい回答を提供しました。これを正解に変更しました。Gil Birmanの回答には賛成票がほとんどないため、この質問を読んでいる人は彼の回答を無視して、投票数が多い他の回答を支持するのではないかと心配しています。ベストアンサーを決定する前に、ギルバーマンのアンサーを強くお勧めします。


ジョシュ・デイビッド・ミラーの答えはギル・バーマンの答えよりも優れていると思います。また、$ watch、$ watchGroup、$ watchCollectionを使用すると、さらに改善できます。中規模から大規模のアプリでは、懸念の分離が非常に重要です。
ジョナサン

@bardev私は両方の答えは役に立たなかったと思います、そして新しい開発者はそれらを完全に間違っていると理解するでしょう。
ザラボーザ2016

あなたが尋ねる問題は、参照するオブジェクトのネイティブJavaScript変数の動作に関するものです。私は以下に少し説明を追加しました
Zalaboza

回答:


100

2番目のアプローチの長所と短所を検討します。

  • 0の {{lastUpdated}}代わりに{{timerData.lastUpdated}}、これは同じように簡単にできる{{timer.lastUpdated}}かもしれませんが、私はもっと読みやすいと主張するかもしれません(しかし、議論しないでください...私はこの点を中立的な評価にしたので、あなたは自分で決めることができます)

  • +1コントローラーがマークアップの一種のAPIとして機能すると便利です。データモデルの構造が変更された場合、(理論的には)htmlパーシャルに触れずにコントローラーのAPIマッピングを更新できます。

  • -1ただし、理論は常に実践的であるとは限らず、通常、変更が要求されたときにマークアップコントローラーロジックを変更する必要があることに気づきます。したがって、APIを作成する余分な労力は、APIの利点を打ち消します。

  • -1さらに、このアプローチはあまりドライではありません。

  • -1データをng-modelコードにバインドする場合$scope.scalar_values、新しいREST呼び出しを行うためにコントローラーにを再パッケージ化する必要があるため、DRYはさらに少なくなります。

  • -0.1余分なウォッチャーを作成する小さなパフォーマンスヒットがあります。また、特定のコントローラーで監視する必要のないデータプロパティがモデルにアタッチされている場合は、ディープウォッチャーに追加のオーバーヘッドが発生します。

  • -1複数のコントローラーに同じデータモデルが必要な場合はどうなりますか?つまり、モデルを変更するたびに更新する複数のAPIがあります。

$scope.timerData = Timer.data;今、魅力的な魅力を感じ始めています...最後のポイントをもう少し詳しく見てみましょう...どのようなモデルの変更について話していましたか?バックエンド(サーバー)のモデル?または、作成されてフロントエンドのみに存在するモデルですか?どちらの場合も、本質的にデータマッピングAPIフロントエンドサービスレイヤー(角度付きファクトリまたはサービス)に属します。(最初の例-私の好み-は、サービスレイヤーにそのようなAPIがないことに注意してください。これは、必要がないほど簡単なので、問題ありません。)

結論として、すべてを分離する必要はありません。そして、マークアップをデータモデルから完全に分離する限り、欠点は利点を上回ります。


コントローラは、一般的にで散らかされるべきではありません$scope = injectable.data.scalar。むしろ、それらは、$scope = injectable.data's、promise.then(..)' s、および$scope.complexClickAction = function() {..}'s

データの分離、つまりビューのカプセル化を実現するための代替アプローチとして、ビューをモデルから分離することが本当に意味があるのは、ディレクティブを使用する場合のみです。しかし、それでも$watchcontrollerまたはlink関数でスカラー値を使用しないでください。これは時間の節約にもなりませんし、コードの保守性や可読性も向上しません。いずれにせよ、angularでの堅牢なテストは通常​​、結果のDOMをテストするため、テストが簡単になることすらありませ。むしろ、ディレクティブでは、オブジェクト形式のデータAPIを要求し、$watchによって作成されたer だけを使用することを支持しng-bindます。


http://plnkr.co/edit/MVeU1GKRTN4bqA3h9Yio

<body ng-app="ServiceNotification">
    <div style="border-style:dotted" ng-controller="TimerCtrl1">
        TimerCtrl1<br/>
        Bad:<br/>
        Last Updated: {{lastUpdated}}<br/>
        Last Updated: {{calls}}<br/>
        Good:<br/>
        Last Updated: {{data.lastUpdated}}<br/>
        Last Updated: {{data.calls}}<br/>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
    <script type="text/javascript">
        var app = angular.module("ServiceNotification", []);

        function TimerCtrl1($scope, Timer) {
            $scope.data = Timer.data;
            $scope.lastUpdated = Timer.data.lastUpdated;
            $scope.calls = Timer.data.calls;
        };

        app.factory("Timer", function ($timeout) {
            var data = { lastUpdated: new Date(), calls: 0 };

            var updateTimer = function () {
                data.lastUpdated = new Date();
                data.calls += 1;
                console.log("updateTimer: " + data.lastUpdated);

                $timeout(updateTimer, 500);
            };
            updateTimer();

            return {
                data: data
            };
        });
    </script>
</body>

更新:私は最終的にこの質問に戻って、どちらのアプローチも「間違っている」とは思わないことを付け加えました。もともと私はジョシュ・デビッド・ミラーの答えが間違っていたと書いていましたが、振り返ってみると彼の主張は完全に有効です。

懸念の分離(接線的に関連している)は別にて、私が考慮に入れなかった防御コピーの別の理由があります。この質問は主に、サービスから直接データを読み取ることを扱います。しかし、もしあなたのチームの開発者が、ビューがそれを表示する前に、コントローラーがデータをなんらかの方法で簡単に変換する必要があると決定したらどうでしょうか?(コントローラーがデータを変換する必要があるかどうかは別の議論です。)最初にオブジェクトのコピーを作成しないと、同じデータを使用する別のビューコンポーネントで意図せずに回帰を引き起こす可能性があります。

この質問が本当に強調しているのは、典型的なAngularアプリケーション(および実際にはすべてのJavaScriptアプリケーション)のアーキテクチャ上の欠点です:懸念の密結合、およびオブジェクトの可変性。最近、React 不変のデータ構造を使用したアプリケーションの設計に夢中になっています。これにより、次の2つの問題が見事に解決されます。

  1. 懸念の分離:コンポーネントは、すべてのデータを小道具を介して消費し、グローバルシングルトン(Angularサービスなど)にほとんどまたはまったく依存せず、ビュー階層でそのに何が起こったかについて何も知りません。

  2. 変更可能性:すべての小道具は不変であり、データの変更を無意識のうちに失うリスクを排除します。

Angular 2.0は、上記の2つのポイントを達成するためにReactから大いに借りることになりました。


1
私が理解するほど、AngularJSを使用してきました。AngularJSコントローラーは、可能な限りシンプルで薄いものである必要があると思います。コントローラに$ watchesを追加すると、ロジックが複雑になります。サービスの値を参照するだけで、はるかに簡単になり、AngularJSの方法のように見えます。–
Mike Barlow-BarDev

3
AngularJSの「十戒」。それは理由のために宣言的です。
ピラウ14

Josh David Millerの答えは「正しくない」ではありません。すべてのための時間と場所があります。
JoshuaDavid 2014年

私はあなたが正しいと思います、@ FireCoding。回答を更新する予定です。
Gil Birman、2014年

@GilBirmanの素晴らしい答え。ディレクティブの記述と例を教えていただけませんか?あなたが言ったことを説明するために、「モデルからビューを切り離すことが本当に意味がある唯一の場所は、ディレクティブです。 ng-bindによって作成されたウォッチャー。」
klode

78

私の観点から$watchは、最善の方法でしょう。

あなたは実際にあなたの例を少し単純化することができます:

function TimerCtrl1($scope, Timer) {
  $scope.$watch( function () { return Timer.data; }, function (data) {
    $scope.lastUpdated = data.lastUpdated;
    $scope.calls = data.calls;
  }, true);
}

それだけで十分です。

プロパティは同時に更新されるため、必要な時計は1つだけです。また、それらは単一のかなり小さいオブジェクトからのものであるため、Timer.dataプロパティを監視するだけに変更しました。に渡される最後のパラメーターは$watch、参照が同じであることを確認するだけでなく、深い等価性をチェックするように指示します。


少しコンテキストを提供するために、サービスの値をスコープに直接配置するよりもこの方法を好むのは、懸念事項を適切に分離するためです。ビューは、操作するためにサービスについて何も知る必要はありません。コントローラーの役割は、すべてを接着することです。その仕事は、サービスからデータを取得して必要な方法で処理し、ビューに必要な詳細を提供することです。しかし、その仕事は単にサービスをビューに沿って渡すことではないと思います。そうでなければ、コントローラはそこで何をしていますか?AngularJS開発者は、テンプレート(たとえばifステートメント)に「ロジック」を含めないことを選択した場合も、同じ理由に従いました。

公平を期すために、おそらくここには複数の視点があります。他の回答を楽しみにしています。


3
もう少し詳しく説明してもらえますか?ビューとサービスの結合が少ないため、$ watchesを好みますか?すなわち、{{lastUpdated}}{{timerData.lastUpdated}}
マークライコック

2
Timer.data$ watchにTimer渡す文字列式はスコープに対して評価されるため、$ watchで使用するには@BarDevを$ scopeで定義する必要があります。これは、その作業を行う方法を示すプランカーです。objectEqualityパラメーターはここに記載されています-3 番目のパラメーター-はあまり説明されていません。
Mark Rajcok 2013

2
パフォーマンスに関して$watchは、非常に非効率的です。stackoverflow.com/a/17558885/932632およびstackoverflow.com/questions/12576798/…で
Krym

11
@Kyrmこれはおそらく一部の状況では当てはまりますが、パフォーマンスを処理するときは、統計的に有意で一般化されたものだけでなく、「臨床的に有意な」パフォーマンスの向上を探す必要があります。既存のアプリケーションにパフォーマンスの問題がある場合は、対処する必要があります。それ以外の場合は、時期尚早の最適化の場合にすぎず、読み取りが難しく、バグが発生しやすく、ベストプラクティスに準拠しておらず、メリットが実証されていません。
Josh David Miller 14

1
ウォッチャーが関数を使用してゲッターを呼び出すと仮定すると、はい。それはうまくいきます。私は、コレクション内のインスタンスを返すサービスの支持者でもあります。この場合、es5のゲッター機能とセッター機能はかなり適切です。
Josh David Miller

19

パーティーに遅れますが、将来のGoogle社員のために-提供された回答を使用しないでください。

JavaScriptは参照によってオブジェクトを渡すメカニズムを備えていますが、「数値、文字列など」の値の浅いコピーのみを渡します。

上記の例では、サービスの属性をバインドする代わりに、サービスをスコープに公開しませんか?

$scope.hello = HelloService;

このシンプルなアプローチにより、angularは双方向バインディングと必要なすべての魔法のことを実行できるようになります。ウォッチャーや不要なマークアップでコントローラーをハッキングしないでください。

また、ビューが誤ってサービス属性を上書きすることが心配な場合は、を使用definePropertyして、読み取り可能、列挙可能、構成可能にするか、ゲッターとセッターを定義します。サービスをより強固にすることで、多くの制御を得ることができます。

最後のヒント:サービスよりもコントローラーの作業に多くの時間を費やしていると、間違っています:(。

あなたが提供したその特定のデモコードで私はあなたがそうすることをお勧めします:

 function TimerCtrl1($scope, Timer) {
   $scope.timer = Timer;
 }
///Inside view
{{ timer.time_updated }}
{{ timer.other_property }}
etc...

編集:

上で述べたように、サービス属性の動作を使用して制御できます defineProperty

例:

// Lets expose a property named "propertyWithSetter" on our service
// and hook a setter function that automatically saves new value to db !
Object.defineProperty(self, 'propertyWithSetter', {
  get: function() { return self.data.variable; },
  set: function(newValue) { 
         self.data.variable = newValue; 
         // let's update the database too to reflect changes in data-model !
         self.updateDatabaseWithNewData(data);
       },
  enumerable: true,
  configurable: true
});

今、私たちのコントローラーで

$scope.hello = HelloService;
$scope.hello.propertyWithSetter = 'NEW VALUE';

私たちのサービスはpropertyWithSetter何とかして値を変更し、新しい値をデータベースに投稿します!

または、私たちは私たちが望むあらゆるアプローチを取ることができます。

MDNドキュメントを参照してくださいdefineProperty


$scope.model = {timerData: Timer.data};スコープで直接ではなくモデルにアタッチするだけで、それが上記で説明していたことはかなり確実です。
Scott Silvi

1
私の知る限りでは、jsオブジェクト参照はServiceのすべてに対して機能します。このようなコーディング:$ scope.controllerVar = ServiceVar、$ scope.controllerVarで行うすべてのことはServiceVarでも行われます。
Kai Wang

@KaiWangは同意します。DefineAttributeを使用することを決定しない限り、コントローラーがサービスデータを誤って変更するのを防ぐために、サービスにセッター関数を持たせることができます。
ザラボーザ2016年

12

この質問には文脈的な要素があると思います。

サービスからデータを単にプルし、その情報をそのビューに放射している場合は、サービスプロパティに直接バインドすることで十分だと思います。ビューで使用するサービスプロパティをモデルプロパティに単純にマップするための定型コード大量に記述たくありません。

さらに、角度のパフォーマンスは2つのことに基づいています。1つ目は、ページにあるバインディングの数です。2つ目は、ゲッター関数の高さです。ミスコはこれについてここで話します

(サービス自体に適用されたデータマッサージとは対照的に)サービスデータに対してインスタンス固有のロジックを実行する必要があり、これの結果がビューに公開されるデータモデルに影響を与える場合、$ watcherが適切であると言えます。関数がそれほど高くない限り。高価な関数の場合は、結果をローカル(コントローラーへの)変数にキャッシュし、$ watcher関数の外部で複雑な操作を実行し、スコープをその結果にバインドすることをお勧めします。

注意点として、あなたはハングするべきではありません任意のあなたの$の範囲から直接プロパティを。$scope変数には、お使いのモデルではありません。モデルへの参照があります。

私の考えでは、単にサービスから情報を放射して表示するための「ベストプラクティス」:

function TimerCtrl1($scope, Timer) {
  $scope.model = {timerData: Timer.data};
};

そして、あなたのビューは含まれます{{model.timerData.lastupdated}}


その提案に注意すると、JavaScriptの専門家ではない人が文字列であるプロパティを使用してそれを実行しようとする可能性があります。その場合、javascriptはオブジェクトへの参照を作成しませんが、rawは文字列をコピーします。(そして、それが変更されても更新されないのは悪いことです)
Valerio 2013

7
私はそれを私の「警告」でカバーしませんでしたが、常にドットを使用する必要があります(つまり、$ scope.modelではなく、$ scopeから外さないでください)。$ scope.model.someStringPropertyがあり、ビューでmodel.someStringPropertyを参照すると、内部ウォッチャーがプロップではなくオブジェクト上にあるため、更新されます。
Scott Silvi 2013

6

上記の例に基づいて、コントローラー変数をサービス変数に透過的にバインドする方法を考えました。

以下の例では、コントローラー$scope.count変数への変更は自動的にサービスcount変数に反映されます。

本番環境では、実際にこのバインディングを使用してサービスのIDを更新しています。サービスのIDは、非同期でデータをフェッチし、そのサービス変数を更新しています。さらにバインディングは、サービスが更新されたときにコントローラーが自動的に更新されることを意味します。

以下のコードはhttp://jsfiddle.net/xuUHS/163/で動作しているのを見ることができます

見る:

<div ng-controller="ServiceCtrl">
    <p> This is my countService variable : {{count}}</p>
    <input type="number" ng-model="count">
    <p> This is my updated after click variable : {{countS}}</p>

    <button ng-click="clickC()" >Controller ++ </button>
    <button ng-click="chkC()" >Check Controller Count</button>
    </br>

    <button ng-click="clickS()" >Service ++ </button>
    <button ng-click="chkS()" >Check Service Count</button>
</div>

サービス/コントローラー:

var app = angular.module('myApp', []);

app.service('testService', function(){
    var count = 10;

    function incrementCount() {
      count++;
      return count;
    };

    function getCount() { return count; }

    return {
        get count() { return count },
        set count(val) {
            count = val;
        },
        getCount: getCount,
        incrementCount: incrementCount
    }

});

function ServiceCtrl($scope, testService)
{

    Object.defineProperty($scope, 'count', {
        get: function() { return testService.count; },
        set: function(val) { testService.count = val; },
    });

    $scope.clickC = function () {
       $scope.count++;
    };
    $scope.chkC = function () {
        alert($scope.count);
    };

    $scope.clickS = function () {
       ++testService.count;
    };
    $scope.chkS = function () {
        alert(testService.count);
    };

}

これは素晴らしい解決策です。ありがとうございます。これは非常に賢明な方法で
役に立ちまし

2

サービス自体バインドするためのより良い方法だと思いますの属性ではなくに。

理由は次のとおりです。

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.7/angular.min.js"></script>
<body ng-app="BindToService">

  <div ng-controller="BindToServiceCtrl as ctrl">
    ArrService.arrOne: <span ng-repeat="v in ArrService.arrOne">{{v}}</span>
    <br />
    ArrService.arrTwo: <span ng-repeat="v in ArrService.arrTwo">{{v}}</span>
    <br />
    <br />
    <!-- This is empty since $scope.arrOne never changes -->
    arrOne: <span ng-repeat="v in arrOne">{{v}}</span>
    <br />
    <!-- This is not empty since $scope.arrTwo === ArrService.arrTwo -->
    <!-- Both of them point the memory space modified by the `push` function below -->
    arrTwo: <span ng-repeat="v in arrTwo">{{v}}</span>
  </div>

  <script type="text/javascript">
    var app = angular.module("BindToService", []);

    app.controller("BindToServiceCtrl", function ($scope, ArrService) {
      $scope.ArrService = ArrService;
      $scope.arrOne = ArrService.arrOne;
      $scope.arrTwo = ArrService.arrTwo;
    });

    app.service("ArrService", function ($interval) {
      var that = this,
          i = 0;
      this.arrOne = [];
      that.arrTwo = [];

      $interval(function () {
        // This will change arrOne (the pointer).
        // However, $scope.arrOne is still same as the original arrOne.
        that.arrOne = that.arrOne.concat([i]);

        // This line changes the memory block pointed by arrTwo.
        // And arrTwo (the pointer) itself never changes.
        that.arrTwo.push(i);
        i += 1;
      }, 1000);

    });
  </script>
</body> 

このプランカーでプレイできます。


1

私はむしろウォッチャーをできるだけ少なくしたいと思います。私の理由は私の経験に基づいており、理論的にはそれを主張するかもしれません。
ウォッチャーの使用に関する問題は、スコープの任意のプロパティを使用して、任意のコンポーネントまたはサービスの任意のメソッドを呼び出すことができることです。
現実の世界のプロジェクトでは、すぐに、追跡されない(追跡が難しいと言う方がいい)一連のメソッドが呼び出され、値が変更されるため、オンボーディングプロセスが特に悲惨になります。


0

サービスを送信するデータをバインドすることは良いアイデアではありませんが(アーキテクチャ)、それが必要な場合は、2つの方法をお勧めします

1)サービス内ではなくデータを取得できます。コントローラー/ディレクティブ内でデータを取得でき、どこにバインドしても問題はありません。

2)angularjsイベントを使用できます。いつでも、($ rootScopeから)シグナルを送信して、どこにいてもキャッチできます。そのeventNameでデータを送信することもできます。

多分これはあなたを助けることができます。例でもっと必要な場合は、ここにリンクがあります

http://www.w3docs.com/snippets/angularjs/bind-value-between-service-and-controller-directive.html



-2

最もエレガントなソリューション...

app.service('svc', function(){ this.attr = []; return this; });
app.controller('ctrl', function($scope, svc){
    $scope.attr = svc.attr || [];
    $scope.$watch('attr', function(neo, old){ /* if necessary */ });
});
app.run(function($rootScope, svc){
    $rootScope.svc = svc;
    $rootScope.$watch('svc', function(neo, old){ /* change the world */ });
});

また、私はEDA(Event-Driven Architectures)を作成しているため、次のような[単純化されたバージョン]のようなことをする傾向があります。

var Service = function Service($rootScope) {
    var $scope = $rootScope.$new(this);
    $scope.that = [];
    $scope.$watch('that', thatObserver, true);
    function thatObserver(what) {
        $scope.$broadcast('that:changed', what);
    }
};

次に、目的のチャネルのコントローラーにリスナーを配置し、この方法でローカルスコープを最新の状態に保ちます。

結論として、物事をSOLIDに保ち、弱い結合を採用している限り、「ベストプラクティス」はそれほど多くありません。むしろ、そのほとんどが好みです。私が後者のコードを推奨する理由は、EDAが本質的に実現可能な最小の結合を持つためです。そして、あなたがこの事実についてあまり心配していなければ、同じプロジェクトで一緒に作業することは避けましょう。

お役に立てれば...

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