Rakenneohjelmointi on ohjelmointiparadigma , joka perustuu ohjelman esittämiseen hierarkkisen lohkorakenteen muodossa . Se käsitteellistettiin 1960-luvun lopulla - 1970-luvun alussa Boehm-Jacopini-lauseen perusteella , joka perustelee matemaattisesti ohjelmien rakenteellisen organisoinnin mahdollisuutta, ja Edsger Dijkstran työn "Goto-operaattorin vaaroista" ( eng. Sitä pidettiin haitallisena ).
Paradigman mukaan mikä tahansa ohjelma, joka on rakennettu ilman goto-käskyä, koostuu kolmesta perusohjausrakenteesta: sekvenssi, haara , silmukka ; lisäksi käytetään aliohjelmia . Samanaikaisesti ohjelman kehitys tapahtuu askel askeleelta "ylhäältä alas" -menetelmällä.
Strukturoitu ohjelmointimetodologia ilmestyi tietokoneilla ratkaistavien tehtävien monimutkaisuuden ja vastaavasti ohjelmistojen monimutkaisuuden seurauksena. 1970-luvulla ohjelmien määrä ja monimutkaisuus saavuttivat sen tason, että perinteinen (strukturoimaton) ohjelmien kehittäminen ei enää täytä käytännön tarpeita. Ohjelmista tuli liian monimutkaisia, jotta niitä ei voida ylläpitää kunnolla. Siksi kehitysprosessin ja ohjelmien rakenteen systematisointia vaadittiin.
Rakenteellisen ohjelmistokehityksen metodologia on tunnustettu "70-luvun vahvimmaksi formalisaatioksi".
Bertrand Meyerin mukaan "Dijkstran käynnistämä ohjelmoinnin vallankumous johti strukturoiduksi ohjelmoimiseksi tunnetulle liikkeelle, joka ehdotti systemaattista, rationaalista lähestymistapaa ohjelmien suunnitteluun. Strukturoidusta ohjelmoinnista on tullut perusta kaikelle ohjelmointimetodologiassa tehtävälle, mukaan lukien objektiohjelmointi " [1] .
Aluksi ajatus strukturoidusta ohjelmoinnista syntyi goto-operaattorin ja sen käytön tarkoituksenmukaisuuden epäilyjen yhteydessä. Heinz Zemanek ilmaisi tällaiset epäilykset ensimmäisen kerran algol-kieltä käsitelleessä kokouksessa Kööpenhaminassa vuoden 1959 alussa. Tämä puhe ei kuitenkaan herättänyt huomiota eikä sillä ollut seurauksia. Edsger Dijkstra muistelee: "Jossain määrin syytän itseäni siitä, etten kyennyt ymmärtämään tämän idean merkitystä tuolloin" [2] [3] [4] .
Tilanne muuttui dramaattisesti kymmenen vuotta myöhemmin, kun Dijkstra julkaisi maaliskuussa 1968 kuuluisan kirjeensä Go To Statement Tarkoitettu haitalliseksi . Tämä on todella historiallinen asiakirja, jolla on ollut merkittävä vaikutus ohjelmoinnin jatkokehitykseen.
Itse asiakirjan kohtalo on erittäin mielenkiintoinen. Tosiasia on, että Dijkstra antoi artikkelille täysin erilaisen otsikon: "Argumentit GO TO -lausuntoa vastaan" (A Case against the GO TO -lausunto).
Julkaisuhetkellä kuitenkin tapahtui jotain käsittämätöntä - jostain syystä artikkeli muuttui mystisesti "Kirjeeksi toimittajalle", ja entinen otsikko katosi yhtä mystisesti. Mitä todella tapahtui? Dijkstra selitti artikkelin salaperäisen muuttamisen kirjeeksi vasta monta vuotta myöhemmin, vuonna 2001, vuosi ennen hänen kuolemaansa.
ACM:n viestintä julkaisi tekstini nimeltä "GOTO-lausuntoa pidetään haitallisena. " Myöhempinä vuosina häntä lainattiin usein. Valitettavasti tämän tekivät usein ihmiset, jotka eivät nähneet siinä muuta kuin otsikko sanoo. Tästä tittelistä on tullut maineeni kulmakivi...
Miten tämä kaikki tapahtui? Lähetin artikkelin, jonka otsikko on "Syyte GO TO -lausuntoa vastaan". Julkaisun nopeuttamiseksi toimittaja muutti artikkelini Kirjeeksi toimittajalle. Samalla hän keksi artikkelille uuden otsikon, jonka hän keksi itse. Toimittaja oli Niklaus Wirth [5] [6] .
Strukturoidun ohjelmoinnin tarkoituksena on lisätä ohjelmoijien tuottavuutta, myös suuria ja monimutkaisia ohjelmistojärjestelmiä kehitettäessä, vähentää virheiden määrää, yksinkertaistaa ohjelmistojen virheenkorjausta, muokkausta ja ylläpitoa.
Tämä tavoite asetettiin ohjelmien monimutkaistuessa ja suurten ohjelmistoprojektien kehittäjien ja johtajien kyvyttömyyteen selviytyä ohjelmistotyökalujen kehittämisen yhteydessä vuosina 1960-1970 ilmenneistä ongelmista [7] .
Strukturoitu ohjelmointi on suunniteltu erityisesti poistamaan ohjelmista koodinlukuvaikeuksista johtuvat sotkut ja virheet, jotka ovat systematisoimattomia, ohjelman lähdekoodin havaitsemisen ja analysoinnin kannalta hankalat . Tällaista tekstiä kutsutaan usein " spagettikoodiksi ".
Spagettikoodi on huonosti suunniteltu, huonosti jäsennelty, hämmentävä ja vaikeasti ymmärrettävä ohjelma , joka sisältää paljon goto-lauseita (erityisesti taaksepäin hyppyjä), poikkeuksia ja muita rakennetta heikentäviä konstruktioita [8] . Yksi tunnetuimmista ohjelmoinnin anti -kuvioista .
Spagettikoodi on nimetty näin, koska ohjelman kulku on kuin kulho spagettia , eli mutkainen ja mutkainen. Joskus kutsutaan "kengurukoodiksi" monien hyppyohjeiden vuoksi .
Nykyään termiä ei sovelleta vain goton väärinkäyttötapauksiin, vaan myös mihin tahansa "monilinkitettyyn" koodiin, jossa sama pieni fragmentti suoritetaan useissa eri tilanteissa ja suorittaa monia erilaisia loogisia toimintoja [8] .
Spagettikoodin virheenkorjaus ja suoritus voidaan suorittaa oikein ja korkealla suorituskyvyllä, mutta sitä on erittäin vaikea ylläpitää ja kehittää [8] . Spagettikoodin jalostaminen uusien toimintojen lisäämiseksi sisältää joskus merkittävän mahdollisuuden uusien virheiden tuomiseen. Tästä syystä on lähes väistämätöntä, että refaktorointi on tärkein lääke spagettiin.
1970-luvulta lähtien ehdoton hyppyoperaattori goto on ollut systemaattisen ja kasvavan kritiikin keskipisteenä. Goto-lauseen virheellinen ja ajattelematon käyttö ohjelman lähdekoodissa johtaa hämmentävään, lukemattomaan " spagettikoodiin ". Tällaisen koodin tekstistä on lähes mahdotonta ymmärtää suoritusjärjestystä ja fragmenttien keskinäistä riippuvuutta.
Tämä näkemys heijastui ensimmäisen kerran Edsger Dijkstran artikkelissa "Go To -operaattoria pidetään haitallisena" [3] [9] . Dijkstra huomasi, että koodin laatu on kääntäen verrannollinen siinä olevien goto-lauseiden määrään. Artikkeli sai laajaa julkisuutta, minkä seurauksena näkemykset goto-operaattorin käytöstä uudistuivat merkittävästi. Teoksessa Notes on Structured Programming [10] Dijkstra väitti, että on paljon helpompaa tarkistaa koodin muodollinen oikeellisuus ilman gotoa .
Koodia, jossa on goto, on vaikea muotoilla, koska se voi rikkoa suoritushierarkian (strukturoidun ohjelmoinnin paradigma), ja siksi sisennystä, joka on suunniteltu heijastamaan ohjelman rakennetta, ei välttämättä aina aseteta oikein. Lisäksi goto-käsky estää kääntäjiä optimoimasta ohjausrakenteita [11] .
Jotkut goton käyttötavat voivat aiheuttaa ongelmia ohjelman suorituslogiikassa:
Argumentit goto-lausetta vastaan osoittautuivat niin vakaviksi, että strukturoidussa ohjelmoinnissa niitä alettiin pitää erittäin ei-toivotuina. Tämä näkyi uusien ohjelmointikielten suunnittelussa. Esimerkiksi goto on laitonta Javassa ja Rubyssa . Useissa moderneissa kielissä se on silti jätetty tehokkuussyistä niissä harvoissa tapauksissa, joissa goton käyttö on perusteltua. Esimerkiksi goto säilyi Adassa , joka on yksi historian arkkitehtonisesti hienostuneimmista kielistä [12] .
Kuitenkin korkean tason kielillä, joilla tämä operaattori on säilytetty, sen käyttöä koskevat pääsääntöisesti ankarat rajoitukset, jotka estävät sen vaarallisimpien käyttötapojen käytön: esimerkiksi valvonnan läpäiseminen on kiellettyä. ulkopuolelta silmukan, menettelyn tai toiminnon sisällä. C++-kielistandardi kieltää muuttujan alustuksen ohittamisen gotolla.
Lauseen muotoili ja todisti italialaiset matemaatikot Corrado Böhm ja Giuseppe Jacopini. He julkaisivat sen vuonna 1965 italiaksi ja vuonna 1966 englanniksi [13] . Lauseen ohella Boehmin ja Jacopinin artikkelissa kuvattiin menetelmiä ei-rakenteellisten algoritmien muuntamiseksi rakenteellisiksi algoritmeiksi käyttämällä esimerkkinä Bohmin luomaa P′′- ohjelmointikieltä . P′′-kieli on ensimmäinen Turingin täydellinen ohjelmointikieli ilman goto -operaattoria .
Böhm-Jacopinin lause on kirjoitettu monimutkaisella kielellä ja epätavallisella merkinnällä. Jos käytämme nykyaikaista terminologiaa ja merkintää, se on muotoa:
Mikä tahansa vuokaavion muodossa annettu ohjelma voidaan esittää kolmella ohjausrakenteella:
jossa f, g ovat lohkokaavioita, joissa on yksi tulo ja yksi lähtö,
p - kunto, THEN, IF, ELSE, WHILE, DO ovat avainsanoja [14] .Selitys. Kaava f SITTEN g tarkoittaa seuraavaa: ohjelma f suoritetaan ensin, sitten ohjelma g.
Kuten Harlan Mills huomauttaa , tämä lause eroaa jyrkästi tavanomaisesta (1960-1970 - luvuilla) ohjelmointikäytännöstä, jolloin goto jump -operaattoreita käytettiin massiivisesti [14] .
Boehm ja Jacopini eivät käyttäneet termiä "strukturoitu ohjelmointi". Siitä huolimatta heidän todistamaansa lausetta (ja sen myöhempiä eri tekijöiden muunnelmia) alettiin myöhemmin kutsua "rakenneohjelmointilauseeksi", "rakennelauseeksi" [14] , "strukturointilauseeksi" [15] .
Strukturoidun ohjelmoinnin muodostuminen ja kehittäminen liittyy Edsger Dijkstra [10] [16] nimeen .
Periaate 1. Sinun tulee lopettaa goto unconditional jump -operaattorin käyttö.
Periaate 2. Mikä tahansa ohjelma on rakennettu kolmesta perusohjausrakenteesta: sekvenssi, haarautuminen, sykli.
Periaate 3. Ohjelmassa perusohjausrakenteet voidaan upottaa toisiinsa mielivaltaisella tavalla. Muita keinoja toimintojen järjestyksen ohjaamiseen ei tarjota.
Periaate 4. Ohjelman toistuvat fragmentit voidaan järjestää alirutiinien (prosedures and functions ) muotoon. Samalla tavalla (aliohjelmien muodossa) on mahdollista järjestää ohjelman loogisesti yhtenäisiä fragmentteja, vaikka niitä ei toistettaisikaan.
Periaate 5. Jokainen loogisesti täydellinen käskyryhmä tulee järjestää lohkoksi . Lohkot ovat strukturoidun ohjelmoinnin perusta.
Lohko on loogisesti ryhmitelty lähdekoodin osa, kuten joukko käskyjä, jotka on kirjoitettu riviin ohjelman lähdekoodissa. Lohkon käsite tarkoittaa, että käskylohkoa tulee käsitellä yhtenä käskynä. Lohkot rajoittavat muuttujien ja funktioiden laajuutta. Lohkot voivat olla tyhjiä tai sisäkkäisiä. Lohkojen rajat on määritelty tiukasti. Esimerkiksi if-käskyssä lohko on rajattu koodilla BEGIN..END(Pascalissa) tai aaltosulkeilla {...} (C:ssä) tai sisennyksellä (Pythonissa).Periaate 6. Kaikilla luetelluilla rakenteilla on oltava yksi tulo ja yksi lähtö.
Mielivaltaisilla ohjausrakenteilla (kuten spagettimaljalla) voi olla mielivaltainen määrä tuloja ja lähtöjä. Rajoittumalla ohjausrakenteisiin, joissa on yksi tulo ja yksi lähtö, saamme mahdollisuuden rakentaa mielivaltaisia ja monimutkaisia algoritmeja käyttämällä yksinkertaisia ja luotettavia mekanismeja [17] .Periaate 7. Ohjelman kehittäminen suoritetaan vaiheittain käyttämällä "ylhäältä alas" -menetelmää (ylhäältä alas -menetelmää) [18] .
Ensin kirjoitetaan pääohjelman teksti, johon jokaisen yhdistetyn loogisen tekstifragmentin sijaan lisätään kutsu aliohjelmalle, joka suorittaa tämän fragmentin. Todellisten, toimivien aliohjelmien sijaan ohjelmaan lisätään kuvitteellisia osia - stubs , jotka yksinkertaisesti sanottuna eivät tee mitään.
Tarkemmin sanottuna tynkä täyttää korvattavan fragmentin (moduulin) rajapinnan vaatimukset, mutta ei suorita toimintojaan tai suorittaa niitä osittain. Sen jälkeen tyngät korvataan tai päivitetään todellisiksi täysipainoisiksi fragmenteiksi (moduuleiksi) ohjelmointisuunnitelman mukaisesti. Jo luodun ohjelman tulee jokaisessa toteutusprosessin vaiheessa toimia oikein suhteessa alempaan tasoon. Tuloksena oleva ohjelma tarkistetaan ja virheenkorjaus tehdään [19] .
Kun ohjelmoija on vakuuttunut siitä, että alirutiinit kutsutaan oikeassa järjestyksessä (eli ohjelman yleinen rakenne on oikea), tynkärutiinit korvataan peräkkäin todellisilla ja jokaisen aliohjelman kehitys suoritetaan samassa järjestyksessä. pääohjelmana. Kehitys loppuu, kun tyngöitä ei ole jäljellä.
Tällainen järjestys varmistaa, että ohjelmoija käsittelee jokaisessa kehitysvaiheessa samanaikaisesti näkyvää ja ymmärrettävää fragmenttijoukkoa ja voi olla varma, että ohjelman kaikkien korkeampien tasojen yleinen rakenne on oikea.
Ohjelmaa ylläpidettäessä ja siihen muutoksia tehtäessä käy ilmi, mitä menettelytapoja on muutettava. Ne otetaan käyttöön vaikuttamatta niihin ohjelman osiin, jotka eivät suoraan liity niihin. Tällä varmistetaan, että muutoksia tehtäessä ja virheitä korjattaessa jokin osa ohjelmasta, joka on tällä hetkellä ohjelmoijan toiminta-alueen ulkopuolella, ei epäonnistu [18] [20] [21] [22] [23] [24 ] .
On myös huomattava, että kirjan "Structured Programming" [25] "esipuheessa" Tony Hoare huomauttaa, että strukturoidun ohjelmoinnin periaatteita voidaan yhtä hyvin soveltaa ohjelmien kehittämiseen sekä "ylhäältä alas" että "alhaalta ylös". [26] .
Aliohjelmat eivät olleet välttämätön edellytys mahdollisuudelle toteuttaa jäsenneltyä ohjelmointia [27] . Aluksi alirutiinit esiintyivät keinona optimoida ohjelmia varatun muistin määrän suhteen - ne mahdollistivat sen, että identtisiä koodilohkoja ei toisteta ohjelmassa, vaan kuvattiin ne kerran ja kutsuttiin niitä tarpeen mukaan. Tähän mennessä[ milloin? ] tästä alirutiinien funktiosta on tullut aputoiminto, jonka päätarkoituksena on ohjelman jäsentäminen sen ymmärtämisen ja ylläpidon helpottamiseksi.
Toimintojen joukon erottaminen aliohjelmaksi ja sen kutsuminen tarvittaessa mahdollistaa integroidun alitehtävän valitsemisen loogisesti, jolla on tyypillinen ratkaisu. Tällaisella toiminnolla on vielä yksi (muistin säästämisen lisäksi) etu verrattuna samantyyppisten toimien toistamiseen. Kaikki aliohjelmassa tehdyt muutokset (viankorjaus, optimointi, toiminnallisuuden laajennus) näkyvät automaattisesti kaikissa sen kutsuissa, kun taas kopioinnissa jokainen muutos on tehtävä jokaisessa muutettavan koodin esiintymisessä.
Jopa niissä tapauksissa, joissa aliohjelmalle on varattu kertaluonteinen toimintosarja, tämä on perusteltua, koska se mahdollistaa ohjelman muodostavien integroitujen koodilohkojen koon pienentämisen, toisin sanoen tehdä ohjelmasta ymmärrettävämmän ja näkyvissä.
Strukturoidun ohjelmoinnin periaatteita noudattamalla tehtiin ohjelmien tekstit, jopa melko suuretkin, normaalisti luettavat. Ohjelmien ymmärtäminen on helpottunut huomattavasti, on tullut mahdolliseksi kehittää ohjelmia normaalissa teollisessa tilassa, jolloin ohjelman ymmärtävät ilman suuria vaikeuksia paitsi sen tekijä, myös muut ohjelmoijat. Tämä mahdollisti siihen aikaan melko suurien ohjelmistojärjestelmien kehittämisen kehitystiimien voimin ja näiden kompleksien ylläpitämisen vuosia, vaikka henkilöstön kokoonpanossa tapahtuisi väistämättömiä muutoksia.
Strukturoitu ohjelmointi parantaa huomattavasti ohjelmien selkeyttä ja luettavuutta [28] . Edward Jordan selittää:
Monien ei-rakenteellisten ohjelmien käyttäytyminen on usein lähempänä Brownin liikettä kuin mitään organisoitua prosessia. Jokainen yritys lukea listaa ajaa ihmisen epätoivoon, koska tällainen ohjelma suorittaa yleensä useita lauseita, minkä jälkeen hallinta siirtyy muutaman sivun alapuolelle. Siellä suoritetaan vielä muutama lause ja ohjaus siirretään jälleen johonkin satunnaiseen pisteeseen. Täällä suoritetaan lisää operaattoreita jne. Useiden tällaisten lähetysten jälkeen lukija unohtaa kuinka kaikki alkoi. Ja hän menettää ajatuksensa.
Toisaalta rakenneohjelmat järjestetään ja suoritetaan peräkkäin [29] .
Strukturoitujen ohjelmien luettavuuden parantuminen johtuu siitä, että goto-lauseen puuttuminen mahdollistaa ohjelman lukemisen ylhäältä alas ilman ohjauksen siirron aiheuttamia katkoksia. Tämän seurauksena voit heti (yhdellä silmäyksellä) löytää ehdot, jotka ovat välttämättömiä yhden tai toisen ohjelman fragmentin muokkaamiseen [30] .
P-teknologia ohjelmien tuotantoon tai "kaksiulotteinen ohjelmointitekniikka" [31] luotiin V. M. Glushkov Institute of Cybernetics -instituutissa [32] . R-ohjelmointitekniikan graafinen järjestelmä on kirjattu standardeihin GOST 19.005-85 [33] , GOST R ISO/IEC 8631-94 [34] ja kansainväliseen standardiin ISO 8631Н.
R-ohjelmointitekniikan kirjoittaja, fysiikan ja matemaattisten tieteiden tohtori, professori Igor Velbitsky ehdotti "ohjelman rakenteen" käsitteen uudelleenarviointia. Hänen mukaansa "rakenne on moniulotteinen käsite. Siksi tämän käsitteen esittäminen lineaaristen tekstien (operaattorien sekvenssien) avulla vähentää rakenteellisen lähestymistavan edut lähes olemattomaksi. Visuaalisen laitteen ja ihmisen ajattelulaitteiston valtavia assosiatiivisia mahdollisuuksia käytetään käytännössä turhaan - rakenteellisten kuvien tunnistamiseen yhtenäisen symbolisarjan muodossa" [35] .
Kaksiulotteisen strukturoidun ohjelmoinnin metodologia eroaa merkittävästi klassisesta yksiulotteisesta (tekstiaalisesta) strukturoidusta ohjelmoinnista [36] [37] .
Strukturoidun ohjelmoinnin ideat kehitettiin silloin, kun tietokonegrafiikkaa ei varsinaisesti ollut vielä olemassa ja algoritmistin ja ohjelmoijan päätyökalu oli yksiulotteinen (lineaarinen tai porrastettu ) teksti. Ennen tietokonegrafiikan tuloa klassisen strukturoidun ohjelmoinnin metodologia oli paras ratkaisu [10] .
Tietokonegrafiikan myötä tilanne on muuttunut. Grafiikan ilmaisukeinojen avulla tuli mahdolliseksi muokata, kehittää ja täydentää kolmen tyyppisiä perus(teksti)ohjausrakennerakenteita sekä hylätä avainsanat kokonaan if , then, else, case , switch, break, while , do, toista, kunnes, for , foreach, jatka, loop, exit, milloin, viimeinen jne. ja korvaa ne ohjausgrafiikalla, eli käytä kaksiulotteista strukturoitua ohjelmointia [33] [36] .
|