AOP로 특정 문제가 더 우아하게 해결됩니까?


19

Aspect Oriented Programming이라는 아이디어를 접했고 몇 가지 우려가 있습니다.

기본 아이디어는 객체를 사용하여 잘 모듈화되지 않은 크로스 커팅 문제를 해결하고 모듈화하려는 것 같습니다. 그것은 모두 매우 훌륭하고 좋습니다.

그러나 AOP의 구현은 모듈 외부에서 코드를 수정하는 것으로 보입니다. 예를 들어, 특정 객체가 함수에서 매개 변수로 전달 될 때 발생하는 상황을 변경하는 양상이 작성 될 수 있습니다. 이것은 모듈 아이디어와 직접적으로 반대되는 것 같습니다. 해당 모듈 외부에서 모듈의 동작을 수정할 수 없어야합니다. 그렇지 않으면 모듈의 전체 지점이 뒤집 힙니다. 그러나 측면은 정확히 그렇게하는 것 같습니다!

기본적으로 측면은 코드 패치 형식으로 보입니다. 빠른 해킹에 유용 할 수 있습니다. 그러나 일반적인 원칙으로 아마도 당신이하고 싶은 것이 아닙니다. Aspect Oriented Programming은 나쁜 연습을하고 일반적인 디자인 원칙을 세우는 것 같습니다.

AOP가 좋은 습관입니까? AOP를 사용하면 특정 프로그래밍 문제가 더 우아하게 해결됩니까?


아, 유명한 원숭이 패치!
Muad'Dib

1
나는 어조를 개선하기 위해 질문을 편집하고 다시 열기로 투표했습니다.
Robert Harvey

Questio는 다시 물었다 여기에 다른 형태로되어있다 : programmers.stackexchange.com/questions/19344/...
피터 보우

답변:


19

Aspect-Oriented Programming을 사용하면 소프트웨어의 주요 기능과 관련이없는 애플리케이션 또는 라이브러리 전체에서 코드를 불필요하게 산란하지 않고 수행하기 어려운 특정 유형의 프로그래밍을 수행 할 수 있습니다 (예 : 교차 절단 문제). 예를 들면 다음과 같습니다.

  1. 로깅 및 모니터링
  2. 성능 분석
  3. 디버깅 및 추적
  4. 기능 취소
  5. 입력 및 출력의 유효성 검사
  6. 기존 객체의 동작 모핑
  7. 객체 필터
  8. 보안 구현
  9. 거래 관리

이러한 교차 절단 문제를 응용 프로그램의 한 부분으로 제한 한 다음 속성, 메서드 호출 차단 또는 동적 프록시를 통해 코드에서 이러한 기능을 참조함으로써 교차 절단 동작을 캡슐화 할 수 있습니다. 여기에는 캡슐화가 응용 프로그램의 다른 곳에서 제공 할 수있는 모든 이점 (즉, 단일 수정 지점)이 있습니다.

여기서 중요한 점은 AOP가 1) 응용 프로그램 전체에서 공통적 인 동작과 2) 응용 프로그램의 기본 기능의 주변 장치를 캡슐화한다는 것입니다.


7

늦게 게임에 나올 것이지만, 나는이 질문을 우연히 발견 할 수있는 후기 개발자를 위해 이것을 제공합니다.

응용 프로그램이 있다면 난 강력하게 AOP에 대해 권합니다 따라 올바르게 작동하도록하십시오. 측면은 다음과 같이 작동합니다.

  • 조언 (추가 행동)이
  • 결합 지점 (메소드 시작 또는 종료와 같은 추가 코드를 첨부 할 수있는 위치 또는 지정된 이벤트가 트리거되는 위치)
  • ... pointcut (주어진 결합 점이 일치하는지 감지하는 패턴) 패턴이 일치하는 곳

컴퓨터를 오랫동안 사용해온 사람이라면 패턴을 사용한다는 사실을 자세히 살펴볼 수 있습니다. 다음 set은 인수에 관계없이 명명 된 모든 메소드와 일치하는 포인트 컷의 예입니다 .

call(* set(..))

그래서 그것은 상당히 쓸모없는 포인트 컷이며 많은 것들에 조언을 적용하기 때문에 조심스럽게 다루는 것이 권장됩니다.

또는 이름이나 서명에 관계없이 모든 것에 조언을 적용합시다 !

execution(* *(..))

여기에는 많은 힘이 있기 때문에주의해야합니다. 그러나 이것은 측면에 대한 논쟁이 아닙니다. 여기에는 많은 힘이 있고 패턴 일치가 쉽게 어려워 질 수 있으므로주의해야합니다 (좋아하는 검색 엔진을 누르십시오) aop 버그와 재미).

따라서 비교적 안전한 포인트 컷처럼 보이는 것이 있습니다 :

pointcut setter(): target(Point) &&
                   ( call(void setX(int)) ||
                     call(void setY(int)) );

명명 된 setX또는 객체 setYPoint메소드가 발견 되면 명시 적으로 조언을 제공합니다 . 메소드는 ints 만 수신 할 수 있으며 반드시 있어야합니다 void. 꽤 안전 해 보이죠? 그러한 방법이 존재하고 올바른 조언을 적용하면 안전합니다. 그렇지 않다면 너무 나쁘다. 조용히 실패합니다.

예를 들어, 친구는 한 번에 모든 사람이 Java 응용 프로그램을 디버깅하려고 시도했지만 잘못된 데이터를 반환했습니다. 자주 발생하지 않았으며 특정 이벤트 나 데이터와 관련이없는 것으로 보입니다. 스레딩 버그로 테스트 또는 감지하기 어려운 것으로 악명 높았습니다. 결과적으로 메소드를 잠그고 "스레드 안전"으로 만드는 측면을 사용하고 있었지만 프로그래머는 메소드의 이름을 바꾸고 포인트 컷이 해당 메소드와 일치하지 않아 응용 프로그램이 자동으로 중단되었습니다.

따라서 저는 사람들에게 AOP를 사용해야한다면 예외와 같은 측면을 예외와 같은 방식으로 처리해야한다고 말합니다 . 제대로 설계된 시스템에서 아무 문제가 없으면 제거 할 수 있으며 소프트웨어는 여전히 올바르게 작동합니다. 그러나 프로그램의 기능이 AOP에 의존하는 경우 보증되지 않는 취약성을 프로그램에 도입하게됩니다.

따라서 로깅, 디버깅 및 추적은 측면이 아닌 보안에 적합한 동작의 좋은 예입니까? 아니. 스레드 안전? 아니.

AOP에 대한 강력한 대안은 traits를 참조하십시오 . 언어에 볼트로 연결되지 않고 언어에 직접 통합되어 있으며 "특성을 인식하는"IDE가 필요하지 않으며 (도움이 될 수 있지만) 필요한 방법이없는 경우 컴파일 타임 오류가 발생합니다. 특성은 처음부터 문제가 더 잘 정의 되었기 때문에 우려 분리를 처리하는 데 훨씬 더 깔끔한 작업을 수행합니다. 나는 그것들을 광범위하게 사용하며 환상적입니다.


AOP를 핵심 기능에 사용해서는 안된다고 주장하기보다는 메소드 이름에 의존하는 포인트 컷이 나쁜 생각이라고 말하는 것이 더 적절할 수 있습니다. 아마도 잠금 및 동기화가 AOP의 좋은 사용 사례가 아니라고 주장 할 것입니다.
Code Bling

2

실제 솔루션뿐만 아니라 AOP가 유일하고 적절한 솔루션 일 수있는 상황 은 소스 코드에 액세스 할 수없는 경우 입니다. 로깅 교차 절단 문제의 피곤한 예를 사용하려면 다음을 수행하십시오.

사용하는 타사 라이브러리에 제어 흐름을 기록한다고 가정 해 봅시다. 로깅 문으로 완벽하게 계측 된 자체 코드가 있습니다. 그러나이 라이브러리에는 소스가 없으므로 로깅 명령문을 추가 할 수 없습니다. 당신이 있기 때문에 바이트 코드를 가지고, AOP는 악기 제 3 자의 라이브러리 어쨌든 당신을 수 있습니다.

어쨌든 로깅 측면을 작성하는 경우 AOP를 통해 로깅을 자체 코드로 구현하는 것도 고려할 수 있습니다.


로깅은 "흥미로운"것입니다. AOP 로깅으로 "이 매개 변수를 사용하여"및 "종료"이외의 다른 작업을 수행 할 수있는 방법은 무엇입니까?

@Thorbjorn : 로깅 / 디버깅 / 추적은 AOP가 도울 수있는 많은 기능 중 하나 일뿐입니다. 나는 그것을 요점을 설명하기 위해 예로 사용했다. 내가하려고하는 요점은 AOP가 타사 바이트 코드를보다 잘 제어 할 수 있다는 것입니다.
Joseph Tanenbaum

물론 AOP 로깅이 단순히 엑시트 종료 로깅 이상의 기능을 수행 할 수 있는지 알고 싶습니까?

사용하는 AOP 도구에 따라 다르지만 수행 할 수있는 작업에는 제한이 있습니다. 종료 엑시트 로깅을 넘어서는 것이 불가능할 수도 있습니다.
Joseph Tanenbaum
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.