Navigace v kódu funguje dobře, když vývojář zůstává v jednom jazyce v jedné kódové základně. Stiskněte F12, přejděte na definici. Klikněte pravým tlačítkem myši na metodu, najděte všechny reference. Tyto interakce se zdají být okamžité, protože IDE má kompletní a koherentní model kódu: zná každý symbol, každý typ, každý řetězec importu. V okamžiku, kdy se tato hranice rozšíří a zahrnuje druhý jazyk, se však tento model rozpadne. IDE zná svůj jazyk, ale ne ten druhý. Vývojář vidí volání, sleduje ho až na okraj aktuálního souboru a pak narazí na zeď: volána funkce se nachází v jiném jazyce, možná v jiném repozitáři, a řídí se jinými konvencemi, kterým nástroj nerozumí. Od tohoto okamžiku se navigace stává manuální. Vývojář přepíná nástroje, vyhledává podle textu a doufá, že výsledek je to, co hledal.
Navigace kódu napříč jazyky
SMART TS XL poskytuje jednotné rozlišení symbolů a navigaci kódu napříč všemi jazyky ve vašem prostředí.
Klikněte zdePro týmy pracující ve skutečně polyglotním prostředí se nejedná o občasnou nepříjemnost. Je to výchozí stav každého významného úkolu. Podnikové systémy běžně zahrnují COBOL a Javu, JCL a SQL, Python a C++ nebo libovolný počet kombinací, které odrážejí desetiletí technologických rozhodnutí vrstvených na sobě. Každá jazyková hranice v tomto zásobníku je místem, kde končí automatická navigace a začíná manuální rekonstrukce. Tření se napříč každým vývojářem, každým úkolem a každým týmem stupňuje, dokud se náklady nestanou strukturálními: pomalejší onboarding, rizikovější změny, delší vyšetřování incidentů a rostoucí závislost na několika málo lidech, kteří mají v hlavě znalosti různých jazyků. Jak bylo zkoumáno v kontextu Řešení statické analýzy v COBOLuProblém s uvažováním napříč jazykovými hranicemi není jen problémem s nástroji. Je to základní překážka bezpečného provozu velkých, heterogenních systémů.
Pochopení toho, proč k tomuto selhání dochází a kolik to v praxi stojí, je prvním krokem k jeho řešení. Tento článek sleduje problém od jeho technických kořenů až po jeho provozní důsledky, zkoumá, proč běžně používané nástroje selhávají na hranicích jazyků, a vysvětluje, co skutečná navigace mezi jazyky vyžaduje pro fungování v podnikovém měřítku.
Co navigace kódu skutečně potřebuje k fungování
Navigace kódu není vyhledávací operace. Je to operace rozlišení. Když se vývojář zeptá „kde je tato funkce definována?“, IDE neprohledává soubory a hledá odpovídající text. Porovnává identifikátor se strukturovaným modelem kódové základny: analyzovanou reprezentací každé třídy, metody, proměnné a typu, které existují v rámci rozsahu, spolu se vztahy mezi nimi. Tento model je vytvářen během indexování, průběžně udržován při změně souborů a je dotazován okamžitě, když je spuštěna navigační akce. Přesnost a úplnost modelu určuje přesnost a úplnost každého výsledku navigace, který vývojář obdrží.
Toto rozlišení mezi vyhledáváním a rozlišením je důležité, protože definuje požadavky pro navigaci v různých jazycích. Textové vyhledávání může prohledávat libovolné soubory bez ohledu na jazyk, protože nečte kód jako kód. Navigační nástroj nemůže fungovat napříč jazykovými hranicemi, pokud nemá vytvořen model, který zahrnuje oba jazyky, nikoli pouze model jednoho jazyka, který dokáže také najít řetězce v souborech patřících druhému. Vytvoření tohoto jednotného modelu je technicky náročné ve srovnání s navigací v jednom jazyce a obtížnost se zvyšuje s počtem použitých různých jazyků. Jak bylo prozkoumáno v podrobném zkoumání... analýza datových a řídicích tokůKód, který funguje správně napříč cestami provádění, vyžaduje strukturální pochopení celé cesty, nikoli pouze segmentů, které spadají do rozsahu platnosti daného nástroje.
Tři specifické funkce, které navigace v kódu vyžaduje a které všechny selhávají různými způsoby na hranicích jazyků, jsou rozlišení symbolů, konstrukce grafů volání a trasování závislostí. Každá z nich si zaslouží samostatné zkoumání, než se zamyslíme nad tím, jak vzájemně fungují v praxi.
Rozlišení symbolů a proč se narušuje na hranicích jazyků
Rozlišování symbolů je proces mapování identifikátoru ve zdrojovém kódu na jeho definici. V prostředí s jedním jazykem je tento proces dobře pochopen: kompilátor nebo interpret jej již provádí a IDE replikují tuto logiku rozlišení pomocí stejných gramatických a typových pravidel. Rozlišování je přesné, protože pravidla jsou v rámci jednoho jazyka jednoznačná.
Na hranici jazyků vyžaduje rozlišení model mostu, který dokáže reprezentovat symboly z obou jazyků v jednotné struktuře a sledovat spojení od identifikátoru v jazyce A k jeho odpovídající definici v jazyce B. Tento most neexistuje ve standardních IDE ani jazykových serverech, protože protokol Language Server Protocol (LSS) byl navržen za předpokladu, že každý jazykový server zpracovává jeden jazyk. Když metoda Java volá program v COBOLu prostřednictvím definovaného rozhraní, jazykový server Java volání metody rozumí, ale nedokáže rozpoznat cíl v COBOLu. Vývojář volání vidí, ví, že někam směřuje, a nemůže ho sledovat, aniž by nástroj úplně opustil.
Uvažujme reprezentativní příklad. Služba Java volá program v COBOLu podle názvu prostřednictvím middlewarové vrstvy:
Jáva
// Java service calling a COBOL program via a legacy middleware adapter
LegacyAdapter.invoke("CUSTINQ", customerRequest);
Java IDE řeší LegacyAdapter.invoke bez problémů. Zná signaturu metody a dokáže přejít k její implementaci. Ale "CUSTINQ" je řetězcový literál na úrovni Javy. IDE nemá žádnou představu o názvech programů v COBOLu, nerozumí tomu, že CUSTINQ odkazuje na specifickou kompilovanou programovou jednotku s vlastními definicemi dat a strukturou odstavců. Navigace se zastaví na řetězci. Vývojář musí ručně najít zdrojový kód COBOLu, otevřít jej v jiném editoru a začít číst bez jakéhokoli strukturálního kontextu o tom, jak se program vztahuje k volajícímu kódu Java.
Konstrukce grafu volání napříč heterogenními kódovými základnami
Graf volání je datová struktura, která znázorňuje, které funkce volají které další funkce v rámci kódové základny. IDE používají grafy volání k implementaci funkcí, jako je „nalezení všech volajících“ a „hierarchie volání“, které vývojáři ukazují každou cestu vedoucí k dané funkci a každou funkci, kterou daná funkce volá. V jednom jazykovém prostředí je konstrukce grafu volání přirozeným vedlejším produktem indexování kódové základny.
Ve vícejazyčném prostředí musí graf volání překračovat hranice jazyků, aby byl úplný. Graf volání, který končí v každém bodě, kde provádění přechází do jiného jazyka, není grafem volání systému; je to kolekce částečných grafů, jeden pro každý jazyk, s nepropojenými hranami na každé hranici jazyka. Pro vývojáře, který sleduje cestu provádění v systému, který mísí jazyky, to znamená, že trasování se ukončí pokaždé, když cesta překročí hranici jazyka, což vyžaduje ruční krok k jejímu opětovnému načtení v dalším jazyce.
Problém je akutní v prostředích mainframů, kde jedna obchodní transakce může zahrnovat orchestraci sekvence provádění pomocí JCL, programy v COBOLu provádějící základní obchodní logiku a dotazy SQL pro čtení a zápis dat. Jak je podrobně popsáno v analýze Mapování JCL do COBOLuTyto tři vrstvy jsou hluboce propletené: JCL definuje, co běží a v jakém pořadí, COBOL definuje, co programy dělají, a SQL definuje, ke kterým datům přistupují. Graf volání, který zahrnuje pouze COBOL, pouze JCL nebo pouze SQL, popisuje spíše fragment systému než samotný systém. Sledování čehokoli smysluplného vyžaduje propojení všech tří vrstev v jednom modelu.
Sledování závislostí při sdílení dat mezi jazyky
Závislosti mezi komponentami ve vícejazyčném systému jsou často zprostředkovány sdílenými daty: databázovou tabulkou, kterou zapisuje COBOL a čte Java, souborem, který vytváří dávková úloha a který spotřebovává API, nebo frontou zpráv, kterou zapisuje producent Pythonu a čte příjemce Go. Tyto závislosti zprostředkované daty jsou skutečné a důsledné. Změna schématu tabulky, formátu souboru nebo struktury zprávy ovlivňuje producenta i příjemce, ale nejsou reprezentovány v modelu závislostí žádného jednotlivého jazyka.
Trasování závislostí ve vícejazyčném prostředí proto vyžaduje pochopení nejen volání mezi kódem, ale i vztahů mezi daty a kódem: které programy čtou nebo zapisují konkrétní sloupec tabulky, které služby závisí na konkrétním formátu souboru a kteří uživatelé jsou ovlivněni změnou ve schématu zpráv. Tento druh trasování je zcela mimo rámec standardní navigace IDE a vyžaduje nástroj, který modeluje celý systém, včetně datové vrstvy, spíše než aby kód každého jazyka zpracovával izolovaně.
Specifické způsoby selhávání navigace v běžných vícejazyčných systémech
Selhání navigace kódu napříč jazyky nejsou abstraktní. Objevují se ve specifických, předvídatelných situacích, které se běžně vyskytují v prostředích podnikového vývoje. Jejich konkrétní zkoumání objasňuje, proč generické vyhledávací nástroje nemohou nahradit skutečnou navigaci napříč jazyky.
COBOL a Java: Nejběžnější hranice mezi podniky
Hranice mezi COBOLem a Javou je nejrozšířenější jazykovou hranicí ve velkých podnikových systémech, zejména ve finančních službách, pojišťovnictví a státní správě. Desítky let investic do COBOLu existují vedle snah o modernizaci Javy v hybridní architektuře, kde COBOL zpracovává dávkové zpracování a Java transakční zpracování a API. Tyto dva jazyky komunikují prostřednictvím definovaných rozhraní: transakce CICS, fronty zpráv, sdílené databáze a předávání dat na základě souborů.
Navigace přes tuto hranici v praxi odhaluje hloubku problému. Vývojář v Javě, který zkoumá neočekávané chování v transakci, musí sledovat cestu provedení do dávkového programu v COBOLu, který zpracoval podkladová data. Java IDE ukazuje, kde je rozhraní vyvoláno. Nemůže ukázat, co program v COBOLu dělá se vstupem, jaká data čte, jaké výpočty provádí nebo co zapisuje zpět. Vývojář potřebuje k pokračování znalosti COBOLu a nástroje pro COBOL, ani jedno z toho nemusí být v týmu zaměřeném na Javu snadno dostupné. Výsledkem je buď pomalé manuální vyšetřování, nebo eskalace k někomu s požadovanými znalostmi, což představuje selhání navigace, která stojí čas a prodlužují dobu trvání incidentu.
Na straně COBOLu dochází k ekvivalentní chybě, když vývojář COBOLu potřebuje pochopit, které služby Java spotřebovávají data, která program COBOL produkuje. Standardní nástroje COBOLu nemají žádný model kódu Java. Vývojář může vidět výstup programu COBOL, včetně zápisu do databáze nebo aktualizace souboru, ale nemůže tento výstup dále sledovat a identifikovat, které služby Java jej čtou. Jakákoli změna výstupního formátu vyžaduje ruční koordinaci s týmy Java, protože neexistuje žádný nástroj, který by dokázal automaticky vyjmenovat konzumenty. Modernizace COBOLu kriticky závisí na vyřešení právě této mezery: dokud nebude v obou jazycích viditelný celý řetězec závislostí, není bezpečná modernizace možná.
JCL a COBOL: Orchestrace bez viditelnosti
JCL je orchestrační vrstva pro dávkové zpracování na mainframech. Řídí, které programy běží, v jakém pořadí, s jakými parametry a s jakými soubory a datovými sadami. Vztah mezi JCL a programy v COBOLu, které vyvolává, je základní strukturální závislostí: změnou JCL se změní chování programů v COBOLu. Změnou očekávaného vstupního formátu programu v COBOLu se může změnit i očekávaný vstupní formát programu v COBOLu.
Standardní nástroje pro analýzu COBOLu neanalyzují JCL. Standardní nástroje pro analýzu JCL neanalyzují COBOL. Spojení mezi krokem JCL, který vyvolává PGM=CUSTINQ a program v COBOLu s názvem CUSTINQ existuje v běžícím systému, ale ne v modelu žádného jednotlivého nástroje. Vývojář používající kterýkoli z nástrojů samostatně nevidí ucelený obraz. Vědí, co daný krok JCL volá, podle názvu, ale neví, co program dělá. Nebo vědí, co program v COBOLu dělá, ale neví, jak je voláno, s jakými parametry nebo v jaké sekvenci streamu úloh.
Tato mezera vytváří specifická rizika pro produkční systémy. Vývojář, který upravuje definice pracovního úložiště programu v COBOLu, může neúmyslně změnit způsob, jakým program zpracovává data předávaná z konkrétního kroku JCL, aniž by ho jakýkoli nástroj varoval, že změna ovlivňuje kontext provádění definovaný v JCL. Vývojář, který restrukturalizuje proceduru JCL, může změnit pořadí, ve kterém se programy spouští, aniž by jakýkoli nástroj ukazoval, které programy v COBOLu na této posloupnosti závisí pro správné fungování. Jak je podrobně popsáno v analýze... Řešení statické analýzy JCL, přehled o závislostech mezi programy a využití datových sad v prostředích JCL vyžaduje specializovanou analýzu, kterou standardní nástroje jednoduše neposkytují.
Zde je ukázka, jak vypadá stejná závislost z pohledu každého jazyka se standardními nástroji oproti tomu, co by ukázal unifikovaný model:
| Co vidí vývojář | Zobrazení pouze JCL | Zobrazení pouze v COBOLu | Sjednocený vícejazyčný pohled |
|---|---|---|---|
| Vyvolání programu | PGM=CUSTINQ (pouze jméno) | Není vidět | Funkce CUSTINQ je volána 3 procedurami JCL se specifickými hodnotami PARM. |
| Vstupní datové sady | Jména DD uvedena | Není vidět | Čte CUSTFILE (definovaný v CUSTMAST.JCL krok 2) |
| Výstupní datové sady | Jména DD uvedena | Není vidět | Zapisuje CUSTRPT (spotřebováno úlohou RPTPRT) |
| Obchodní logika | Není vidět | POSTUPNÍ ODDĚLENÍ viditelné | Úplný tok od volání JCL přes logiku COBOLu až po výstup |
| Dopad změny | Neznámý | Neznámý | 4 JCL procedury, 2 následné COBOL programy, 1 databázová tabulka |
Moderní jazykové balíčky: Python, Go a C# napříč službami
V distribuovaných systémech postavených na moderních jazykech má problém navigace jinou podobu. Spíše než mezera mezi jazyky COBOL a Java představuje výzvu hranice služeb v kombinaci s polyglotovým stackem. Služba zpracování dat v Pythonu napájí API Go, které napájí front-end v C#. Každá služba je postavena s vlastními nástroji, vlastní konfigurací IDE a vlastním modelem závislostí. Propojení mezi službami existují na vrstvě API, ale standardní navigační nástroje nemají žádný model vztahů mezi službami API.
Vývojář, který upravuje strukturu odpovědi ve službě Pythonu, potřebuje vědět, na kterých polích závisí Go API a která pole nakonec zobrazí front-end C#. Bez navigace napříč jazyky a službami musí ručně kontrolovat kód každé následné služby, hledat odkazy na příslušné názvy polí a doufat, že konvence pojmenování jsou dostatečně konzistentní, aby bylo vyhledávání spolehlivé. Jak bylo diskutováno v kontextu Nástroje pro statickou analýzuI v rámci jedné služby Go je pochopení hierarchií volání a sledování závislostí mezi moduly netriviálním problémem. Rozšíření tohoto problému napříč hranicemi služeb a jazyků současně je řádově těžší.
Stejný vzorec platí i pro Systémy C# které volají sdílené služby napsané v Javě, nebo Python pipelines které zapisují do databází spotřebovaných aplikacemi .NET. V každém případě standardní nástroje pro každý jazyk poskytují přesnou navigaci v rámci daného jazyka a na hranici, kde provádění přechází do jiného jazyka nebo služby, neprodukují nic užitečného.
SQL a aplikační kód: Neviditelná datová vrstva
Jazyk SQL je přítomen téměř v každém podnikovém systému, a přesto je to nejčastěji přehlížená součást navigace mezi jazyky. Aplikační kód píše dotazy SQL, které odkazují na názvy tabulek, názvy sloupců, podmínky spojení a uložené procedury. Schéma databáze definuje tyto tabulky a sloupce. Vztah mezi kódem aplikace a schématem databáze je závislost, která, pokud je narušena změnou schématu, způsobuje selhání za běhu. Standardní IDE však berou řetězce SQL jako řetězce, nikoli jako kód s navigovatelnou strukturou.
Vývojář, který mění název sloupce ve schématu, musí najít každý odkaz na tento sloupec v každé aplikaci, v každém jazyce a v každém dotazu. Textové vyhledávání názvu sloupce je nespolehlivé: krátké názvy sloupců kolidují s názvy proměnných, zprávami protokolu a komentáři. Vyhledávání s ohledem na symboly vyžaduje nástroj, který modeluje jak schéma SQL, tak kód aplikace, který na něj odkazuje, a chápe, že "customer_id" v řetězci dotazu Java je odkaz na sloupec databáze customer_ida dokáže vyjmenovat všechny takové odkazy napříč jazyky. Bez tohoto modelu jsou změny schématu manuálně náročné a statisticky neúplné.
Proč rozšíření IDE a jazykové servery tento problém nemohou vyřešit
Rozšíření IDE a jazykové servery jsou navrženy tak, aby poskytovaly inteligenci specifickou pro daný jazyk. Analyzují kód podle specifické gramatiky, vytvářejí index symbolů specifický pro daný jazyk a obsluhují dotazy prostřednictvím protokolu Language Server Protocol, který definuje standardní rozhraní pro jazykové funkce, včetně přechodu na definici, vyhledávání odkazů a dokumentace při najetí myší. Protokol je na transportní vrstvě jazykově nezávislý, ale obsahově specifický: každý jazykový server produkuje výsledky pouze pro svůj vlastní jazyk.
Propojení dvou jazykových serverů v rámci stejného IDE neřeší navigaci mezi jazyky. Každý server má svůj vlastní index. Když vývojář požádá o „nalezení všech referencí“ pro symbol, požadavek se přesměruje na jazykový server pro jazyk aktuálního souboru. Tento server vrátí reference, o kterých ví, a které jsou omezeny na soubory, které indexoval. Nedotazuje se na druhý jazykový server, a i kdyby ano, neexistoval by žádný sdílený model symbolů, jehož prostřednictvím by bylo možné vyjádřit vztahy mezi jazyky.
Toto je strukturální omezení architektury LSP, nikoli konfigurační problém. Lze jej částečně obejít ve specifických, úzkých případech, jako je jazykový server, který také analyzuje inline SQL v rámci f-řetězců Pythonu, ale nelze jej zobecnit na libovolné závislosti mezi jazyky, aniž by se vytvořil přesně ten druh jednotného vícejazyčného modelu, který jde nad rámec toho, k čemu byl jakýkoli jazykový server navržen. výzvy, kterým čelí statická analýza při metaprogramování v rámci jednoho jazyka ilustrují hloubku problému: pokud uvažování o dynamicky generovaném kódu v jednom jazyce vyžaduje specializované techniky, uvažování napříč více jazyky s různými gramatikami a běhovými modely vyžaduje zcela odlišný architektonický přístup.
Které jazykové servery fungují dobře (a kde se zastaví)
Jazykové servery vynikají v úkolech, pro které byly navrženy: diagnostika v reálném čase, inteligentní doplňování, rozlišení symbolů v jednom jazyce a refaktoring v editoru v omezeném rozsahu. Tyto funkce jsou cenné a neměly by být ignorovány. Problém není v tom, že jazykové servery jsou nedostatečné nástroje; problém je v tom, že se jedná o jednomu jazyku používané k řešení vícejazyčných problémů a že nesoulad vede k předvídatelným a nákladným selháním přesně v bodech, kde je přesnost nejdůležitější.
Níže uvedená tabulka srovnává specifické navigační úlohy s tím, co poskytují jazykové servery, a s tím, kde začíná mezera:
| Navigační úkol | LSP v jednom jazyce | LSP napříč jazykovými hranicemi |
|---|---|---|
| Přejít na definici | Přesné, okamžité | Selže: zastaví se na místě volání |
| Najít všechny reference | Dokončit v rámci indexovaných souborů | Neúplné: chybí odkazy v jiných jazycích |
| Hierarchie volání | Přesné pro volající hovořící jedním jazykem | Zkráceno: volající hranice chybí |
| Přejmenovat symbol | Bezpečně v jednom jazyce | Nebezpečné: přejmenování chybí v použití v různých jazycích |
| Analýza dopadů | Omezeno na aktuální jazyk | Slepý vůči následným spotřebitelům v jiných jazycích |
Grep a textové vyhledávání: Proč nejsou přijatelnou náhradou
Když jazykové servery selhávají na hranicích, vývojáři sahají po textovém vyhledávání. grep, vyhledávání na úrovni IDE a vyhledávání na platformě, jako je GitHub Code Search, všechny vyhledávají řetězce v souborech bez ohledu na jazyk. Nemají pojem „symbol“ nebo „odkaz“, pouze výskyty řetězců. Zkráceně řečeno, pro běžné identifikátory to znamená obrovské sady výsledků, které vyžadují ruční filtrování. U identifikátorů, které existují ve více jazycích s různými významy, výsledky spojují odlišné prvky kódu, které sdílejí stejný název.
Nebezpečnější než šum je neúplnost. Textové vyhledávání přehlíží odkazy tam, kde se konvence pojmenování v různých jazycích liší, kde je identifikátor konstruován dynamicky, kde je spojení zprostředkováno konfigurací nebo registrem jmen, nebo kde je vztah vyjádřen daty spíše než přímým odkazem na kód. Tyto mezery nejsou ve výsledcích vyhledávání viditelné: vývojář vidí, co vyhledávání našlo, nemá jak zjistit, co přehlédlo, a rozhoduje se na základě neúplného obrazu, který se jeví jako úplný. Jak bylo zkoumáno v širším kontextu... statická analýza kódu pro udržovatelnostNeschopnost přesně uvažovat o tom, co kód dělá a s čím se propojuje, není drobnou nepříjemností, která je hlavní příčinou hromadění technického dluhu, závad vzniklých během údržby a rostoucích nákladů na bezpečné provádění změn.
Provozní náklady, které se hromadí na jazykových hranicích
Výše popsané selhání navigace se neprojevují jako jednorázové problémy. Hromadí se napříč každým úkolem, každým vývojářem a každým týmem, který pracuje ve vícejazyčném prostředí. Pochopení nákladů vyžaduje pohled na opakující se situace, kdy navigace selhává, a výpočet celkového efektu.
Zaškolení v Polyglot Teams trvá výrazně déle
Vývojář, který se připojí k týmu pracujícímu v jednom jazyce a s jednou kódovou základnou, se může relativně rychle stát produktivním. IDE se stará o navigaci, kód se prostřednictvím své struktury samodokumentuje a mentální model, který vývojář vytváří, odráží skutečný systém. Vývojář, který se připojí k týmu pracujícím ve více jazycích, čelí zásadně odlišné situaci. Nástroje nedokážou překonat hranice, takže mentální model musí být vytvořen ručně pomocí dokumentace, párového programování a metody pokus-omyl.
Toto manuální vytváření modelu trvá týdny, nikoli dny. Vývojář se musí naučit nejen kód ve svém primárním jazyce, ale také dostatek informací o sousedních jazycích, aby rozuměl tomu, co volají, co volá je a jaká data proudí přes hranice. Ve velkých organizacích s vysokou fluktuací nebo častými rotacemi týmů je tato prodloužená doba zaškolování spíše opakujícím se nákladem než jednorázovou investicí. Každý, kdo se připojí k polyglotnímu týmu, hradí plné náklady na rekonstrukci mezijazyčného mentálního modelu od nuly, protože nástroje neposkytují nic, co by ho posunulo dál.
Produkční incidenty trvají déle, když stopy překračují jazykové hranice
Pokud produkční incident vyžaduje trasování cesty provádění, která překračuje jazykové hranice, je každé překročení hranice manuálním krokem. Vývojář v pohotovosti, který již pracuje pod časovým tlakem, musí přepnout nástroje, vyhledávat podle textu v kódové základně jiného jazyka a ručně propojit výsledky se trasováním, které vytvářel. V systému se třemi nebo čtyřmi jazykovými vrstvami může kompletní vyšetřování kořenové příčiny vyžadovat čtyři nebo pět takových překročení hranic, přičemž každé z nich přidává minuty k vyšetřování, které se měří v době, kdy jeho dopad ovlivňuje uživatele.
Kumulativním efektem v celé organizaci provozující vícejazyčné služby je systematicky prodlužovaná průměrná doba řešení jakéhokoli incidentu, který překročí jazykovou hranici. Nejde o selhání jednotlivých vývojářů; jde o strukturální důsledek nástrojů, které nemodelují propojení, která systém skutečně má. Organizace, které investovaly do viditelnosti v různých jazycích, konzistentně uvádějí rychlejší řešení incidentů jako jeden z nejpřímějších a nejměřitelnějších přínosů, a to právě proto, že tato investice eliminuje manuální kroky překračování hranic, které prodlužují dobu vyšetřování.
Rizikové změny se stávají rizikovějšími bez viditelnosti dopadu na více jazyků
Každá změna sdíleného kódu ve vícejazyčném systému s sebou nese neurčené riziko, dokud není známa celá sada uživatelů napříč všemi jazyky. Bez navigace mezi jazyky není toto riziko určeno před provedením změny. Objeví se dodatečně, když se nefunkční uživatelé objeví během testování nebo, co je horší, v produkčním prostředí. Nejedná se o vzácný způsob selhání. Je to standardní výsledek udržování sdílených datových struktur, rozhraní nebo utilit v systému, kde uživatelé navazující na systém hovoří různými jazyky.
Konzervativní reakcí na tuto nejistotu je nadměrná opatrnost: větší testovací úsilí, delší cykly revizí, více koordinačních schůzek a častější pozastavení změn v kritických obdobích. To vše jsou reálné náklady, které se hromadí v každém cyklu změn ve vícejazyčném systému. Představují čas a úsilí vynaložené na kompenzaci absence navigace v různých jazycích, spíše než investované do poskytování hodnoty. krajina modernizace starých časů je z velké části utvářen těmito nahromaděnými náklady: organizace sahají po modernizaci, protože údržba stávajících systémů se stala neúnosně nákladnou a selhání navigace v různých jazycích jsou hlavním faktorem těchto nákladů na údržbu.
Co vlastně vyžaduje navigace v různých jazycích
Řešení navigace kódu napříč více jazyky vyžaduje vytvoření jednotného modelu, který jazykové servery jednotlivě nemohou poskytnout. Tento model musí splňovat několik požadavků, které jsou nezbytnými podmínkami pro užitečnou navigaci napříč jazyky, nikoli volitelnými vylepšeními.
Jeden sdílený index symbolů zahrnující všechny jazyky. Každý pojmenovaný prvek v každém jazyce, včetně funkcí, tříd, polí, procedur, tabulek a definic dat, musí být reprezentován v jednom indexu se společným modelem identity. Identita symbolu nemůže být specifická pro daný jazyk, pokud se na něj mají vztahovat odkazy z jiných jazyků.
Analyzátory s ohledem na jazyk pro každý jazyk v systému. Každý jazyk musí být analyzován pomocí vlastní gramatiky, nikoli aproximován generickým analyzátorem nebo porovnáváním vzorů. Strukturální výstup každého analyzátoru musí být mapován na model sdílené identity, aby bylo možné vztahy mezi jazyky vyjádřit jako spojení mezi správně identifikovanými symboly.
Explicitní modelování mezijazykových rozhraní. Mechanismy, kterými různé jazyky interagují, včetně volání programů podle jména, databázových tabulek, formátů souborů, schémat zpráv a API kontraktů, musí být v modelu reprezentovány jako prvotřídní typy připojení, nikoli jako neprůhledné řetězce nebo zcela vynechány z modelu.
Trasování závislostí, které zahrnuje vztahy na datové vrstvě. Model musí reprezentovat nejen volání mezi kódy, ale i závislosti zprostředkované daty, protože ve vícejazyčných systémech jsou data často primárním médiem, jehož prostřednictvím se výstup z jednoho jazyka stává vstupem z jiného jazyka.
Výkon dotazů, který podporuje interaktivní navigaci. Index musí podporovat odezvu dotazu v kratší době než jedna sekunda pro běžné navigační operace. Model, který vyžaduje dávkovou analýzu spíše než interaktivní dotazy, je užitečný pro analýzu dopadu offline, ale nemůže nahradit navigaci v reálném čase během aktivního vývoje.
Tyto požadavky popisují platformu pro podnikovou inteligenci kódu, nikoli rozšíření IDE nebo jazykový server. Vytvoření a údržba takové platformy je technickým základem pro fungování vícejazyčné navigace kódu v praxi. Alternativa, která spočívá v akceptování selhání navigace a placení jejich nákladů donekonečna, se stává méně udržitelnou, čím větší a složitější vícejazyčný systém roste.
Jak SMART TS XL Podporuje vícejazyčnou navigaci
SMART TS XL je postaven na předpokladu, že podnikové systémy nelze chápat optikou jediného jazyka ani jediného repozitáře. Jeho platforma Software Intelligence přijímá zdrojový kód ze všech jazyků a platforem v prostředí, analyzuje každý z nich pomocí jazykově specifické analýzy a vytváří jednotný index křížových odkazů, který reprezentuje vztahy mezi prvky bez ohledu na to, do kterého jazyka patří. Navigační dotazy proti tomuto indexu vracejí výsledky, které překračují hranice jazyků, protože index modeluje celý systém, nikoli jeho jazykově specifickou část.
Platforma explicitně modeluje mezijazyková rozhraní, která standardní nástroje ignorují. Krok JCL, který vyvolává program v COBOLu podle názvu, je v grafu křížových odkazů reprezentován jako závislost, která propojuje krok JCL s programovou jednotkou v COBOLu. Metoda Java, která zapisuje do databázové tabulky, je reprezentována jako datová závislost, která propojuje kód Java s definicí tabulky a odtud s jakýmkoli jiným jazykem, který čte stejnou tabulku. COBOLská učebnice, na kterou odkazuje více programů, je reprezentována jako sdílená definice, takže jakákoli změna struktury učebnice okamžitě zobrazí všechny programy, kterých se změna ovlivní, bez ohledu na jazyk. Toto explicitní modelování mezijazykových závislostí odlišuje skutečnou platformu pro navigaci mezi jazyky od souboru jazykově specifických nástrojů fungujících paralelně.
SMART TS XLSchopnost analýzy dopadů demonstruje praktickou hodnotu tohoto sjednoceného modelu. Když vývojář potřebuje pochopit důsledky změny sdílené komponenty, jako je definice dat v COBOLu, prvek schématu databáze, rozhraní Java nebo procedura JCL, platforma sleduje graf závislostí z dané komponenty napříč všemi jazykovými hranicemi a vrací kompletní obraz o tom, co bude ovlivněno. Výsledek je prezentován jako přehledná zpráva uspořádaná podle jazyka, komponenty a konkrétního referenčního umístění, což vývojářům poskytuje kompletní informace, které potřebují před provedením změny, a nikoli až dodatečně. Tato schopnost přímo řeší akumulaci rizik popsanou v předchozí části a převádí neurčené riziko napříč jazyky na kvantifikovaný a vyčíslitelný dopad.
Navigace mezi jazyky jako vlastnost celého systému
Ústředním poznatkem tohoto článku je, že navigace kódu ve vícejazyčných prostředích je vlastností celého systému, nikoli jednotlivého jazykového nástroje. IDE, které perfektně zvládá COBOL, a samostatné IDE, které perfektně zvládá Javu, společně nevytvářejí systém, který by se pohyboval na hranici COBOL-Java. Vytvářejí dva nezávislé navigační systémy s mezerou mezi nimi a právě v této mezeře se nacházejí nejdůležitější vztahy v systému.
Překlenutí této mezery vyžaduje jiný druh nástroje: takový, který modeluje systém jako celek, reprezentuje vztahy napříč jazykovými hranicemi jako prvotřídní entity a poskytuje navigaci, která tyto vztahy sleduje, kamkoli vedou. Pro organizace provozující komplexní, vícejazyčné systémy v podnikovém měřítku není tato schopnost luxusem. Každý den vývoje bez ní je dnem, kdy se náklady na selhání mezijazyčné navigace hromadí: v podobě pomalejšího zavádění, delších incidentů, rizikovějších změn a postupné koncentrace nenahraditelných znalostí u jednotlivců, kteří ručně vytvořili mezijazyčné mentální modely, které tyto nástroje nemohou poskytnout.