
See artikkel on tĂ”lge . Kuid enne seda vĂ€ike sissejuhatus. Kuidas tekivad zombid? Igal inimesel on olnud olukordi, kus tahaks tĂ”sta sĂ”pra vĂ”i kolleegi oma tasemele, aga see ei Ă”nnestu. Ja tegelikult ei Ă”nnestu see mitte ainult sinul, vaid ka temal: ĂŒhel tasandil on normaalne palk, ĂŒlesanded ja nii edasi, teisel tasandil aga vajadus mĂ”elda. MĂ”tlema sundimine on ebameeldiv ja valus. Ta loobub kiiresti ja jĂ€tkab kodeerimist, tĂ€iesti mĂ”istust mitte kasutades. Sa suudad ette kujutada, kui palju energiat tuleb kulutada Ă”petatud abituse barjÀÀri ĂŒletamiseks, ja lihtsalt ei tee seda. Nii tekivad zombid, keda vĂ”iks nagu ravida, aga tunduvalt ei tegeleta sellega.
Kui ma nĂ€gin, et (jah, jah, see sama mees Ă”pikutes) ja teeb mitte ettekande, vaid kĂŒsimuste-vastuste sessiooni, siis ma veidi Ă€revaks jĂ€in. Igaks juhuks, Leslie on maailmakuulus teadlane, kes on pĂ”hiteoste autor jaotatud arvutustes, ja te vĂ”ite teda ehk tunda La-tĂ€htede poolest LaTeX-is â âLamport TeXâ. Teiseks murettekitavaks faktoriks on tema nĂ”udmine: igaĂŒhel, kes tuleb, tuleb (tĂ€iesti tasuta) eelnevalt kuulata paar tema ettekannet, vĂ€lja mĂ”elda vĂ€hemalt ĂŒks kĂŒsimus ja siis juba tulla. Otsustasin vaadata, mida Lamport rÀÀgib â ja see on suurepĂ€rane! See on tĂ€pselt see asi, maagiline link-tablett zombituse raviks. Hoian ette: tekst vĂ”ib âpĂ”ledaâ neile, kes armastavad ĂŒlipainduvaid meetodeid ja ei armasta testida kirjutatut.
PÀrast hublukat algabki seminar tÔlge. Head lugemist!
ĂkskĂ”ik, millise ĂŒlesande te endale vĂ”tate, peate alati lĂ€bima kolm sammu:
- otsustamine, millist eesmÀrki soovite saavutada;
- otsustamine, kuidas te tÀpselt oma eesmÀrk Àra tÀidate;
- oma eesmÀrgi saavutamine.
See kehtib ka programmeerimise kohta. Kui me kirjutame koodi, peame meie:
- otsustama, mida programm tegema peab;
- mĂ”tlema, kuidas ta oma ĂŒlesannet tĂ€itma peab;
- sobiva koodi kirjutama.
Viimane samm on loomulikult vÀga oluline, kuid sellest ma tÀna rÀÀkima ei hakka. Selle asemel arutame esimesi kahte. Iga arendaja teeb need enne alustamist. Te ei istu kirjutama, kui te ei ole otsustanud, mida tÀpselt kirjutate: brauser vÔi andmebaas. Teie eesmÀrgi mÔte peab kindlasti olema olemas. Ja te peate kindlasti lÀbi mÔtlema, mida programm tÀpselt tegema hakkab, mitte kirjutama lihtsalt lohistically lootuses, et kood kuidagi muutub brauseriks.
Kuidas tegelikult toimub see esmase koodi planeerimine? Kui palju pingutust peaksime sellele kulutama? KĂ”ik sĂ”ltub sellest, kui keerulist probleemi me lahendame. Eeldame, et soovime kirjutada tĂ”rkeresistentset jaotatud sĂŒsteemi. Sellisel juhul peaksime kĂ”ike hoolikalt lĂ€bi mĂ”tlema enne, kui hakkame koodiga tegelema. Aga kui peame lihtsalt suurendama tervet muutuja vÀÀrtust 1 vĂ”rra? Esmapilgul tundub see triviaalne ja mĂ”tlemist ei vajata, kuid siis me meenutame, et vĂ”ib juhtuda ĂŒlevu. SeetĂ”ttu, et mĂ”ista, kas probleem on lihtne vĂ”i keeruline â tuleb alguses mĂ”elda.
Kui eelnevalt lĂ€bi mĂ”elda vĂ”imalikke lahendusi probleemile, saab vĂ€ltida vigu. Kuid selleks peab teie mĂ”tlemine olema selge. Selle saavutamiseks tuleb oma mĂ”tted kirja panna. Mulle meeldib vĂ€ga Dick Gindoni ĂŒtlus: "Kui sa kirjutad, nĂ€itab loodus sulle, kui lohakalt sa mĂ”tled." Kui te ei kirjuta, siis tundub teile lihtsalt, et te mĂ”tletemis. Ja oma mĂ”tteid tuleb kirja panna spetsifikatsioonide kujul.
Spetsifikatsioonid tĂ€idavad mitmeid funktsioone, eriti suurtes projektides. Kuid ma rÀÀgin ainult ĂŒhest neist: nad aitavad meil selgelt mĂ”elda. Selgelt mĂ”elda on vĂ€ga oluline ja ĂŒsna keeruline, seega vajame siin igasugust abi. Millisel keeles peaksime spetsifikatsioone kirjutama? See on alati esimene kĂŒsimus arendajatele: millises keeles kirjutame. Ăhte Ă”igesti vastust sellele ei ole: probleemid, mida me lahendame, on liiga mitmekesised. MĂ”nedele on kasulik TLA+ â see on spetsifikatsioonide keel, mille ma vĂ€lja töötasin. Teistele on mugavam kasutada hiina keelt. KĂ”ik sĂ”ltub olukorrast.
KĂŒsimus on selles: kuidas saavutada selgemat mĂ”tlemist? Vastus: me peame mĂ”tlema nagu teadlased. See mĂ”tlemisviis on viimase 500 aasta jooksul hĂ€sti toiminud. Teaduses loome me matemaatilisi mudeleid reaalsusest. Astronoomia oli ilmselt esimene teadus rangemas mĂ”ttes. Astronoomias kasutatavates matemaatilistes mudelites kujutatakse taevakehi punktidena, millel on mass, asukoht ja impulss, kuigi tegelikkuses on nad ÀÀrmiselt keerulised objektid koos mĂ€gede ja ookeanidega, tĂ”usude ja mÔÔnadega. See mudel, nagu iga teine, on loodud konkreetsete probleemide lahendamiseks. See sobib suurepĂ€raselt mÀÀramaks, kuhu suunata teleskoop, kui tuleb leida planeet. Kuid kui soovite prognoosida selle planeedi ilma, siis see mudel ei sobi.
Matemaatika vĂ”imaldab meil mÀÀrata mudeli omadusi. Ja teadus nĂ€itab, kuidas need omadused seostuvad reaalsusega. RÀÀgime meie teadusest, arvutiteadusest. Reaalsus, millega me töötame, on vĂ€ga erinevad arvutisĂŒsteemid: protsessorid, mĂ€ngukonsoolid, arvutid, mis kĂ€itavad programme jne. RÀÀgin programmi kĂ€ivitamisest arvutis, kuid, ĂŒldiselt, kehtivad kĂ”ik need jĂ€reldused igasuguste arvutisĂŒsteemide kohta. Meie teaduses kasutame palju erinevaid mudeleid: Turingi masin, osaliselt jĂ€rjestatud sĂŒndmustega kogud ja paljud teised.
Mis on programm? See on iga kood, mida saab kĂ€sitleda iseseisvalt. Oletame, et peame kirjutama brauseri. Me tĂ€idame kolm ĂŒlesannet: projekteerime programmi esitluse kasutajale, seejĂ€rel kirjutame programmi kĂ”rge taseme skeemi ja lĂ”puks kirjutame koodi. Koodi kirjutamise kĂ€igus mĂ”istame, et peame kirjutama teksti vormindamise vahendi. Siin peame jĂ€lle lahendama kolm ĂŒlesannet: mÀÀratlema, millist teksti see vahend tagastab; valima vormindamise algoritmi; kirjutama koodi. Sellel ĂŒlesandel on oma alauuend: liite Ă”igesti sĂ”nadesse. Selle alateema lahendame samuti kolmes etapis â nagu nĂ€eme, need korduvad mitmel tasandil.
Vaatame lÀhemalt esimese sammu: millist probleemi programm lahendab. Siin modellime programmi tihti kui funktsiooni, mis vÔtab sisse teatud sisendandmed ja annab vÀlja teatud vÀljundandmed. Matemaatikas kirjeldatakse funktsiooni tavaliselt kui jÀrjestatud paaride hulka. NÀiteks, ruutfunktsioon naturaalarvude jaoks on kirjeldatud kui hulk {, , , , ...}. Selle funktsiooni mÀÀramispiirkond on paaride esimeste elementide hulk, see tÀhendab naturaalarve. Funktsiooni mÀÀratlemiseks peame nÀitama selle mÀÀramispiirkonna ja valemi.
Aga matemaatikas olevad funktsioonid ei ole samad, mis programmeerimiskeeltes. Matemaatika on oluliselt lihtsam. Kuna mul pole aega keerukate nĂ€idete jaoks, vaatame lihtsat: funktsioon C keeles vĂ”i staatiline meetod Java keeles, mis tagastab kahe tĂ€isarvu suurima ĂŒhise jagaja. Selle meetodi spetsifikatsioonis kirjutame: arvutab GCD(M,N) argumentide jaoks M ja N, kus GCD(M,N) â funktsioon, mille mÀÀramispiirkond on tĂ€isarvude paaride hulk, ja tagastatav vÀÀrtus on suurim tĂ€isarv, millesse jagub M ja N. Kuidas see mudel reaalsusega seondub? Mudel opereerib tĂ€isarvudega, kuid C-s vĂ”i Java-s on meil 32-bitised int. See mudel vĂ”imaldab meil otsustada, kas algoritm GCD, on Ă”ige, kuid see ei takista ĂŒlevoolu vigu. Selleks oleks vajalik keerulisem mudel, mille jaoks pole aega.
RÀÀgime funktsiooni piirangutest mudelina. MĂ”nede programmide (nt operatsioonisĂŒsteemide) töö ei ole lihtsalt kindlatele argumentidele kindla vÀÀrtuse tagastamine, need vĂ”ivad töötada pidevalt. Lisaks on funktsioon mudelina kehva sobivuse tĂ”ttu teise sammu jaoks: probleemi lahendamise plaani koostamine. Kiirusortimine ja mullisortimine arvutavad sama funktsiooni, kuid need on tĂ€iesti erinevad algoritmid. SeetĂ”ttu kasutan programmi eesmĂ€rgi saavutamise viisi kirjeldamiseks teist mudelit, nimetame seda standardselt kĂ€itumismudeliks. Programm on selles esitatud kĂ”ikide lubatud kĂ€itumiste koguna, millest igaĂŒht saab omakorda vaadelda seisundite jĂ€rjestikuse kogumina, kus seisund on muutuja vÀÀrtuste mÀÀramine.
Vaadakem, kuidas nÀeb vÀlja teise sammu protsess Euclide algoritmis. Peame arvutama GCD(M, N). Algatame M kuidas x, vaid N kuidas y, seejÀrel lahutame suuremast muutujast vÀiksema, kuni need on vÔrdsed. NÀiteks, kui M = 12, vaid N = 18, saame kirjeldada jÀrgmist kÀitumist:
[x = 12, y = 18] â [x = 12, y = 6] â [x = 6, y = 6]
Ja kui M = 0 ja N = 0? ĐĐŸĐ»Ń ĐŽĐ”Đ»ĐžŃŃŃ ĐœĐ° ĐČŃĐ” ŃĐžŃла, ĐżĐŸŃŃĐŸĐŒŃ ĐœĐ°ĐžĐ±ĐŸĐ»ŃŃĐ”ĐłĐŸ ЎДлОŃĐ”Đ»Ń ĐČ ŃŃĐŸĐŒ ŃĐ»ŃŃаД ĐœĐ”Ń. Đ ŃŃĐŸĐč ŃĐžŃŃаŃОО ĐœĐ°ĐŒ ĐœŃĐ¶ĐœĐŸ ĐČĐ”ŃĐœŃŃŃŃŃ Đș пДŃĐČĐŸĐŒŃ ŃĐ°ĐłŃ Đž ŃĐżŃĐŸŃĐžŃŃ: ĐŽĐ”ĐčŃŃĐČĐžŃДлŃĐœĐŸ лО ĐœĐ°ĐŒ ĐœŃĐ¶ĐœĐŸ ĐČŃŃĐžŃĐ»ŃŃŃ ĐĐĐ ĐŽĐ»Ń ĐœĐ”ĐżĐŸĐ»ĐŸĐ¶ĐžŃДлŃĐœŃŃ
ŃĐžŃДл? ĐŃлО ĐČ ŃŃĐŸĐŒ ĐœĐ”Ń ĐœĐ”ĐŸĐ±Ń
ĐŸĐŽĐžĐŒĐŸŃŃĐž, ŃĐŸ ĐœŃĐ¶ĐœĐŸ ĐżŃĐŸŃŃĐŸ ĐžĐ·ĐŒĐ”ĐœĐžŃŃ ŃпДŃĐžŃĐžĐșаŃĐžŃ.
Siin tasub teha vĂ€ike kĂ”rvaleviide tootlikkusele. Seda mÔÔdetakse sageli pĂ€evade jooksul kirjutatud koodiread. Kuid teie töö on palju kasulik, kui olete kĂ”rvaldada teatud arvu ridu, kuna teil on vĂ€hem avastatav viga. Ja koodist vabanemine on kĂ”ige lihtsam just esimesel sammul. On tĂ€iesti vĂ”imalik, et kĂ”ik need nipsud, mida proovite rakendada, pole tegelikult vajalikud. Kiireim viis programmi lihtsustamiseks ja aja sÀÀstmiseks on mitte teha asju, mida ei maksa teha. Teine samm on teisel kohal ajasÀÀstu potentsiaaliga. Kui mÔÔdate tootlikkust kirjutatud ridade arvu jĂ€rgi, siis ĂŒlesande tĂ€itmise viisi mĂ”tlemine muudab teid vĂ€hem tootlikuks, kuna saate sama ĂŒlesande lahendada vĂ€iksema koodihulgaga. TĂ€pset statistikat ma siin anda ei saa, kuna mul pole vĂ”imalik loendada ridade arvu, mille ma ei kirjutanud just seetĂ”ttu, et kulutasin aega spetsifikatsioonile, st esimest ja teist sammu. Ja eksperimenti ei saa ka lĂ€bi viia, sest eksperimentides ei tohi me esimest sammu lĂ€bi viia, ĂŒlesanne on eelnevalt mÀÀratud.
Mitteformaalsete spetsifikatsioonide koostamisel on lihtne jĂ€tta arvesse paljusid raskusi. Pole midagi keerulist rangete spetsifikatsioonide kirjutamisel funktsioonide jaoks, sellest ma ei rÀÀgi. Selle asemel arutame rangete spetsifikatsioonide kirjutamist standardsete kĂ€itumismudelite jaoks. On teoreem, mis ĂŒtleb, et iga kĂ€itumiste kogumit saab kirjeldada koos ohutuse omadusega (safety) ja elujĂ”udluse omadusega (liveness). Turvalisus tĂ€hendab, et midagi halba ei juhtu, programm ei anna vale vastust. JĂ€tkusuutlikkus tĂ€hendab, et varem vĂ”i hiljem juhtub midagi head, st programm annab varem vĂ”i hiljem Ă”ige vastuse. Ăldiselt on turvalisus olulisem nĂ€itaja, vead tekivad kĂ”ige sagedamini just siin. Seega, ajakulu sÀÀstmiseks ei hakka ma jĂ€tkusuutlikkusele keskenduma, kuigi see on samuti oluline.
Me saavutame turvalisuse, koostades kĂ”igepealt palju vĂ”imalikke algtingimusi. Teiseks, seosed kĂ”igi vĂ”imalike jĂ€rgneva seisundiga iga olukorra jaoks. KĂ€itume nagu teadlased ja mÀÀratleme seisundeid matemaatiliselt. Algtingimuste kogumit kirjeldatakse valemiga, nĂ€iteks Euclidi algoritmi puhul: (x = M) â§ (y = N). Teatud vÀÀrtuste korral M ja N on ainult ĂŒks algne seisund. Seos jĂ€rgmise seisundiga kirjeldatakse valemiga, kus jĂ€rgmise seisundi muutujad kantakse ĂŒle kriipsudena, samas kui kĂ€esoleva seisundi muutujad jÀÀvad ilma kriipsudeta. Euclidi algoritmi puhul kĂ€sitleme kahte valemit, millest ĂŒhes x on suurim vÀÀrtus, ja teises â y:

Esimesel juhul on uus vÀÀrtus y vana vÀÀrtuse y ega ole muutunud, samas kui uus vÀÀrtus x saadakse suurest muutujast vÀiksema lahutamisega. Teisel juhul teeme vastupidi.
Naaseme Euclidi algoritmi juurde. Oletame taas, et M = 12, N = 18. See mÀÀratleb ainulaadse algseisundi, (x = 12) â§ (y = 18). Siis asendame need vÀÀrtused ĂŒlaltoodud valemis ja saame:

Siin on ainus vĂ”imalik lahendus: x' = 18 - 12 â§ y' = 12, ja saame kĂ€itumise: [x = 12, y = 18]. Sama moodi saame kirjeldada kĂ”iki olekuid meie kĂ€itumises: [x = 12, y = 18] â [x = 12, y = 6] â [x = 6, y = 6].
Viimases seisundis [x = 6, y = 6] kui mĂ”lemad lauseosad on vale, siis jĂ€rgnevat seisundit ei ole. Nii et meil on tĂ€ielik spetsifikatsioon teise sammu kohta â nagu nĂ€eme, on see tĂ€iesti tavaline matemaatika, nagu inseneride ja teadlaste seas, mitte midagi imelikku, nagu arvutiteaduses.
Need two formulae can be combined into a single temporal logic formula. It is elegant and easy to explain, but there is currently no time for that. Temporal logic may only be necessary for the liveness property; it is not needed for security. Temporal logic as such is not appreciated; it is not quite conventional mathematics, but in the case of liveness, it is a necessary evil.
In Euclid's algorithm for each value x ja y there are unique values x' ja y', which make the relation with the next state true. In other words, the Euclidean algorithm is deterministic. To model a nondeterministic algorithm, the current state must have several possible future states, and each value of the variable without a stroke must have several values of the variable with a stroke for which the relation with the next state holds true. This is not difficult to do, but I will not provide examples now.
To create a working tool, formal mathematics is needed. How to make a formal specification? For this, we will need a formal language, for example, . The specification of Euclid's algorithm will look as follows in this language:

The equality sign with a triangle indicates that the value on the left side of the sign is defined as equal to the value on the right side of the sign. Essentially, a specification is a definition, in our case, two definitions. To the TLA+ specification, declarations and some syntax need to be added, as shown in the slide above. In ASCII it looks like this:

As we can see, nothing complicated. The specification in TLA+ can be verified, i.e. check all possible behaviors in a small model. In our case, this model will be defined values M ja N. This is a very efficient and straightforward verification method that is entirely automated. Moreover, formal proofs of validity can be written and checked mechanically, but this takes a lot of time, which is why almost no one does it.
TLA+ peamine puudus on see, et see on matemaatika, ja programmeerijad ning arvutiteadlastel on matemaatika ees hirm. Esmapilgul vĂ”ib see kĂ”lada naljakalt, kuid kahjuks rÀÀgin ma seda tĂ€iesti tĂ”siselt. Minu kolleeg rÀÀkis just sellest, kuidas ta ĂŒritas selgitada TLA+d mitmele arendajale. Kui ekraanile ilmusid valemid, sai neil kohe klaasist pilk. Nii et kui TLA+ tundub hirmuĂ€ratav, siis on vĂ”imalik kasutada , mis on omamoodi mĂ€ngurakendusprogrammeerimise keel. PlusCalis vĂ”ib vĂ€ljend olla mis tahes TLA+ vĂ€ljend, see tĂ€hendab, et sisuliselt on see mis tahes matemaatiline vĂ€ljend. Lisaks on PlusCalis sĂŒntaks mittedeterministlikele algoritmidele. Kuna PlusCalis saab kirjutada mis tahes TLA+ vĂ€ljendi, on see oluliselt vĂ€ljendusrikkam kui ĂŒkski reaalne programmeerimiskeel. Edasi, PlusCal kompileeritakse kergesti loetavaks TLA+ spetsifikatsiooniks. See ei tĂ€henda muidugi, et keeruline PlusCal spetsifikatsioon muutub lihtsaks TLA+-iks â lihtsalt vastavus nende vahel on ilmselge, ei toimu lisakompleksuse teket. LĂ”puks saab seda spetsifikatsiooni kontrollida TLA+ tööriistade abil. Ăldiselt vĂ”ib PlusCal aidata ĂŒletada matemaatika foobiat, seda on isegi programmeerijatel ja arvutiteadlastel lihtne mĂ”ista. Minevikus olin ma umbes 10 aastat aktiivne PlusCali algoritmide avaldamisel.
VĂ”ib-olla leidub keegi, kes vĂ€idab, et TLA+ ja PlusCal on matemaatika, ja matemaatika töötab ainult vĂ€ljamĂ”eldud nĂ€idetes. Praktikas on aga vajalik reaalne keel, mis sisaldab tĂŒĂŒpe, protseduure, objekte ja nii edasi. See ei ole nii. Siin on, mida kirjutab Chris Newcomb, kes töötas Amazonis: âKasutame TLA+ kĂŒmnes suures projektis, ja igal juhul andis selle kasutamine olulise panuse arendusse, kuna suutsime ohtlikud vead kinni pĂŒĂŒda enne, kui need jĂ”udsid tootmisse, ja kuna see andis meile arusaama ja kindlust, mis oli vajalik agressiivsete jĂ”udluse optimeerimiste jaoks, mis ei mĂ”jutanud programmi tĂ”elisust". Tihti vĂ”ib kuulda, et formaalsete meetodite kasutamisel sĂŒnnib ebaefektiivne kood â praktikas on aga kĂ”ike just vastupidi. Lisaks on levinud arvamus, et juhte on vĂ”imatu veenda formaalsete meetodite vajalikkuses, isegi kui programmeerijad on veendunud nende kasulikkuses. Ja Newcomb kirjutab: âJuhtijad nĂ€evad nĂŒĂŒd kĂ”iki vĂ”imalusi, et kirjutada TLA+ spetsiifikasid ning eraldavad selleks spetsiaalselt aegaâ. Nii et kui juhtijad nĂ€evad, et TLA+ töötab, vĂ”tavad nad selle rÔÔmuga vastu. Chris Newcomb kirjutas seda umbes kuus kuud tagasi (oktoobris 2014), kuid nĂŒĂŒd, kui ma tean, kasutatakse TLA+ 14 projektis, mitte 10. Teine nĂ€ide puudutab XBox 360 kavandamist. Charles Tecker sai praktikandi, kes kirjutas mĂ€lusĂŒsteemi spetsiifikatsiooni. TĂ€nu sellele spetsiifikatsioonile avastati viga, mida muidu ei oleks mĂ€rgatud, ja mille tĂ”ttu oleks iga XBox 360 nelja tunni pĂ€rast crashinud. IBM-i insenerid kinnitasid, et nende testid ei oleks seda viga avastanud.
TLA+ kohta saate internetis rohkem lugeda, aga nĂŒĂŒd rÀÀgime mitteformaalsetest spetsiifikatsioonidest. Me ei pea sageli kirjutama programme, mis arvutavad maassima jagaja ja sarnaseid asju. Oluliselt sagedamini kirjutame programme, nagu nĂ€iteks struktuuriprindimise tööriist (pretty-printer), mille ma kirjutasin TLA+-le. PĂ€rast kĂ”ige lihtsamat töötlemist nĂ€eks TLA+ kood vĂ€lja jĂ€rgnev:

Aga antud nĂ€ites tahtis kasutaja tĂ”enĂ€oliselt, et konjunktiivsete ja vĂ”rdsusmĂ€rkide joondus oleks ĂŒhtlane. Nii et Ă”ige vormindamine nĂ€eks pigem vĂ€lja nii:

Vaatame teist nÀidet:

Siin oli vastupidi, vĂ”rdsus-, liitmis- ja korrutamismĂ€rkide joondus allikas juhuslik, seega oli kĂ”ige lihtsam töötlemine tĂ€iesti piisav. Ăldiselt pole tĂ€pset matemaatilist mÀÀratlust Ă”igele vormindusele, sest âĂ”igeâ tĂ€henduses tĂ€hendab ânagu kasutaja soovibâ, mida matemaatiliselt mÀÀratleda ei saa.
Tundub, et kui meil ei ole tĂ”evÀÀrtuse mÀÀratlust, siis on spetsiifikatsioon kasutu. Aga see ei ole nii. Kui me ei tea, mida programm tĂ€pselt tegema peab, ei tĂ€henda see, et me ei peaks selle töö peale mĂ”tlema â vastupidi, peaksime sellele rohkem aega kulutama. Spetsiifikatsioon on sel juhul eriti oluline. Optimaalse programmi mÀÀramine struktuuriprinterile on vĂ”imatu, aga see ei tĂ€henda, et me ei peaks sellega tegelema, ja koodi kirjutamine vooluna ei ole Ă”ige lĂ€henemine. LĂ”puks kirjutasin kuue reegli ja mÀÀratlustega spetsiifikatsiooni kommentaaride kujul Java-failis. Siin on ĂŒks nĂ€ide reeglitest: left-comment token on LeftComment, mis on joondatud selle katva tokeniga. See reegel on kirjutatud, ĂŒtleme, matemaatilises inglise keeles: LeftComment joondatud, left-comment ja kattev token â terminid koos mÀÀratlustega. See on see, kuidas matemaatikud matemaatikat kirjeldavad: nad kirjutavad terminite mÀÀratlusi ja nende pĂ”hjal reeglid. Sellise spetsifikatsiooni kasu on see, et kuue reegli mĂ”istmine ja silumine on oluliselt lihtsam kui 850 koodi rida. Pean ĂŒtlema, et nende reeglite kirjutamine ei olnud kerge, nende silumiseks kulus ĂŒsna palju aega. Just selle eesmĂ€rgi nimel kirjutasin koodi, mis teatas, millist reeglit kasutatakse. TĂ€nu sellele, et ma kontrollisin neid kuut reeglit mitmete nĂ€idete peal, ei pidanud ma siluma 850 koodi rida, ja vigade leidmine osutus ĂŒsna lihtsaks. Java jaoks on selleks suurepĂ€rased tööriistad. Kui ma lihtsalt koodi kirjutanud oleksin, oleks see mulle oluliselt kauem aega vĂ”tnud ja vormindamine oleks olnud halvem.
Miks ei saanud kasutusele vĂ”tta formaalset spetsifikatsiooni? Ăhelt poolt ei ole Ă”igsuse tagamine siin liiga oluline. Struktuurne printimine ei sobi kindlasti kellelegi, seega ei pidanud ma tagama, et see töötas kĂ”igis ebatavalistes olukordades. Veel olulisem on see, et mul ei olnud adekvaate tööriistu. TLA+ mudelite kontrollimisvahend siin ei tööta, seega oleksin pidanud nĂ€idised kĂ€sitsi kirjutama.
Antud spetsifikatsioonil on omad jooned, mis on tavalised kĂ”igi spetsifikatsioonide puhul. See on kĂ”rgemal tasemel kui kood. Seda saab rakendada mistahes keeles. Selle kirjutamiseks ei ole kasu mistahes tööriikudest vĂ”i meetoditest. Ăkski programmeerimise kursus ei aita teil seda spetsifikatsiooni kirjutada. Ja ei ole olemas tööriistu, mis vĂ”iksid selle spetsifikatsiooni vajaduse kaotada, kui just ei kirjuta keelt, mis on mĂ”eldud struktuurse printimise programmide kirjutamiseks TLA+ abil. LĂ”puks, see spetsifikatsioon ei ĂŒtle midagi selle kohta, kuidas me koodi kirjutame, see nĂ€itab ainult, mida see kood teeb. Me kirjutame spetsifikatsiooni, et aidata meil probleemile mĂ”elda, enne kui hakkame koodist mĂ”tlema.
Kuid sellel spetsifikatsioonil on ka omadused, mis eristavad seda teistest spetsifikatsioonidest. 95% teistest spetsifikatsioonidest on oluliselt lĂŒhemad ja lihtsamad:

Edasi, see spetsifikatsioon on reeglite kogum. Ăldiselt on see halbade spetsifikatsioonide tunnus. Reeglite kogumi tagajĂ€rgede mĂ”istmine on ĂŒsna keeruline ja seepĂ€rast pidin ma nende tĂ”rkeotsimiseks palju aega kulutama. Sellegipoolest ei leidnud ma sellisel juhul paremat lahendust.
Tasub öelda paar sĂ”na programmidest, mis töötavad pidevalt. Ăldiselt töötavad need paralleelselt, nagu nĂ€iteks operatsioonisĂŒsteemid vĂ”i jaotatud sĂŒsteemid. VĂ€ga vĂ€hesed saavad nendega vaimselt vĂ”i paberil toime, ja ma ei kuulu nende hulka, ehkki kunagi suutsin. SeepĂ€rast on vajalikud tööriistad, mis kontrollivad meie tööd â nĂ€iteks TLA+ vĂ”i PlusCal.
Miks pidin kirjutama spetsifikatsiooni, kui ma juba teadsin, mida kood peaks tegema? Tegelikult tundus mulle lihtsalt, et ma tean seda. Lisaks, kui olemas on spetsifikatsioon, ei pea vÔÔras inimene enam koodi sĂŒĂŒvima, et mĂ”ista, mida see tĂ€pselt teeb. Mul on reegel: ĂŒldiselt ei peaks olema mingeid ĂŒldisi reegleid. Sellel reeglil on muidugi erand, see on ainus ĂŒldine reegel, millele ma toetun: koodi spetsifikatsioon peab edastama inimestele kĂ”ik, mis neile on vajalik selle koodi kasutamiseks.
Nii et, mida peavad programmeerijad teadma mĂ”tlemisest? Esiteks, sama, mis kĂ”ik: kui sa ei kirjuta, siis tundub sul ainult, et sa mĂ”tled. Lisaks tuleb mĂ”elda enne kodeerimist, mis tĂ€hendab, et tuleb kirjutada enne kodeerimist. Spetsifikatsioon on see, mida me kirjutame enne, kui hakkame kodeerima. Spetsifikatsioon on vajalik igasuguse koodi jaoks, mida keegi teine vĂ”ib kasutada vĂ”i muuta. Ja see 'keegi' vĂ”ib olla ka koodi autor ĂŒks kuu pĂ€rast kirjutamist. Spetsifikatsioon on vajalik suurte programmide ja sĂŒsteemide, klasside, meetodite ja mĂ”nikord isegi keeruliste osade jaoks ĂŒksiku meetodi sees. Mida tĂ€pselt tuleb koodi kohta kirjutada? Tuleb kirjeldada, mida see teeb, st mida vĂ”ib-olla on kasulik teada igal inimesel, kes seda koodi kasutab. MĂ”nikord vĂ”ib olla vajalik ka mĂ€rkida, kuidas tĂ€pselt kood oma eesmĂ€rgini jĂ”uab. Kui see meetod on lĂ€bi kĂ€idud algoritmide kursusel, siis nimetame seda algoritmiks. Kui see aga on midagi spetsiifilisemat ja uut, siis nimetame seda kĂ”rgetasemeliseks projekteerimiseks. Formaalset vahet siin ei ole: mĂ”lemad on abstraktsed programmimudelid.
Kuidas tĂ€pselt peaks kirjutama koodi spetsifikatsiooni? Peamine: see peab olema tasemelt kĂ”rgem kui ise kood. See peab kirjeldama olekuid ja kĂ€itumisi. See peab olema nii rangelt, kui probleem nĂ”uab. Kui kirjutate spetsifikatsiooni ĂŒlesande teostamise kohta, siis saab selle kirjutada pseudokoodina vĂ”i PlusCal abil. Spetsifikatsioonide kirjutamist tuleb Ă”ppida formaalsetest spetsifikatsioonidest. See annab teile vajalikud oskused, mis aitavad ka mitteformaalsetes. Ja kuidas Ă”ppida kirjutama formaalseid spetsifikatsioone? Kui me Ă”ppisime programmeerimist, siis kirjutasime programme ja seejĂ€rel tĂ”rkeotsisime neid. Sama kehtib siin: peate kirjutama spetsifikatsiooni, kontrollima seda mudeli kontrollimise vahendi abil ja parandama vea. TLA+ ei pruugi olla kĂ”ige parem keel formaalseks spetsifikatsiooniks, ja teie spetsiifiliste vajaduste jaoks sobib tĂ”enĂ€oliselt hoopis muu keel. TLA+ eeliseks on see, et see Ă”petab suurepĂ€raselt matemaatilist mĂ”tlemist.
Kuidas siduda spetsifikatsiooni ja koodi? Selleks on vajalikud kommentaarid, mis seovad matemaatilisi mÔisteid ja nende rakendust. Kui töötate graafikute kallal, siis programmitasandil on teil sÔlmede massiivid ja seoste massiivid. SeetÔttu peate kirjutama, kuidas graaf neid programmise struktuure rakendab.
Oluline on mĂ€rkida, et eelpool rÀÀgitu ei puuduta koodi kirjutamise protsessi. Kui kirjutate koodi, ehk tĂ€idate kolmandat sammu, peate samuti mĂ”tlema ja kavandama programmi. Kui osaĂŒlesanne osutub keeruliseks vĂ”i ebaselgeks, tuleb kirjutada selle jaoks spetsifikatsioon. Kuid koodi endast ma siin ei rÀÀgi. Te vĂ”ite kasutada ĂŒkskĂ”ik millist programmeerimiskeelt vĂ”i metoodikat, asi ei ole nendes. Lisaks ei vabasta eelnevast rÀÀgitu teid koodi testimise ja tĂ”rkeotsingu vajadusest. Isegi kui abstraktne mudel on Ă”igesti kirjutatud, vĂ”ivad selle rakenduses esineda vead.
Spetsifikatsioonide kirjutamine on lisasamm koodi kirjutamise protsessis. Selle kaudu on vÔimalik paljusid vigu tuvastada vÀhemate pingutustega - me teame seda Amazonist pÀrit programmeerijate kogemuse pÔhjal. Spetsifikatsioonide abil tÔuseb programmide kvaliteet. Miks me siis nii sageli ilma nendeta lÀbi saame? Sest kirjutamine on keeruline. Ja kirjutamine on keeruline, sest see nÔuab mÔtlemist, aga mÔtlemine on samuti keeruline. Alati on lihtsam nÀida, et mÔtleme. Siin saab tuua analoogia jooksmisega - mida rohkem te jooksete, seda kiiremini te jooksete. Peate oma lihaseid treenima ja kirjutamise harjutusi tegema. Praktika on vajalik.
Spetsifikatsioon vĂ”ib olla vale. Te vĂ”isite kuskil eksida, vĂ”imalik, et nĂ”uded on muutunud vĂ”i on vajalikud tĂ€iustused. Iga kood, mida keegi kasutab, tuleb muuta, seega aeg-ajalt lakkab spetsifikatsioon vastamast programmale. Ideaalis peaks sellisel juhul kirjutama uue spetsifikatsiooni ja koodi tĂ€ielikult ĂŒmber. Me teame hĂ€sti, et keegi seda ei tee. Praktiliselt me 'patch' koodi ja ehk vĂ€rskendame spetsifikatsiooni. Kui see paratamatult varem vĂ”i hiljem juhtub, siis miks ĂŒldse spetsifikatsioone kirjutada? Esiteks, inimese jaoks, kes teie koodi muudab, on iga liigne sĂ”na spetsifikatsioonis kuldavÀÀrt, ja see inimene vĂ”ite olla ka teile endale. Ma kritiseerin end sageli seetĂ”ttu, et spetsifikatsioon on ebapiisav, kui muudan oma koodi. Ning kirjutad rohkem spetsifikatsioone kui koodi. Seega, kui te muudate koodi, tuleb spetsifikatsiooni alati vĂ€rskendada. Teiseks, iga muutmisega muutub kood halvemaks, seda on jĂ€rjest raskem lugeda ja hooldada. See on entropia suurenemine. Kuid kui te ei alusta spetsifikatsioonist, siis iga kirjutatud rida on muutmine ja kood on algusest peale kohmakas ja raskesti loetav.
Nagu ĂŒtles , ei ole ĂŒhtki lahingut vĂ”idetud plaani jĂ€rgi ja ei ole ĂŒhtki lahingut vĂ”idetud ilma plaanita. Ja ta teadis lahingutest midagi. On arvamus, et spetsifikatsioonide kirjutamine on ajaraiskamine. MĂ”nikord on see tĂ”si ja ĂŒlesanne on nii lihtne, et pole mĂ”tet sellele mĂ”elda. Kuid alati tuleb meeles pidada, et kui teil soovitatakse spetsifikatsioone mitte kirjutada, tĂ€hendab see, et teile soovitatakse mitte mĂ”elda. Ja sellest tuleb iga kord mĂ”elda. Ălesande lĂ€bi mĂ”tlemine ei garanteeri, et te eksite. Nagu me teame, ei ole keegi leiutanud imetootlat ja programmeerimine on keeruline tegevus. Kuid kui te ei mĂ”tle ĂŒlesanne lĂ€bi, siis teete kindlalt vigu.
Rohkem TLA+ ja PlusCal kohta saab lugeda spetsiaalselt veebilehelt, kuhu pÀÀseb minu isikliku lehe kaudu. . Sellega olen lÔpetanud, aitÀh tÀhelepanu eest.
Tulet meelde, et see on tÔlge. Kui kirjutate kommentaare, pidage meeles, et autor neid ei loe. Kui tÔeliselt soovite autoriga suhelda, siis ta on Hydra 2019 konverentsil, mis toimub 11.-12. juulil 2019 Peterburis. Piletid on saadaval ostmiseks. .
Allikas: habr.com
