[javascript] 모델 데이터와 행동을 어디에 둘 것인가? [tl; 닥터; 서비스 이용]

최신 프로젝트를 위해 AngularJS와 협력하고 있습니다. 설명서 및 자습서에서 모든 모델 데이터는 컨트롤러 범위에 포함됩니다. 컨트롤러에 사용할 수 있어야하므로 해당보기 내에 있어야합니다.

그러나 모델이 실제로 구현되어야한다고 생각하지 않습니다. 예를 들어 복잡하고 개인 속성이있을 수 있습니다. 또한 다른 컨텍스트 / 앱에서 재사용하고 싶을 수도 있습니다. 컨트롤러에 모든 것을 넣으면 MVC 패턴이 완전히 중단됩니다.

모든 모델의 동작에 대해서도 마찬가지입니다. DCI 아키텍처를 사용 하고 데이터 모델과 동작을 분리하려면 동작을 유지하기 위해 추가 객체를 도입해야합니다. 이것은 역할과 상황을 소개함으로써 이루어집니다.

DCI == D ATA C ollaboration I nteraction

물론 모델 데이터와 동작은 일반 자바 스크립트 객체 또는 “클래스”패턴으로 구현할 수 있습니다. 그러나 AngularJS 방법은 무엇입니까? 서비스를 사용하십니까?

따라서이 질문에 귀착됩니다.

AngularJS 모범 사례에 따라 컨트롤러에서 분리 된 모델을 어떻게 구현합니까?



답변

여러 컨트롤러에서 사용할 수있는 것을 원하면 서비스를 사용해야합니다. 다음은 간단한 예입니다.

myApp.factory('ListService', function() {
  var ListService = {};
  var list = [];
  ListService.getItem = function(index) { return list[index]; }
  ListService.addItem = function(item) { list.push(item); }
  ListService.removeItem = function(item) { list.splice(list.indexOf(item), 1) }
  ListService.size = function() { return list.length; }

  return ListService;
});

function Ctrl1($scope, ListService) {
  //Can add/remove/get items from shared list
}

function Ctrl2($scope, ListService) {
  //Can add/remove/get items from shared list
}


답변

현재 DCI는 아니지만이 패턴을 시도하고 있습니다.이 서비스는 고전적인 서비스 / 모델 분리 (웹 서비스와 통신하는 서비스 (모델 CRUD) 및 객체 속성 및 메소드 정의 모델)를 제공합니다.

모델 객체가 자체 속성에서 작동 하는 메소드가 필요할 때 마다이 패턴 만 사용한다는 점에 유의하십시오 . 개선 된 getter / setter와 같은 모든 곳에서 사용됩니다. 나는 모든 서비스에 대해 체계적으로 이것을 옹호 하지 않습니다 .

편집 :이 패턴은 “앵귤러 모델은 평범한 오래된 자바 스크립트 객체”만트라에 어긋날 것이라고 생각했지만,이 패턴은 완벽하게 괜찮습니다.

편집 (2) : 더 명확하게하기 위해 Model 클래스를 사용하여 간단한 게터 / 세터 (예 : 뷰 템플릿에 사용)를 고려합니다. 큰 비즈니스 로직의 경우 모델에 대해 “알고”별도의 서비스를 사용하는 것이 좋지만 모델과는 별도로 유지되며 비즈니스 로직 만 포함합니다. 원하는 경우 “비즈니스 전문가”서비스 계층이라고 부릅니다.

service / ElementServices.js (선언에 Element가 주입되는 방식에 주목)

MyApp.service('ElementServices', function($http, $q, Element)
{
    this.getById = function(id)
    {
        return $http.get('/element/' + id).then(
            function(response)
            {
                //this is where the Element model is used
                return new Element(response.data);
            },
            function(response)
            {
                return $q.reject(response.data.error);
            }
        );
    };
    ... other CRUD methods
}

model / Element.js (angularjs 팩토리를 사용하여 오브젝트 작성 용)

MyApp.factory('Element', function()
{
    var Element = function(data) {
        //set defaults properties and functions
        angular.extend(this, {
            id:null,
            collection1:[],
            collection2:[],
            status:'NEW',
            //... other properties

            //dummy isNew function that would work on two properties to harden code
            isNew:function(){
                return (this.status=='NEW' || this.id == null);
            }
        });
        angular.extend(this, data);
    };
    return Element;
});


답변

Angularjs 문서는 다음과 같이 명확하게 설명합니다.

다른 많은 프레임 워크와 달리 Angular는 모델에 대한 제한이나 요구 사항이 없습니다. 모델에 액세스하거나 모델을 변경하기 위해 상속 할 클래스 나 특수 접근 자 메서드가 없습니다. 모델은 기본, 객체 해시 또는 전체 객체 유형일 수 있습니다. 간단히 말해서 모델은 일반 JavaScript 객체입니다.

AngularJS 개발자 안내서-V1.5 개념-모델

따라서 모델을 선언하는 방법은 귀하에게 달려 있습니다. 간단한 자바 스크립트 객체입니다.

나는 개인적으로 Angular Services를 사용하지 않을 것입니다.


답변

DCI는 패러다임이므로 언어를 지원하는 DCI 또는 지원하지 않는 앵귤러 JS 방법이 없습니다. 소스 변환을 기꺼이 사용하려는 경우 JS는 DCI를 잘 지원하고 그렇지 않은 경우 몇 가지 단점이 있습니다. 다시 DCI는 C # 클래스가 서비스를 제공한다고 말하는 것보다 의존성 주입과 더 이상 관련이 없습니다. 따라서 angulusJS를 사용하여 DCI를 수행하는 가장 좋은 방법은 DCI를 JS 방식으로 수행하는 것입니다. 이는 DCI가 처음에 공식화되는 방식과 매우 비슷합니다. 소스 변환을 수행하지 않으면 역할 메소드가 컨텍스트 외부에서도 오브젝트의 일부가되기 때문에 소스 변환을 완전히 수행 할 수 없지만 이는 일반적으로 메소드 주입 기반 DCI의 문제점입니다. fullOO.info 를 보면 DCI에 대한 권위있는 사이트에서는 메소드 주입을 사용하는 루비 구현을 보거나 볼 수 있습니다. 여기 DCI에 대한 자세한 정보를. 그것은 주로 RUby 예제와 관련이 있지만 DCI는 그와 무관합니다. DCI의 핵심 중 하나는 시스템의 기능과 시스템의 기능이 분리되어 있다는 것입니다. 따라서 데이터 객체는 꽤 멍청하지만 컨텍스트 역할 방법의 역할에 바인딩되면 특정 동작을 사용할 수 있습니다. 역할은 단순히 식별자이며, 그 식별자를 통해 객체에 액세스 할 때 역할 방법을 사용할 수 있습니다. 역할 객체 / 클래스가 없습니다. 방법 주입을 통해 역할 방법의 범위는 정확히 설명 된 것과 같지 않지만 가깝습니다. JS 컨텍스트의 예는 다음과 같습니다.

function transfer(source,destination){
   source.transfer = function(amount){
        source.withdraw(amount);
        source.log("withdrew " + amount);
        destination.receive(amount);
   };
   destination.receive = function(amount){
      destination.deposit(amount);
      destination.log("deposited " + amount);
   };
   this.transfer = function(amount){
    source.transfer(amount);
   };
}


답변

AngularJS의 모델에 대한이 기사는 다음과 같은 도움이 될 수 있습니다.

http://joelhooks.com/blog/2013/04/24/modeling-data-and-state-in-your-angularjs-application/


답변

다른 포스터에서 언급했듯이 Angular는 모델링을위한 기본 클래스를 제공하지 않지만 여러 기능을 유용하게 제공 할 수 있습니다.

  1. RESTful API와 상호 작용하고 새 객체를 만드는 방법
  2. 모델 간 관계 설정
  3. 백엔드에 유지하기 전에 데이터 유효성 검증 실시간 오류 표시에도 유용
  4. 불필요한 HTTP 요청을 방지하기위한 캐싱 및 지연 로딩
  5. 상태 머신 후크 (저장, 업데이트, 생성, 신규 등의 전후)

이 모든 것들을 잘 수행하는 하나의 라이브러리는 ngActiveResource ( https://github.com/FacultyCreative/ngActiveResource입니다. )입니다. 전체 공개-이 라이브러리를 작성했으며 여러 엔터프라이즈 규모 응용 프로그램을 작성하는 데 성공적으로 사용했습니다. 잘 테스트되었으며 Rails 개발자에게 친숙한 API를 제공합니다.

우리 팀과 저는이 라이브러리를 계속해서 적극적으로 개발하고 있으며, 더 많은 Angular 개발자들이이 라이브러리에 기여하고 전투 테스트하는 것을보고 싶습니다.


답변

오래된 질문이지만 Angular 2.0의 새로운 방향을 제시하면 주제가 그 어느 때보 다 관련성이 있다고 생각합니다. 가장 좋은 방법은 가능한 한 특정 프레임 워크에 대한 종속성이 거의없는 코드를 작성하는 것입니다. 직접적인 가치를 추가하는 프레임 워크 특정 부분 만 사용하십시오.

현재 Angular 서비스는 차세대 Angular에 적용 할 수있는 몇 가지 개념 중 하나 인 것 같습니다. 따라서 모든 논리를 서비스로 이동하는 일반적인 지침을 따르는 것이 현명 할 것입니다. 그러나 Angular 서비스에 직접 의존하지 않아도 분리 된 모델을 만들 수 있다고 주장합니다. 필요한 종속성과 책임만으로 자체 포함 된 객체를 만드는 것이 좋습니다. 또한 자동화 된 테스트를 수행 할 때 삶을 훨씬 쉽게 만듭니다. 단일 책임은 요즘 번거로운 일이지만 많은 의미가 있습니다!

다음은 객체 모델을 돔에서 분리하는 데 도움이되는 패턴의 예입니다.

http://www.syntaxsuccess.com/viewarticle/548ebac8ecdac75c8a09d58e

핵심 목표는 뷰 에서처럼 단위 테스트에서 사용하기 쉬운 방식으로 코드를 구성하는 것입니다. 이를 달성하면 현실적이고 유용한 테스트를 작성할 수있는 좋은 위치에 있습니다.