AOP супраць функцый
Аспэктна-арыентаванае праграмаванне (AOP) даволі папулярна. Матывацыя да гэтага добра растлумачана ў адпаведным артыкуле Вікіпедыі.

AOP - выдатны інструмент для сапраўды глабальных паняццяў, такіх як пратакаляванне, якія не ўплываюць непасрэдна на логіку кода. Аднак праблемы з AOP выяўляюцца, калі ён выкарыстоўваецца для такіх рэчаў, як аўтарызацыя. Гэтыя аспекты прыкладання павінны быць добра бачныя ў адпаведным кодзе, каб распрацоўшчык мог адразу ўбачыць, ці правільна яны рэалізаваны пры чытанні адпаведнага зыходнага кода. Рамкі, заснаваныя на AOP, звычайна вырашаюць яго, выкарыстоўваючы анатацыі метадаў:
@RequireRole (Role.Admin) // добра бачны аспект вясёлае абнаўленнеUserPermissions (…) { // Логіка тут }
Аднак, з пункту гледжання чытальнасці, ён мала чым адрозніваецца ад функцыянальнага падыходу да той жа праблемы, выкарыстоўваючы функцыю RequRole замест анатацыі @RequireRole:
вясёлае абнаўленнеUserPermissions (…) { RequRole (Role.Admin) // кідае SecurityException // Логіка тут }
Больш за тое, функцыянальны падыход мае перавагу ў тым, што ён таксама павялічвае да больш складаных праверак дазволаў, напрыклад, аналізуючы параметры метаду, перш чым вызначыць, якую ролю карыстальніка патрабуе.
Тое ж тычыцца і іншых аспектаў, такіх як транзакцыі. На жаль, функцыянальна ўяўляць больш складаныя паняцці на Java складана і нязручна, што стварае штучную папулярнасць для АОП у рамках экасістэмы Java.
Аднак гэта не з Катлінам. У Kotlin, замест Java-падыходу да транзакцый з AOP і такіх анатацыяў:
@Transactional вясёлае абнаўленнеUserPermissions (…) { // Логіка тут }
Гэта так жа чытэльна і чыста выглядае, калі перапісана ў функцыянальным парадку:
fun updateUserPermissions (…) = транзакцый { // Логіка тут }
Перавага гэтага функцыянальнага падыходу заключаецца ў тым, што вы заўсёды можаце Ctrl / Cmd + націснуць на дэкларацыю транзакцыйнай функцыі ў IDE і адразу ж паглядзець, што менавіта яна робіць, што звычайна немагчыма ні ў адной з часта выкарыстоўваных рамак AOP. Нават калі навігацыя да зыходнага кода аспекту забяспечваецца плагінам IDE, расшыфроўка яго логікі патрабуе ведаў асобных багатых API і / або канвенцый.
На жаль, гэтая функцыянальная замена для AOP на аснове анатацыі ў Котліне не адразу прыводзіць да таго выпадку, калі да той жа функцыі ўжываюцца некалькі аспектаў, калі фігурныя дужкі і адступы пачынаюць збірацца:
fun updateUserPermissions (…) = прапісаны { транзакцыйны { // Логіка тут } }
Арыентацыя складаецца ў тым, каб стварыць камбінаваную функцыю больш высокага парадку, каб забяспечыць захаванасць сайта з выкарыстаннем некалькіх аспектаў:
fun updateUserPermissions (…) = loggedTransactional { // Логіка тут }
Яшчэ адным недахопам функцыянальнага падыходу з'яўляецца тое, што такія аспекты, як вядзенне рэгістрацыі, маюць патрэбу ў доступе да параметраў метаду. Звычайна яны даступныя непасрэдна ў традыцыйных рамках АОП праз спецыяльныя API, але функцыі Котліна не могуць лёгка атрымаць доступ да іх. Такім чынам, для таго каб рэальна прадставіць аспект рэгістрацыі ў рэальным жыцці чыста функцыянальным спосабам, трэба ўсё-ткі напісаць значную колькасць кодавых пласцін:
fun updateUserPermissions (params: Params) = logged ("updateUserPermissions ($ params)") { // Логіка тут }
Гэта разгляд па-ранейшаму робіць AOP інструментам выбару для рэгістрацыі, калі вам трэба мець яго ва ўсім дадатку глабальна і паслядоўна, але я лічу, што выкарыстанне AOP для такіх аспектаў, як аўтарызацыя і транзакцыі, з'яўляецца злоўжываннем, улічваючы багатыя функцыянальныя абстракцыі, якія даступныя ў Kotlin . Функцыі спраўляюцца з гэтымі аспектамі лепш і чысцей.
У заключэнне я б сказаў, што далейшае ўдасканаленне функцыянальных абстракцый для забеспячэння яшчэ лепшай замены AOP можа стаць перспектыўным вектарам будучай эвалюцыі для мовы Котліна. Якавыя рамкі AOP на аснове Java звычайна характэрныя для JVM і ўспрымаюцца як нейкая непразрыстая магія, у той час як функцыянальныя абстракцыі Kotlin сапраўды крос-платформавыя і празрыстыя для карыстальніка.