Tietokoneohjelma

**Tietokoneohjelma** (usein lyhyesti vain **ohjelma**, ) on joukko ennalta laadittuja käskyjä, suunnitelma tai proseduuri, jota seuraten tietokone suorittaa sille valmistellun ongelmanratkaisutehtävän: ohjelmia yleisesti kutsutaan ohjelmistoksi () vastakohtana laitteistolle (). Ohjelma on yksiselitteinen järjestetty sarja käskyjä ratkaisun saavuttamiseksi.

Ohjelmat ovat konkreettisiä esityksiä abstrakteista algoritmeista, jotka perustuvat tiettyihin rakenteellisiin esityksiin datasta. Tietorakenteet riippuvat käytetyistä algoritmeista sekä päinvastoin. Data on ongelman ratkaisemiseen valittu abstraktio todellisesta maailmasta. Ohjelmointikieli on abstraktio tietokoneesta. Ohjelmoinnilla tarkoitetaan näiden keinojen käyttämistä jonkin ongelman ratkaisemiseksi.

Tietokoneohjelmalla voidaan käytännössä tarkoittaa seuraavia asioita:
* Tietokoneen ajettavissa olevaa konekoodia eli konekielistä ohjelmaa, joka on tyypillisesti tallennettu tietokoneen pysyväismuistiin, kuten kiintolevylle.
* Jollain ihmisen kirjoitettavaksi ja luettavaksi tarkoitetulla ohjelmointikielellä laadittua ohjelma- tai lähdekoodia, jota tietokone ei voi ajaa suoraan vaan joka pitää joko tulkata tai kääntää konekielelle tätä varten tehdyllä erityisellä ohjelmalla.
* prosessi on ajossa oleva ohjelma (lukuun ottamatta aivan pienimpiä sulautettuja järjestelmiä).

Ohjelmien koot vaihtelevat suuresti. Yleinen tapa verrata ohjelmien kokoa on laskea lähdekoodin rivien lukumäärä. Lyhin mielekäs ohjelma voi olla yhden rivin mittainen, kun taas suurimmat ohjelmistot ovat miljoonia rivejä pitkiä.

## Historia
Ennen digitaalisen tietokoneen kehittämistä ohjelman kaltaisia menetelmiä on käytetty muun muassa kutomakoneille ja automaattipianoille.

Ada Lovelace kirjoitti 1800-luvulla Charles Babbagen analyyttiselle koneelle algoritmin Bernoullin lukujen laskemiseen, jonka johdosta Lovelacea pidetään ensimmäisenä ohjelmoijana. Lovelacen työn merkittävyys on sen yksityiskohdissa kuten ryhmittely ja toistorakenteen keksiminen. Lovelace myös totesi muuttujien tilojen seurannan merkityksen ja merkintätavan niiden esittämiselle.

## Yleistä

Tavallisesti ohjelmat käsittelevät niille syötettyä tietoja ja tuottavat siitä halutun lopputuloksen. Harvinaisempaa on, että lähtötietoja ei anneta, mutta tämäkin on mahdollista esimerkiksi laskettaessa piille likiarvoa. 

Varhaiset ohjelmat olivat pitkälti muotoa lue syöte, tee laskenta, tulosta tulokset. Tämäntyyppiset ohjelmat sopivat hyvin eräajotyyppiseen käsittelyyn, jossa etukäteen valmistellaan syöttötiedot ja itse ohjelman ajo tehdään myöhemmin. Nykyohjelmista vain harvat ovat tätä tyyppiä. Useimmat pöytätietokoneiden ohjelmat ovat interaktiivisia, jolloin ohjelma vastaa käyttäjän tekemiin syötteisiin saman tien. Koska seuraava syöte voi riippua ohjelman antamasta vastauksesta, ero perinteiseen ohjelmaan on suuri.

Varsinaisten tietokoneiden lisäksi ohjelmia on myös monissa laitteissa, kuten matkapuhelimissa, viihde-elektroniikan laitteissa ja kodinkoneissa. Tällaisia laitteita kutsutaan sulautetuiksi järjestelmiksi, koska ohjelma ja laitteisto muodostavat käyttäjän kannalta kiinteän kokonaisuuden. Sulautetuissa järjestelmissä ohjelmat ovat usein *reaktiivisia*, mikä ohjelman rakenteen kannalta vastaa interaktiivisuutta, mutta laskentaan tulevat tiedot voivat olla lähtöisin käyttäjän lisäksi myös oheislaitteilta, antureilta tai toisista ohjelmista. Esimerkki ohjelmistosta, joka on sekä interaktiivinen että reaktiivinen, on vaikkapa tulospalveluohjelmisto, jolla käyttäjä voi kysyä eri sarjojen tai kilpailijoiden tilannetta (interaktiivisuus), ja jossa tilanne päivittyy muualta kuten väliaikapisteiltä tai maaliviivalta tulevien tietojen mukaan (reaktiivisuus).

Immateriaalioikeuden kannalta ohjelmat kuuluvat tekijänoikeuksien piiriin. Immateriaalioikeuksien kannalta mielenkiintoisia ovat laajalle levinneet vapaat ohjelmistot.

## Ulkoiset rajapinnat

Tietokoneohjelmalla ei olisi juurikaan käyttöä, mikäli se ei pystyisi kommunikoimaan millään tavalla ympäristönsä kanssa. Tämän vuoksi jokaiseen tietokoneohjelmaan liittyy ulkoisia rajapintoja, joiden avulla ohjelma voi kommunikoida ympäristönsä kanssa. Esimerkiksi lämpömittariin liitetty anturi voi lähettää väyläsignaalin, jonka antaman arvon perusteella tietokoneohjelma voi ohjata rakennuksen lämpötilaa. 

Tietokoneohjelman ohjaama tai tietokoneohjelmaa ohjaava ympäristö voi koostua oheislaitteista tai muista tietokoneohjelmista. Koska erilaisia ympäristöjä voi olla teoriassa rajaton määrä, ohjelmien tarvitsemia ulkoisia rajapintoja on pyritty standardoimaan. Mitä vakiintuneempi ulkoinen rajapinta on, sitä useampi tietokoneohjelma sitä pystyy käyttämään ja sitä kestävämpi hyöty rajapinnasta saavutetaan. Tietotekniikan suurimmat kehitysaskeleet ovatkin usein olleet ulkoisten rajapintojen onnistuneita vakiintumisia, esimerkiksi mikroprosessorien käskykannan vakiintuminen tai käyttöjärjestelmien toimintaperiaatteiden yhtenäistyminen.

Tietokoneohjelman kommunikointi ympäristön kanssa voi tapahtua synkronisesti tai asynkronisesti. Lisäksi ohjelma voi sallia tietyn ulkoisen tapahtuman keskeyttää itsensä. Vaihtoehtoisesti ohjelma voi aika-ajoin tarkkailla ulkoista maailmaa lukemalla ulkoisen rajapinnan kautta tilatietoa.

Fyysisten laitteiden ohjaamista varten tietokoneiden prosessoreissa on määriteltynä mekanismeja, joiden avulla ohjelma voi kirjoittaa tai lukea tietoa mikroprosessorin suorittimen ulkopuolelta. Konekielen tasolla nämä ovat prosessoriin liitettyjä portteja tai I/O -muistialueita, joiden kautta tietokoneohjelmat pystyvät oikein toimiessaan ohjaamaan fyysisiä tai virtuaalisia kokonaisuuksia sekä lukemaan näiden kokonaisuuksien syöttämää tietoa. Tietokoneohjelmien rakentamista helpotetaan siten, että nämä palvelut abstraktoidaan käyttöjärjestelmän, laiteajureiden tai sovelluskirjastojen (API) avulla siten että ohjelman kirjoittajan ei tarvitse ymmärtää ulkoisten palveluiden tai laitteistojen sisäistä toimintaa.

Tietokoneohjelmille ulkoisia rajapintoja tarjoavat muun muassa

* mikroprosessoriarkkitehtuuri (esimerkiksi I/O -portit, keskusmuisti, väylät, konekieli)
* käyttöjärjestelmä (esimerkiksi ohjelmien käynnistäminen, muistin varaaminen, prosessit)
* laitteistoajurit (esimerkiksi näytölle piirtäminen, videokaappaus, tulostaminen)
* sovelluskehitysympäristö (esimerkiksi ohjelmointikirjastot, poikkeustilanteiden hallinta)
* sovelluskirjastot ja komponentit (monipuolisia palveluita lähes mihin tahansa tarkoitukseen)
* toiset ohjelmat tai ohjelmistot

Käyttöjärjestelmä, laitteistoajurit, sovelluskehitysympäristöt, sovelluskirjastot ja komponentit ovat yleisnimiä tiettyihin tarkoituksiin erikoistuneista tietokoneohjelmista. Ohjelma käyttää tarvitsemiaan palveluita ajoympäristöstä ja sen abstraktiotasosta riippuen. Alimmalla tasolla oleva mikroprosessori tarjoaa tietokoneohjelmille palveluita, joiden avulla ne voivat aikaansaada fyysisiä muutoksia ympäristössään, esimerkiksi vaihtaa väylän signaalin tason toiseksi.

Kukin rajapinnan toteuttava ohjelma tai laitteisto voi rajoittaa oikeuksia ulkoisten palveluiden käyttöön. Tietotekniikassa monet tietoturvakysymykset liittyvät ulkoisten rajapintojen oikeuksien hallintaan.

## Ohjelmien siirrettävyys
Koska eri suorittimien konekielet ovat erilaisia, ei konekielimuodossa olevaa ohjelmaa voi ajaa kaikissa tietokoneissa. Joskus myös samasta suorittimesta on hieman eri versioita, ja tällöin yleensä on pyritty siihen, että uudempi versio pystyy ajamaan vanhemman suorittimien konekieltä, mutta ei toisin päin. Käännettyjen ohjelmien siirrettävyyttä rajoittaa siis suorittimen ymmärtämä konekieli. Tosin tämä ei ole ainoa rajoittava tekijä. Kohdesuorittimen lisäksi kääntäjä tietää käytössä olevan käyttöjärjestelmän tarjoamat palvelut ja käytännöt. Koska nämä eroavat eri käyttöjärjestelmissä, toiselle käyttöjärjestelmälle tehtyä konekielistä ohjelmaa ei voi ajaa tietokoneessa, vaikka suoritin olisikin sama.

Tilanne muuttuu, jos käytetään tulkkeja. Tällöin tarvitaan kyseiselle konekielelle ja käyttöjärjestelmälle toteutettu ohjelmointikielen tulkki, mutta sitten tämä tulkki pystyykin suorittamaan lähdekielimuodossa ohjelmaa riippumatta siitä, mihin ympäristöön se on alun perin tehty. Tosin
tulkkikin voi tarjota käyttöjärjestelmästä riippuvia palveluita, mutta jos ohjelmoija on osannut
välttää näitä, ei siirrettävyysongelmaa pitäisi tulla.

Ohjelmointikielellä kirjoitettu ohjelma voidaan myös kääntää uudelleen eri suoritintyypeille ja käyttöjärjestelmille. Periaatteessa ohjelmien pitäisi olla helposti siirrettäviä tällä tasolla, mutta käytännössä ohjelmoija voi tehdä moniakin sellaisia ratkaisuja, jotka rajoittavat siirrettävyyttä. Näitä ovat muun muassa oletukset kokonaislukujen arvoalueesta tai liukulukujen tarkkuudesta. Ohjelmoija voi myös käyttää käyttöjärjestelmäkohtaisia operaatioita.

Edellä olevien kahden vaihtoehdon ongelmien eli tulkkaamisen hitauden ja käännetyn ohjelman huonon siirrettävyyden takia käytetään joissain tilanteissa niin sanottua välikoodia. Tällöin ohjelma on jo käännetty, mutta ei konekielelle, vaan eräänlaiseen välimuotoon, jota kohdekoneessa oleva välikoodin tulkki tulkitsee. Tätä tekniikkaa voidaan käyttää esimerkiksi verkkosovelluksia ohjelmoitaessa, jossa käyttäjän koneen ominaisuuksia ei voida tietää etukäteen (katso myös Java-kieli).

Ohjelmien siirrettävyyttä voivat rajoittaa myös sen tarvitsemat resurssit kuten muistin määrä, suorittimen nopeus tai jokin erityinen oheislaite. Esimerkiksi DVD:lle tallentava ohjelma on käyttökelvoton ilman laitetta, joka osaa tehdä varsinaisen DVD-levylle kirjoittamisen.

Hankkiessaan ohjelmaa käyttäjän on tiedettävä käyttökoneen suoritinarkkitehtuuri ja käyttöjärjestelmä. Monet vapaat tai valmiiksi käännetyt ohjelmat löytyvät arkistokoneilta näiden tietojen mukaan lajiteltuina.

## Ohjelmien luotettavuus
Oikein toimivan ohjelman ohjelmointitavalla ei ole merkitystä käyttäjälle. Valitettavasti ohjelmien täydellinen testaaminen on käytännössä (ja joissain tapauksessa jo teoriassakin) mahdotonta, joten aivan yksinkertaisimpia ohjelmia lukuun ottamatta ohjelmissa on oletusarvoisesti jokin havaitsematon virhe. Siitä huolimatta ohjelma voi olla hyvinkin käyttökelpoinen, sillä virhe voi esiintyä hyvin harvoin tai niin pieni, että siitä ei ole käytännön haittaa.

Eri käyttötarkoitukseen tehtyjen ohjelmien luotettavuusvaatimukset ovat hyvin erilaisia. Interaktiivinen julkaisuohjelma voi olla harmillinen toimiessaan väärin, mutta virheestä ei silti seuraa välittömästi vaaratilanteita tai vastaavaa. Sen sijaan vaikkapa lentokoneen ohjausohjelmiston virhe voisi pudottaa koneen taivaalta.

Osassa ohjelmia on oikean toiminnan lisäksi tärkeää ohjelman oikea ajoitus. Jos ohjelma toimii väärään aikaan, siis joko liian aikaisin tai liian myöhään, seurauksena voi olla järjestelmän täysi toimimattomuus. Esimerkiksi matkapuhelinliikenteessä yksikin väärään aikaan lähettävä puhelin voi pimentää koko tukiaseman alueen liikenteen. Ohjelmia, joissa aikatekijä on osa ohjelman oikeellisuutta, kutsutaan reaaliaikaohjelmiksi.

Yksi ohjelmien toimimattomuusongelma liittyy siihen, että niiden ajoympäristöä vaihdetaan. Syynä voi olla esimerkiksi käyttöjärjestelmän tai dynaamisen ohjelmakirjaston päivittäminen uuteen versioon.

## Ohjelmien sovittaminen
Ohjelmien sovittamisella tarkoitetaan sitä, että ohjelman toimintaa voidaan muuttaa käyttöpaikan tarpeiden mukaan. Sovittaminen voi olla tehty käännösvaiheessa, mutta parhaimmillaan sama ohjelma toimii eri tavalla eri käyttöpaikoissa. Tiedot asetuksista on tällöin talletettu joko ohjelma-  tai käyttäjäkohtaiseen
alustustiedostoon.

Mikäli sovittaminen ylittää kulttuuri- ja kielirajoja, puhutaan lokalisoinnista. Lokalisoinnilla voidaan vaihtaa ohjelman käyttöliittymän kieli toiseksi,
vaihtaa kellonajan tai päivämäärän esitystapaa, päättää onko käytössä desimaalipiste ja -pilkku, muuttaa käytössä olevia värejä ja niin edelleen.

## Katso myös
* Käyttöjärjestelmä
* Käyttöliittymä
* Kirjasto (tietotekniikka)
* Ohjelmointikieli
* Sovellusohjelma
* Mikro-ohjelma

## Lähteet

## Aiheesta muualla