Мусіць,
У дадзеным артыкуле, агляднай па сваім характары, мы паспрабуем разгледзець некаторыя асновы архітэктуры Eclipse як платформы для пабудовы інтэграваных сродкаў распрацоўкі і даць пачатковае ўяўленне пра кампаненты Eclipse, якія ўтвараюць падмурак тэхналагічнай платформы для "новага канфігуратара" 1C: Прадпрыемства,
Увядзенне ў архітэктуру Eclipse
Разгледзім спачатку некаторыя агульныя аспекты архітэктуры Eclipse на прыкладзе
У першую чаргу варта адзначыць, што для Eclipse характэрна досыць выразнае архітэктурнае расслаенне, з аддзяленнем моўна-незалежнай функцыянальнасці ад функцыянальнасці, прызначанай для падтрымкі пэўных моў праграмавання, і аддзяленнем UI-незалежных "ядзерных" (core) кампанент ад кампанентаў, злучаных з падтрымкай карыстацкага інтэрфейсу.
Так, Eclipse Platform вызначае агульную, моўна-незалежную інфраструктуру, а Java development tools дадаюць да Eclipse поўнафункцыянальную Java IDE. Як Eclipse Platform, так і JDT складаюцца з некалькіх кампанентаў, кожная з якіх адносіцца або да UI-незалежнага "ядра", або да пласта UI (мал. 1).
Мал. 1. Eclipse Platform і JDT
Пералічоны асноўныя кампаненты Eclipse Platform:
- Час выканання - Вызначае інфраструктуру плагінаў. Для Eclipse характэрна модульная архітэктура. Па сутнасці, Eclipse з'яўляецца калекцыяй "кропак пашырэння" і "пашырэнняў".
- Працоўная прастора - Кіруе адным ці некалькімі праектамі. Праект складаецца з тэчак і файлаў, якія адлюстроўваюцца непасрэдна на файлавую сістэму.
- Standard Widget Toolkit (SWT) - Дае базавыя элементы карыстацкага інтэрфейсу, інтэграваныя з аперацыйнай сістэмай.
- JFace — Дае шэраг UI фрэймворкаў, пабудаваных па-над SWT.
- Варштат - Вызначае UI-парадыгму Eclipse: рэдактары, уяўленні, перспектывы.
Трэба сказаць, што Eclipse Platform дае і мноства іншых карысных кампанентаў для пабудовы інтэграваных сродкаў распрацоўкі, сярод якіх можна адзначыць Debug, Compare, Search, і Team. Асобна варта згадаць JFace Text - аснову для пабудовы "разумных рэдактараў" зыходнага кода. Нажаль, нават беглы разгляд гэтых кампанент, роўна як і кампанент UI-пласта не ўяўляецца магчымым у рамках дадзенага артыкула, таму ў пакінутай частцы гэтай часткі мы абмяжуемся аглядам асноўных "ядзерных" кампанент Eclipse Platform і JDT.
Core Runtime
Інфраструктура плагінаў Eclipse заснавана на
Core Workspace
Практычна любое інтэграванае асяроддзе распрацоўкі, пабудаванае на аснове Eclipse Platform, працуе з Eclipse workspace. Менавіта workspace звычайна змяшчае зыходны код распрацоўванага ў IDE прыкладанні. Workspace напрамую адлюстроўваецца на файлавую сістэму і складаецца з праектаў, якія змяшчаюць тэчкі і файлы. Гэтыя праекты, тэчкі, і файлы называюцца рэсурсамі workspace. Рэалізацыя workspace у Eclipse служыць як бы кэшам па стаўленні да файлавай сістэмы, што дазваляе прыкметна паскорыць абыход дрэва рэсурсаў. Акрамя таго, workspace дае шэраг дадатковых сэрвісаў, у тым ліку
За падтрымку workspace і яго рэсурсаў адказвае кампанента Core Resources (убудова org.eclipse.core.resources). У прыватнасці, гэтая кампанента дае праграмны доступ да workspace у выглядзе мадэлі рэсурсаў. Для эфектыўнай працы з гэтай мадэллю кліентам патрэбен просты спосаб прадстаўлення спасылкі на рэсурс. Пры гэтым аб'ект, непасрэдна які захоўвае стан рэсурсу ў мадэлі, было б пажадана схаваць ад кліенцкага доступу. Інакш, у выпадку, напрыклад, выдаленні файла, кліент мог бы працягваць утрымліваць аб'ект, якога ўжо няма ў мадэлі, з вынікаючымі адгэтуль праблемамі. Eclipse вырашае гэтую задачу, выкарыстоўваючы так званы апрацоўваць рэсурсу. Handle выступае ў ролі ключа (ён ведае толькі шлях да рэсурсу ў workspace) і цалкам кантралюе доступ да ўнутранага аб'екта мадэлі, які непасрэдна захоўвае інфармацыю аб стане рэсурса. Дадзены дызайн з'яўляецца варыяцыяй патэрна
Мал. 2 ілюструе ідыёму Handle / Body ў дачыненні да мадэлі рэсурсаў. Інтэрфейс IResource уяўляе handle рэсурсу і з'яўляецца API, у адрозненне ад класа Resource, які рэалізуе гэты інтэрфейс, а таксама класа ResourceInfo, уяўлялага body, якія API не з'яўляюцца. Падкрэслім, што handle ведае толькі шлях да рэсурсу адносна кораня workspace і не ўтрымоўвае ў сабе спасылку на resource info. Аб'екты resource info утвораць так званае "дрэва элементаў" (element tree). Гэтая структура дадзеных цалкам матэрыялізаваная ў памяці. Каб знайсці асобнік resource info, які адпавядае некатораму handle, element tree абыходзіцца ў адпаведнасці з шляхам, якія захоўваюцца ў гэтым handle.
Мал. 2. IResource і ResourceInfo
Як мы ўбачым у далейшым, базавы дызайн мадэлі рэсурсаў (можна назваць яго handle-based) выкарыстоўваецца ў Eclipse і для іншых мадэляў. А пакуль пералічоны некаторыя адметныя ўласцівасці гэтага дызайну:
- Handle з'яўляецца аб'ектам-значэннем (value object). Аб'екты-значэнні - гэта немутабельныя (immutable) аб'екты, роўнасць якіх не грунтуецца на ідэнтычнасці. Такія аб'екты могуць бяспечна выкарыстоўвацца ў якасці ключа ў хэшаваных кантэйнерах. Некалькі экзэмпляраў handle могуць спасылацца на адзін і той жа рэсурс. Для іх параўнання трэба выкарыстоўваць метад equals(Object).
- Handle вызначае паводзіны рэсурсу, але не змяшчае інфармацыю аб стане рэсурсу (адзіныя дадзеныя, якія ён захоўвае, гэта "ключ", шлях да рэсурсу).
- Handle можа спасылацца на неіснуючы рэсурс (альбо рэсурс, які яшчэ не створаны, альбо рэсурс, які ўжо выдалены). Існаванне рэсурса можна праверыць з дапамогай метаду IResource.exists().
- Некаторыя аперацыі могуць быць рэалізаваны зыходзячы выключна з інфармацыі, якая захоўваецца ў самым handle (так званыя handle-only аперацыі). Прыкладамі з'яўляюцца IResource.getParent(), getFullPath(), і да т.п. Рэсурс неабавязкова павінен існаваць для паспяховага выканання такой аперацыі. Аперацыі, для паспяховага выканання якіх патрабуецца, каб рэсурс існаваў, выкідваюць выключэнне (CoreException), калі рэсурс не існуе.
Eclipse дае эфектыўны механізм натыфікацыі аб зменах рэсурсаў workspace (мал. 3). Рэсурсы могуць змяняцца як у выніку дзеянняў, выкананых у самой Eclipse IDE, так і ў выніку выкананні сінхранізацыі з файлавай сістэмай. У абодвух выпадках якія падпісаліся на натыфікацыі кліентам падаецца дэталёвая інфармацыя аб зменах у выглядзе "рэсурсных дэльт" (resource delta). Дэльта апісвае змены паміж двума станамі (пад-)дрэва рэсурсаў workspace і сама з'яўляецца дрэвам, кожны вузел якога апісвае змену некаторага рэсурсу і ўтрымоўвае спіс дэльт наступнага ўзроўня, якія апісваюць змены даччыных рэсурсаў.
Мал. 3. IResourceChangeEvent і IResourceDelta
Заснаваны на рэсурсных дэльтах механізм натыфікацыі валодае наступнымі характарыстыкамі:
- Адзіная змена і мноства змен апісваюцца з дапамогай адной і той жа структуры, паколькі дэльта будуецца па прынцыпе рэкурсіўнай кампазіцыі. Кліенты-падпісчыкі могуць апрацоўваць натыфікацыі аб змене рэсурсаў з дапамогай рэкурсіўнага спуску па дрэве дэльт.
- Дэльта змяшчае поўную інфармацыю аб змяненні рэсурсу, у тым ліку яго перамяшчэнне і / або змяненне асацыіраваных з ім «маркераў» (у выглядзе маркераў прадстаўляюцца, напрыклад, памылкі кампіляцыі).
- Паколькі спасылкі на рэсурс робяцца праз handle, дэльта можа натуральным чынам спасылацца на выдалены рэсурс.
Як мы неўзабаве ўбачым, асноўныя складнікі дызайну механізму натыфікацыі аб змене мадэлі рэсурсаў актуальныя і для іншых handle-based мадэляў.
JDT Core
Мадэль рэсурсаў Eclipse workspace з'яўляецца фундаментальнай моўна-незалежнай мадэллю. Кампанента JDT Core (убудова org.eclipse.jdt.core) падае API для навігацыі і аналізу структуры workspace з пункта гледжання Java, так званую "мадэль Java" (Java model). Гэты API вызначаны ў тэрмінах элементаў Java, у адрозненне ад ніжэйлеглага API мадэлі рэсурсаў, які вызначаны ў тэрмінах тэчак і файлаў. Асноўныя інтэрфейсы дрэва элементаў Java намаляваны на мал. 4.
Мал. 4. Элементы мадэлі Java
Мадэль Java выкарыстоўвае тую ж ідыёму handle/body, што і мадэль рэсурсаў (мал. 5). IJavaElement - гэта handle, а JavaElementInfo гуляе ролю body. Інтэрфейс IJavaElement вызначае пратакол, агульны для ўсіх элементаў Java. Некаторыя з яго метадаў з'яўляюцца handle-only: getElementName(), getParent(), і да т.п. Аб'ект JavaElementInfo захоўвае стан адпаведнага элемента: яго структуру і атрыбуты.
Мал. 5. IJavaElement і JavaElementInfo
Мадэль Java мае некаторыя адрозненні ў рэалізацыі базавага дызайну handle/body у параўнанні з мадэллю рэсурсаў. Як адзначалася вышэй, у мадэлі рэсурсаў element tree, вузламі якога з'яўляюцца аб'екты resource info, цалкам змяшчаецца ў памяці. Але ў мадэлі Java можа быць значна большая колькасць элементаў, чым у дрэве рэсурсаў, бо ў ёй прадстаўлена, у тым ліку, і ўнутраная структура .java і .class файлаў: тыпы, палі, і метады.
Каб пазбегнуць поўнай матэрыялізацыі ўсяго дрэва элементаў у памяці, рэалізацыя мадэлі Java выкарыстоўвае абмежаваны па памеры LRU-кэш element info, дзе ключом з'яўляецца handle IJavaElement. Аб'екты element info ствараюцца па запыце па меры таго як адбываецца рух дрэва элементаў. Пры гэтым найменш часта выкарыстоўваныя элементы выцясняюцца з кэша, і спажыванне памяці мадэллю застаецца абмежаваным зададзеным памерам кэша. Гэта яшчэ адна перавага handle-based дызайну, які цалкам хавае такія падрабязнасці рэалізацыі ад кліенцкага кода.
Механізм натыфікацыі аб змене элементаў Java у агульных рысах аналагічны разгледжанаму вышэй механізму адсочвання змен рэсурсаў workspace. Кліент, які жадае адсочваць змены ў мадэлі Java, падпісваецца на натыфікацыі, якія прадстаўляюцца ў выглядзе аб'екта ElementChangedEvent, які змяшчае IJavaElementDelta (мал. 6).
Мал. 6. ElementChangedEvent і IJavaElementDelta
Мадэль Java не ўтрымоўвае інфармацыю аб целе метадаў або дазволе імёнаў, таму для дэталёвага аналізу кода, напісанага на Java, JDT Core падае дадатковую (не handle-based) мадэль:
Паколькі сінтаксічныя дрэвы могуць спажываць значную колькасць памяці, JDT кэшуецца толькі адно AST, для актыўнага рэдактара. У адрозненне ад мадэлі Java, AST звычайна разглядаецца як "прамежкавая", "часовая" мадэль, на элементы якой кліентам не варта ўтрымліваць спасылкі па-за кантэкстам аперацыі, якая прывяла да стварэння AST.
Пералічаныя тры мадэлі (Java model, AST, bindings) сумесна з'яўляюцца асновай для пабудовы "інтэлектуальных сродкаў распрацоўкі" у JDT, сярод якіх магутны рэдактар Java з разнастайнымі "памочнікамі", розныя дзеянні па апрацоўцы зыходнага кода (сярод якіх арганізацыя спісу імпарту імёнаў і фарматаванне у адпаведнасці з настроеным стылем), інструменты пошуку і рэфактарынгу. Пры гэтым мадэль Java гуляе адмысловую ролю, паколькі менавіта яна выкарыстоўваецца ў якасці асновы для візуальнага падання структуры распрацоўванага прыкладання (напрыклад, у Package Explorer, Outline, Search, Call Hierarchy, і Type Hierarchy).
Кампаненты Eclipse, якія выкарыстоўваюцца ў 1С:Enterprise Developments Tools
На мал. 7 паказаны кампаненты Eclipse, якія ўтвараюць падмурак тэхналагічнай платформы для 1C: Enterprise Development Tools.
Мал. 7. Eclipse як платформа для 1С: Enterprise Development Tools
Eclipse Platform дае базавую інфраструктуру. Мы разгледзелі некаторыя аспекты гэтай інфраструктуры ў папярэднім раздзеле.
Як любы па-сапраўднаму ўніверсальная прылада, EMF падыходзіць для рашэння шырокага спектру задач, звязаных з мадэляваннем, але некаторыя класы мадэляў (напрыклад, разгледжаныя вышэй handle-based мадэлі) могуць мець патрэбу ў больш спецыялізаваных сродках мадэлявання. Распавядаць аб EMF - занятак няўдзячнае, асабліва ў абмежаваных рамках аднаго артыкула, паколькі гэта прадмет асобнай кнігі, і даволі тоўстай. Адзначым толькі, што якасная сістэма абагульненняў, пакладзеная ў аснову EMF, дазволіла з'явіцца на свет цэлым спектры праектаў, прысвечаных мадэляванню, якія ўваходзяць у праект верхняга ўзроўню.
1С: Enterprise Development Tools актыўна выкарыстоўваюць як EMF сам па сабе, так і шэраг іншых праектаў Eclipse Modeling. У прыватнасці, Xtext з'яўляецца адной з асноў сродкаў распрацоўкі для такіх моў 1С:Прадпрыемства, як убудаваная мова праграмавання і мова запытаў. Іншы асновай гэтых сродкаў распрацоўкі з'яўляецца праект Eclipse Handly, на якім мы спынімся больш падрабязна (з пералічаных кампанентаў Eclipse ён пакуль найменш вядомы).
Асноўныя архітэктурныя прынцыпы handle-based мадэляў, такія як ідыёма handle/body, разглядаліся вышэй на прыкладзе мадэлі рэсурсаў і Java-мадэлі. Тамака жа адзначалася, што і мадэль рэсурсаў, і мадэль Java з'яўляюцца важнымі асновамі для Eclipse Java development tools (JDT). А паколькі практычна ўсе *DT праекты Eclipse маюць архітэктуру аналагічную JDT, тое не будзе вялікім перабольшаннем сказаць, што handle-based мадэлі ляжаць у аснове шматлікіх, калі не ўсіх IDE, пабудаваных па-над Eclipse Platform. Напрыклад, у Eclipse C/C++ Development Tooling (CDT) маецца handle-based мадэль C/C++, гуляючая ў архітэктуры CDT тую ж самую ролю, што і Java-мадэль у JDT.
Да з'яўлення Handly, Eclipse не прапанаваў спецыялізаваных бібліятэк для пабудовы моўных handle-based мадэляў. Існыя зараз мадэлі ствараліся ў асноўным з дапамогай непасрэднай адаптацыі кода Java-мадэлі (aka copy/paste), у тых выпадках, калі гэта дазваляе Eclipse Public License (EPL). (Зразумела, што, скажам, для праектаў самога Eclipse гэта звычайна не з'яўляецца праблемай з юрыдычнага пункта гледжання, чаго не скажаш аб прадуктах з зачыненым зыходным кодам.) Апроч характэрнай для яе бессістэмнасці, такая методыка прыводзіць да добра вядомых праблем: дубляванню кода, прыўнесеным пры адаптацыі памылак, і да т.п. Што яшчэ горш, выніковыя мадэлі застаюцца "рэччу ў сабе" і не выкарыстоўваюць існуючы патэнцыял для уніфікацыі. А вылучэнне агульных паняццяў і пратаколаў для моўных handle-based мадэляў магло б прывесці да стварэння паўторна выкарыстоўваных кампанент для працы з імі, аналагічна таму, як гэта адбылося ў выпадку з EMF.
Нельга сказаць, што ў Eclipse не было разумення гэтых праблем. Яшчэ ў 2005 годзе
У пэўным сэнсе, праект Handly закліканы вырашаць прыкладна тыя ж задачы, што і EMF, але для handle-based мадэляў, і ў першую чаргу моўных (г.зн. уяўлялых элементы структуры некаторай мовы праграмавання). Ніжэй пералічаны асноўныя мэты, якія ставіліся пры праектаванні Handly:
- Вылучэнне асноўных абстракцый прадметнай вобласці.
- Скарачэнне намаганняў і павышэнне якасці рэалізацыі моўных handle-based мадэляў за кошт паўторнага выкарыстання кода.
- Прадастаўленне ўніфікаванага API мета-ўзроўню да выніковых мадэляў, якое робіць магчымым стварэнне агульных кампанент IDE, якія працуюць з моўнымі handle-based мадэлямі.
- Гнуткасць і маштабаванасць.
- Інтэграцыя з Xtext (у асобным пласце).
Для вылучэння агульных паняццяў і пратаколаў былі прааналізаваны існуючыя рэалізацыі моўных handle-based мадэляў. Асноўныя інтэрфейсы і базавыя рэалізацыі, якія прадстаўляюцца Handly, паказаны на мал. 8.
Мал. 8. Агульныя інтэрфейсы і базавыя рэалізацыі элементаў Handly
Інтэрфейс IElement уяўляе handle элемента і з'яўляецца агульным для элементаў усіх мадэляў, заснаваных на Handly. Абстрактны клас Element рэалізуе абагульнены механізм handle / body (мал. 9).
Мал. 9. IElement і абагульненая рэалізацыя handle/body
Акрамя таго, Handly падае абагульнены механізм натыфікацыі аб змене элементаў мадэлі (мал. 10). Як можна бачыць, у агульных рысах ён аналагічны механізмам натыфікацыі, рэалізаваным у мадэлі рэсурсаў і Java-мадэлі, і выкарыстоўвае IElementDelta для ўніфікаванага падання інфармацыі аб змене элемента.
Мал. 10. Агульныя інтэрфейсы і базавыя рэалізацыі механізма натыфікацыі Handly
Разгледжаная вышэй частка Handly (мал. 9 і 10) можа выкарыстоўвацца для падання практычна любых handle-based мадэляў. Для стварэння моўных мадэляў праект прапануе дадатковую функцыянальнасць – у прыватнасці, агульныя інтэрфейсы і базавыя рэалізацыі для элементаў структуры зыходнага тэксту, так званых source elements (мал. 8). Інтэрфейс ISourceFile уяўляе зыходны файл, а ISourceConstruct - элемент усярэдзіне зыходнага файла. Абстрактныя класы SourceFile і SourceConstruct рэалізуюць абагульненыя механізмы для падтрымкі працы з зыходнымі файламі і іх элементамі, напрыклад, працу з тэкставымі буферамі, прывязку да каардынатаў элемента ў зыходным тэксце, reconciling мадэлі з бягучым змесцівам буфера working copy, і да т.п. Рэалізацыя гэтых механізмаў звычайна з'яўляецца дастаткова няпростай задачай, і Handly можа істотна скараціць намаганні па распрацоўцы моўных handle-based мадэляў за кошт прадастаўлення якасных базавых рэалізацый.
Акрамя пералічаных вышэй асноўных механізмаў, Handly падае інфраструктуру тэкставых буфераў і "здымкаў" (snapshots), падтрымку інтэграцыі з рэдактарамі зыходнага кода (уключаючы рэалізаваную "са скрынкі" інтэграцыю з Xtext editor), а таксама некаторыя агульныя UI-кампаненты, якія працуюць з заснаванымі на Handly мадэлямі, такія як outline framework. Для ілюстрацыі сваіх магчымасцяў праект дае некалькі прыкладаў, у тым ліку і рэалізацыю мадэлі Java на Handly. (У параўнанні з поўнай рэалізацыяй Java-мадэлі ў JDT, дадзеная мадэль наўмысна некалькі спрошчана для большай навочнасці.)
Як было адзначана раней, сур'ёзная ўвага пры пачатковым праектаванні Handly і далейшым развіцці надавалася і працягвае надавацца маштабаванасці і гнуткасці.
У прынцыпе, handle-based мадэлі дастаткова добра маштабуюцца “by design”. Напрыклад, ідыёма handle/body дазваляе абмежаваць колькасць спажыванай мадэллю памяці. Але ёсць і нюансы. Так, пры выпрабаваннях Handly на маштабаванасць была выяўлена праблема ў рэалізацыі механізма натыфікацыі пры змене вялікай колькасці элементаў пабудова дэльт займала занадта шмат часу. Аказалася, што тая ж самая праблема прысутнічае і ў Java-мадэлі JDT, з якой быў у свой час адаптаваны адпаведны код. Мы выправілі памылку ў Handly і падрыхтавалі аналагічны патч для JDT, які быў з падзякай прыняты. Гэта ўсяго толькі адзін з прыкладаў, калі ўкараненне Handly у існуючыя рэалізацыі мадэляў магло б быць патэнцыйна карысным, бо ў гэтым выпадку такую памылку можна было б выправіць за ўсё ў адным месцы.
Каб зрабіць укараненне Handly у існуючыя рэалізацыі мадэляў тэхнічна магчымым, бібліятэка павінна валодаць значнай гнуткасцю. Асноўная праблема складаецца ў тым, каб захаваць зваротную сумяшчальнасць па API мадэлі. Гэтая задача была вырашана ў
Гнуткасць мае і іншыя аспекты. Напрыклад, Handly амаль не накладвае абмежаванняў на структуру мадэлі і можа выкарыстоўвацца як для мадэлявання моў агульнага прызначэння, так і для прадметна-арыентаваных моў. Пры пабудове структуры зыходнага файла, Handly не прадпісвае нейкую пэўную форму падання AST і ў прынцыпе не патрабуе нават самай наяўнасці AST, забяспечваючы, такім чынам, сумяшчальнасць з практычна любымі механізмамі сінтаксічнага аналізу. Нарэшце, Handly падтрымлівае паўнавартасную інтэграцыю з Eclipse workspace, але таксама можа працаваць і непасрэдна з файлавымі сістэмамі, дзякуючы інтэграцыі з
Бягучая версія
Як адзначалася вышэй, адзін з гэтых прадуктаў - 1C:Enterprise Development Tools, дзе Handly з самага пачатку выкарыстоўваецца для мадэлявання элементаў высокаўзроўневай структуры такіх моў 1С:Прадпрыемства, як убудаваная мова праграмавання і мова запытаў. Іншы прадукт менш вядомы шырокай публіцы. Гэта
Спадзяемся, што пасля выпуску версіі 1.0 з гарантыяй стабільнасці API і вынахадам праекту са стану інкубацыі, у Handly з'явяцца і новыя адаптэры. Пакуль жа праект працягвае абкатку і наступнае ўдасканаленне API, выпускаючы па двух вялікіх рэлізу ў год у чэрвені (у тую ж дату, што і адначасовы рэліз Eclipse) і снежні, забяспечваючы прадказальны графік, на які могуць спадзявацца адаптэры. Можна яшчэ дадаць, што паказчык "bug rate" праекту застаецца на стабільна нізкім узроўні і Handly з самых першых версій надзейна працуе ў прадуктах ранніх адаптараў. Для далейшага знаёмства з Eclipse Handly можна выкарыстоўваць
Крыніца: habr.com