Kanske,
I den här artikeln, som är översiktlig till sin natur, kommer vi att försöka titta på några av grunderna i Eclipse-arkitekturen som en plattform för att bygga integrerade utvecklingsverktyg och ge en första uppfattning om Eclipse-komponenterna som utgör grunden för tekniken plattform för den "nya konfiguratorn" 1C: Enterprise.
Introduktion till Eclipse Architecture
Låt oss först titta på några allmänna aspekter av Eclipse-arkitekturen med hjälp av exemplet
Först och främst bör det noteras att Eclipse kännetecknas av en ganska tydlig arkitektonisk skiktning, med separation av språkoberoende funktionalitet från funktionalitet utformad för att stödja specifika programmeringsspråk, och separation av UI-oberoende "kärn"-komponenter från komponenter associerade med stödjande användargränssnitt.
Således definierar Eclipse-plattformen en gemensam, språkoberoende infrastruktur, och Java-utvecklingsverktygen lägger till en fullfjädrad Java IDE till Eclipse. Både Eclipse Platform och JDT består av flera komponenter, som var och en tillhör antingen en UI-oberoende "kärna" eller ett UI-lager (Figur 1).
Ris. 1. Eclipse Platform och JDT
Låt oss lista huvudkomponenterna i Eclipse Platform:
- Runtime — Definierar plugin-infrastrukturen. Eclipse kännetecknas av en modulär arkitektur. Eclipse är i huvudsak en samling av "förlängningspunkter" och "förlängningar".
- Arbetsyta — Leder ett eller flera projekt. Ett projekt består av mappar och filer som mappas direkt till filsystemet.
- Standard Widget Toolkit (SWT) - Ger grundläggande användargränssnittselement integrerade med operativsystemet.
- JFace — Tillhandahåller ett antal UI-ramverk byggda ovanpå SWT.
- Arbetsbänk — Definierar Eclipse UI-paradigmet: redaktörer, vyer, perspektiv.
Det måste sägas att Eclipse Platform också tillhandahåller många andra användbara komponenter för att bygga integrerade utvecklingsverktyg, inklusive Debug, Compare, Search och Team. Särskilt bör nämnas JFace Text - grunden för att bygga "smarta redigerare" av källkod. Tyvärr är inte ens en översiktlig undersökning av dessa komponenter, såväl som UI-lagerkomponenterna, möjlig inom ramen för denna artikel, så i resten av detta avsnitt kommer vi att begränsa oss till en översikt av de viktigaste "kärnkomponenterna" i Eclipse Platform och JDT.
Core Runtime
Eclipse-plugin-infrastrukturen är baserad på
Core Workspace
Nästan alla integrerade utvecklingsmiljöer som är byggda ovanpå Eclipse-plattformen fungerar med Eclipse-arbetsytan. Det är arbetsytan som vanligtvis innehåller källkoden för applikationen som utvecklats i IDE. Arbetsytan mappas direkt till filsystemet och består av projekt som innehåller mappar och filer. Dessa projekt, mappar och filer kallas Resurser arbetsyta. Workspace-implementeringen i Eclipse fungerar som en cache i förhållande till filsystemet, vilket gör det möjligt att avsevärt påskynda genomgången av resursträdet. Dessutom tillhandahåller workspace en rad tilläggstjänster, bl.a
Core Resources-komponenten (org.eclipse.core.resources plugin) är ansvarig för att stödja arbetsytan och dess resurser. I synnerhet ger denna komponent programmatisk åtkomst till arbetsytan i formuläret resursmodeller. För att arbeta effektivt med denna modell behöver kunderna ett enkelt sätt att presentera en länk till en resurs. I det här fallet skulle det vara önskvärt att dölja objektet som direkt lagrar resursens tillstånd i modellen från klientåtkomst. Annars kan klienten, vid t.ex. radering av en fil, fortsätta att hålla ett objekt som inte längre finns i modellen, med efterföljande problem. Eclipse löser detta problem med något som kallas hantera resurs. Handle fungerar som en nyckel (det känner bara till sökvägen till resursen i arbetsytan) och kontrollerar fullständigt åtkomsten till det interna modellobjektet, som direkt lagrar information om resursens tillstånd. Denna design är en variant av mönstret
Ris. Figur 2 illustrerar handtag/kroppsformspråket som det tillämpas på resursmodellen. IResource-gränssnittet representerar handtaget för en resurs och är ett API, till skillnad från klassen Resource, som implementerar detta gränssnitt, och klassen ResourceInfo, som representerar kroppen, som inte är API:er. Vi betonar att handle bara känner till sökvägen till resursen i förhållande till arbetsytans rot och inte innehåller en länk till resursinformation. Resursinfoobjekt bildar ett så kallat ”elementträd”. Denna datastruktur är helt materialiserad i minnet. För att hitta resursinformationsinstansen som motsvarar ett handtag, korsas elementträdet enligt sökvägen som är lagrad i det handtaget.
Ris. 2. IResource och ResourceInfo
Som vi kommer att se senare används resursmodellens grundläggande design (vi kan kalla den handtagsbaserad) i Eclipse även för andra modeller. För nu, låt oss lista några av de utmärkande egenskaperna hos denna design:
- Handtag är ett värdeobjekt. Värdeobjekt är oföränderliga objekt vars likhet inte bygger på identitet. Sådana föremål kan säkert användas som nyckel i hashade behållare. Flera instanser av handtag kan referera till samma resurs. För att jämföra dem måste du använda metoden equals(Object).
- Handle definierar beteendet hos en resurs, men innehåller inte information om resursens tillstånd (den enda data som lagras är "nyckeln", sökvägen till resursen).
- Handle kan referera till en resurs som inte finns (antingen en resurs som ännu inte har skapats eller en resurs som redan har tagits bort). Förekomsten av en resurs kan kontrolleras med metoden IResource.exists() .
- Vissa operationer kan implementeras enbart baserat på information som lagras i själva handtaget (så kallade handle-only operations). Exempel är IResource.getParent(), getFullPath(), etc. Resursen behöver inte finnas för att en sådan operation ska lyckas. Operationer som kräver att en resurs existerar för att lyckas kastar ett CoreException om resursen inte finns.
Eclipse tillhandahåller en effektiv mekanism för att meddela ändringar i arbetsytans resurser (Figur 3). Resurser kan ändras antingen som ett resultat av åtgärder som utförs inom själva Eclipse IDE eller som ett resultat av synkronisering med filsystemet. I båda fallen får kunder som prenumererar på aviseringar detaljerad information om förändringarna i form av "resursdelta". Ett delta beskriver förändringar mellan två tillstånd i ett resursträd för arbetsytan (under-) och är i sig ett träd, vars varje nod beskriver en ändring av en resurs och innehåller en lista med delta på nästa nivå som beskriver ändringar av underordnade resurser.
Ris. 3. IResourceChangeEvent och IResourceDelta
Meddelandemekanismen baserad på resursdelta har följande egenskaper:
- En enda förändring och många förändringar beskrivs med samma struktur, eftersom deltat är byggt med principen om rekursiv sammansättning. Abonnentklienter kan behandla meddelanden om resursändringar med hjälp av rekursiv nedstigning genom ett träd med delta.
- Deltat innehåller fullständig information om ändringar av resursen, inklusive dess rörelse och/eller ändringar i "markörerna" som är associerade med den (till exempel representeras kompileringsfel som markörer).
- Eftersom resursreferenser görs via handtaget, kan delta naturligt referera till en fjärrresurs.
Som vi snart kommer att se är huvudkomponenterna i utformningen av meddelandemekanismen för resursmodelländringar också relevanta för andra handtagsbaserade modeller.
JDT kärna
Eclipse arbetsyta resursmodellen är en grundläggande språkagnostisk modell. JDT Core-komponenten (plugin org.eclipse.jdt.core) tillhandahåller ett API för att navigera och analysera arbetsytans struktur ur ett Java-perspektiv, den så kallade "Java-modellen" (Java-modell). Detta API är definierat i termer av Java-element, till skillnad från den underliggande resursmodellens API, som definieras i termer av mappar och filer. Huvudgränssnitten för Java-elementträdet visas i fig. 4.
Ris. 4. Java Model Elements
Java-modellen använder samma handtag/kroppsspråk som resursmodellen (Figur 5). IJavaElement är handtaget, och JavaElementInfo spelar rollen som kroppen. IJavaElement-gränssnittet definierar ett protokoll som är gemensamt för alla Java-element. Några av dess metoder är endast handtag: getElementName(), getParent(), etc. JavaElementInfo-objektet lagrar tillståndet för motsvarande element: dess struktur och attribut.
Ris. 5. IJavaElement och JavaElementInfo
Java-modellen har vissa skillnader i implementeringen av den grundläggande handtag/kroppsdesignen jämfört med resursmodellen. Som noterats ovan, i resursmodellen, är elementträdet, vars noder är resursinformationsobjekt, helt i minnet. Men Java-modellen kan ha ett betydligt större antal element än resursträdet, eftersom den också representerar den interna strukturen för .java- och .class-filer: typer, fält och metoder.
För att undvika att fullständigt materialisera hela trädet av element i minnet, använder Java-modellimplementeringen en LRU-cache med begränsad storlek med elementinformation, där nyckeln är handle IJavaElement. elementinfoobjekt skapas på begäran när elementträdet navigeras. I det här fallet kastas de minst frekvent använda objekten från cachen, och modellens minnesförbrukning förblir begränsad till den angivna cachestorleken. Detta är en annan fördel med handtagsbaserad design, som helt döljer sådana implementeringsdetaljer från klientkoden.
Mekanismen för att meddela ändringar av Java-element liknar i allmänhet mekanismen för att spåra ändringar av arbetsyteresurser som diskuterats ovan. En klient som vill övervaka ändringar i Java-modellen prenumererar på meddelanden, som representeras som ett ElementChangedEvent-objekt som innehåller en IJavaElementDelta (Figur 6).
Ris. 6. ElementChangedEvent och IJavaElementDelta
Java-modellen innehåller inte information om metodkroppar eller namnupplösning, så för detaljerad analys av kod skriven i Java tillhandahåller JDT Core ytterligare en (icke-handtagsbaserad) modell:
Eftersom syntaxträd kan förbruka en betydande mängd minne cachar JDT endast en AST för den aktiva redigeraren. Till skillnad från Java-modellen ses AST vanligtvis som en "mellanliggande", "tillfällig" modell, vars element klienter inte bör ha referenser till utanför sammanhanget för den operation som ledde till skapandet av AST.
De listade tre modellerna (Java-modell, AST, bindningar) utgör tillsammans grunden för att bygga "intelligenta utvecklingsverktyg" i JDT, inklusive en kraftfull Java-editor med olika "hjälpare", olika åtgärder för att bearbeta källkod (inklusive att organisera en lista över import namn och formatering enligt den anpassade stilen), sök- och refaktoreringsverktyg. I det här fallet spelar Java-modellen en speciell roll, eftersom det är den som används som grund för en visuell representation av strukturen för applikationen som utvecklas (till exempel i Package Explorer, Outline, Search, Call Hierarki och Typ Hierarki).
Eclipse-komponenter som används i 1C:Enterprise Developments Tools
I fig. Figur 7 visar Eclipse-komponenterna som utgör grunden för teknikplattformen för 1C:Enterprise Development Tools.
Ris. 7. Eclipse som plattform för 1C:Enterprise Development Tools
Eclipse Plattform tillhandahåller grundläggande infrastruktur. Vi tittade på några aspekter av denna infrastruktur i föregående avsnitt.
Som alla verkligt generella verktyg är EMF lämplig för att lösa ett brett spektrum av modelleringsproblem, men vissa klasser av modeller (till exempel de handtagsbaserade modellerna som diskuteras ovan) kan kräva mer specialiserade modelleringsverktyg. Att prata om EMF är en otacksam uppgift, särskilt inom de begränsade gränserna för en artikel, eftersom detta är föremål för en separat bok, och en ganska tjock sådan. Låt oss bara notera att det högkvalitativa systemet av generaliseringar som ligger till grund för EMF möjliggjorde uppkomsten av en hel rad projekt dedikerade till modellering, som ingår i toppnivåprojektet
1C:Enterprise Development Tools använder aktivt både EMF själv och ett antal andra Eclipse Modeling-projekt. I synnerhet är Xtext en av grunderna för utvecklingsverktyg för sådana 1C:Enterprise-språk som det inbyggda programmeringsspråket och frågespråket. En annan grund för dessa utvecklingsverktyg är Eclipse Handly-projektet, som vi kommer att diskutera mer i detalj (av de listade Eclipse-komponenterna är det fortfarande den minst kända).
De grundläggande arkitektoniska principerna för handtagsbaserade modeller, såsom handtag/kroppsformspråket, diskuterades ovan med hjälp av resursmodellen och Java-modellen som exempel. Den noterade också att både resursmodellen och Java-modellen är viktiga grunder för Eclipse Java-utvecklingsverktyg (JDT). Och eftersom nästan alla *DT Eclipse-projekt har en arkitektur som liknar JDT, skulle det inte vara en stor överdrift att säga att handtagsbaserade modeller ligger till grund för många, om inte alla IDE:er byggda ovanpå Eclipse Platform. Till exempel har Eclipse C/C++ Development Tooling (CDT) en handtagsbaserad C/C++-modell som spelar samma roll i CDT-arkitekturen som Java-modellen gör i JDT.
Innan Handly erbjöd Eclipse inga specialiserade bibliotek för att bygga handtagsbaserade språkmodeller. De modeller som för närvarande finns skapades huvudsakligen genom att direkt anpassa Java-modellkoden (aka kopiera/klistra in), i de fall det tillåter Eclipse Public License (EPL). (Självklart är detta vanligtvis inte en juridisk fråga för t.ex. Eclipse projekterar sig själva, men inte för produkter med stängd källkod.) Förutom dess inneboende slumpmässighet, introducerar denna teknik välkända problem: kodduplicering som introduceras av vid anpassning till fel, etc. Vad som är värre är att de resulterande modellerna förblir "saker i sig själva" och inte drar fördel av potentialen för enande. Men att isolera vanliga koncept och protokoll för handtagsbaserade språkmodeller kan leda till skapandet av återanvändbara komponenter för att arbeta med dem, liknande vad som hände i fallet med EMF.
Det är inte så att Eclipse inte förstod dessa problem. Tillbaka 2005
I en viss mening är Handly-projektet utformat för att lösa ungefär samma problem som EMF, men för handtagsbaserade modeller, och främst språk (dvs representerar delar av strukturen för något programmeringsspråk). De huvudsakliga målen som sattes upp när du designade Handly listas nedan:
- Identifiering av ämnesområdets huvudsakliga abstraktioner.
- Minska arbetet och förbättra kvaliteten på implementeringen av handtagsbaserade språkmodeller genom återanvändning av kod.
- Tillhandahåller ett enhetligt API på metanivå till de resulterande modellerna, vilket gör det möjligt att skapa gemensamma IDE-komponenter som fungerar med språkhandtagsbaserade modeller.
- Flexibilitet och skalbarhet.
- Integration med Xtext (i ett separat lager).
För att lyfta fram vanliga koncept och protokoll analyserades befintliga implementeringar av språkhandtagsbaserade modeller. Huvudgränssnitten och grundläggande implementeringar som tillhandahålls av Handly visas i fig. 8.
Ris. 8. Vanliga gränssnitt och grundläggande implementeringar av Handly-element
IElement-gränssnittet representerar handtaget för ett element och är gemensamt för element i alla Handly-baserade modeller. Den abstrakta klassen Element implementerar den generaliserade handtag/kroppsmekanismen (fig. 9).
Ris. 9. IElement och generisk handtag/kroppsimplementering
Dessutom tillhandahåller Handly en generaliserad mekanism för att meddela om ändringar i modellelement (Fig. 10). Som du kan se liknar den i stort sett de meddelandemekanismer som implementerats i resursmodellen och Java-modellen, och använder IElementDelta för att tillhandahålla en enhetlig representation av information om elementändringar.
Ris. 10. Allmänna gränssnitt och grundläggande implementeringar av Handly-meddelandemekanismen
Handly-delen som diskuterats ovan (fig. 9 och 10) kan användas för att representera nästan alla handtagsbaserade modeller. För att skapa språklig modeller erbjuder projektet ytterligare funktionalitet - i synnerhet gemensamma gränssnitt och grundläggande implementeringar för element i källtextstrukturen, den s.k. källelement (Fig. 8). ISourceFile-gränssnittet representerar en källfil och ISourceConstruct representerar ett element i källfilen. De abstrakta klasserna SourceFile och SourceConstruct implementerar generaliserade mekanismer för att stödja arbete med källfiler och deras element, till exempel att arbeta med textbuffertar, binda till koordinaterna för ett element i källtexten, stämma av modeller med det aktuella innehållet i en arbetskopieringsbuffert , etc. Att implementera dessa mekanismer är vanligtvis en utmaning, och Handly kan avsevärt minska ansträngningen att utveckla handtagsbaserade språkmodeller genom att tillhandahålla basimplementeringar av hög kvalitet.
Utöver de centrala mekanismerna som anges ovan tillhandahåller Handly en infrastruktur för textbuffertar och ögonblicksbilder, stöd för integration med källkodsredigerare (inklusive direktintegrering med Xtext-redigeraren), samt några vanliga UI-komponenter som arbeta med källkodsredigerare Handly modeller som outline framework. För att illustrera dess kapacitet ger projektet flera exempel, inklusive en implementering av Java-modellen i Handly. (Jämfört med den fullständiga implementeringen av Java-modellen i JDT, är denna modell avsiktligt något förenklad för större tydlighet.)
Som nämnts tidigare låg och fortsätter att ligga på skalbarhet och flexibilitet ett stort fokus under Handlys första design och efterföljande utveckling.
Handtagsbaserade modeller skalar i princip ganska bra "by design". Till exempel låter handtag/kroppsformspråket dig begränsa mängden minne som konsumeras av en modell. Men det finns också nyanser. Sålunda, när man testade Handly för skalbarhet, upptäcktes ett problem i implementeringen av meddelandemekanismen - när ett stort antal element ändrades tog det för mycket tid att konstruera delta. Det visade sig att samma problem fanns i JDT Java-modellen, från vilken motsvarande kod en gång anpassades. Vi fixade buggen i Handly och förberedde en liknande patch för JDT, som togs emot med tacksamhet. Detta är bara ett exempel där introduktion av Handly i befintliga modellimplementeringar potentiellt kan vara användbart, eftersom en sådan bugg i det här fallet skulle kunna fixas på bara ett ställe.
För att göra det tekniskt möjligt att implementera Handly i befintliga modellimplementeringar måste biblioteket ha betydande flexibilitet. Huvudproblemet är att upprätthålla bakåtkompatibilitet över API-modellen. Detta problem löstes i
Flexibilitet har också andra aspekter. Till exempel lägger Handly nästan inga begränsningar på modellens struktur och kan användas för att modellera både generella och domänspecifika språk. När man konstruerar strukturen för källfilen föreskriver Handly inte någon speciell form av AST-representation och kräver i princip inte ens närvaron av en AST själv, vilket säkerställer kompatibilitet med nästan vilken analysmekanism som helst. Slutligen stöder Handly full integration med Eclipse arbetsyta, men kan också arbeta direkt med filsystem tack vare dess integration med
Aktuell version
Som nämnts ovan är en av dessa produkter 1C:Enterprise Development Tools, där Handly används från allra första början för att modellera delar av högnivåstrukturen för sådana 1C:Enterprise-språk som det inbyggda programmeringsspråket och frågespråket . En annan produkt är mindre känd för allmänheten. Detta
Vi hoppas att efter releasen av version 1.0 med en garanti för API-stabilitet och att projektet lämnar inkubationsläget, kommer Handly att ha nya användare. Under tiden fortsätter projektet att testa och ytterligare förbättra API:t, och släpper två "stora" utgåvor per år - i juni (samma datum som den samtidiga Eclipse-releasen) och december, vilket ger ett förutsägbart schema som användare kan lita på. Vi kan också tillägga att projektets "buggfrekvens" förblir på en konsekvent låg nivå och Handly har arbetat tillförlitligt i produkter från tidiga användare sedan de allra första versionerna. För att utforska Eclipse Handly ytterligare kan du använda
Källa: will.com