AngularJS : 디자인 패턴 이해


147

AngularJS의 책임자 인 Igor Minar가 작성한 이 글 의 맥락에서 :

MVC vs MVVM vs MVP . 많은 개발자들이 토론과 논쟁에 시간과 시간을 할애 할 수있는 논란의 여지가있는 주제입니다.

몇 년 AngularJS와 내용은 가까운 MVC (또는 오히려 그것의 클라이언트 측의 한 변형)에 있지만, 시간과 많은 리팩토링 및 API 개선 덕분에 끝난, 그것은 이제 더 가까이 MVVM - $ 범위 객체는 간주 될 수 있는 ViewModel 되고있는 Controller 라고하는 함수로 장식되었습니다 .

프레임 워크를 분류하여 MV * 버킷 중 하나에 넣을 수 있다는 장점이 있습니다. 프레임 워크를 사용하여 빌드되는 응용 프로그램을 나타내는 멘탈 모델을보다 쉽게 ​​만들 수 있으므로 개발자가 API를보다 편안하게 사용할 수 있습니다. 또한 개발자가 사용하는 용어를 설정하는 데 도움이 될 수 있습니다.

말하지만, 개발자들이 MV * 넌센스에 대해 논쟁하는 데 시간을 낭비하는 것보다 잘 디자인되고 관심사 분리를 따르는 킥-어스 앱을 만드는 것이 좋습니다. 그리고 이런 이유로 나는 AngularJSMVW 프레임 워크로 선언합니다 – Model-View-Whatever . " 어떤 것이든지 당신을 위해 일하는 것 " 의미하는 곳 .

Angular는 프리젠 테이션 로직과 비즈니스 로직 및 프리젠 테이션 상태를 멋지게 분리 할 수있는 유연성을 제공합니다. 하루 종일 중요하지 않은 사항에 대한 열띤 토론보다는 생산성과 응용 프로그램 유지 보수성을 향상시키는 데 사용하십시오.

클라이언트 측 애플리케이션에서 AngularJS MVW (Model-View-Whatever) 디자인 패턴을 구현하기위한 권장 사항 또는 지침이 있습니까?


MV * 넌센스에 대해 논쟁하는 데 시간을 낭비하는 것보다
Shirgill Farhan

1
단어 클래스 디자인 패턴을 따르기 위해 Angular가 필요하지 않습니다.
usefulBee

답변:


223

귀중한 많은 소스 덕분에 AngularJS 앱에서 구성 요소를 구현하기위한 일반적인 권장 사항이 있습니다.


제어 장치

  • 컨트롤러는 모델과 뷰 사이의 중간 계층 이어야합니다 . 가능한 한 얇게 만드십시오 .

  • 컨트롤러에서 비즈니스 로직피하는 것이 좋습니다 . 모델로 이동해야합니다.

  • 컨트롤러는 메소드 호출 (자식이 부모와 통신을 원할 때 가능) 또는 $ emit , $ broadcast$ on 메소드를 사용하여 다른 컨트롤러와 통신 할 수 있습니다 . 전송 및 브로드 캐스트 된 메시지는 최소한으로 유지해야합니다.

  • 컨트롤러는 프리젠 테이션 또는 DOM 조작을 신경 쓰지 않아야합니다 .

  • 중첩 된 컨트롤러 하십시오 . 이 경우 상위 컨트롤러는 모델로 해석됩니다. 대신 공유 서비스로 모델을 주입하십시오.

  • 컨트롤러의 범위프리젠 테이션 모델 디자인 패턴 과 같이 뷰와 모델 을 바인딩 하고 뷰 모델
    캡슐화 하는 데 사용해야합니다 .


범위

로 처리 범위 읽기 전용 템플릿에쓰기 전용 가능한 컨트롤러 . 범위의 목적은 모델이 아니라 모델을 참조하는 것입니다.

양방향 바인딩 (ng-model)을 수행 할 때 범위 속성에 직접 바인딩하지 않아야합니다.


모델

AngularJS의 모델은 service에 의해 정의 된 싱글 톤 입니다.

모델은 데이터와 디스플레이를 분리하는 훌륭한 방법을 제공합니다.

모델은 일반적으로 정확히 하나의 종속성 (일부 형태의 이벤트 이미 터 형태, ​​일반적으로 $ rootScope )을 가지며 테스트 가능한 도메인 로직을 포함하므로 단위 테스트의 주요 후보입니다 .

  • 모델은 특정 단위의 구현으로 간주되어야합니다. 단일 책임 원칙을 기반으로합니다. Unit은 실세계에서 단일 엔티티를 나타내고 데이터 및 상태의 관점에서 프로그래밍 세계에서 기술 할 수있는 관련 로직의 자체 범위를 담당하는 인스턴스입니다 .

  • 모델은 애플리케이션의 데이터를 캡슐화 하고 해당 데이터에 액세스하고 조작 할 수있는 API 를 제공 해야합니다.

  • 모델은 휴대가능 하여 유사한 응용 분야로 쉽게 운반 할 수 있습니다.

  • 모델에서 단위 로직을 분리하면보다 쉽게 ​​찾고 업데이트하고 유지 관리 할 수 ​​있습니다.

  • 모델은 전체 응용 프로그램에 공통적 인보다 일반적인 글로벌 모델의 방법을 사용할 수 있습니다.

  • 구성 요소 결합을 줄이고 단위 테스트 가능성유용성을 높이는 데 의존하지 않는 경우 의존성 주입을 사용하여 모델에 다른 모델의 구성을 피하십시오 .

  • 모델에서 이벤트 리스너를 사용하지 마십시오. 단일 책임 원칙 측면에서 테스트하기가 더 어렵고 일반적으로 모델을 종료합니다.

모델 구현

모델이 데이터 및 상태 측면에서 일부 논리를 캡슐화해야하므로 멤버에 대한 액세스를 구조적으로 제한해야하므로 느슨한 결합을 보장 할 수 있습니다.

AngularJS 애플리케이션에서이를 수행하는 방법은 팩토리 서비스 유형을 사용하여 정의하는 것 입니다. 이를 통해 개인 속성 및 메서드를 매우 쉽게 정의 할 수 있으며 공개적으로 액세스 가능한 항목을 한 곳에서 반환하여 개발자가 실제로 읽을 수 있습니다.

:

angular.module('search')
.factory( 'searchModel', ['searchResource', function (searchResource) {

  var itemsPerPage = 10,
  currentPage = 1,
  totalPages = 0,
  allLoaded = false,
  searchQuery;

  function init(params) {
    itemsPerPage = params.itemsPerPage || itemsPerPage;
    searchQuery = params.substring || searchQuery;
  }

  function findItems(page, queryParams) {
    searchQuery = queryParams.substring || searchQuery;

    return searchResource.fetch(searchQuery, page, itemsPerPage).then( function (results) {
      totalPages = results.totalPages;
      currentPage = results.currentPage;
      allLoaded = totalPages <= currentPage;

      return results.list
    });
  }

  function findNext() {
    return findItems(currentPage + 1);
  }

  function isAllLoaded() {
    return allLoaded;
  }

  // return public model API  
  return {
    /**
     * @param {Object} params
     */
    init: init,

    /**
     * @param {Number} page
     * @param {Object} queryParams
     * @return {Object} promise
     */
    find: findItems,

    /**
     * @return {Boolean}
     */
    allLoaded: isAllLoaded,

    /**
     * @return {Object} promise
     */
    findNext: findNext
  };
});

새 인스턴스 만들기

의존성 주입을 중단하기 시작하고 라이브러리가 특히 제 3 자에게 어색하게 작동하므로 새로운 기능을 반환하는 팩토리를 사용하지 마십시오.

동일한 작업을 수행하는 더 좋은 방법은 팩토리를 API로 사용하여 getter 및 setter 메소드가 첨부 된 오브젝트 콜렉션을 리턴하는 것입니다.

angular.module('car')
 .factory( 'carModel', ['carResource', function (carResource) {

  function Car(data) {
    angular.extend(this, data);
  }

  Car.prototype = {
    save: function () {
      // TODO: strip irrelevant fields
      var carData = //...
      return carResource.save(carData);
    }
  };

  function getCarById ( id ) {
    return carResource.getById(id).then(function (data) {
      return new Car(data);
    });
  }

  // the public API
  return {
    // ...
    findById: getCarById
    // ...
  };
});

글로벌 모델

일반적으로 이러한 상황을 피하고 모델을 올바르게 설계하여 컨트롤러에 주입하여보기에 사용할 수 있도록하십시오.

특히 일부 방법은 응용 프로그램 내에서 전역 접근성을 필요로합니다. 이를 가능하게하기 위해 $ rootScope 에서 ' common '속성을 정의 하고 애플리케이션 부트 스트랩 동안 commonModel에 바인딩 할 수 있습니다 .

angular.module('app', ['app.common'])
.config(...)
.run(['$rootScope', 'commonModel', function ($rootScope, commonModel) {
  $rootScope.common = 'commonModel';
}]);

모든 글로벌 메소드는 ' 공통 '속성 내에 있습니다. 이것은 일종의 네임 스페이스 입니다.

그러나 $ rootScope에 직접 메소드를 정의하지 마십시오 . 이로 인해 뷰 범위 내에서 ngModel 지시문과 함께 사용 하면 예기치 않은 동작 이 발생할 수 있으며 일반적으로 범위가 흩어지고 범위 메서드가 문제를 재정의합니다.


자원

리소스를 사용하면 다른 데이터 소스 와 상호 작용할 수 있습니다 .

single-responsibility-principle을 사용하여 구현해야합니다 .

특히 HTTP / JSON 엔드 포인트에 재사용 가능한 프록시입니다.

모델에 리소스가 주입되어 데이터를 전송 / 검색 할 수 있습니다.

자원 구현

RESTful 서버 측 데이터 소스와 상호 작용할 수있는 자원 오브젝트를 작성하는 팩토리입니다.

리턴 된 자원 오브젝트에는 하위 레벨 $ http 서비스와 상호 작용할 필요없이 상위 레벨 작동을 제공하는 조치 메소드가 있습니다.


서비스

모델과 리소스는 모두 서비스 입니다.

서비스는 독립적 이며 느슨하게 결합 된 독립적 인 기능 단위입니다.

서비스는 Angular가 서버 측에서 클라이언트 측 웹 앱으로 가져 오는 기능으로, 오랫동안 서비스가 일반적으로 사용되었습니다.

Angular 앱의 서비스는 의존성 주입을 사용하여 서로 연결된 대체 가능한 객체입니다.

Angular는 다양한 유형의 서비스와 함께 제공됩니다. 각각 자체 사용 사례가 있습니다. 자세한 내용은 서비스 유형 이해를 읽으십시오 .

애플리케이션에서 서비스 아키텍처의 기본 원칙 을 고려 하십시오.

일반적으로 웹 서비스 용어 에 따르면 :

서비스는 제공자 엔티티 및 요청자 엔티티의 관점에서 일관된 기능을 형성하는 태스크를 수행하는 기능을 나타내는 추상 자원입니다. 사용하려면 구체적인 제공자 에이전트가 서비스를 실현해야합니다.


클라이언트 측 구조

일반적으로 응용 프로그램의 클라이언트 쪽은 모듈 로 분할됩니다 . 각 모듈은 하나의 단위 로 테스트 할 수 있어야합니다 .

유형이 아닌 기능 / 또는 기능 에 따라 모듈을 정의하십시오 . 자세한 내용은 Misko의 프레젠테이션 을 참조하십시오.

모듈 구성 요소는 일반적으로 컨트롤러, 모델, 뷰, 필터, 지시문 등과 같은 유형별로 그룹화 될 수 있습니다.

그러나 모듈 자체는 재사용 가능 하고 전송 가능 하며 테스트 가능 합니다.

개발자가 코드의 일부와 모든 종속 항목을 찾는 것이 훨씬 쉽습니다.

자세한 내용 은 Large AngularJS 및 JavaScript 응용 프로그램의 코드 구성을 참조 하십시오.

폴더 구조의 예 :

|-- src/
|   |-- app/
|   |   |-- app.js
|   |   |-- home/
|   |   |   |-- home.js
|   |   |   |-- homeCtrl.js
|   |   |   |-- home.spec.js
|   |   |   |-- home.tpl.html
|   |   |   |-- home.less
|   |   |-- user/
|   |   |   |-- user.js
|   |   |   |-- userCtrl.js
|   |   |   |-- userModel.js
|   |   |   |-- userResource.js
|   |   |   |-- user.spec.js
|   |   |   |-- user.tpl.html
|   |   |   |-- user.less
|   |   |   |-- create/
|   |   |   |   |-- create.js
|   |   |   |   |-- createCtrl.js
|   |   |   |   |-- create.tpl.html
|   |-- common/
|   |   |-- authentication/
|   |   |   |-- authentication.js
|   |   |   |-- authenticationModel.js
|   |   |   |-- authenticationService.js
|   |-- assets/
|   |   |-- images/
|   |   |   |-- logo.png
|   |   |   |-- user/
|   |   |   |   |-- user-icon.png
|   |   |   |   |-- user-default-avatar.png
|   |-- index.html

각도 응용 프로그램 구조화의 좋은 예는 angular -app에 의해 구현됩니다 -https : //github.com/angular-app/angular-app/tree/master/client/src

이것은 현대 응용 프로그램 생성기에서도 고려됩니다-https: //github.com/yeoman/generator-angular/issues/109


5
"컨트롤러에서 비즈니스 로직을 피하는 것이 좋습니다. 모델로 이동해야합니다." 그러나 공식 문서에서 "일반적으로 컨트롤러는 너무 많은 일을 시도해서는 안됩니다. 단일 뷰에 필요한 비즈니스 로직 만 포함해야합니다." 우리도 같은 얘기를하고 있습니까?
op1ekun

3
컨트롤러를 뷰 모델로 취급합니다.
Artem Platonov

1
+1. 여기 좋은 조언이 있습니다! 2. 불행히도의 예 searchModel는 재사용 성 조언을 따르지 않습니다. constant서비스 를 통해 상수를 가져 오는 것이 더 좋습니다 . 3. 여기에 무슨 의미가 있는가? :Try to avoid having a factory that returns a new able function
Dmitri Zaitsev

1
또한 객체의 prototype속성을 덮어 쓰면 상속이 중단되고 대신 사용할 수 있습니다.Car.prototype.save = ...
Dmitri Zaitsev

2
@ChristianAichinger, 이것은 JavaScript 프로토 타입 체인의 특성에 관한 것입니다. JavaScript 프로토 타입 체인은 object양방향 바인딩 표현식에서를 사용하여 정확한 속성이나 setter함수에 쓰도록합니다 . 스코프의 직접 속성을 사용하는 경우 ( 점없이 ) 프로토 타입 체인에 쓸 때 새로 생성 된 속성을 사용하여 원하는 대상 속성을 숨길 위험이 있습니다. 이것은 Misko의 프레젠테이션
Artem Platonov에서

46

나는 당신이 제공 한 인용에서 볼 수 있듯이 Igor가 이것을 받아들이는 것은 훨씬 더 큰 문제의 빙산의 일각에 불과하다고 생각합니다.

MVC 와 그 파생물 (MVP, PM, MVVM)은 단일 에이전트 내에서 모두 훌륭하고 멋지지만 서버-클라이언트 아키텍처는 모든 목적을 위해 2- 에이전트 시스템이며 사람들은 종종 이러한 패턴에 너무 집착하여 당면한 문제는 훨씬 더 복잡합니다. 이러한 원칙을 준수하려고 시도하면 실제로 결함이있는 아키텍처가됩니다.

이것을 조금씩 해봅시다.

지침

견해

각도 컨텍스트 내에서보기는 DOM입니다. 지침은 다음과 같습니다.

하다:

  • 현재 범위 변수 (읽기 전용)
  • 컨트롤러에 조치를 요청하십시오.

하지 마십시오 :

  • 어떤 논리라도 넣으십시오.

유혹적이고 짧고 무해한 것처럼 보입니다.

ng-click="collapsed = !collapsed"

Javascript 파일과 HTML 파일을 모두 검사하는 데 필요한 시스템 작동 방식을 이해하려면 모든 개발자에게 의미가 있습니다.

컨트롤러

하다:

  • 범위에 데이터를 배치하여 뷰를 '모델'에 바인딩하십시오.
  • 사용자 조치에 응답하십시오.
  • 프리젠 테이션 로직 다루기.

하지 마십시오 :

  • 모든 비즈니스 로직을 다루십시오.

마지막 지침의 이유는 컨트롤러가 엔티티가 아닌 뷰의 자매이기 때문입니다. 재사용이 불가능합니다.

지시문은 재사용 할 수 있지만 지시문도 뷰에 대한 자매 (DOM)입니다.

물론 뷰는 개체를 나타내지 만 다소 구체적인 경우입니다.

다시 말해, 컨트롤러는 프리젠 테이션에 초점을 두어야합니다. 비즈니스 로직을 도입하면 부풀어지고 관리하기 어려운 컨트롤러가 생길뿐만 아니라 우려 분리 원칙을 위반하는 것입니다.

따라서 Angular의 컨트롤러는 실제로 Presentation Model 또는 MVVM에 가깝습니다 .

컨트롤러가 비즈니스 로직을 다루지 않으면 누가해야합니까?

모델이란 무엇입니까?

고객 모델은 종종 부분적이고 부실합니다

오프라인 웹 응용 프로그램 또는 매우 간단한 응용 프로그램 (엔티티가 거의 없음)을 작성하지 않는 한 클라이언트 모델은 다음과 같습니다.

  • 부분
    • 페이지 매김의 경우와 같이 모든 엔티티를 갖지 않습니다.
    • 또는 페이지 매김의 경우와 같이 모든 데이터가 없습니다
  • 부실 -시스템에 둘 이상의 사용자가있는 경우 언제든지 클라이언트가 보유한 모델이 서버가 보유한 모델과 동일한 지 확인할 수 없습니다.

실제 모델은 지속되어야합니다

기존 MCV에서는이 모델 만 유지 됩니다. 우리가 모델에 관해 이야기 할 때마다, 그것들은 어느 시점에서 지속되어야합니다. 클라이언트는 임의로 모델을 조작 할 수 있지만 서버 왕복이 성공적으로 완료 될 때까지 작업이 완료되지 않습니다.

결과

위의 두 가지 사항은주의해야합니다. 고객이 보유한 모델에는 부분적이고 간단한 비즈니스 로직 만 포함될 수 있습니다.

따라서, 그것은 사용 소문자로, 클라이언트의 컨텍스트 내에서, 아마도 현명하다 M- 정말 그래서 MVC , MVPMVVM을 . 큰 M것은 서버입니다.

비즈니스 로직

비즈니스 모델에 대한 가장 중요한 개념 중 하나는 두 가지 유형으로 세분화 할 수 있다는 것입니다 (세 번째 뷰 비즈니스 는 다른 날의 이야기이므로 생략합니다 ).

  • 도메인 로직 -일명 엔터프라이즈 비즈니스 규칙 - 애플리케이션 독립적 인 로직. 예를 들어, 모델에 firstNamesirName속성을 지정하면 getter와 같은 getFullName()애플리케이션 독립형으로 간주 될 수 있습니다.
  • 응용 프로그램 논리 - 응용 프로그램 별 규칙응용 프로그램 비즈니스 규칙 . 예를 들어, 오류 점검 및 처리.

클라이언트 컨텍스트 내에서이 두 가지 모두 '실제'비즈니스 로직아니라는 점을 강조하는 것이 중요합니다. 클라이언트의 중요한 부분 만 처리합니다. 응용 프로그램 논리 (도메인 논리가 아님)는 서버와의 통신 및 대부분의 사용자 상호 작용을 촉진해야합니다. 도메인 로직은 주로 소규모, 엔티티 별 및 프리젠 테이션 중심입니다.

문제는 여전히 남아 있습니다-각도 응용 프로그램 내에서 어디로 던지십니까?

3 대 4 레이어 아키텍처

이 모든 MVW 프레임 워크는 3 개의 레이어를 사용합니다.

세 서클.  내부-모델, 중간 컨트롤러, 외부 모습

그러나 클라이언트와 관련하여 두 가지 근본적인 문제가 있습니다.

  • 모델이 부분적이고 부실하며 지속되지 않습니다.
  • 애플리케이션 로직을 넣을 곳이 없습니다.

이 전략의 대안은 4 계층 전략입니다 .

내부에서 외부로 4 개의 원-엔터프라이즈 비즈니스 규칙, 응용 프로그램 비즈니스 규칙, 인터페이스 어댑터, 프레임 워크 및 드라이버

여기서 중요한 것은 응용 프로그램 비즈니스 규칙 계층 (사용 사례)이며, 종종 클라이언트에게 잘못 적용됩니다.

이 계층은 Martin Fowler가 작업 스크립트 서비스 계층 이라고 부르는 인터랙 터 (Uncle Bob)에 의해 구현됩니다 .

구체적인 예

다음 웹 애플리케이션을 고려하십시오.

  • 이 응용 프로그램에는 페이지 매김 된 사용자 목록이 표시됩니다.
  • 사용자는 '사용자 추가'를 클릭하십시오.
  • 사용자 세부 정보를 채우는 양식으로 모델이 열립니다.
  • 사용자가 양식을 작성하고 제출을 누르십시오.

이제 몇 가지 일이 발생해야합니다.

  • 양식은 고객이 확인해야합니다.
  • 요청은 서버로 보내 져야한다.
  • 오류가 있으면이를 처리해야합니다.
  • 사용자 목록은 페이지 매김으로 인해 업데이트가 필요할 수도 있고 필요하지 않을 수도 있습니다.

우리는이 모든 것을 어디에 던지나요?

아키텍처에를 호출하는 컨트롤러가 포함 된 $resource경우이 모든 것이 컨트롤러 내에서 발생합니다. 그러나 더 나은 전략이 있습니다.

제안 된 솔루션

다음 다이어그램은 Angular 클라이언트에 다른 애플리케이션 로직 계층을 추가하여 위의 문제를 해결하는 방법을 보여줍니다.

4 개의 상자-DOM은 Controller를 가리키며, 이는 Application Resource를 가리키며 $ resource를 가리 킵니다.

따라서 컨트롤러 사이에 $ resource에 레이어를 추가합니다.이 레이어는 그것을 interactor 라고 부릅니다 .

  • A는 서비스 . 사용자의 경우이라고 할 수 있습니다 UserInteractor.
  • 이 방법에 대응 제공하는 경우를 사용하여 , 애플리케이션 로직을 캡슐화 .
  • 그것은 제어 서버에 만든 요청을. 이 계층은 자유 형식 매개 변수를 사용하여 $ resource를 호출하는 컨트롤러 대신 서버에 대한 요청이 도메인 논리가 작동 할 수있는 데이터를 반환하도록합니다.
  • 반환 된 데이터 구조를 도메인 로직 프로토 타입으로 장식합니다 .

그리고 위의 구체적인 예의 요구 사항과 함께 :

  • 사용자는 '사용자 추가'를 클릭하십시오.
  • 컨트롤러는 인터랙 터에게 빈 사용자 모델을 요청합니다. validate()
  • 제출시 컨트롤러는 모델 validate()메소드를 호출합니다 .
  • 실패하면 컨트롤러가 오류를 처리합니다.
  • 성공하면 컨트롤러는 인터랙 터를 createUser()
  • 인터랙 터는 $ resource를 호출합니다
  • 응답하면 인터랙 터는 오류를 컨트롤러에 위임하여 오류를 처리합니다.
  • 응답에 성공하면 인터랙 터는 필요한 경우 사용자 목록이 업데이트되도록합니다.

따라서 AngularJS는 MVW (W는 무엇이든)로 정의됩니다. 컨트롤러 (모든 비즈니스 로직 포함) 또는 뷰 모델 / 프리젠 테이션 (비즈니스 로직없이 뷰를 채우는 코드 만 있음)을 BL로 선택할 수 있기 때문에 별도의 서비스? 내가 맞아?
BAD_SEED

가장 좋은 답변입니다. 4 계층 각도 앱의 GitHub에 대한 실제 사례가 있습니까?
RPallas

1
@RPallas, 아니요. (시간이 있었으면 좋겠습니다). 우리는 현재 '애플리케이션 로직'이 경계 인터랙 터 인 아키텍처를 시도하고 있습니다. 컨트롤러와 컨트롤러 사이의 리졸버와 뷰 로직이있는 뷰 모델. 우리는 여전히 실험 중이므로 장단점의 100 %가 아닙니다. 그러나 일단 완료되면 어딘가에 블로그를 작성하기를 바랍니다.
Izhaki

1
@heringer 기본적으로 도메인 엔터티를 나타내는 OOP 구문 모델을 소개했습니다. 컨트롤러가 아닌 리소스와 통신하는 것이이 모델입니다. 도메인 논리를 캡슐화합니다. 컨트롤러는 모델을 호출하고 차례로 모델을 호출합니다.
Izhaki

1
@ alex440 아니요. 지금 두 달이 지났지 만이 주제에 관한 심각한 블로그 게시물이 제 손가락 끝에 있습니다. 크리스마스가 다가오고 있습니다.
Izhaki

5

Artem의 답변에서 훌륭한 조언과 비교할 때 사소한 문제이지만 코드 가독성 측면 return에서 변수를 정의 할 때 코드에서 앞뒤로 이동하는 것을 최소화하기 위해 객체 내부에서 API를 완전히 정의하는 것이 가장 좋습니다 .

angular.module('myModule', [])
// or .constant instead of .value
.value('myConfig', {
  var1: value1,
  var2: value2
  ...
})
.factory('myFactory', function(myConfig) {
  ...preliminary work with myConfig...
  return {
    // comments
    myAPIproperty1: ...,
    ...
    myAPImethod1: function(arg1, ...) {
    ...
    }
  }
});

return객체가 "너무 붐비는"것처럼 보이면 서비스가 너무 많이 수행하고 있다는 표시입니다.


0

AngularJS는 전통적인 방식으로 MVC를 구현하지 않고 오히려 MVVM (Model-View-ViewModel)에 더 가까운 것을 구현합니다. Model-> 우리가 알고 있듯이 angular의 모델은 평범한 오래된 JS 객체이거나 응용 프로그램의 데이터 일 수 있습니다.

뷰-> angularJS의 뷰는 지시문이나 명령어 또는 바인딩을 적용하여 angularJS에 의해 구문 분석되고 컴파일 된 HTML입니다. 여기서 요점은 각도입니다. 입력은 단순한 HTML 문자열 (innerHTML)이 아닙니다. 브라우저로 작성된 DOM입니다.

ViewModel-> ViewModel은 실제로 angularJS의 경우 뷰와 모델 사이의 바인더 / 브리지이며 $ scope이며 Controller를 사용하여 $ scope를 초기화하고 확장합니다.

대답을 요약하고 싶다면 angularJS 응용 프로그램에서 $ scope가 데이터를 참조하면 Controller가 동작을 제어하고 View는 Controller와 상호 작용하여 레이아웃을 처리하여 그에 따라 동작합니다.


-1

이 문제에 대해 명확하게 설명하기 위해 Angular는 정규 프로그래밍에서 이미 경험했던 다양한 디자인 패턴을 사용합니다. 1) 모듈과 관련하여 컨트롤러 또는 지침, 공장, 서비스 등을 등록 할 때. 여기서는 전역 공간에서 데이터를 숨기고 있습니다. 어떤 모듈 패턴 입니다. 2) 각도가 범위 변수를 비교하기 위해 더티 검사를 사용하는 경우 여기에서 관찰자 패턴을 사용합니다 . 3) 컨트롤러의 모든 부모 자식 범위는 프로토 타입 패턴을 사용합니다 . 4) 서비스를 주입하는 경우 팩토리 패턴을 사용합니다 .

전반적으로 다른 알려진 디자인 패턴을 사용하여 문제를 해결합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.