Apakah masalah tertentu diselesaikan dengan lebih elegan dengan AOP?

19

Saya telah menemukan ide Pemrograman Berorientasi Aspek, dan saya memiliki beberapa kekhawatiran dengannya.

Gagasan dasarnya adalah bahwa kita ingin mengambil perhatian lintas sektoral yang tidak termodulasi dengan baik menggunakan objek dan memodulasi mereka. Itu semua sangat baik dan baik.

Tetapi implementasi AOP tampaknya seperti memodifikasi kode dari luar modul. Jadi, misalnya, sebuah aspek dapat ditulis yang mengubah apa yang terjadi ketika objek tertentu dilewatkan sebagai parameter dalam suatu fungsi. Ini tampaknya bertentangan langsung dengan ide modul. Saya seharusnya tidak dapat mengubah perilaku modul dari luar modul itu, jika tidak seluruh modul akan terbalik. Tetapi aspek tampaknya melakukan hal itu!

Pada dasarnya, aspek-aspek tampaknya menjadi bentuk tambalan kode. Ini mungkin berguna untuk beberapa peretasan cepat; tetapi, sebagai prinsip umum mungkin itu bukan sesuatu yang ingin Anda lakukan. Bagi saya, Pemrograman Berorientasi Aspek tampaknya menerapkan praktik buruk dan meningkatkan prinsip desain umum.

Apakah AOP praktik yang baik? Apakah masalah pemrograman tertentu diselesaikan dengan lebih elegan dengan AOP?

Winston Ewert
sumber
ahhh, tambalan monyet yang terkenal!
Muad'Dib
1
Saya telah mengedit pertanyaan untuk meningkatkan nadanya, dan memilih untuk membuka kembali.
Robert Harvey
Questio juga telah diminta kembali dalam bentuk yang berbeda di sini: programmers.stackexchange.com/questions/19344/…
Peter Boughton

Jawaban:

19

Pemrograman Berorientasi Aspek memungkinkan untuk melakukan jenis pemrograman tertentu yang sulit dilakukan tanpa perlu menyebarkan kode di seluruh aplikasi atau pustaka Anda yang tidak terkait dengan fungsi utama perangkat lunak Anda (yaitu masalah lintas sektoral). Contohnya termasuk:

  1. Penebangan dan Pemantauan
  2. Analisis kinerja
  3. Debugging dan Tracing
  4. Batalkan Fungsionalitas
  5. Validasi input dan output
  6. Mengubah perilaku objek yang ada
  7. Filter Objek
  8. Implementasi Keamanan
  9. Mengelola transaksi

Dengan membatasi kekhawatiran lintas sektor seperti pada satu bagian aplikasi, dan kemudian merujuk fitur-fitur ini dalam kode melalui atribut, intersepsi pemanggilan metode, atau proksi dinamis, Anda mengizinkan enkapsulasi perilaku lintas sektoral; enkapsulasi ini memiliki semua manfaat (yaitu satu titik modifikasi tunggal) akan memberikan tempat lain di aplikasi Anda.

Poin kunci di sini adalah bahwa AOP merangkum perilaku yang 1) umum di seluruh aplikasi, dan 2) periferal ke fungsionalitas utama aplikasi.

Robert Harvey
sumber
7

Datang terlambat ke permainan, tapi saya menyediakan ini untuk pengembang nanti yang mungkin menemukan pertanyaan ini.

Saya akan sangat menyarankan terhadap AOP jika aplikasi Anda bergantung padanya untuk beroperasi dengan benar. Aspek kerjanya seperti ini:

  • Saran (perilaku tambahan) diterapkan untuk
  • Menggabungkan poin (tempat-tempat di mana kode tambahan dapat dilampirkan, metode mulai atau berakhir, atau ketika suatu peristiwa tertentu memicu)
  • ... di mana titik potong (pola yang mendeteksi apakah titik gabungan yang diberikan cocok) pola cocok

Bagi siapa pun yang sudah lama menggunakan komputer, fakta bahwa pola yang digunakan mungkin sesuatu yang harus diperhatikan. Jadi, inilah contoh titik potong yang cocok dengan metode apa pun yang dinamai setapa pun argumennya:

call(* set(..))

Jadi itu pointcut yang cukup menyapu dan harus jelas bahwa penanganan ini dengan hati-hati disarankan (tidak ada permainan kata-kata) karena Anda menerapkan saran untuk banyak hal.

Atau, mari kita terapkan saran untuk semuanya , terlepas dari nama atau tanda tangan!

execution(* *(..))

Jadi jelas kita harus berhati-hati karena ada banyak daya di sini, tapi ini bukan argumen terhadap aspek - ini argumen untuk hati-hati karena ada banyak daya di sini dan pencocokan pola dapat dengan mudah serba salah (tekan saja mesin pencari favorit Anda untuk aop bug dan bersenang-senang).

Jadi, inilah yang terlihat sebagai titik potong yang relatif aman:

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

Itu secara eksplisit memberikan saran jika metode bernama setXatau setYpada Pointobjek ditemukan. Metode hanya dapat menerima intdan mereka harus void. Terlihat cukup aman, bukan? Nah, itu aman jika metode itu ada dan Anda sudah menerapkan saran yang benar. Jika tidak, terlalu buruk; itu diam-diam gagal.

Sebagai contoh, seorang teman mencoba men-debug aplikasi Java di mana setiap orang sesekali senang, itu akan mengembalikan data yang salah. Itu adalah kegagalan yang jarang terjadi dan tampaknya tidak berkorelasi dengan kejadian atau data tertentu pada khususnya. Itu adalah bug threading, sesuatu yang terkenal sulit untuk diuji atau dideteksi. Ternyata, mereka menggunakan aspek untuk mengunci metode dan membuatnya "thread aman", tetapi seorang programmer mengganti nama metode dan sebuah pointcut gagal mencocokkannya, sehingga menyebabkan kerusakan aplikasi diam-diam.

Jadi, saya memberi tahu orang-orang bahwa jika mereka harus menggunakan AOP, untuk memperlakukan aspek seperti pengecualian: dalam sistem yang dirancang dengan baik dan jika tidak ada yang salah, mereka dapat dihapus dan perangkat lunak masih berfungsi dengan benar. Namun, jika fungsionalitas program tergantung pada AOP, Anda memperkenalkan kerapuhan pada program Anda yang tidak beralasan.

Jadi, logging, debugging dan tracing adalah contoh perilaku yang sempurna untuk aspek, tetapi keamanan? Nggak. Keamanan benang? Nggak.

Untuk alternatif yang lebih baik untuk AOP, lihat ciri-ciri . Alih-alih dibaut ke bahasa, mereka diintegrasikan ke dalamnya secara langsung, tidak perlu IDE "trait aware" (meskipun dapat membantu) dan memiliki kegagalan waktu kompilasi jika metode yang Anda butuhkan tidak ada. Ciri-ciri melakukan pekerjaan yang jauh lebih bersih dalam menangani pemisahan masalah karena masalahnya lebih baik ditentukan sejak awal. Saya menggunakannya secara luas dan mereka luar biasa.

Curtis Poe
sumber
Daripada berargumen bahwa AOP tidak boleh digunakan untuk fungsionalitas inti, mungkin lebih tepat untuk mengatakan bahwa pointcuts yang bergantung pada nama metode adalah ide yang buruk. Saya mungkin berpendapat bahwa penguncian dan sinkronisasi juga bukan kasus penggunaan yang baik untuk AOP.
Kode Bling
2

Satu situasi di mana AOP mungkin menjadi satu-satunya solusi yang layak dan praktis adalah ketika Anda tidak memiliki akses ke kode sumber . Untuk menggunakan contoh lama dari keprihatinan lintas sektoral Penebangan:

Katakanlah Anda ingin mencatat aliran kontrol di perpustakaan pihak ketiga yang Anda konsumsi. Anda memiliki kode Anda sendiri yang sepenuhnya dilengkapi dengan pernyataan logging. Namun, untuk perpustakaan ini Anda tidak memiliki sumbernya, sehingga tidak mungkin untuk menambahkan pernyataan logging Anda. Karena Anda memang memiliki bytecode, AOP memungkinkan Anda untuk instrumen perpustakaan pihak ketiga itu.

Dan jika Anda tetap membuat aspek Logging, Anda sebaiknya mempertimbangkan untuk menerapkan Logging dengan AOP melalui kode Anda sendiri.

Joseph Tanenbaum
sumber
Penebangan adalah untuk hal-hal yang "menarik". Bagaimana Anda bisa melakukan hal lain selain "memasukkan dengan parameter ini" dan "keluar" dengan pendataan AOP?
@Thorbjorn: Logging / debugging / tracing hanyalah salah satu dari banyak area fungsionalitas yang AOP dapat bantu. Saya menggunakannya sebagai contoh untuk menggambarkan poin saya. Poin yang saya coba sampaikan adalah bahwa AOP memberi Anda lebih banyak kontrol atas bytecode pihak ketiga.
Joseph Tanenbaum
tentu, tapi saya benar-benar ingin tahu apakah logging AOP dapat melakukan lebih dari sekadar masuk-keluar logging?
Tergantung pada alat AOP yang Anda gunakan, tetapi pasti ada batasan untuk apa yang dapat Anda lakukan. Mungkin sangat mustahil untuk melampaui logging masuk-keluar.
Joseph Tanenbaum