Leia kõik aegunud funktsiooni kutsujad

Kuidas leida kõik aegunud funktsiooni kutsujad enne selle eemaldamist

Vananenud funktsiooni eemaldamine koodibaasist on kontseptuaalselt üks lihtsamaid asju, mida arendaja teha saab. Kustuta definitsioon, kinnita, et miski seda ei kasuta, tee commit. Praktikas on iga funktsiooni puhul, mis on eksisteerinud piisavalt kaua, et see oleks vanadustatud, samm „kinnita, et miski seda ei kasuta“, see, kus protsess laguneb. Funktsiooni võidakse kutsuda koodist, mis on kirjutatud aastaid tagasi kellegi poolt, kes enam meeskonnas ei ole, repositooriumist, mis saab harva muudatusi, keele või raamistiku abil, mis praegusele meeskonnale ei kuulu. Seda saab kutsuda kaudselt läbi wrapperi, peegelduse või käitusaja lähetusmehhanismi kaudu, mis ei ilmu üheski staatilises kutsumisgraafikus. Sellele võidakse viidata genereeritud koodis, testimise tugiraamistikus või konfiguratsioonifailis, mis selle nime järgi käivitab. Arendaja, kes märgib selle vanadunuks, ja arendaja, kes selle lõpuks eemaldab, ei pruugi sellest midagi teada ilma tööriistata, mis suudab luua täieliku, repositooriumideülese kutsujate inventuuri.

Enne millegi eemaldamist leidke iga helistaja

SMART TS XL loob keelteülese kõnegraafiku, mis tuvastab iga funktsiooni kutsuja enne muudatuse tegemist.

Kliki siia

Selle vale teo hind on kohene ja konkreetne. Mittetäieliku kutsuja tuvastamisega eemaldatud funktsioon põhjustab käitusaja tõrkeid süsteemides, mis sellest endiselt sõltuvad. Ühe juurutusega monoliidis on tõrkepind piiratud. Hajutatud süsteemis, kus on mitu teenust, millest igaüks on juurutatud iseseisvalt, tekivad tõrked kaskaadis: funktsiooni pakkunud teenus värskendatakse, tarbijaid mitte ja tõrked ilmnevad käitusajal tootmises süsteemides, mis võivad kuuluda erinevatele meeskondadele. Suurarvuti keskkonnas, kus COBOL-programmid kutsuvad jagatud utiliidi paragrahve nimepidi, ei pruugi tõrge ilmneda enne konkreetse paketitöö käivitamist, mis võib olla iganädalane või igakuine, muutes puuduva viite tavapäraste testimistsüklite ajal nähtamatuks. Nagu uuriti vananenud koodi haldamise laiemas kontekstis , suurenevad riskid aja jooksul: mittetäielikult eemaldatud aegunud kood on ohtlikum kui alles jäetud aegunud kood, sest eemaldamine loob terviklikkuse illusiooni, samal ajal kui ülejäänud kutsujad jätkavad töötamist definitsiooni vastu, mida enam ei eksisteeri.

See artikkel on praktiline juhend helistajate avastamiseks enne funktsioonide eemaldamist: mida nõuab täielik helistajate inventuur, miks tööriistad, milleni arendajad esimesena haaravad, on struktuurilt ebapiisavad, kuidas erinevat tüüpi helistamissuhted nõuavad erinevaid analüüsimeetodeid ja milline näeb välja tõeline süsteemideülene helistajate loendamine ettevõtte mastaabis koodibaasides, mis segavad keeli, platvorme ja repositooriume.

Miks helistaja leidmine on raskem, kui paistab

Kutsujate avastamise pinnataseme versioon on tuttav igale arendajale: paremklõpsake IDE-s funktsiooni nimel, valige „Leia kõik viited” või „Kuva kutsehierarhia” ja vaadake tulemused üle. See toimib usaldusväärselt ühe IDE eksemplari laaditud projekti ulatuses. Niipea kui koodibaas ulatub sellest ulatusest välja, muutuvad tulemused mittetäielikuks viisil, mis pole väljundis nähtav. IDE ei näita, milliseid kutsujaid ta ei leidnud, kuna ta ei indekseerinud neid sisaldavaid repositooriume. Arendaja näeb tulemuste komplekti, mis näib olevat täielik, ja jätkab vastavalt.

See on kutsujate avastamise struktuurne probleem ulatuslikul kasutamisel: tööriistad, mida arendajad kõige ladusamalt kasutavad, on piiratud nende indekseerimisulatusega ning suurtes, hajutatud ja mitmekeelsetes süsteemides hõlmab see ulatus vaid murdosa kohtadest, kus antud funktsiooni võidakse kutsuda. Arendaja usaldus tulemuste täielikkuse vastu on pöördvõrdeline otsingu tegeliku täielikkusega. Väikeses, ühes keeles koodibaasis on IDE-kõnede hierarhia tõeliselt usaldusväärne. Ettevõtte süsteemis, mis hõlmab mitut repositooriumi, keelt ja juurutuskeskkonda, on see süstemaatiliselt eksitav. Nagu koodi entroopia ja refaktoriseerimisriski kontekstis analüüsiti , võivad pärandmoodulid sõltuda aegunud liidestest, samas kui uuemad teenused kutsuvad endiselt algselt varasemate keskkondade jaoks loodud rutiine ja just need süsteemidevahelised kutsumissuhted on need, mida IDE-ga piiratud otsing ei näe.

Helistaja tuvastamise ebaõnnestumise konkreetsete põhjuste mõistmiseks tuleb uurida iga peamist kõnetüüpi: otsekõned, kaudsed kõned, keelteülesed kutsumised ja dünaamilised dispetšerkõned. Igaüks neist ebaõnnestub erinevatel põhjustel ja nende õigeks lahendamiseks on vaja erinevaid analüüsitehnikaid.

Otsekõned üle hoidla piiride

Otsekõned on kõige lihtsam kõnetüüp: üks funktsioon kutsub teist funktsiooni nimepidi. Ühe repositooriumi piires saavad IDE-d nendega usaldusväärselt hakkama. Repositooriumi piiride üleselt analüüs ebaõnnestub, kuna IDE indekseerimine ei ulatu üle piiri. Kui repositoorium A defineerib jagatud utiliidifunktsiooni ja repositooriumid B, C ja D impordivad selle ning kutsuvad selle välja, näeb iga repositooriumi IDE ainult oma indekseeritud ulatuses toimuvaid kõnesid.

See mitme hoidla kutsumismuster on mikroteenuste arhitektuurides pigem norm kui erand, kus jagatud teegid avaldatakse pakettidena ja neid tarbitakse kümnete teenuste vahel. Teegi hooldaja, kes jagatud paketis funktsiooni aegunuks tunnistab, peab teadma, millised tarbivad teenused seda endiselt kutsuvad. Nende IDE ei tea tarbijate kohta midagi. Paketihaldur teab, millised teenused paketist sõltuvad, kuid mitte seda, millist konkreetset funktsiooni paketis iga teenus kutsub. Vastendamine olekust „see teenus kasutab selle paketi versiooni X” olekuseni „see teenus kutsub seda konkreetset aegunud funktsiooni” nõuab iga tarbija lähtekoodi indekseerimist ja kutse lahendamist konkreetse funktsiooni definitsioonini.

Kaudsed kõned: ümbrised, delegaadid ja fassaadid

Funktsiooni ei saa selle tarbijad otse kutsuda. Seda saab kutsuda wrapper-funktsiooni kaudu, mis pakub täiendavat logimist, veakäsitlust või parameetrite teisendamist. Selle saab määrata delegaadile või funktsiooni pointerile ja kutsuda välja delegaadi kaudu. See võib olla registreeritud teenuseregistris või plugin-raamistikus ja kutsuda nimepidi välja dispetšeri mehhanismi kaudu. Kõigil neil juhtudel annab aegunud funktsiooni kõnede otsene otsing mittetäieliku tulemuse, kuna tegelikud kutsujad kutsuvad wrapperit või dispetšerit, mitte aegunud funktsiooni ennast.

Ümbrise vahendatud kutsumine on eriti levinud suurtes koodibaasides, kus läbilõikavad probleemid, nagu logimine, autoriseerimine ja uuesti proovimise loogika, on ümbrisemustrite kaudu kihistatud põhifunktsioonide ümber. Logimisutiliidi poolt mähitud aegunud funktsiooni kutsub sisuliselt iga ümbrise kutsuja, mitte ükski kood, mis sisaldab aegunud funktsiooni nime. Nende kutsujate tuvastamine nõuab ümbrise jälgimist: logimisutiliit kutsub aegunud funktsiooni ja iga logimisutiliidi kutsuja on seega aegunud funktsiooni kaudne kutsuja. See rekursiivne kutsumisgraafi läbimine eristab põhjalikku kutsujate inventuuri pinnataseme viiteotsingust.

Vaatleme tüüpilist Java näidet, kus aegunud meetodile pääseb juurde delegeerimiskihi kaudu:

Java

// Deprecated in the core service
@Deprecated
public BillingResult calculateLegacyFee(Account account) {
    // original implementation
}

// Facade that delegates; not visible as a direct caller in a simple reference search
public BillingResult computeFee(Account account) {
    return calculateLegacyFee(account);  // indirect caller
}

// Actual consumer; calls computeFee, unaware of the underlying deprecated method
public void processMonthlyBilling(List<Account> accounts) {
    accounts.forEach(a -> computeFee(a));  // two hops from the deprecated function
}

Otsing „Leia kõik viited” calculateLegacyFee Tulu computeFee ainsa helistajana. See ei vasta processMonthlyBilling, mis on aegunud käitumise tegelik tarbija. Täielik helistajate inventuur nõuab kõnegraafi läbimist ülesvoolu läbi computeFee et tuvastada iga tee, mis lõpuks aegunud meetodit kutsub.

Keeleülesed kutsumised

Keelteülesed kõned on kategooria, kus standardsed kutsujate avastamise tööriistad kõige täielikumalt läbi kukuvad. Kui Java teenus kutsub COBOL-programmi nime järgi vahetarkvara kihi kaudu, kui Pythoni skript kutsub salvestatud protseduuri, mis mähib aegunud funktsiooni, või kui JCL-töö kutsub programmi selle PROGNAME järgi, mis kutsub sisemiselt aegunud lõiku, siis ükski neist seostest ei ilmu ühegi keele kutsumisgraafikus. Iga keele tööriistad näevad ainult oma poolt kutsumisest.

Suurarvutikeskkondades on keeltevahelised kõned struktuursed ja laialt levinud. JCL-töövoog määrab käivitatava COBOL-programmi nime. COBOL-programm kutsub lõike ja alamprogramme nime järgi. Koopiateekides määratletud utiliidilõigud on jagatud paljude programmide vahel. Kui koopiateekis olev lõik on aegunud, nõuab kõigi kutsujate leidmine COBOL-kõnede seoste (millised programmid hõlmavad koopiateeki ja millised kutsuvad lõiku), JCL-i kutsumissuhete (millised tööd neid programme kutsuvad) ja kõigi keeltevaheliste liideste (Java või SQL, mis nende programmidega suhtlevad) mõistmist. Ükski tööriist ei hõlma kõiki neid seoseid. Nagu uuriti pärandsüsteemide staatilise analüüsi analüüsis , ei näe tänapäevaste keskkondade jaoks loodud staatilise analüüsi tööriistad täielikku pilti sellest, kuidas pärandprogramme käivitatakse, kutsutakse ja omavahel ühendatakse, kui kutsumissuhted hõlmavad samaaegselt JCL-i, COBOL-i ja süsteemidevahelisi liideseid.

Dünaamiline saatmine ja peegeldus

Mõned kutsujad ei kutsu funktsiooni välja selle lähtekoodis oleva sõnasõnalise nimega, vaid mehhanismi abil, mis lahendab funktsiooni käitusajal: peegeldus Javas või .NET-is, getattr/__call__ Pythonis, hiline sidumine COBOL-is läbi CALL identifier, dünaamiline lähetamine polümorfismi kaudu või stringipõhine kutsumine pluginraamistikes ja konfiguratsioonipõhistes süsteemides. Need kutsujad ei sisalda aegunud funktsiooni nime mingil kujul, mida staatiline analüüs saaks usaldusväärselt tuvastada.

Konfiguratsioonifail, mis määrab funktsiooni nime stringina, laaditakse käitusajal ja mida kasutatakse funktsiooni kutsumiseks peegelduse kaudu, on kutsuja, mis ei ilmu kusagil üheski lähtekoodi analüüsis. Pluginate raamistik, mis tuvastab ja kutsub esile registreeritud käitlejaid liidese abil, on kutsuja, mis ilmub kõnegraafikus ainult kutsununa lähetusmehhanismile, mitte kutsununa ühelegi konkreetsele käitlejale. Nende kutsujate tuvastamine nõuab dünaamiliste lähetusmustrite leidmiseks staatilise analüüsi, tegelike kutsumiste jälgimiseks käitusaja jälgimise ning konfiguratsiooni ja registreerimisloogika käsitsi kontrollimise kombinatsiooni, mis määrab, millistele funktsioonidele ülesanded suunatakse. Nagu arutleti hägustatud ja genereeritud koodi staatilise analüüsi uurimisel , kui täitmisteed ei ole lähtekoodis otse väljendatud, peab staatiline analüüs rekonstrueerima tõenäolised teed struktuurimustrite, mitte otseste tekstiviidete põhjal ning need rekonstruktsioonid nõuavad lähetusmehhanismi enda keeleteadlikku analüüsi.

Mille tööriistade arendajad esimesena kätte saavad ja kus nad peatuvad

Helistaja tuvastamisel kasutatavate tööriistade jaoks on olemas ennustatav jada ning sama ennustatav punkt, kus igaüks neist enam usaldusväärseid tulemusi ei anna. Selle jada mõistmine on oluline, sest iga tööriista väljund näib olevat täielik isegi siis, kui see seda ei ole.

IDE kõnede hierarhia: usaldusväärne ühe projekti piires

IDE kõnehierarhia funktsioonid on kõige loomulikum esimene samm. IntelliJ IDEA, Visual Studio, VS Code ja Eclipse pakuvad kõik mingil kujul „leida kõik kutsujad” või „näita kõnehierarhiat”, mis loetleb rekursiivselt valitud funktsiooni kutsujad praeguse projekti või tööruumi indekseeritud ulatuses. Funktsiooni puhul, mida kasutatakse ainult ühes repositooriumis ja ühes keeles, on need funktsioonid täpsed ja piisavad.

Piirang on ulatuse määramisel selgesõnaline: „indekseeritud ulatuse piires“. Helistajad teistes repositooriumides, teistes keelte käituskeskkondades või teenustes, mis sõltuvad sellest koodist paketihalduri, mitte otsese projektiviite kaudu, jäävad ulatusest välja. IDE ei näita, mida ta ei otsinud. Arendaja saab tulemuste komplekti ja tal puudub ülevaade sellest, kui palju täiendavaid repositooriume on olemas, mida ei indekseeritud, kui paljud neist kasutavad aegunud funktsiooni või kas tulemus „null helistajat“ tähendab tegelikult null helistajat või „null helistajat süsteemi osas, mida see tööriist näeb“.

grep ja tekstiotsing: lai, aga struktuurilt pime

Kui kahtlustatakse, et IDE-otsing on mittetäielik, on järgmine samm tavaliselt tekstiotsing: käsuga grep saadaolevates lähtekoodikataloogides või platvormiotsing GitHubi või GitLabi koodiotsingu kaudu. See laiendab ulatust märkimisväärselt ja leiab kutsujaid ka teistest repositooriumidest, kui need repositooriumid on ligipääsetavad. Struktuuriline probleem seisneb selles, et tekstiotsing leiab stringe, mitte väljakutseid. See tagastab funktsiooni nime iga esinemise, sealhulgas kommentaarid, mis mainivad funktsiooni, dokumentatsioonistringid, logiteated, mis nimetavad funktsiooni silumise eesmärgil, ja stringi literaalid, mis sisaldavad funktsiooni nime, kuid ei kutsu seda välja. Samuti ei leia see kutsujaid, mille puhul funktsiooni nimi erineb otsingustringist: kutsujad aliaste kaudu, osaliselt COBOL-i vastendatud nimede kaudu, kus nimed võivad olla lühendatud, või dünaamilise kutsumise kaudu, kus nimi pannakse käitusajal kokku.

Tekstiotsingu tulemuste komplekt vajab käsitsi filtreerimist, et teha kindlaks, millised esinemised on tegelikud otsingusaidid, millised dokumentatsiooniviited ja millised stringi kokkupõrgetest tulenevad valepositiivsed tulemused. Suures süsteemis on see filtreerimine iseenesest märkimisväärne pingutus ja filtreerimisprotsess ei suuda täielikkust kontrollida: kui otsingutulemus jäi vahele, kuna see kasutas teist nime, ei sisalda filtreeritud tulemuste komplekt väljajätmise kohta mingeid märke.

Kompilaatori hoiatused ja @Deprecated Annotatsioonid

Kaasaegsed programmeerimiskeeled ja tööriistaketid pakuvad aegumise annotatsioonimehhanisme, mis genereerivad hoiatusi aegunud funktsioonide kutsumisel. Java @Deprecated märkus koos -Xlint:deprecation annab kompileerimise ajal hoiatusi kõnekohtades. C#-d [Obsolete] atribuut genereerib ehituse ajal hoiatusi. Go tava nimetada aegunud funktsioone ja dokumenteerida neid godocis ei tekita hoiatusi automaatselt. Need mehhanismid on väärtuslikud, kuid teatud määral piiratud: need toimivad ainult nende kutsujate puhul, kes kompileeruvad sama koodibaasi alusel, milles aegumine on märgitud.

Helistaja, kes kasutab teegi vanemat versiooni, mis on varasem kui @Deprecated annotatsioon, ei saa hoiatust. Helistaja, kes kasutab binaarset artefakti lähtekoodist kompileerimise asemel, ei saa hoiatust. Helistaja teises keeles, mis kutsub läbi keeltevahelise liidese, ei saa hoiatust. Ja mis kõige tähtsam, kompileerimise ajal tekkivad hoiatused on kompilaatori vaate jaoks lokaalsed: need hoiatavad nähtud kõnede eest, mitte teistes repositooriumides asuvate kõnede eest, mis kompileeritakse eraldi. Kompilaatori hoiatuste kasutamine ainsa helistaja avastamise mehhanismina mitme teenusega süsteemis jätab vahele kõik iseseisvalt kompileeruvad helistajad, mis on mikroteenuste arhitektuurides tavaline seisund.

Staatilise analüüsi tööriistad: paremad, kuid piiratud ulatusega

Eesmärgipäraselt loodud staatilise analüüsi tööriistad pakuvad täpsemat helistajate loendit kui IDE-d oma sihtkeele jaoks ja võivad sageli ületada repositooriumi piire, kui need on konfigureeritud indekseerima mitut koodibaasi. Need loovad korralikke kõnegraafe, selle asemel et tugineda teksti sobitamisele, käsitlevad aliasingut ja kaudseid kõnesid paremini kui IDE-otsing ning neid saab käivitada CI-torujuhtmetes, et püüda kinni uusi helistajaid nende lisamisel. Need on kõige võimekam saadaolev ühe keele lähenemisviis.

Piirang on sama ulatuse piir, mis piirab IDE-sid, aga nüüd tööriista tasandil: Java staatilise analüüsi tööriist ei indekseeri COBOL-programme, COBOL-analüsaator ei indekseeri Java teenuseid ja kumbki ei indekseeri JCL-töövooge. Süsteemis, kus aegunud funktsioon on COBOL-utiliit, mida kutsutakse välja JCL-töödest käivitatud COBOL-programmidest ja mille andmeväljundit tarbivad Java teenused, näeb iga staatilise analüüsi tööriist ühte fragmenti kutsesuhtest. Nagu oluliste refaktorimistehnikate kontekstis uuritud , nõuab kõigi antud koodiosa täitmisteede, sealhulgas haruldaste veatingimuste ja varuharude tuvastamine sellist täielikku kutsegraafi kaardistamist, mida ühe keele tööriistad ei suuda keelepiiride piires luua.

Mida täielik helistajate inventuur tegelikult nõuab

Ettevõtte süsteemis oleva aegunud funktsiooni täielik kutsujate loend ei ole otsingutulemus. See on struktureeritud loend kõigist täitmisteedest, mille kaudu aegunud funktsioonini jõuda saab, sealhulgas otsesed, kaudsed, keelteülesed ja dünaamiliselt saadetavad teed. Selle loendi koostamine nõuab mitmeid võimalusi, mida ükski standardne tööriist ei paku.

Ühendatud keelteülene kõnegraaf. Kõnegraaf peab hõlmama kõiki süsteemi keeli. JCL-protseduuri kõne COBOL-programmile, COBOL-programmi kõne jagatud utiliidi lõigule ja Java-teenuse kõne samale COBOL-programmile vahetarkvara liidese kaudu peavad kõik olema sama graafi sõlmed ja servad. Aegunud funktsioon on selles graafis sõlm ja kutsuja loendamine on kõigi sissetulevate servade, nii otseste kui ka transitiivsete, läbimine, olenemata sellest, millisest keelest need pärinevad.

Rekursiivne läbimine läbi täieliku kõnegraafi. Otsekõnejad on ainult esimene kiht. Täielik inventuur nõuab kõnegraafi järgimist ülesvoolu läbi kaudsete kutsujate, ümbrisfunktsioonide ja fassaadikihtide, kuni läbimine jõuab funktsioonideni, millel pole oma kutsujaid ja mis on kõneahelate tegelikud sisenemispunktid. Iga funktsioon teel, mis lõpeb aegunud funktsiooniga, on kutsuja asjakohases mõttes: aegunud funktsiooni eemaldamine katkestab kõik seda läbivad teed.

Repositooriumidevaheline indekseerimine. Kutsegraaf peab sisaldama koodi igast repositooriumist, mis võiks funktsiooni potentsiaalselt kutsuda, sealhulgas repositooriumidest, mis sõltuvad funktsioonist jagatud teegi või paketi kaudu. See nõuab kõigi repositooriumide samaaegset indekseerimist ja repositooriumidevaheliste impordisuhete lahendamist, et ühendada ühe repositooriumi kõned teise repositooriumi definitsioonidega.

Kaudsete kutsumismustrite tuvastamine. Analüüs peab tuvastama peegelduse, dünaamilise lähetamise, funktsiooniviidete, delegaatide ja stringipõhise kutsumise kaudu konfiguratsioonifailides tehtud kõned. Need nõuavad pigem mustripõhist tuvastamist kui otsest kõne serva lahendamist: dünaamiliste lähetamismehhanismide leidmist koodist ja selle kindlaksmääramist, millistele funktsioonidele need saavad millistel tingimustel suunata.

Aktiivsete kutsujate ja ainult test- või surnud kutsujate eristamine. Kõik kutsujad ei vaja sama vastust. Kutsuja, mis eksisteerib ainult aegunud funktsiooni enda testseadmes, tuleb puhastamise osana eemaldada, mitte migreerida. Koodis olev kutsuja, mis on kasutusanalüüsi abil tuvastatud surnud koodina, ei ole funktsiooni eemaldamise blokeerija. Nende eristuste mõistmiseks on vaja ühendada kutsujate loend teabega selle kohta, millised kooditeed on tegelikult aktiivsed. Nagu surnud koodi tuvastamise uurimisel staatilise analüüsi abil üksikasjalikult kirjeldatud , võivad kättesaamatud kood ja kasutamata funktsioonid missioonikriitilistes süsteemides aastaid püsida mittetäieliku dokumentatsiooni või ajalooliste sõltuvuste ebakindluse tõttu ning aegunud funktsiooni kutsujate inventuur peab eristama kutsujaid, kes on ise aktiivsed, ja kutsujaid, kes on ise surnud.

Aeglasest eemaldamiseni kulgev protsess: struktureeritud lähenemisviis

Enamiku helistaja avastamise ebaõnnestumiste allikaks on aegunud funktsioonide eemaldamise käsitlemine ühe sündmusena, mitte struktureeritud protsessina. Õige lähenemisviis käsitleb eemaldamist mitmefaasilise protsessi viimase sammuna, mis algab ammu enne koodi kustutamist.

1. etapp: märgistamine ja mõõtmine

Esimene samm on funktsiooni märkimine aegunuks, kasutades keele sisseehitatud mehhanismi (@Deprecated Jaavas [Obsolete] C#-s #[deprecated] (Rustis või sobivas ekvivalendis) ja algtaseme kutsujate arvu määramine. See algtase ei ole ühegi üksiku otsingu tulemus; see on iga teadaoleva koodibaasi indekseerimise ja tulemuste loendamise tulemus, mis võib funktsiooni kutsuda. Algtasemel on kaks eesmärki: see kvantifitseerib migratsiooni ulatust ja pakub võrdlusaluse, mille suhtes saab edusamme kutsujate migreerimisel mõõta.

Baasjoon peaks olema korraldatud helistaja tüübi ja asukoha järgi:

Helistaja kategooriaLoendamaPrioriteetomanik
Otsehelistajad samas hoidlasNKõrgePraegune meeskond
Otsehelistajad sõltuvates teenustesNKõrgeTeenuse omanikud
Helistajad ümbrisfunktsioonide kauduNKeskmineÜmbrise omanikud
Kutsujad genereeritud või raamistiku koodisNKeskmineRaamistiku meeskond
Helistajad ainult testkoodisNMadalPraegune meeskond
Helistajad surnud koodisNAinult koristusPraegune meeskond

2. etapp: teavitamine ja migreerimine

Täieliku helistajate inventuuri korral muutub migreerimine pigem organiseeritud kui reaktiivseks ettevõtmiseks. Iga helistaja omanikku teavitatakse konkreetsetest kõne asukohtadest: mitte „võib-olla kutsute seda funktsiooni välja”, vaid „kutsete seda funktsiooni välja real 247”. BillingService.java, rida 82 AccountProcessor.javaja integreerimistestis real 14 BillingServiceTest.java.” Sellist spetsiifilisuse taset võimaldab helistaja inventuur ja üldised aegumishoiatused ei suuda pakkuda.

Teavituse kõrval on oluline esitada ka migratsioonitee. Aegumine peaks sisaldama asendusfunktsiooni dokumentatsiooni, kirjeldust vana ja uue rakenduse käitumuslike erinevuste kohta ning juhul, kui muudatus pole triviaalne, koodinäidet, mis näitab enne ja pärast. Teiste meeskondade koodibaaside kutsujate puhul tuleks migratsiooni ajakava selgesõnaliselt läbi rääkida, mitte ühepoolselt välja kuulutada, kuna neil meeskondadel on oma prioriteedid ja tarnekohustused. Nagu andmebaaside refaktoreerimise kontekstis uuritud sõltuvates süsteemides , on uue struktuuri tarbijate järkjärguline lisamine enne vana struktuuri aegumist distsipliin, mis hoiab ära murranguliste muudatuste ilmumise ootamatute juhtumitena.

3. etapp: helistajate arvu jälgimine

Baasmõõtmise ja planeeritud eemaldamiskuupäeva vahel tuleks helistajate arvu pidevalt jälgida. Iga kord, kui helistaja liigub asendusfunktsiooni, väheneb arv. Eemaldamisvärav saavutatakse siis, kui aktiivsete helistajate arv jõuab nullini (ainult test- ja surnud koodiga helistajad võidakse funktsiooniga samaaegselt eemaldada). Pidev jälgimine nõuab helistajate loendamise käivitamist ajakava alusel CI-torustiku osana, mitte tuginemist ühekordsele inventuurile, mis koodi muutudes aegub.

Jälgimine püüab kinni ka aegunud funktsioonid, mis on lisatud aegunud perioodil. Suurtes organisatsioonides on tavaline, et migreerimisakna ajal kirjutatakse uut koodi, mis kutsub aegunud funktsiooni, kas seetõttu, et arendaja ei olnud aegumisest teadlik, kuna koodi ülevaatus jättis selle märkamata või seetõttu, et automatiseeritud koodigeneraator loob koodi, mis kutsub aegunud funktsiooni. Aegunud funktsiooni CI-taseme helistajate tuvastamine, mis on konfigureeritud uutes kõnekohtades nurjuma, hoiab ära helistajate arvu kasvu migreerimise ajal.

4. etapp: Enne eemaldamist kontrollige täielikkust

Vahetult enne funktsiooni eemaldamist tuleks kutsujate loendamine viimast korda läbi viia kõigi teadaolevate koodibaaside täieliku ulatuse suhtes. See viimane kontroll toimib turvaväravana: see kinnitab, et aktiivsete kutsujate arv on jõudnud nullini ja tuvastab kõik hilisemas etapis lisandused, mida CI-seire ei tabanud. Sel hetkel peaks inventuur kontrollima ka dünaamiliste kutsujate puudumist: konfiguratsioonifailid, mis viitavad funktsioonile stringi abil, peegelduspõhised registreeringud ja kõik muud kaudsed kutsumismehhanismid, mis tuvastati esialgse analüüsi käigus.

Kontrollimine peaks laienema kõigi jagatud teekide või pakettide sõltuvusgraafikule, mis avaldavad aegunud funktsiooni. Kui funktsioon on osa avalikust API-st, mida kasutavad välised osapooled, peab eemaldamise ajakava arvestama väliste tarbijatega, kellega sisemise koodianalüüsi abil ei pruugita ühendust saada. Sisemiste süsteemide puhul hõlmab kontrollimine kõiki indekseeritud koodibaase. Avalikult avaldatud API-de puhul hõlmab kontrollimine teadaolevaid tarbijaid ja määratletud aegumisperioodi, mille jooksul välised tarbijad peavad migreeruma.

Kuidas helistaja avastamine toimib erinevalt pärand- ja suurarvutikeskkondades

Eespool kirjeldatud väljakutsed kehtivad iga suure tarkvarasüsteemi kohta, kuid eriti teravad on need suurarvuti- ja pärandkeskkondades, kuna kõnede suhted nendes keskkondades väljenduvad mehhanismide kaudu, mida tänapäevased helistaja tuvastamise tööriistad ei ole loodud analüüsima.

COBOL-keskkondades kutsutakse funktsioone välja CALL-lausete abil, mis võivad sihtmärgile viidata literaalstringi, programmi nime sisaldava andmeüksuse või protseduuri pointeri abil. Literaalstringi juhtum on lahendatav staatilise analüüsi abil; andmeüksuse juhtum nõuab andmevoo analüüsi, et teha kindlaks, millist väärtust andmeüksus kutse hetkel omada võib; ja protseduuri pointeri juhtum nõuab pointeri määramise jälgimist. Kõik need kutsemehhanismid ilmuvad lähtekoodis erinevalt ja nende lahendamiseks on vaja erinevat analüüsi.

JCL-keskkondades kutsutakse programme välja nime järgi EXEC PGM= lausetes. Programmi nimi on string, mis seob kompileeritud mooduliga laadimisteegis. COBOL-programmi kutsujate jälgimine JCL-i kaudu nõuab JCL-i parsimist, et eraldada programminimed, seotada need nimed neid rakendavate kompileeritud COBOL-programmidega ja lahendada, millised COBOL-lõigud nendes programmides kutsuvad aegunud utiliiti. See mitmeastmeline lahendus on täielikult väljaspool nii COBOL-analüsaatori kui ka isoleeritult töötava JCL-analüsaatori ulatust.

Jagatud käsikirjad on eriti oluline juhtum COBOL-keskkondades. Käsikirjas määratletud aegunud lõik võib paljudesse programmidesse lisada COPY-lausete kaudu. Lõik ei dubleerita füüsiliselt igas programmis; see lisatakse kompileerimise ajal. Analüüs, mis loendab lõigu nime esinemisi lähtekoodifailides ilma käsikirjade kaasamisi lahendamata, põhjustab nii üleloendamist (lõigu definitsiooni leidmine käsikirjast endast) kui ka alaloendamist (jättes tähelepanuta asjaolu, et igal käsikirja sisaldaval programmil on juurdepääs lõigule). Kutsuja õigeks tuvastamiseks on vaja mõista, millised programmid milliseid käsikirjasid sisaldavad ja milliseid lõike nendes käsikirjades nad tegelikult kutsuvad. Kõvakodeeritud viidete ja nende allavoolu tarbijate vaheline seos illustreerib, miks nende programmitaseme kutsumissuhete lahendamine on oluline enne mis tahes struktuurimuutust: see, mis näib olevat lihtne stringiviide, võib olla ainus mehhanism, mille kaudu kümned programmid saavutavad kriitilise funktsionaalsuse.

Kuidas SMART TS XL Loob täieliku helistajate inventuuri

SMART TS XL loob ühtse kõnegraafiku iga keele, platvormi ja repositooriumi vahel indekseeritud keskkonnas. COBOL-programmid, JCL-töövood, Java-teenused, .NET-rakendused, SQL-i salvestatud protseduurid, Pythoni skriptid ja muud lähtekoodiartefaktid parsitakse kõik keelespetsiifilise analüüsi abil ühiseks ristviidegraafiks. Iga funktsioon, lõik, protseduur, meetod ja programmiüksus on selles graafikus sõlm. Iga kõnesuhe, olgu see siis COBOL-kõnelause, Java-meetodi kutsumine, JCL EXEC PGM või SQL EXEC, on tüübitud serv. Graafik kujutab süsteemi täielikku kõnetopoloogiat, mitte keelepõhist osavaadet.

Kui funktsioon on eemaldamiseks märgitud, SMART TS XLKutsujate loendamine läbib sihtfunktsiooni sõlmest saabuvate kõnede graafikut, kogudes kõik kutsujad kõnehierarhia igal tasandil. Läbimine on rekursiivne, järgides graafikut läbi ümbrisfunktsioonide, fassaadikihtide ja vaheutiliitide, kuni see jõuab funktsioonideni, millel pole kutsujaid ja mis esindavad kõneahelate tegelikke sisenemispunkte. Tulemused on järjestatud keele, repositooriumi, kutsuja tüübi ja kõne sügavuse järgi, andes meeskonnale struktureeritud inventuuri, mis eraldab otsesed kutsujad kaudsetest kutsujatest ja aktiivsed kutsujad surnud koodi kutsujatest.

Platvormi mõjuanalüüsi võimalus laiendab seda struktureeritud muutuste mõju aruandeks: mitte ainult see, millised funktsioonid kutsuvad aegunud funktsiooni, vaid ka see, millised programmid, teenused, pakk-tööd ja JCL-protseduurid on mõjutatud sõltuvusahela igal tasandil. See aruanne on artefakt, mis muudab aegumisest eemaldamiseni kulgeva protsessi teostatavaks: see nimetab omanikud, tuvastab konkreetsed kõne asukohad ja kvantifitseerib migratsiooni ulatuse, mis on vajalik enne, kui eemaldamine saab ohutult jätkuda. Nagu ettevõtte muudatuste juhtimise mõjuanalüüsi üksikasjades uuriti , on võime loetleda mõjutatud komponendid enne struktuurimuudatuse tegemist keerukate ja omavahel ühendatud ettevõttesüsteemide ohutu toimimise põhinõue.

SMART TS XL toetab ka aegumisprotsessi pideva jälgimise faasi. Kuna ristviidete graafikut värskendatakse pidevalt lähtekoodi muudatuste indekseerimise käigus, on aegunud funktsiooni kutsujate arv alati ajakohane. CI-torustiku integratsioon võimaldab automatiseeritud kontrollidel nurjuda aegunud funktsioonide uute kutsumiste korral, jõustades migratsioonidistsipliini uue koodi lisamise hetkel, mitte avastades rikkumisi hiljem. See esialgse loendamise, migratsioonijuhiste ja pideva jälgimise kombinatsioon hõlmab aegunud funktsiooni kogu elutsüklit alates märkustest kuni ohutu eemaldamiseni.

Funktsioonide eemaldamine ilma kahetsuseta

Erinevus sujuvalt kulgeva funktsiooni eemaldamise ja tootmistõrkeid põhjustava eemaldamise vahel seisneb peaaegu alati kutsuja tuvastamise täielikkuses. Eemaldamine ise on lihtne: kustuta definitsioon ja juuruta. Ettevalmistus on see, kus töö toimub, ja ettevalmistus on sama hea kui kutsuja inventuur, millel see põhineb.

Süsteemides, kus kõnegraaf on pealiskaudne, ühekeelne ja asub ühes repositooriumis, on IDE kõnehierarhia ja kompilaatori hoiatused piisavaks ettevalmistuseks. Süsteemides, kus kõnegraaf hõlmab mitut keelt, mitut repositooriumi, mitut platvormi ja potentsiaalselt aastakümneid koodi, katavad need tööriistad väikese ja teadmata osa tegelikust kutsuja pinnast. Lõhe selle vahel, mida nad tagastavad, ja selle vahel, mis tegelikult funktsiooni kutsub, ongi tootmisvead.

Eesmärgipäraselt loodud keelte- ja hoidlateülene kutsujate loendamine ei ole funktsioonide eemaldamise arendaja töövoo täiustus. See on eeltingimus selle töövoo ohutuks käivitamiseks mis tahes süsteemis, mis on piisavalt keeruline, et oleks kogunenud selliseid süsteemidevahelisi kutsumissuhteid, mida ettevõtte koodibaasides olevad aegunud funktsioonid tavaliselt kannavad. Iga aegunud funktsioon, mis eemaldatakse ilma täieliku kutsujate inventuurita, on väljalase, mis sisaldab teadmata arvu käitusaja tõrkeid, mis ootavad konkreetset täitmisteed, mis jõuab puuduva definitsioonini. Selle tundmatu kõrvaldamiseks ongi struktureeritud kutsujate avastamine mõeldud.