Programování

Generování kódu pomocí Javadoc

Automatické generování kódu je ve vývoji softwaru stále běžnější, což je výsledkem potřeby skrýt složitost před vývojářem softwaru a přijetí různých standardních a de facto standardních rozhraní pro programování aplikací. Skrytí složitosti před vývojářem lze prokázat vytvořením tříd pahýlů a koster v CORBA z jejich popisů jazyků definic rozhraní a některými objektově orientovanými databázemi, které vytvářejí potřebný kód adaptéru pro přetrvávání a načítání objektů z databáze.

Java obsahuje mnoho API, která vývojáři Java považují za de facto standardy. Složitost těchto API se pohybuje od těch, které tvoří „jádro“ jazyka Java, až po ta, která se nacházejí v platformě Java 2 Enterprise Edition. Například rozhraní Java Database Connectivity API představuje sjednocující rozhraní pro interakci s databázemi od různých společností. Předpokládejme, že chcete, aby byl objekt Java schopen přetrvávat v databázi implementací jednoduchého Uložit() metoda, která mapuje atributy objektu na databázovou tabulku. Tato metoda by extrahovala atributy z objektu a použila rozhraní JDBC API k vytvoření příkazu JDBC, který je spuštěn proti databázi. Po implementaci Uložit() metoda pro několik tříd, začnete vidět podobnosti ve struktuře kódu a opakující se povahu implementace této metody. Základní atributy objektu je často nutné přepsat a „zapojit“ do příslušného Java API. To je situace, kdy může být generátor kódu užitečným nástrojem, který můžete mít ve své programovací sadě nástrojů.

Pomocí generátoru kódu můžete automatizovat proces některých zdlouhavých, opakujících se a chybových úkolů kódování. Skutečnost, že se připojujete ke známým API, zvyšuje užitečnost takového nástroje, protože je použitelný pro široké publikum vývojářů. Kromě toho lze některé obvykle „vlastní“ rámce specifické pro doménu považovat za pevné cíle API pro generátory kódu.

Generátor kódu může být časově úsporným nástrojem, který zvyšuje kvalitu kódu a zavádí formálnější a automatizovanější přístup k části vývojového cyklu. Další výhodou automatického generování kódu je synchronizace definic objektů napříč různými programovacími jazyky. V mnoha úzce vázaných aplikacích musí být stejný obchodní objekt (například objednávka na nákup akcií) konzistentně zastoupen v C ++, Java a SQL. Schopnost vydávat různé reprezentace ze společného modelu je k dispozici v různých modelových nástrojích; Zjistil jsem však, že je nepříjemné používat tyto nástroje k dosažení požadované úrovně přizpůsobení. Vyhrazený vlastní generátor kódu je dostatečně jednoduchý na to, aby se vytvořil, a nespája vás s konkrétním modelovacím nástrojem.

Cesta k Javadocu

Cesta, kterou se můj tým vydal k výběru Javadocu pro účely generování kódu, byla poněkud dlouhá a pravděpodobně běžná. V raných implementacích jsme pomocí Perl skriptů analyzovali vlastní gramatiku metadat v textovém souboru. Jednalo se o ad hoc řešení a přidávání dalších výstupních formátů bylo obtížné. Náš druhý, krátkodobý pokus byl upravit existující kompilátor IDL založený na Javě. Brzy jsme si uvědomili, že k odesílání rad do generátoru kódu bude nutné zavést další klíčová slova IDL. Vytvoření rozšíření IDL nebo dokonce od nuly pomocí nástrojů, jako jsou lex a yacc (které rozdělují zdrojový soubor na tokeny a definují kód, který je vyvolán pro každý rozpoznaný token), nebyly osobně chutné. (Další informace najdete v části Zdroje.)

Třetím slibnějším řešením bylo popsat metadata třídy pomocí XML. Definování schématu XML DTD a vytváření dokumentů XML k popisu tříd se zdálo jako přirozené přizpůsobení. Soubor pak bylo možné ověřit a snadno analyzovat. Abychom se vyhnuli začátku od nuly, napadlo mě, že se někdo musel pokusit vytvořit podobný XML DTD, a brzy jsem narazil na XMI. XMI je plnohodnotný popis UML pomocí XML a nyní se používá jako výměnný formát mezi nástroji UML. (Další informace najdete v části Zdroje.)

Dokumenty XML, které popisovaly třídy, však byly velmi podrobné a obtížně se upravovaly ručně. Existuje prostě příliš mnoho zdánlivě nadbytečných značek a popisů, které je třeba projít, abyste mohli změnit jeden atribut třídy. Manipulace se soubory XML na úrovni aplikační domény může být také docela zdlouhavá. IBM alphaWorks produkuje sadu nástrojů XMI, která výrazně usnadňuje zpracování dokumentů XML založených na XMI, ale rozhraní API sady XMI pro manipulaci s popisy tříd je extrémně podobné rozhraní Java Reflection nebo Doclet API. S ohledem na to se moje organizace rozhodla použít přístup doclet, který byl úspěšný.

Představujeme Javadoc

Javadoc je program používaný k vytvoření dokumentace Java API ve formátu HTML. Je distribuován jako součást sady Java SDK a jeho výstupní fáze je navržena tak, aby byla rozšiřitelná vytvořením doclet. Rozhraní Doclet API poskytuje infrastrukturu pro přístup ke všem aspektům souboru zdrojového kódu Java, který byl analyzován Javadocem. Pomocí rozhraní Doclet API, které je podobné rozhraní Reflection API, můžete projít popisem třídy Java, přistupovat k vlastním značkám Javadoc a zapisovat výstup do souboru. Standardní doclet, který se používá k výrobě dokumentace HTML, to dělá; při procházení celým zdrojovým kódem Java zapisuje soubory HTML. Podrobnější informace o Javadocu naleznete ve zdrojích.

Vytvořením jednoduchých tříd Java, které obsahují atributy a některé vlastní značky Javadoc, umožníte těmto třídám sloužit jako jednoduchý popis metadat pro generování kódu. Javadoc analyzuje tyto třídy metadat a vlastní doclety přistupují k informacím o třídě metadat a vytvářejí konkrétní implementace třídy metadat ve specifických programovacích jazycích, jako je Java, C ++ nebo SQL. Můžete také vytvořit varianty standardního docletu, který vytváří jednoduché tabulky HTML popisující třídu metadat, které by bylo vhodné zahrnout do dokumentu textového editoru. Tyto třídy Java metadat slouží stejnému účelu jako popis IDL, jehož syntaxe je podobná C ++.

Použití Javadocu jako nástroje pro generování kódu má několik výhod:

  • Nemusíte psát žádný parsovací kód; analýzu tříd metadat provádí Javadoc a je prezentována ve snadno použitelném rozhraní API.
  • Pomocí vlastních značek Javadoc přidáváte dostatečnou flexibilitu k definování speciálních háčků během generování kódu.
  • Jelikož jsou typy Java dobře definovány, int je 32 bitů; k dosažení této úrovně jasnosti proto nemusíte zavádět další klíčová slova primitivního typu.
  • Třídy metadat Java můžete zkontrolovat syntaxí a dalšími chybami kompilací.

Představujeme doclety

Před skokem do docletu používaného pro generování kódu představím jednoduchý příklad „Hello World“, který odhalí příslušné části toho, jak vytvářet, spouštět a hrát si s Doclet API. Ukázkový kód pro SimpleDoclet je uveden níže. (Zdrojový kód tohoto článku můžete získat v části Zdroje.) Pokud považujete tento kód za skutečně zdlouhavý pro skutečný program „Hello World“, web Sun nabízí ještě jednodušší doclet, který vám pomůže začít. (Viz Zdroje.)

balíček codegen.samples; import com.sun.javadoc. *; importovat java.text. *; public static boolean start (RootDoc ​​root) {// iterace ve všech třídách. ClassDoc [] třídy = root.classes (); for (int i = 0; i <classes.length; i ++) {// iterujte všemi metodami a vytiskněte jejich názvy. MethodDoc [] metody = třídy [i] .methods (); out („Metody“); ven("-------"); pro (int j = 0; j

Výše uvedený doclet vytiskne popisné informace o třídách, metodách, polích a některé informace o značce Javadoc třídy SimpleOrder.java vypsáno níže:

public class SimpleOrder {public SimpleOrder () {} public String getSymbol () {return Symbol; } public int getQuantity () {{popisný návrat Množství; } / ** * Platný symbol akcií. * * @see Další informace naleznete ve velké knize platných symbolů. * / soukromý řetězcový symbol; / ** * Celkový objem objednávky. * * @mytag Moje vlastní značka. * / private int Množství; soukromý řetězec OrderType; soukromý plovák Cena; soukromé trvání řetězce; private int AccountType; private int TransactionType; } 

Po kompilaci těchto souborů vyvoláte nástroj Javadoc pomocí tohoto příkazu:

javadoc -private -doclet codegen.samples.SimpleDoclet SimpleOrder.java 

The - soukromý Možnost říká Javadoc vystavit informace o soukromém poli a metodě a -doclet volba říká Javadocu, co má doclet vyvolat. Posledním parametrem je soubor, který má být analyzován. Výstupem programu je:

Načítání zdrojového souboru SimpleOrder.java ... Vytváření informací o Javadocu ... Metody ------- Metoda: name = getSymbol Metoda: name = getQuantity Fields ------ Pole: name = Symbol, comment = A valid symbol akcií., typ = java.lang.String; Název značky pole = @ viz Hodnota značky pole = Velká kniha platných symbolů pro více informací. Pole: name = Množství, komentář = Celkový objem objednávky., Type = int; Název značky pole = @mytag Hodnota značky pole = Moje vlastní značka. Pole: name = OrderType, comment =, type = java.lang.String; Pole: name = Price, comment =, type = float; Pole: name = Duration, comment =, type = java.lang.String; Pole: name = AccountType, comment =, type = int; Pole: name = TransactionType, comment =, type = int; 

Ukázkový kód ukazuje, že Doclet API je obsažen v balíčku com.sun.javadoc. Jelikož se připojujete k nástroji Javadoc a nevytváříte samostatnou aplikaci, Javadoc zavolá váš doclet z metody veřejný statický booleovský start (root RootDoc).

Jednou Start metoda se provádí, RootDoc uchovává všechny informace analyzované Javadocem. Potom můžete začít procházet všemi analyzovanými třídami vyvoláním metody třídy() na RootDoc. Tato metoda vrací a ClassDoc pole popisující všechny analyzované třídy. ClassDoc zase obsahuje metody jako pole () a metody(). Tyto metody se vracejí FieldDoc a MethodDoc pole, která popisují všechna pole a metody analyzované třídy. Metodu obsahují všechny třídy „Doc“ značky, který vrací a Štítek pole popisující vlastní i standardní značky Javadoc. Standardní značka použitá v tomto příkladu je @vidět.

The ven() metoda jednoduše zabalí standardní výstup a MessageFormat třída pomáhá formátovat výstup podle pevné šablony.

Opakovaně použitelné třídy pro generování kódu

Ve světle výše uvedeného příkladu doufám, že souhlasíte s tím, že vytváření vlastních docletů a extrahování informací o třídách pomocí rozhraní Doclet API je snadné. Další krok k analýze tříd Java a generování kódu do souboru je poměrně přímočarý. Abychom usnadnili vytváření doletů pro generování kódu, vyvinul jsem malou sadu rozhraní a abstraktních základních tříd. Níže je uveden diagram tříd těchto tříd nástrojů.

Rozhraní Výrobce definuje podpis metody public void make (ClassDoc classdoc) které použijete k interakci s vašimi generátory kódu. Abstraktní třída CodeMaker poskytuje výchozí implementace pro manipulaci se soubory a odsouzení, které jsou společné pro všechny generátory kódu. Specifické generátory kódu dědí z abstraktní základní třídy a poskytují implementaci udělat metoda. The udělat metoda má třídu ClassDoc jako argument, ne RootDoc. To způsobí Výrobce pro zadání logiky generování kódu na úrovni třídy.

Všechny třídy analyzované Javadocem jsou v metodě plug-in doclets zalomeny Start. Níže je uveden příklad toho, jak se to dělá (popsáno v souboru SimpleMakerDoclet.java):

public static boolean start (RootDoc ​​root) {ClassDoc [] třídy = root.classes (); // Nastavení CodeMakers pro spuštění Maker simplemaker = new SimpleCodeMaker ("Description Maker"); // Iterace ve všech třídách a provedení metody „make“, kterou vytvořil Maker (int i = 0; i <classes.length; i ++) {ClassDoc classdoc = classes [i]; simplemaker.make (classdoc); } návrat true; } 

Následuje část kódu z jednoduchého generátoru kódu SimpleCodeMaker, který plní stejný úkol jako SimpleDoclet dříve uvedené. Namísto odeslání výstupu na obrazovku SimpleCodeMaker uloží jej do souboru v podadresáři pánské třídy. Provádění udělat metoda se také stává strukturovanější pomocí samostatných metod pro zpracování polí a metod. Pouze metody udělat a processMethods jsou zde uvedeny pro stručnost.

$config[zx-auto] not found$config[zx-overlay] not found