Lập trình hướng đối diện so với lập trình hướng đối tượng


199

Giống như hầu hết các nhà phát triển ở đây và trên toàn thế giới, tôi đã phát triển các hệ thống phần mềm bằng cách sử dụng các kỹ thuật lập trình hướng đối tượng (OOP) trong nhiều năm. Vì vậy, khi tôi đọc rằng lập trình hướng theo khía cạnh (AOP) giải quyết nhiều vấn đề mà OOP truyền thống không giải quyết được hoàn toàn hoặc trực tiếp, tôi dừng lại và nghĩ, liệu nó có thật không?

Tôi đã đọc rất nhiều thông tin cố gắng tìm hiểu các chìa khóa của mô hình AOP này và tôi ở cùng một nơi, vì vậy, tôi muốn hiểu rõ hơn về lợi ích của nó trong phát triển ứng dụng thế giới thực.

Có ai có câu trả lời?


7
Tất cả các câu trả lời đều rất tốt, đây là một trường hợp hoàn hảo cho một câu trả lời được chỉnh sửa trong cộng đồng sẽ kết hợp tất cả chúng. Tất cả đều nói cùng một điều nhưng theo những cách khác nhau và sử dụng các ví dụ khác nhau làm tăng giá trị tổng thể
Vinko Vrsalovic

Câu trả lời:


323

Tại sao "đấu"? Nó không phải là "vs". Bạn có thể sử dụng lập trình Aspect hướng kết hợp với lập trình chức năng, nhưng cũng có thể kết hợp với lập trình hướng đối tượng. Nó không phải là "so với", đó là "Lập trình hướng đối tượng với lập trình hướng đối tượng".

Đối với tôi AOP là một loại "lập trình meta". Mọi thứ mà AOP làm cũng có thể được thực hiện mà không cần nó bằng cách thêm mã. AOP chỉ giúp bạn viết mã này.

Wikipedia có một trong những ví dụ tốt nhất cho lập trình meta này. Giả sử bạn có một lớp đồ họa với nhiều phương thức "set ... ()". Sau mỗi phương thức thiết lập, dữ liệu của đồ họa thay đổi, do đó đồ họa thay đổi và do đó đồ họa cần được cập nhật trên màn hình. Giả sử để sơn lại đồ họa, bạn phải gọi "Display.update ()". Cách tiếp cận cổ điển là giải quyết điều này bằng cách thêm nhiều mã hơn . Cuối mỗi phương thức set bạn viết

void set...(...) {
    :
    :
    Display.update();
}

Nếu bạn có 3 phương thức thiết lập, đó không phải là vấn đề. Nếu bạn có 200 (giả thuyết), thật khó để thêm cái này ở mọi nơi. Ngoài ra, bất cứ khi nào bạn thêm một phương thức thiết lập mới, bạn phải chắc chắn không quên thêm phần này vào cuối, nếu không bạn chỉ tạo ra một lỗi.

AOP giải quyết vấn đề này mà không cần thêm hàng tấn mã, thay vào đó bạn thêm một khía cạnh:

after() : set() {
   Display.update();
}

Và đó là nó! Thay vì tự viết mã cập nhật, bạn chỉ cần nói với hệ thống rằng sau khi đạt đến điểm đặt set (), nó phải chạy mã này và nó sẽ chạy mã này. Không cần cập nhật 200 phương thức, không cần đảm bảo rằng bạn không quên thêm mã này vào một phương thức thiết lập mới. Ngoài ra, bạn chỉ cần một điểm cắt:

pointcut set() : execution(* set*(*) ) && this(MyGraphicsClass) && within(com.company.*);

Điều đó nghĩa là gì? Điều đó có nghĩa là nếu một phương thức được đặt tên là "set *" (* có nghĩa là bất kỳ tên nào có thể theo sau khi đặt), bất kể phương thức nào trả về (dấu sao đầu tiên) hoặc tham số nào (dấu hoa thị thứ ba) đó là phương thức của MyGraphicsClass đây là phương thức lớp là một phần của gói "com.company. *", sau đó đây là một điểm cắt set (). Và mã đầu tiên của chúng tôi cho biết " sau khi chạy bất kỳ phương thức nào là một điểm cắt đặt, hãy chạy mã sau".

Xem làm thế nào AOP thanh lịch giải quyết vấn đề ở đây? Trên thực tế mọi thứ được mô tả ở đây có thể được thực hiện tại thời gian biên dịch. Bộ tiền xử lý AOP chỉ có thể sửa đổi nguồn của bạn (ví dụ: thêm Display.update () vào cuối mỗi phương thức cắt điểm đặt) trước khi tự biên dịch lớp.

Tuy nhiên, ví dụ này cũng cho thấy một trong những nhược điểm lớn của AOP. AOP thực sự đang làm một cái gì đó mà nhiều lập trình viên coi là " Chống mẫu ". Mẫu chính xác được gọi là " Hành động từ xa ".

Hành động ở xa là một mô hình chống (lỗi phổ biến được nhận biết) trong đó hành vi trong một phần của chương trình thay đổi dữ dội dựa trên khó khăn hoặc không thể xác định các hoạt động trong phần khác của chương trình.

Là một người mới tham gia một dự án, tôi có thể chỉ cần đọc mã của bất kỳ phương thức thiết lập nào và xem nó bị hỏng, vì dường như nó không cập nhật màn hình. Tôi không thấy bằng cách chỉ nhìn vào mã của phương thức set, rằng sau khi nó được thực thi, một số mã khác sẽ "được thực thi" một cách kỳ diệu để cập nhật màn hình. Tôi coi đây là một nhược điểm nghiêm trọng! Bằng cách thay đổi phương thức, các lỗi lạ có thể được đưa ra. Hiểu rõ hơn về dòng mã trong đó một số thứ dường như hoạt động chính xác, nhưng không rõ ràng (như tôi đã nói, chúng chỉ hoạt động một cách kỳ diệu ... bằng cách nào đó), thực sự rất khó.

Cập nhật

Chỉ cần làm rõ rằng: Một số người có thể có ấn tượng Tôi đang nói AOP là một cái gì đó xấu và không nên được sử dụng. Đó không phải là những gì tôi đang nói! AOP thực sự là một tính năng tuyệt vời. Tôi chỉ nói "Sử dụng cẩn thận". AOP sẽ chỉ gây ra sự cố nếu bạn trộn lẫn mã thông thường và AOP cho cùng một khía cạnh . Trong ví dụ trên, chúng ta có khía cạnh cập nhật các giá trị của một đối tượng đồ họa và vẽ đối tượng được cập nhật. Thực tế đó là một khía cạnh duy nhất. Mã hóa một nửa của nó là mã thông thường và nửa còn lại của nó là khía cạnh là những gì thêm vấn đề.

Nếu bạn sử dụng AOP cho một khía cạnh hoàn toàn khác, ví dụ để đăng nhập, bạn sẽ không gặp phải vấn đề chống mẫu. Trong trường hợp đó, một người mới tham gia dự án có thể tự hỏi "Tất cả những thông điệp tường trình này đến từ đâu? Tôi không thấy bất kỳ đầu ra nhật ký nào trong mã", nhưng đó không phải là một vấn đề lớn. Những thay đổi anh ta thực hiện đối với logic chương trình sẽ khó phá vỡ cơ sở nhật ký và những thay đổi được thực hiện đối với cơ sở nhật ký sẽ khó phá vỡ logic chương trình của anh ta - những khía cạnh này hoàn toàn tách biệt. Sử dụng AOP để ghi nhật ký có lợi thế là mã chương trình của bạn hoàn toàn có thể tập trung vào làm bất cứ điều gì cần làm và bạn vẫn có thể ghi nhật ký tinh vi, mà không làm cho mã của bạn bị lộn xộn bởi hàng trăm thông điệp tường trình ở khắp mọi nơi. Ngoài ra khi mã mới được giới thiệu, thông điệp nhật ký kỳ diệu sẽ xuất hiện vào đúng thời điểm với đúng nội dung.

Vì vậy, việc sử dụng AOP tốt trong ví dụ của tôi sẽ là luôn ghi nhật ký nếu có bất kỳ giá trị nào được cập nhật thông qua phương thức đã đặt. Điều này sẽ không tạo ra một mô hình chống và hầu như không phải là nguyên nhân của bất kỳ vấn đề.

Người ta có thể nói, nếu bạn có thể dễ dàng lạm dụng AOP để tạo ra quá nhiều vấn đề, thì đó là một ý tưởng tồi để sử dụng tất cả. Tuy nhiên, công nghệ nào không thể bị lạm dụng? Bạn có thể lạm dụng đóng gói dữ liệu, bạn có thể lạm dụng thừa kế. Khá nhiều công nghệ lập trình hữu ích có thể bị lạm dụng. Hãy xem xét một ngôn ngữ lập trình hạn chế đến mức nó chỉ chứa các tính năng không thể bị lạm dụng; một ngôn ngữ mà các tính năng chỉ có thể được sử dụng như ban đầu chúng được sử dụng. Một ngôn ngữ như vậy sẽ bị hạn chế đến mức không thể tranh cãi nếu nó thậm chí có thể được sử dụng cho lập trình trong thế giới thực.


4
Ghi nhật ký dường như là một ví dụ cụ thể trong đó AOP không dẫn đến Hành động ở khoảng cách xa. Tại thời điểm này, wikipedia là ví dụ về việc sử dụng khía cạnh cho những thứ như kiểm tra bảo mật, điều này thực sự làm cho chương trình trở nên dễ hiểu hơn nhiều.
kizzx2

7
@ kizzx2: Trên thực tế, điểm tuyệt vời khi đăng nhập - đó là ví dụ tốt nhất tôi từng thấy cho đến nay về sức mạnh của AOP, mà không biết nhiều về AOP. Cám ơn vì đã chia sẻ!
sai lầm ngớ ngẩn

@Mecki, ví dụ của bạn được đơn giản hóa quá mức và không phản ánh trường hợp sử dụng chung. Trong ví dụ của bạn, Display.updatekhông có bất kỳ đối số. Điều gì xảy ra nếu chúng ta cần truyền vào các đối số (ví dụ: thông thường một loghàm sẽ yêu cầu messagetham số)? Sau đó, chúng ta có cần thêm rất nhiều mã soạn sẵn để thực hiện theo cách AOP không?
Pacerier

3
@Pacerier Ví dụ của tôi được đơn giản hóa vì SO không phải là một diễn đàn giảng dạy. Tôi chỉ trả lời câu hỏi của người hỏi, có lẽ chi tiết hơn nhiều so với mức cần thiết. Nếu bạn muốn biết thêm về AOP, hãy thử đọc một số tài liệu lập trình viên và nếu bạn có một câu hỏi chi tiết, tại sao không hỏi nó ở đây? Không, không phải trong một bình luận, hãy đi và tạo một câu hỏi mới bởi vì đó là tất cả những gì SO. Tôi chắc chắn ai đó sẽ có thể xua tan nghi ngờ của bạn trong một câu trả lời.
Mecki

2
@Pacerier Xin lỗi, nhưng tôi không thấy quan điểm của bạn. Xem tại đây: stackoverflow.com/a/8843713/15809 Mã này ghi lại mọi cuộc gọi đến mọi phương thức công khai bao gồm tất cả các loại và giá trị của đối số phương thức. Bạn viết chính xác điều này một lần và không có mã soạn sẵn nào được thêm vào bất kỳ phương thức nào, đó chỉ là mã được hiển thị trong câu trả lời.
Mecki

29

biểu đồ định hướng theo khía cạnh cung cấp một cách hay để thực hiện các mối quan tâm xuyên suốt như đăng nhập, bảo mật. Các concers xuyên suốt này là những phần logic phải được áp dụng ở nhiều nơi nhưng thực sự không liên quan gì đến logic kinh doanh.

Bạn không nên xem AOP như một sự thay thế của OOP, hơn nữa là một tiện ích bổ sung tuyệt vời, giúp mã của bạn sạch sẽ hơn, kết nối lỏng lẻo và tập trung vào logic nghiệp vụ. Vì vậy, bằng cách áp dụng AOP, bạn sẽ nhận được 2 lợi ích chính:

  1. Logic cho mỗi mối quan tâm hiện đang ở một nơi, trái ngược với việc bị phân tán khắp nơi trên cơ sở mã.

  2. các lớp sạch hơn vì chúng chỉ chứa mã cho mối quan tâm chính của chúng (hoặc chức năng cốt lõi) và các mối quan tâm thứ cấp đã được chuyển sang các khía cạnh.


27

OOP và AOP không loại trừ lẫn nhau. AOP có thể là sự bổ sung tốt cho OOP. AOP đặc biệt tiện dụng để thêm mã tiêu chuẩn như ghi nhật ký, theo dõi hiệu suất, v.v. vào các phương thức mà không làm tắc nghẽn mã phương thức với mã tiêu chuẩn này.


10

Tôi nghĩ rằng không có câu trả lời chung cho câu hỏi này, nhưng một điều cần lưu ý là, AOP không thay thế OOP mà thêm các tính năng phân rã nhất định giải quyết cái gọi là sự chuyên chế của thành phần chi phối ( 1 ) (hoặc mối quan tâm xuyên suốt).

Nó chắc chắn sẽ giúp ích trong một số trường hợp miễn là bạn kiểm soát các công cụ và ngôn ngữ để sử dụng cho một dự án cụ thể, nhưng cũng thêm một mức độ phức tạp mới về tương tác giữa các khía cạnh và nhu cầu về các công cụ bổ sung như AJDT vẫn hiểu chương trình của bạn.

Gregor Kiczales từng có một bài nói chuyện giới thiệu thú vị về AOP tại Google Tech Talks mà tôi khuyên bạn nên xem: Lập trình hướng theo khía cạnh: Nghiên cứu cấp tiến về mô đun .


8

Trước hết AOP sẽ không thay thế OOP. AOP mở rộng OOP. Các ý tưởng và thực hành của OOP có liên quan. Có một thiết kế đối tượng tốt có lẽ sẽ giúp mở rộng nó với các khía cạnh dễ dàng hơn.

Tôi nghĩ rằng những ý tưởng mà AOP mang lại rất quan trọng. Chúng tôi cần tìm ra cách để thực hiện các mối quan tâm xuyên suốt đối với các lớp khác nhau trong chương trình của bạn mà không phải tự thay đổi các lớp. Nhưng tôi nghĩ rằng AOP cuối cùng sẽ trở thành một phần của các công cụ khác mà chúng ta sử dụng chứ không phải là một công cụ hoặc kỹ thuật riêng biệt. Chúng tôi đã thấy điều này xảy ra.

Một vài ngôn ngữ động như Ruby và Python có cấu trúc ngôn ngữ như mixin giải quyết các vấn đề tương tự. Điều này trông rất giống AOP nhưng được tích hợp tốt hơn trong ngôn ngữ.

Spring và Castle và một vài khung tiêm phụ thuộc khác có các tùy chọn để thêm hành vi vào các lớp mà chúng tiêm. Đây là một cách để thực hiện dệt thời gian chạy và tôi nghĩ rằng điều này có rất nhiều tiềm năng.

Tôi không nghĩ bạn sẽ phải học một mô hình hoàn toàn mới để sử dụng AOP. Các ý tưởng rất thú vị nhưng đang dần được hấp thụ bởi các công cụ và ngôn ngữ hiện có. Chỉ cần thông báo và thử các công cụ này.


1

AOP là một mô hình lập trình mới liên quan đến khái niệm này. Một khía cạnh là một thực thể phần mềm thực hiện một phần phi chức năng cụ thể của ứng dụng.

Tôi nghĩ rằng bài viết này là một nơi tốt để bắt đầu với Lập trình hướng theo khía cạnh: http://www.jaftalks.com/wp/index.php/int sinhtion-to-aspect-oriented-programming /


1

Tôi đến trễ để trả lời câu hỏi này nhưng đây là một trong những chủ đề yêu thích của tôi vì vậy hãy để tôi chia sẻ quan điểm của mình.

OOP chủ yếu được sử dụng để tổ chức logic kinh doanh của bạn trong khi AOP giúp tổ chức những thứ phi chức năng của bạn như Kiểm toán, Ghi nhật ký, Quản lý giao dịch, Bảo mật, v.v.

Bằng cách này, bạn có thể tách rời logic nghiệp vụ của mình bằng logic phi hư cấu giúp mã sạch hơn.

Ưu điểm của rái cá là bạn có thể áp dụng lời khuyên (ví dụ kiểm toán) mà không cần thực hiện bất kỳ giao diện nào mang lại sự linh hoạt cao để sửa đổi mà không cần chạm vào logic nghiệp vụ

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.