AOP vs funkcijas

Aspektorientētā programmēšana (AOP) ir diezgan populāra. Motivācija tam ir labi izskaidrota attiecīgajā Wikipedia rakstā.

AOP ir lielisks rīks patiesi globālām koncepcijām, piemēram, mežizstrāde, kas tieši neietekmē koda loģiku. Tomēr problēmas ar AOP parādās, ja to izmanto vairāk ar uzņēmējdarbību saistītām lietām, piemēram, autorizācijai. Šiem lietojumprogrammas aspektiem jābūt skaidri redzamiem attiecīgajā kodā, lai izstrādātājs, lasot atbilstošo avota kodu, nekavējoties redzētu, vai tie tiek pareizi ieviesti. AOP balstīti ietvari parasti to atrisina, izmantojot metožu anotācijas:

@RequireRole (Role.Admin) // skaidri redzams aspekts
jautri atjauninātUserPermissions (…) {
    // loģika šeit
}

Tomēr no lasāmības viedokļa tas daudz neatšķiras no funkcionālās pieejas vienai un tai pašai problēmai, izmantojot @RequireRole anotācijas funkcijas funkciju NõRole:

jautri atjauninātUserPermissions (…) {
    needRole (Role.Admin) // izmet SecurityException
    // loģika šeit
}

Turklāt funkcionālās pieejas priekšrocība ir tā, ka tā palielina arī sarežģītākas atļauju pārbaudes, piemēram, analizē metodes parametrus, pirms izlemj, kura lietotāja loma ir nepieciešama.

Tas pats attiecas uz citiem aspektiem, piemēram, darījumiem. Diemžēl ir sarežģīti un neērti funkcionāli attēlot Java sarežģītas koncepcijas, kas rada mākslīgu popularitāti AOS ietvariem Java ekosistēmā.

Tomēr Kotlin tā nav. Kotlinā, nevis Java līdzīga pieeja darījumiem ar AOP un šādas anotācijas:

@Transactional
jautri atjauninātUserPermissions (…) {
    // loģika šeit
}

Funkcionāli pārrakstot, tas ir tikpat labi salasāms un tīrs:

jautri updateUserPermissions (…) = darījuma {
    // loģika šeit
}

Šīs funkcionālās pieejas priekšrocība ir tā, ka jūs vienmēr varat IDT noklikšķināt uz darījuma funkcijas deklarācijas un uzreiz redzēt, ko tieši tā dara, kas parasti nav iespējams ar kādu no parasti izmantotajiem AOP ietvariem. Pat ja navigāciju uz aspekta avota kodu nodrošina IDE spraudnis, tā loģikas atšifrēšanai ir nepieciešamas zināšanas par atsevišķu bagātinātu API un / vai konvencijām.

Diemžēl šī funkcionālā nomaiņa, kas balstīta uz anotācijām balstītā AOP Kotlinā, netiek nekavējoties piemērota gadījumam, kad vienai un tai pašai funkcijai tiek piemēroti vairāki aspekti kā cirtaini stiprinājumi, un ievilkums sāk sakrāties:

jautri updateUserPermissions (…) = reģistrēts {
    darījumu {
        // loģika šeit
    }
}

Risinājums ir izveidot kombinētu augstākas kārtas funkciju, lai vairāku aspektu lietošanas vieta būtu tīra.

jautri updateUserPermissions (…) = loggedTransactional {
    // loģika šeit
}

Vēl viens funkcionālās pieejas trūkums ir tāds, ka tādiem aspektiem kā reģistrēšana ir nepieciešama piekļuve metodes parametriem. Parasti tie ir tieši pieejami tradicionālajos AOP ietvaros, izmantojot īpašas API, taču Kotlin krājuma funkcijas tām nevar viegli piekļūt. Tātad, lai reāli attēlotu reālās dzīves mežizstrādes aspektu tīri funkcionālā veidā, joprojām ir jāuzraksta ievērojams daudzums katlu plākšņu koda:

jautri updateUserPermissions (params: Params) =
    reģistrēts ("updateUserPermissions ($ params)")) {
        // loģika šeit
    }

Šis apsvērums joprojām padara AOP par izvēles rīku reģistrēšanai, ja jums tas patiešām ir nepieciešams visā pasaulē un konsekventi savā lietojumprogrammā, taču es uzskatu, ka AOP izmantošana tādiem aspektiem kā autorizācija un darījumi ir ļaunprātīga izmantošana, ņemot vērā bagātīgās funkcionālās abstrakcijas, kas ir pieejamas Kotlīnā. . Funkcijas šos aspektus apstrādā labāk un tīrāk.

Noslēgumā es teiktu, ka turpmāki funkcionālās abstrakcijas uzlabojumi, lai nodrošinātu vēl labāku AOP nomaiņu, varētu būt daudzsološs kotlīņu valodas turpmākās attīstības vektors. Java balstītie AOP ietvari parasti ir specifiski JVM un tiek uztverti kā zināma necaurspīdīga maģija, savukārt Kotlin funkcionālās abstrakcijas patiešām ir vairāku platformu un lietotājiem pārskatāmas.