Eclipse-platform
API-regler
Version 0.15 - sidst revideret 30. maj 2001 kl. 12
I det følgende beskrives reglerne for klienters brug af Eclipse-platformens API og andre komponenter.
Hvad betyder det at være API
Eclipse-platformen definerer API-elementer, der kan bruges af dens kunder, som er
ISV'er, der skriver plugins. Disse plugins kan også selv definere API-elementer for deres kunder
osv. API-elementer er ansigtet udadtil: de indeholder en angivelse af, hvad de skal gøre, og
hvordan de skal bruges. API-elementer er understøttet: Eclipse-platformsteamet retter
implementeringsfejl, hvor der er en afvigelse fra den angivne funktionsmåde. Eftersom der ofte er en høj omkostning forbundet med at introducere API-ændringer, vil
Eclipse-platformsteamet også forsøge at udvikle API-elementer gradvist gennem
på hinanden følgende store releases.
Sådan skelner du mellem API'er og ikke-API'er
API'er er i følge deres natur dokumenterede og har en specifikation i modsætning
til ikke-API-elementer, som er interne implementeringsdetaljer, der normalt
udgives uden dokumentation eller specifikationer. Hvis du derfor ikke kan finde dokumentationen
til et element, er det normalt en god indikation af, at det ikke er API.
Som et forsøg på at trække skillelinjen mere kraftigt op, er kodebasen for platformen delt
i API- og ikke-API-pakker, hvor alle API-elementer er erklæret i
præcist angivne API-pakker.
-
API-pakke - en Java-pakke, som indeholder mindst én API-klasse eller
API-grænseflade. Navnene på API-pakkerne annonceres i dokumentationen til komponenten.
Hvis det er muligt, bør alle andre pakker, som kun indeholder implementeringsdetaljer,
indeholde ordet "internal" i pakkenavnet. Navnene på
API-pakker kan lovligt vises i klientkode. Der er følgende for selve Eclipse-platformen:
-
org.eclipse.foo.* - f.eks. org.eclipse.swt.widgets,
org.eclipse.ui
eller org.eclipse.core.runtime
-
org.eclipse.foo.internal.* - ikke API. Interne implementeringspakker
-
org.eclipse.foo.examples.* - ikke API. Dette er eksempler
-
org.eclipse.foo.tests.* - ikke API. Dette er testserier
-
API-klasse eller -grænseflade - en offentligt klasse eller grænseflade i
en API-pakke eller et offentligt eller beskyttet klasse- eller grænseflademedlem, der er
erklæret i eller overtaget fra en anden API-klasse eller -grænseflade.
Navnene på
API-klasser og -grænseflader kan lovligt vises i klientkode.
-
API-metode eller -konstruktør - en offentligt eller beskyttet
metode eller konstruktør, som er erklæret i eller overtaget fra en API-klasse eller
-grænseflade. Navnene på
API-metoder kan lovligt vises i klientkode.
-
API-felt - et offentligt eller beskyttet
felt, som er erklæret i eller overtaget fra en API-klasse eller
-grænseflade. Navnene på
API-felter kan lovligt vises i klientkode.
Alt andet anses for at være interne implementeringsdetaljer, som ingen klienter har
adgang til. Lovlig klientkode må aldrig referere til navnene på
ikke-API-elementer, heller ikke ved brug af Java-refleksion. I nogle tilfælde bruges Java-sprogets
navneadgangsregler til at afvise ugyldige referencer.
Der er imidlertid mange tilfælde, hvor det ikke er muligt. Hvis du overholder følgende regel,
kan du undgå problemet:
-
Brug kun officielt dokumenterede API'er. Referér kun til pakker, som er dokumenterede
i den offentliggjorte API Javadoc for komponenten.
Referér aldrig til en pakke, som hører til en anden komponent, hvor ordet "internal"
indgår i dens navn - det er aldrig API'er. Referér aldrig til en pakke, som der ikke findes
et offentliggjort API Javadoc for - det er heller aldrig et API.
Generelle regler
Specifikationen af API-elementer genereres ud fra Javadoc-kommentarer i elementets
Java-kildekode. For visse elementtyper er specifikationen i form af en kontrakt. I tilfældet med metoder er kontrakten f.eks. mellem to parter, kalderen af metoden og
implementoren af metoden. Grundreglen er:
-
Overhold alle kontrakter. Kontrakterne er beskrevet i den offentliggjorte
Javadoc for de API-elementer, du bruger.
Udtrykket "must" i en API-kontrakt betyder, at det er partens pligt at sikre, at
betingelsen altid opfyldes. Hvis denne pligt ikke opfyldes, anses det for at være en
programmeringsfejl med uspecificerede og muligvis uforudsigelige konsekvenser.
-
Du skal overholde "must". Du skal være særligt opmærksom på forhold, hvor der
bruges "must".
Andre fornuftige regler:
-
Stol ikke på tilfældig funktionsmåde. Tilfældig funktionsmåde er en funktionsmåde, som er
observeret ved eksperiment eller i praksis, men som ikke garanteret af en API-specifikation.
-
Undlad at behandle NULL som et objekt. NULL er mere end mangel af et objekt.
Antag, at alt er ikke-NULL, medmindre API-specifikationen angiver det modsatte.
-
Forsøg ikke at snyde med Java-refleksion. Det hjælper dig ikke at bruge Java-refleksion
til at omgå Java-compilerens kontrol. Der er ingen yderligere
API-kontrakter til brug for refleksion. Refleksion øger blot sandsynligheden for at
stole på uspecificeret funktionsmåde og interne implementeringsdetaljer.
-
Brug dine egne pakker. Undlad at erklære kode i en pakke, som hører til en
anden komponent. Erklær altid din egen kode i dine egne pakker.
Kald af offentlige API-metoder
For de fleste klienter fungerer størstedelen af Eclipse-API'et som offentlige
metoder til API-grænseflader eller -klasser, som klienten kan kalde, når det er
nødvendigt.
-
Kontrollér forhåndsbetingelser. Kontrollér, at en API-metodes forhåndsbetingelser er opfyldt,
før metoden kaldes. I modsat fald antager kalderen, at metodens efterfølgende betingelser
vil være opfyldt, umiddelbart efter at der returneres fra kaldet.
-
NULL-parametre. Undlad at overføre NULL som en parameter til en API-metode, medmindre
det udtrykkeligt er angivet, at parameteren tillader NULL. Det er muligvis den mest
almindelige programmeringsfejl.
-
Begrænsede kaldere. Undlad at kalde en API-metode, hvis det er angivet, at den
kun er tilgængelig for bestemte kaldere, medmindre du er en af dem. I visse situationer skal
metoder være del af det offentlige API for at kunne bruge en bestemt klasse af
kaldere (ofte interne). Hvis du kalder en af disse metoder på det forkerte tidspunkt,
kan det have uspecificerede og muligvis uforudsigelige konsekvenser.
-
Fejlfindingsmetoder. Undlad at kalde En API-metode, som er mærket "kun til
fejlfinding". De fleste toString()-metoder hører f.eks. til denne kategori.
-
Parameteropsamling. Undlad at overføre et array, en samling eller et andet omskifteligt
objekt som en parameter til en API-metode og derefter ændre det overførte objekt. Det kan kun medføre problemer.
Oprettelse af forekomster af platforms-API-klasser
Det er ikke alle konkrete API-klasser, som hvem som helst kan oprette forekomster af.
API-klasser kan have en oprettelseskontrakt, som angiver vilkårene for oprettelse af
forekomster. Kontrakten kan også dække andre emner som f.eks. tilbageværende ansvar for
initialisering (f.eks. konfiguration af en bestemt egenskab, før
forekomsten er fuldstændigt aktiv) og tilhørende ansvar for livscyklus (f.eks.
kald af dispose() for at frigive styresystemressourcer, som forekomsten benytter). De klasser, der er designet til, at klienter kan oprette forekomster af dem, er
udtrykkeligt markeret i Javadoc-klassekommentaren med sætninger som f.eks. "Clients
may instantiate".
-
Begrænsede forekomstoprettere (instantiators). Undlad at oprette en forekomst af en API-klasse, hvis det er angivet, at den
kun er tilgængelig for bestemte parter, medmindre du er en af dem.
I visse situationer skal
klasser være del af det offentlige API, så en bestemt part (ofte intern) kan bruge
dem. Hvis du opretter en forekomst af en disse klasser forkert,
kan det have uspecificerede og muligvis uforudsigelige konsekvenser.
Oprettelse af underklasser af platforms-API-klasser
Kun en delmængde af API-klasserne er designet til at kunne oprettes som underklasser. API-klasser
har en underklassekontrakt, som angiver vilkårene for erklæring af underklasser. Kontrakten dækker også ansvar for initialisering og livscyklus. De klasser, der er designet til, at klienter kan oprette underklasser af dem, er
udtrykkeligt markeret i Javadoc-klassekommentaren med sætninger som f.eks. "Clients
may subclass".
-
Begrænsede underklasseoprettere (subclassers). Undlad at oprette en underklasse af en API-klasse, som
ikke er designet til det. Brug klasserne, som om de er erklæret
som "final". Sådanne klasser kaldes undertiden for "soft final".
Kald af beskyttede API-metoder
Det er generelt tilladt at kalde overtagne beskyttede og offentlige metoder inde fra
en underklasse. Det kræver imidlertid ofte mere omhyggelighed at kalde dem på denne måde end at
kalde offentlige metoder uden for hierarkiet.
Tilsidesættelse af API-metoder
Kun en delmængde af de offentlige og beskyttede API-metoder er designet til at
blive tilsidesat. Hver API-metode
har en underklassekontrakt, som angiver vilkårene for, at en underklasse kan
tilsidesætte den. Tilsidesættelse er som standard ikke tilladt.
Det er vigtig at undersøge underklassekontrakten for den aktuelle metodeimplementering, der
tilsidesættes, fordi vilkårene i underklassekontrakterne ikke automatisk overføres sammen med den
metode, der tilsidesættes.
-
Undlad at tilsidesætte en offentlig eller beskyttet API-metode, medmindre det udtrykkeligt
er tilladt. Medmindre andet er angivet, skal metoderne behandles, som om de er erklæret
som "final". Sådanne metoder kaldes undertiden for "soft final"-metoder.
Hvis den tilladte type tilsidesættelse er:
- "implement" - den abstract-metode, der er erklæret for underklassen, skal
være implementeret af en konkret underklasse.
- "extend" - den metode, der er erklæret for underklassen, skal starte metoden
for superklassen (kun én gang).
- "re-implement" - den metode, der er erklæret for underklassen, må ikke starte metoden
for superklassen.
- "override" - den metode, der er erklæret for underklassen, må starte metoden
for superklassen efter behov.
-
Kontrollér efterfølgende betingelser. Kontrollér, at eventuelle efterfølgende betingelser, der er
angivet for API-metoden, er opfyldt af implementeringen ved retur.
-
Kontrollér forhåndsbetingelser proaktivt. Undlad at antage, at de forhåndsbetingelser, der er
angivet for API-metoden, nødvendigvis er opfyldt ved indgang. Selv om metodeimplementeringen
har ret til ikke at kontrollere de angivne forhåndsbetingelser, er det normalt en god idé
at kontrollere forhåndsbetingelserne, når det er praktisk muligt og forholdsvis billigt, for at
kunne advare om ukorrekte kaldere.
-
NULL-resultat. Undlad at returnere NULL som resultat fra en API-metode, medmindre det udtrykkeligt
er dokumenteret i den angivende grænseflade eller superklasse, at NULL er tilladt.
-
Returnér kopier. Undlad at returnere et array, en samling eller et andet omskifteligt
objekt, der ikke kan erstattes, som resultat fra en API-metode. Returnér altid en
kopi for at undgå problemer med kaldere, som eventuelt ændrer objektet.
Implementering af platforms-API-grænseflader
Kun en delmængde af API-grænsefladerne er designet til at kunne implementeres
af klienter. API-grænseflader
har en kontrakt, som angiver vilkårene for deres implementering. De grænseflader, der er designet til at
blive implementeret af klienter, er
udtrykkeligt markeret i Javadoc-klassekommentaren med sætninger som f.eks. "Clients
may implement". En klient kan kun erklære en undergrænseflade af en
API-grænseflade, hvis klienten har tilladelse til at implementere den.
-
Begrænsede implementorer. Undlad at implementere en API-grænseflade, hvis det er angivet, at den
kun er tilgængelig for bestemte parter, medmindre du er en af dem. Grænseflader bruges i mange situationer til at
skjule interne implementeringsdetaljer.
Implementering af offentlige API-metoder
Se "Tilsidesættelse af API-metoder".
Adgang til felter i API-klasse og -grænseflader
Klienter kan læse API-felter, hvoraf de fleste er "final". Visse struct-lignende
objekter har ikke-final offentlige felter, som klienter kan læse og skrive, medmindre
andet er angivet.
-
NULL-felter. Undlad at angive et API-felt til NULL, medmindre det udtrykkeligt er
tilladt.
Konvertering af objekter med en kendt API-type
Et objekt med en kendt API-type kan kun konverteres til en anden API-type (eller
konverteres betinget vha. instanceof), hvis det udtrykkeligt er tilladt i API'et.
-
Konvertering og instanceof. Undlad at bruge instanceof- og cast-udtryk til at øge, hvad der
allerede vides om et objekt, ud over hvad API understøtter.
Forkert brug afdækker tilfældige implementeringdetaljer, som ikke garanteres af
API'et.
Det er naturligvis altid uhensigtsmæssigt at konvertere et objekt til en ikke-API-klasse eller
grænseflade.
Hvis reglerne ikke følges
Der er en konsekvens ved at overtræde reglerne, uanset om det er tilsigtet eller
uforvarende. Det ville måske være lettere for alle involverede parter, hvis der var et API-politi, som
straffede for overtrædelse af reglerne. Det er imidlertid ikke tilfældet.
Overholdelsen af API'er er mest baseret på tillid, hvor hver klient er ansvarlig for at
kende og overholde reglerne.
Kontrakterne på API-elementerne afgrænser den funktionsmåde, der er understøttet og
anerkendt. Efterhånden som Eclipse-platformen modnes og udvikler sig, vil det være API-kontrakterne, der
styrer udviklingen. Uden for disse kontrakter er intet understøttet og kan når som helst
ændres uden varsel, selv mellem releases eller forskellige styresystemer. Hvis klientkoden ikke
overholder de ovenstående regler, kan der opstå fejl på forskellige versioner og
rettelsesniveauer af platformen. Der kan også opstå fejl, når koden afvikles på de
underliggende styresystemer, med en forskellige blanding af samtidigt installerede
pluginS, med et andet arbejdsbænkperspektiv og så videre. Der er ingen, som interesserer sig for, præcist hvordan en bestemt overtrædelse senere
kan skabe problemer for dig. Til dem, som vælger at ignorere reglerne: Sig ikke, at du ikke blev advaret. Og forvent ikke andet end: "Hvad sagde vi".
På den anden side skal enhver klient-plugin-kode, som overholder de ovenstående regler,
kunne fungere på forskellige versioner og rettelsesniveauer af platformen, på de
forskellige underliggende styresystemer og i fredelig sameksistens med andre plugins. Hvis alle følger reglerne, udgør Eclipse-platformen en stabil og understøttet basis for
nye og spændende produkter.