Component Object Model
Ingress: Alle er enige om at inndeling av
programvare i komponenter er en bra ting. Microsoft har sin arkitektur for
dette som kalles COM, og som vi skal se på her. Vi skal også se på hva
konkurrentene til Microsoft foretar seg på dette området.
Å bryte
opp programvaren i komponenter innebærer at man legger større flid i å bestemme
hvordan komponenten skal påvirke og bli påvirket av sine omgivelser. I
programmererlingo kalles dette for "grensesnittet", og at
grensesnittet skal være uten "sideeffekter". Gjør man denne jobben
skikkelig, kan en komponent bygges og testes helt separat, og når den fungerer
som ønsket, kan den brukes om og om igjen i forskjellige programmer uten at det
oppstår noen overraskelser.
Dette har
programmererne visst i 30 år, men drømmen om "reusable software" er
aldri blitt oppfylt slik som man har håpet: At ute i verden skulle det flyte av
komponenter i et enormt utvalg, og at programutvikling skulle koke ned til å
lage et "lim" som satte sammen komponentenes funksjonalitet på en
riktig måte. Grunnene til at dette aldri har fungert slik, er bl.a. at man har
undervurdert den oppslutning som kreves rundt én slik komponentmodell for at
ikke det hele skal pulveriseres rundt mange forskjellige konkurrerende
teknologier.
Også idag
har vi mange forslag og halvt utviklede løsninger som gjør krav på å kunne være
den ene teknologien som skal "frelse verden". Microsoft har en slik
teknologi, og med den tyngden som Microsoft utgjør i leverandørmarkedet, må et
utspill fra den kanten ansees som interessant allerede i utgangspunktet. "Alle
andre" prøver på sin side å lage allianser som kan utgjøre en like sterk
kraft i markedet, f.eks. Object Management Group med modellen "Corba"
- Common Object Request Broker Architecture. I tillegg kommer en liten "kjekkas"
som kalles Java med teknologi som mange finner interessant.
Vi skal i
denne omgang fokusere litt på Micosofts bidrag, som kalles Common Object Model
(COM). COM dreier seg om en arkitektur som beskriver hvordan programkomponenter
kan kalle på tjenester i andre programkomponenter i en klient-tjener fasong. Og
det hele skal foregå innen en objektorientert programmeringsmodell, slik at
nøkkelbegreper som klassifikasjon og arvelighet skal være tatt vare på.
Objekter
har en tilstand (datavariabler), og
de har metoder for å spørre eller
endre på denne tilstanden. Det vanlige er også at dataene er innkapslet, dvs. at dataene bare kan
sees direkte fra den koden som utgjør metodene for objektet.
I
Microsoft-verdenen kan et objekt være implementert av en DLL (dynamisk lastet
kodemodul) og et datasegment som tilhører denne. I dette tilfellet kan vi laste
inn DLL’en, og kalle metodene (prosedyrene) i denne på samme måte som vi alltid
har gjort, og la kompilatoren for programmeringsspråket sørge for "objekt-utseendet".
I andre tilfeller ønsker vi at objektets metoder skal utføres i en egen såkalt "prosess-kontekst",
dvs. i en prosess som er adskilt fra klientens prosess (i en EXE-fil). Dessuten
ønsker vi at objektet (med tilstand og metoder) skal kunne befinne seg på et
annen maskin, slik at all overføring av parametre og returdata må foregå
gjennom et datanettverk.
Ideelt
sett bør det ikke vedkomme programmereren hvilken av disse tre alternativene
som faktisk brukes, det bør være en avgjørelse som tas under konfigureringen av
det ferdige systemet. Derfor kan det ikke være noen forskjell på hvordan et
objekt skal behandles, om det så nås på den ene eller den andre måten. Dette
kravet er det som gjør COM og andre objektmodeller svært kompliserte; for å
kalle på objekter i sin enkleste form må vi bruke mekanismer og følge regler
som er tilpasset en mulig distribusjon av objekter rundt i nettverket.
Interfaces
Tjenestene
til et COM-objekt viser seg gjennom noe som kalles "Interfaces", her
kaller vi dem Grensesnitt. Et
grensesnitt er en samling metoder for å behandle objektets tilstand (data). Når
en klient ber om å få laget et objekt av en bestemt klasse, vil klienten få i retur opplysninger (en peker) til ett av
grensesnittene, og kan kalle de metodene som er gruppert under dette. En av
metodene som tilbys er å spørre etter opplysninger om andre grensesnitt, som
kan sette klienten i stand til å kalle metoder gruppert der.
Hvorfor
flere grensesnitt til ett og samme objekt? Noen objektorienterte
programmeringsspråk, f.eks. C++, har ikke et "grensesnitt"-begrep,
men legger alle mulige metoder i samme kurv. Java, derimot har mulighet for
flere grensesnitt gjennom "interface"-deklarasjoner. Tanken er at
metoder som hører sammen og utgjør en hovedfunksjon tilobjektet, skal grupperes
i et eget "navneområde" (metoder i forskjellige grensesnitt kan ha
samme navn).
En annen
grunn til å ha flere grensesnitt er en spesiell egenskap ved COM-arkitekturen: Et grensesnitt skal aldri endres! Når
det først har fått sin utforming, må alle endringer i metodene skje ved at det
etableres en ny "versjon" av grensesnittet. Den gamle må beholdes "for
evig", og vil dermed sørge for at gamle klienter fortsatt vil virke. Versjonshåndering
altså, og vi har sansen for et strengt regime for å unngå versjonsproblematikk,
mer "tilllitsfulle" metoder i andre teknologier har vist seg ikke å
virke godt i praksis.
Arvelighet
I
objektorientert programmering bruker vi begrepet "arvelighet" for å
ordne objektklassene i et hierarki av egenskaper. Arvelighet betyr at et objekt
tilbyr alle de metoder som finnes i klasser "over seg" i dette
hierarkiet.
I alle de
objektorienterte programmeringsspråkene som vi har vært borte i, har slik
arvelighet betydd å "arve kode". Med det menes at et objekt arver både definisjon og kode i metodene
høyere opp i hierarkiet.
I COM
finner vi en enklere modell som vi kan kalle "arvet definisjon". I
COM vil altså en klasse arve grensesnittene til sin "morklasse", men
må selv skaffe koden for å implementere dette grensesnittet.
Et slikt
skjema skaper enklere mekanismer for å finne frem til den koden som skal
utføres når man kaller metoden til et objekt. Mindre grad av såkalt "dynamisk
binding" til objektets metoder, mindre behov for å lagre hele
klassehierarkiet i hvert enkelt objekt, og mindre tvetydighet når man tvinger
et objekt til å tilhøre en annen klasse (casting).
Flertydighet
Flertydighet
eller "Polymorfisme" er betegnelsen på en nøkkelegenskap ved
objektorienterte systemer. Flere objektklasser kan ha metoder som heter det
samme. I prosedyreorienterte systemer er ikke dette mulig, der må man lage
f.eks. prosedyrene "PrintStack", "PrintArray" og "PrintReal".
I et objektorientert system kan man lage en "Print"-metode for hver
klasse, og deretter overlate til kompilatoren å finne ut hvem av dem som skal
kalles, basert på kunnskapen om de objektene som brukes som parameter.
Slik
flertydighet er det kompilatoren som tilbyr. For en arkitektur som befatter seg
med kompilert kode er flertydighet et lite sentralt begrep. COM støtter nemlig
uten videre muligheten for at objekter av ulik klasse kan ha metoder med samme
navn.
Flertydighet betyr derimot også at samme objekt kan ha metoder med samme navn, men med ulikt parameteroppsett. Slik flertydighet er ikke støttet av COM.