Seperti yang dikatakan klasik, "Saya tahu bahwa cepat atau lambat kita akan sampai pada hal itu". Jadi saya, setelah bertahun-tahun hidup tenang dengan Symfony pada pekerja dan ReactPHP dalam proyek hewan peliharaan, cocok dengan pembuatan kerangka kerja saya.
Tapi ceritanya baru saja dimulai. Dan bagaimana dengan mereka yang gagasannya telah berkembang ke tingkat produksi, tetapi tetap menjadi solusi khusus? Saya menemukan seseorang yang mengetahui jawaban atas pertanyaan ini - penulis dan pengembang utama kerangka kerja berorientasi aspek.
Halo! Berikut adalah transkrip parsial dari podcast saya "Between the Brackets" - wawancara dengan orang-orang menarik dari dunia PHP. Dalam episode ini, kita akan berbicara dengan Alexander Lisachenko, pembuat kerangka kerja berbasis Java yang sering kali menggunakan Google.
Jika Anda lebih nyaman mendengarkan, ada contoh yang lebih teknis dalam versi audio .
Kemungkinan besar, tidak semua dari kita menemukan hal seperti AOP - pemrograman berorientasi aspek di PHP. Dan Sasha terjebak dan membuat keputusan sendiri untuk menyeret benda ini ke aplikasi kami.
Sergey Zhuk, Skyeng dan DriftPHP: Mari kita mulai dari awal - apa itu AOP dan masalah apa yang dipecahkannya?
Alexander Lisachenko, PHP Russia dan Go! AOP : Idenya bukanlah hal baru. AOP ditemukan di Xerox untuk mengatasi masalah fungsionalitas ujung ke ujung. Dan di dunia Java, pendekatan ini secara aktif digunakan untuk memeriksa fungsionalitas seperti otorisasi, otentikasi, caching, logging, fitur pengelolaan matikan, pemutus sirkuit.
Berbagai macam tugas dapat diselesaikan dengan menggunakan aspek. Mari gunakan contoh:
- . , . , , . β , .
- β . , - . , , - .
- : , , . Xdebug β .
- , β circuit breaker, , , , .
Jika kita melihat aplikasinya, kita akan melihat bahwa fragmen kode seperti itu ditemukan di mana-mana dan sangat tidak nyaman untuk bekerja dengannya. Yang disebut fungsionalitas ujung ke ujung ini ada di seluruh aplikasi.
Dan tidak ada cara yang baik untuk mengelompokkannya menggunakan pemrograman berorientasi objek tradisional.
Ya, tentu saja, kita dapat mencoba menggunakan dekorator - tetapi jika kita ingin kelas kita menerapkan antarmuka yang sama, kita perlu menerapkan atau membuat setiap metode langsung di dekorator. Artinya, memiliki dekorator untuk semua kelas yang ingin kita cache.
Sergey Zhuk: Oke, saya mengerti. Tetapi untuk ini sudah ada beberapa ekstensi PECL, bahkan kerangka kerjanya. Mengapa Anda memutuskan untuk menulis sendiri?
Aleksandr Lisachenko: Ya, Anda telah mencatat dengan benar bahwa sudah ada sejumlah solusi. Tapi, menurut saya, mereka memiliki kekurangan yang signifikan.
Beberapa solusi mencoba mengubah kode sumber, segera menyematkan saran khusus ke dalam kelas tertentu - potongan kode yang diulang dari satu metode ke metode lainnya. Dengan xlt mereka menghasilkan satu kelas dan memasukkan semuanya ke dalamnya. Secara umum, lebih baik tidak membuka kode ini sama sekali)
Kelas solusi kedua adalah ekstensi. Sebagai contoh, PHP AOP - pada prinsipnya cukup fungsional, tetapi ia melakukan semuanya saat runtime. Ketika kami menambahkan satu saran, sepertinya semuanya baik-baik saja, tetapi kami menambahkan yang kedua dan kecepatan mulai menurun secara proporsional. Oleh karena itu, pada sepuluh tip, aplikasi mulai melambat, dan jika kita menambahkan beberapa lusin lagi, itu semua - waktu habis dijamin.
Entah bagaimana, kebetulan saya melihat bagaimana sebuah ide yang disebut "filter" diimplementasikan dalam kerangka kerja Lithium - prototipe middleware modern seperti itu. Kami membuat beberapa poin yang sebelumnya diketahui dalam program, dan filter dapat diterapkan ke poin ini - sebelum dan sesudah panggilan. Ide ini tampak sangat menarik sehingga saya memutuskan untuk menulis aplikasi dan mengekspos fungsionalitas lintas sektor menggunakan filter ini. Saya mulai mempelajari bagaimana hal itu dilakukan di Jawa.
Dan saya menyadari bahwa di PHP tidak mungkin untuk menerapkannya begitu saja. Itu mungkin momen paling menarik.
Secara umum, seluruh proses penulisan kerangka kerja adalah perjuangan terus-menerus dengan "tidak" dan "tidak mungkin". Tampaknya saya tidak dapat menerapkan hal-hal mendasar, tetapi lebih menarik untuk mengatasinya.
Sergey Zhuk: Saya tidak bisa tidak bertanya. Mengapa Go AOP? Rilis pertama kerangka kerja berlangsung pada awal 2013, bahasa Go sudah ada saat itu, dan Anda memiliki PHP. Ini seperti dengan JavaScript dan Java, bukan?)
Alexander Lisachenko: Komitmen pertama tidak sama dengan awal pengembangan lokal di komputer saya) Saat itu, Go belum populer. Saya googling, melihat bahwa ada semacam pengembangan internal oleh Google, itu menempati beberapa ceruk sendiri ... Dan tidak mengganggu.
Saya memilih nama kerangka itu sendiri, berdasarkan keinginan internal, bisa dikatakan,. Dari go - "go", "forward", "do".
Sergei Zhuk: Lalu tidak ada pemikiran untuk mengganti nama?
Alexander Lisachenko: Secara resmi, nama lengkap Go! AOPPHP . Namun seiring berjalannya waktu, saya menghapus PHP, karena dimasukkan melalui Composer dan sepertinya tidak ada gunanya membuat minyak berminyak.
Sejauh ini, saya mendapatkan beberapa lalu lintas tambahan: banyak orang yang mencoba menemukan AOP untuk Go akhirnya menggunakan kerangka kerja PHP saya. Mungkin di beberapa versi mendatang perlu ditekankan bahwa ini bukan tentang Go. Sejauh ini, belum ada yang memulai masalah di GitHub terkait hal ini. Tidak ada keluhan dari Google atau komunitas juga.
Sergey Zhuk: Ok, bagaimana ini diterapkan dari sudut pandang kode klien? Di sini saya memiliki aplikasi, misalnya, di Laravel, ada beberapa integrasi dengan layanan pihak ketiga, saya ingin mencatat panggilan ini.
Alexander Lisachenko: Sudah ada modul khusus untuk Laravel. Dia akan memasukkan semua yang Anda butuhkan ke dalam sistem, mengkonfigurasinya. Anda perlu menulis aspek - ini akan menjadi layanan, Anda akan menandainya dan secara otomatis akan diambil oleh inti AOP. Pada aspek yang paling, Anda perlu memahami di titik aplikasi mana, di kelas dan metode mana, Anda ingin mengimplementasikan fungsionalitas caching. Anda dapat menentukan metode secara langsung dengan tanda tangan (tetapi opsinya tidak terlalu fleksibel, sehingga metode dapat diubah namanya, tetapi tetap dalam aspek), atau Anda dapat menandai metode dengan anotasi. Opsi kedua lebih fleksibel: jika perlu untuk menyimpan cache, cukup tandai sebagai dapat disimpan dalam cache, dan mesin akan melakukan cache untuk Anda dan memanggil callback, yang ada di kode aspek.
Pada saat memuat kelas Anda dengan Composer, framework akan mengintervensi dan memeriksa apakah ada versi yang siap untuk kelas ini di cache dengan aspek yang disematkan. Jika ada, dia segera mengembalikannya, tidak ada pemeriksaan tambahan yang dilakukan saat runtime. Jika tidak ada cache, maka kita akan membangun pohon AST, dan di atas pohon ini kita akan membuat kelas refleksion, tetapi tanpa memuatnya ke dalam memori. Dan saat ini kita dapat mengubahnya sesuai keinginan kita, yaitu menenun kode aspek di dalam kelas ini.
Saya tidak suka mie dalam aspek dan memutuskan untuk membagi kelas menjadi dua bagian.
Kelas asli tetap tidak berubah - hanya namanya yang berubah. Dan kelas kedua muncul dengan nama kelas asli, yang memperluas yang utama dan dapat, jika perlu, mengganti beberapa metode.
Mengapa, sebenarnya, warisan. Ada banyak metode dan kelas yang mengembalikan contoh kembali. Misalnya, metode rantai terkenal: kita memanggil metode rantai pada objek, mengembalikan $ this. Jika kita mendekorasi, maka panggilan pertama akan berfungsi, tetapi aspeknya akan jatuh. Bersamaan dengan pewarisan, memori disimpan - karena masih ada satu contoh di memori.
Sergey Zhuk: Semua arsitektur ini, mesin, apakah Anda sudah memikirkan semuanya sejak awal atau?
Alexander Lisachenko:Ada banyak hal yang harus diselami. Misalnya, saya tidak begitu paham dengan AST, jadi saya mempelajari banyak disiplin ilmu yang berkaitan dengan deskripsi tata bahasa. Dan jika Anda melihat kerangka kerja saya, maka pointcut saya mengimplementasikan tata bahasa lengkap dan memiliki sintaksnya sendiri - ini mungkin salah satu pencapaian hebat. Anda dapat menulis ekspresi kompleks sebanyak yang Anda suka, misalnya, "panggilan metode publik apa pun yang tidak dimulai dengan aset, mengimplementasikan antarmuka ini dan itu di dalam ruang ini dan itu".
Saya juga menggali banyak hal di dalam PHP. Saya melihat di mana ekstensi itu, bagaimana mereka bekerja. Di suatu tempat saya duduk dengan pembuatan profil, mengoptimalkan sesuatu, disetel: tetapi sekarang, jika Anda hanya menghubungkan kerangka AOP, aplikasi akan menambahkan beberapa milidetik 7-10 lucu. Pada tingkat respons klasik 100 milidetik, bahkan tidak terlihat bahwa kerangka besar seperti itu disebut di bawah tenda.
Sergey Zhuk: Apakah ada kekhususan untuk kerangka kerja PHP yang berbeda?
Alexander Lisachenko: Pada prinsipnya, kerangka kerja AOP dianggap sebagai perpustakaan umum yang tidak memerlukan pengikatan khusus. Syarat utamanya adalah menggunakan Composer. Tapi itu tidak terlalu bersahabat dengan Symfony.
Ada terlalu banyak sihir hitam di Symfony, dan ketika itu berbenturan dengan sihir dalam kerangka saya, yang terkuat, Symfony, menang.
Secara umum, ide dari Symfony adalah adanya sebuah wadah, Anda perlu menggunakannya dan tidak menciptakan kerangka kerja terpisah untuk mendapatkan fungsionalitas AOP. Ada cara yang lebih tradisional: sertakan bundel - katakanlah, JMS AOP atau bundel Symfony Go AOP saya .
Sergey Zhuk: Mari kita bicara tentang komunitas dan pesaing. Apakah kamu punya mereka
Alexander Lisachenko: Sejauh yang saya tahu, ada tiga kerangka kerja sekarang. Ada Ray. Aop, tetapi tidak akan berguna untuk produksi, karena tidak tahu bagaimana bekerja secara efektif dengan Komposer. Penulis Flow menyajikan kerangka kerja mereka dengan saus yang kami miliki AOP di sini. Ada sesuatu yang lain di samping kerangka kerja Cina, ada tali di atas Swoole, tetapi ini semua di tingkat ekstensi, dan ekstensi tidak boleh dilewatkan oleh admin untuk alasan keamanan. Saya masih memiliki kerangka kerja klasik, dan tetap hidup di versi apa pun.
Adapun komunitas. Mungkin hanya ada empat orang yang memahami dan memahami dengan baik: saya, satu orang dari Serbia, dan dua orang dari pekerjaan saya sebelumnya yang berpartisipasi dalam semua yang saya lakukan. Secara alami, saya menunjukkan kepada mereka semua perkembangan dan hasil saya. Beberapa bulan terakhir, ketika saya berganti pekerjaan, menaruh sedikit usaha dan energi menjadi open source, tetapi ia hidup dan bekerja secara mandiri.
, - Z-Engine β c , , PHP.
Saya berencana, segera setelah waktu luang, untuk terus mengerjakan Z-Engine dan membuat versi kerangka kerja berikutnya, berdasarkan struktur internal bahasa itu sendiri. Ini akan bekerja hampir seperti AspectJ Java. Tujuannya adalah untuk sampai ke sana dengan PHP 8.
Sergey Zhuk: Ini hampir merupakan penulisan ulang framework yang lengkap?
Alexander Lisachenko: Tidak, saya sudah membusuk semuanya. Hanya proses injeksi kode yang berubah: secara harfiah ada beberapa kelas yang bertanggung jawab untuk mengedit kelas tertentu. Dan dalam hal ini, kelas ini tidak akan membuat file di cache dengan struktur yang berbeda, tetapi saat ini pada saat runtime akan mengubah OPcache dan memodifikasi struktur PHP di memori.
Sergey Zhuk: Dan bagaimana sikap umum komunitas PHP terhadap topik ini? Saya menyukai PHP asinkron, yang membuat beberapa orang acuh tak acuh. Bagaimana kabarmu dengan itu?
Alexander Lisachenko: Akan selalu ada orang yang mengatakan bahwa kami dapat melakukan ini tanpa AOP, mengapa kami membutuhkannya dalam aplikasi. Jawaban saya adalah jika Anda tidak bekerja di suatu perusahaan, aspek-aspeknya tidak berguna bagi Anda. Dan jika Anda berpikir bahwa Anda memiliki perusahaan, tetapi Anda memiliki satu layanan dan 2-3 pengembang, ini juga tidak akan bekerja untuk Anda) AOP bekerja dengan baik dalam tim yang terdiri dari beberapa lusin orang, masing-masing menulis dengan gayanya sendiri, ada, biasanya beberapa aplikasi, dan biasanya arsitektur layanan mikro.
Saya tahu pasti bahwa ada sejumlah perusahaan besar yang menggunakan kerangka kerja di rumah: Prancis, Rusia. Kebetulan beberapa pesan dengan rasa syukur tiba di pos: mereka berkata, mereka mengira kami memiliki satu bulan kerja, tetapi mereka menggali kerangka kerja Anda dan menyelesaikan tugas itu dalam beberapa hari. Orang-orang menghemat satu bulan pekerjaan pengembang mereka, itu bagus.
Sergey Zhuk: Apakah Anda melakukan aktivitas pendidikan? Kerangka kerja Anda sudah cukup tua, tetapi saya melihat sekilas tutorial - jarang. Saya pikir jika Anda bertanya kepada sepuluh orang apa AOP itu, sembilan akan mengatakan mereka tidak tahu.
Alexander Lisachenko: Ya, itu benar.
Sergey Zhuk: Meskipun, mungkin bagus kalau mereka tidak tahu?
Alexander Lisachenko:Ini adalah poin yang bisa diperdebatkan) Tapi ada masalah yang saya miliki dan masih saya miliki - ini adalah dokumentasi. Saya tidak suka menulis dokumentasi secara alami. Saya dapat menulis solusi yang keren, saya dapat menemukan beberapa hal yang tidak biasa, perpustakaan, tetapi dengan dokumentasi itu hanya merepotkan.
Bahkan pada suatu saat seorang teman dari Serbia menyarankan kepada saya: ayo kita menulis. Dan bahkan mulai menulisnya, tetapi setelah beberapa saat sekeringnya juga berakhir ... Dan ternyata mereka tidak kaya akan dokumentasi, katakanlah.
Sergey Zhuk: Jadi, seleksi alam? Yang paling gigih, yang mendaki, menggali lebih dalam, mereka menggunakannya ...
Alexander Lisachenko: Ya, dan ini adalah orang-orang yang memiliki level yang cukup agar tidak gagal.
Sergey Zhuk: Apakah Anda pernah menerima umpan balik dari orang-orang yang telah menggunakan kerangka kerja dengan cara yang tidak dapat Anda duga?
Alexander Lisachenko: Ya, ada kasus seperti itu. Misalnya, Mikhail Bodnarchuk, yang menulis AspectMock . Dia mengambil kerangka kerja dan menyadari bahwa dengan itu dia bisa memecahkan masalah mendapatkan metode akhir, kelas, dan bahkan fungsi untuk direndam.
Cerita lain dilontarkan oleh orang-orang yang merefaktor ulang aplikasi lama, dan mereka tidak memiliki tes - secara umum, semuanya klasik. Dengan bantuan kerangka kerja saya, mereka merekam dengan apa setiap metode tertentu dipanggil dan membuat aspek global. Sebelum memanggil semua metode publik di semua kelas dalam folder ini, telah ditulis apa yang dipanggil dan apa yang dikembalikan dengan: tipe apa, nilai apa. Kemudian mereka mulai menjalankan aplikasi ini di bawah beban untuk mendapatkan semua kemungkinan status kode. Mereka mendapat sekumpulan nilai otomatis yang diizinkan untuk setiap metode, dan mengembalikan nilai. Artinya, mereka mengambil snapshot dari seluruh state, dan kemudian mengatur aspek kebalikannya, yang memanggil metode dan memeriksa apakah logikanya telah berubah.
Faktanya, mereka berhasil menerapkan pemfaktoran ulang kode otomatis tanpa menutupinya dengan pengujian.
Ide yang sangat keren sehingga untuk beberapa waktu saya memikirkan tentang cara membuat alat untuk aplikasi lama sehingga saya dapat membekukan semua kelas, melihat dengan apa dan bagaimana mereka dipanggil, dan kemudian, selama pemfaktoran ulang, periksa apakah koneksi yang ada tidak putus. Tetapi untuk mengimplementasikannya dalam beberapa jenis alat yang dapat dialihdayakan belum berhasil.
ps Terima kasih telah membaca dan mendengarkan sampai akhir! Lebih banyak episode podcast dapat ditemukan di sini .