ProgrammÄ“Å”ana ir vairāk nekā kodÄ“Å”ana

ProgrammÄ“Å”ana ir vairāk nekā kodÄ“Å”ana

Å is ir tulkoÅ”anas raksts Stenfordas seminārs. Bet pirms tam ir Ä«ss ievads. Kā veidojas zombiji? Ikviens ir nonācis situācijā, kad vēlas pacelt draugu vai kolēģi lÄ«dz savam lÄ«menim, bet tas neizdodas. Turklāt ā€œneizdodasā€ ne tik daudz jums, bet viņam: vienā skalas pusē ir normāla alga, uzdevumi un tā tālāk, bet otrā ir nepiecieÅ”amÄ«ba domāt. DomāŔana ir nepatÄ«kama un sāpÄ«ga. ViņŔ ātri padodas un turpina rakstÄ«t kodu, neizmantojot savas smadzenes. JÅ«s saprotat, cik daudz pūļu ir nepiecieÅ”ams, lai pārvarētu iemācÄ«tās bezpalÄ«dzÄ«bas barjeru, un jÅ«s to vienkārÅ”i nedarāt. Tā veidojas zombiji, kurus it kā ir iespējams izārstēt, bet Ŕķiet, ka neviens to nedarÄ«s.

Kad es to redzēju Leslija Lamporta (jā, tas pats draugs no mācÄ«bu grāmatām) nāk uz Krieviju un nesniedz ziņojumu, bet gan jautājumu un atbilžu sesiju, es biju nedaudz piesardzÄ«gs. Katram gadÄ«jumam, Leslijs ir pasaulē pazÄ«stams zinātnieks, izkliedētās skaitļoÅ”anas pamatdarbu autors, un jÅ«s, iespējams, viņu pazÄ«stat arÄ« pēc LaTeX burtiem La - ā€œLamport TeXā€. Otrs satraucoÅ”ais faktors ir viņa prasÄ«ba: katram atnākuÅ”ajam ir (pilnÄ«gi bez maksas) iepriekÅ” jānoklausās pāris viņa referātu, jāizdomā vismaz viens jautājums par tiem un tikai tad jānāk. Es nolēmu redzēt, ko Lamports tur pārraida, un tas ir lieliski! Tas ir tieÅ”i tas, burvju saiÅ”u tablete zombiju ārstÄ“Å”anai. BrÄ«dinu: teksts var nopietni sadedzināt tos, kam patÄ«k Ä«paÅ”i veiklās metodikas un kuriem nepatÄ«k pārbaudÄ«t rakstÄ«to.

Pēc habrokata faktiski sākas semināra tulkoÅ”ana. Izbaudi lasÄ«Å”anu!

Neatkarīgi no tā, kādu uzdevumu jūs uzņematies, jums vienmēr ir jāveic trīs darbības:

  • izlemiet, kādu mērÄ·i vēlaties sasniegt;
  • izlemiet, kā tieÅ”i jÅ«s sasniegsiet savu mērÄ·i;
  • sasniegt savu mērÄ·i.

Tas attiecas arÄ« uz programmÄ“Å”anu. Kad mēs rakstām kodu, mums ir nepiecieÅ”ams:

  • izlemt, kas tieÅ”i programmai jādara;
  • precÄ«zi noteikt, kā tai bÅ«tu jāpilda savs uzdevums;
  • uzrakstiet atbilstoÅ”o kodu.

Pēdējais solis, protams, ir ļoti svarÄ«gs, bet es par to Å”odien nerunāŔu. Tā vietā mēs apspriedÄ«sim pirmos divus. Katrs programmētājs tos veic pirms darba sākÅ”anas. JÅ«s nesēdat, lai rakstÄ«tu, ja vien neesat izlēmis, ko rakstāt: pārlÅ«kprogrammu vai datu bāzi. JābÅ«t noteiktam priekÅ”statam par mērÄ·i. Un jÅ«s noteikti domājat par to, ko tieÅ”i programma darÄ«s, un nerakstiet to nejauÅ”i, cerot, ka pats kods kaut kā pārvērtÄ«sies par pārlÅ«kprogrammu.

Kā tieÅ”i notiek Ŕī koda iepriekŔēja domāŔana? Cik daudz pūļu mums vajadzētu pielikt Å”ajā jautājumā? Tas viss ir atkarÄ«gs no tā, cik sarežģītu problēmu mēs risinām. Pieņemsim, ka mēs vēlamies uzrakstÄ«t defektiem izturÄ«gu sadalÄ«tu sistēmu. Å ajā gadÄ«jumā mums vajadzētu rÅ«pÄ«gi pārdomāt lietas, pirms apsēsties pie kodÄ“Å”anas. Ko darÄ«t, ja mums vienkārÅ”i jāpalielina vesels mainÄ«gais par 1? No pirmā acu uzmetiena Å”eit viss ir triviāls un nav jādomā, bet tad atceramies, ka var rasties pārplÅ«de. Tāpēc, pat lai saprastu, vai problēma ir vienkārÅ”a vai sarežģīta, vispirms ir jādomā.

Ja iepriekÅ” pārdomājat iespējamos problēmas risinājumus, varat izvairÄ«ties no kļūdām. Bet tas prasa, lai jÅ«su domāŔana bÅ«tu skaidra. Lai to panāktu, jums ir jāpieraksta savas domas. Man patÄ«k Dika Gindona citāts: ā€œKad tu raksti, daba parāda, cik pavirÅ”a ir tava domāŔana.ā€ Ja jÅ«s nerakstāt, jÅ«s tikai domājat, ka domājat. Un jums ir jāpieraksta savas domas specifikāciju veidā.

Specifikācijas kalpo daudzām funkcijām, Ä«paÅ”i lielos projektos. Bet es runāŔu tikai par vienu no tiem: tie palÄ«dz mums skaidri domāt. Skaidra domāŔana ir ļoti svarÄ«ga un diezgan sarežģīta, tāpēc mums ir vajadzÄ«ga palÄ«dzÄ«ba. Kādā valodā jāraksta specifikācijas? Kopumā programmētājiem tas vienmēr ir pirmais jautājums: kādā valodā mēs rakstÄ«sim? Nav vienas pareizas atbildes: mÅ«su risināmās problēmas ir pārāk dažādas. Dažiem cilvēkiem TLA+ ir manis izstrādāta specifikācijas valoda. Citiem ērtāk izmantot Ä·Ä«nieÅ”u valodu. Tas viss ir atkarÄ«gs no situācijas.

SvarÄ«gāks jautājums ir: kā mēs varam panākt skaidrāku domāŔanu? Atbilde: Mums jādomā kā zinātniekiem. Å is ir domāŔanas veids, kas ir labi strādājis pēdējos 500 gadus. Zinātnē mēs veidojam matemātiskos realitātes modeļus. Astronomija, iespējams, bija pirmā zinātne Ŕī vārda tieŔā nozÄ«mē. Astronomijā izmantotajā matemātiskajā modelÄ« debess Ä·ermeņi parādās kā punkti ar masu, stāvokli un impulsu, lai gan patiesÄ«bā tie ir ārkārtÄ«gi sarežģīti objekti ar kalniem un okeāniem, bēgumiem un bēgumiem. Å is modelis, tāpat kā jebkurÅ” cits, tika izveidots noteiktu problēmu risināŔanai. Tas ir lieliski piemērots, lai noteiktu, kur vērst teleskopu, ja vēlaties atrast planētu. Bet, ja vēlaties paredzēt laikapstākļus uz Ŕīs planētas, Å”is modelis nedarbosies.

Matemātika ļauj noteikt modeļa Ä«paŔības. Un zinātne parāda, kā Ŕīs Ä«paŔības ir saistÄ«tas ar realitāti. Parunāsim par mÅ«su zinātni, datorzinātnēm. Realitāte, ar kuru mēs strādājam, ir dažāda veida skaitļoÅ”anas sistēmas: procesori, spēļu konsoles, datori, kuros darbojas programmas, un tā tālāk. Es runāŔu par programmas izpildi datorā, bet kopumā visi Å”ie secinājumi attiecas uz jebkuru skaitļoÅ”anas sistēmu. MÅ«su zinātnē mēs izmantojam daudz dažādu modeļu: TjÅ«ringa maŔīnu, daļēji sakārtotus notikumu kopumus un daudzus citus.

Kas ir programma? Å is ir jebkurÅ” kods, ko var apsvērt atseviŔķi. Pieņemsim, ka mums ir jāraksta pārlÅ«kprogramma. Mēs veicam trÄ«s uzdevumus: noformējam lietotāja prezentāciju par programmu, pēc tam uzrakstām programmas augsta lÄ«meņa diagrammu un visbeidzot uzrakstām kodu. Rakstot kodu, mēs saprotam, ka mums ir jāraksta teksta formatētājs. Å eit atkal jāatrisina trÄ«s problēmas: jānosaka, kādu tekstu Å”is rÄ«ks atgriezÄ«s; izvēlieties formatÄ“Å”anas algoritmu; rakstÄ«t kodu. Å im uzdevumam ir savs apakÅ”uzdevums: pareizi ievietot defises vārdos. ArÄ« Å”o apakÅ”uzdevumu risinām trÄ«s soļos ā€“ kā redzam, tie atkārtojas daudzos lÄ«meņos.

SÄ«kāk apskatÄ«sim pirmo soli: kādu problēmu programma atrisina. Å eit mēs visbiežāk modelējam programmu kā funkciju, kas ņem zināmu ievadi un dod kādu izvadi. Matemātikā funkciju parasti raksturo kā sakārtotu pāru kopu. Piemēram, naturālu skaitļu kvadrātoÅ”anas funkcija ir aprakstÄ«ta kā kopa {<0,0>, <1,1>, <2,4>, <3,9>, ā€¦}. Šādas funkcijas definÄ«cijas domēns ir katra pāra pirmo elementu kopa, tas ir, naturālie skaitļi. Lai definētu funkciju, mums jānorāda tās domēns un formula.

Bet funkcijas matemātikā nav tādas paÅ”as kā funkcijas programmÄ“Å”anas valodās. Matemātika ir daudz vienkārŔāka. Tā kā man nav laika sarežģītiem piemēriem, aplÅ«kosim vienkārÅ”u: funkciju C vai statisku metodi Java, kas atgriež lielāko kopējo divu veselu skaitļu dalÄ«tāju. Å Ä«s metodes specifikācijā rakstÄ«sim: aprēķina GCD(M,N) par argumentiem M Šø NKur GCD(M,N) - funkcija, kuras domēns ir veselu skaitļu pāru kopa, un atgriežamā vērtÄ«ba ir lielākais veselais skaitlis, kas dalÄ«ts ar M Šø N. Kā realitāte atŔķiras ar Å”o modeli? Modelis darbojas ar veseliem skaitļiem, un C vai Java mums ir 32 biti int. Å is modelis ļauj mums izlemt, vai algoritms ir pareizs GCD, taču tas nenovērsÄ«s pārpildes kļūdas. Tam bÅ«tu nepiecieÅ”ams sarežģītāks modelis, kuram nav laika.

Parunāsim par funkcijas kā modeļa ierobežojumiem. Dažas programmas (piemēram, operētājsistēmas) ne tikai atgriež noteiktu vērtÄ«bu noteiktiem argumentiem; tās var darboties nepārtraukti. Turklāt funkcija kā modelis ir slikti piemērota otrajam solim: problēmas risināŔanas plānoÅ”anai. Ātrā kārtoÅ”ana un burbuļu kārtoÅ”ana aprēķina vienu un to paÅ”u funkciju, taču tie ir pilnÄ«gi atŔķirÄ«gi algoritmi. Tāpēc, lai aprakstÄ«tu veidu, kā sasniegt programmas mērÄ·i, es izmantoju citu modeli, sauksim to par standarta uzvedÄ«bas modeli. Programma tajā tiek attēlota kā visu derÄ«go uzvedÄ«bu kopums, no kuriem katrs, savukārt, ir stāvokļu secÄ«ba, un stāvoklis ir vērtÄ«bu pieŔķirÅ”ana mainÄ«gajiem.

ApskatÄ«sim, kā izskatÄ«sies EiklÄ«da algoritma otrais solis. Mums ir jāaprēķina GCD(M, N). Mēs inicializējam M kā xUn N kā y, pēc tam atkārtoti atņemiet mazāko no Å”iem mainÄ«gajiem lielumiem, lÄ«dz tie ir vienādi. Piemēram, ja M = 12Un N = 18, mēs varam aprakstÄ«t Ŕādu uzvedÄ«bu:

[x = 12, y = 18] ā†’ [x = 12, y = 6] ā†’ [x = 6, y = 6]

Un ja M = 0 Šø N = 0? Nulle dalās ar visiem skaitļiem, tāpēc Å”ajā gadÄ«jumā nav lielākā dalÄ«tāja. Å ajā situācijā mums ir jāatgriežas pie pirmā soļa un jājautā: vai mums tieŔām ir jāaprēķina GCD nepozitÄ«viem skaitļiem? Ja tas nav nepiecieÅ”ams, jums vienkārÅ”i jāmaina specifikācija.

Å eit ir vietā Ä«sa atkāpe par produktivitāti. To bieži mēra dienā uzrakstÄ«to koda rindiņu skaitā. Bet jÅ«su darbs ir daudz noderÄ«gāks, ja atbrÄ«vojaties no noteikta rindu skaita, jo jums ir mazāk vietas kļūdām. Un vienkārŔākais veids, kā atbrÄ«voties no koda, ir pirmais solis. Iespējams, ka jums vienkārÅ”i nav vajadzÄ«gi visi zvani un svilpes, ko mēģināt Ä«stenot. Ātrākais veids, kā vienkārÅ”ot programmu un ietaupÄ«t laiku, ir nedarÄ«t lietas, kuras nevajadzētu darÄ«t. Otrajam solim ir otrs lielākais laika taupÄ«Å”anas potenciāls. Ja mēra produktivitāti uzrakstÄ«to rindiņu izteiksmē, tad domas par to, kā izpildÄ«t uzdevumu, liks jums mazāk produktÄ«vs, jo jÅ«s varat atrisināt to paÅ”u problēmu ar mazāku kodu. Å eit nevaru sniegt precÄ«zu statistiku, jo man nav iespējas saskaitÄ«t rindiņu skaitu, kuras neuzrakstÄ«ju specifikācijas, tas ir, pirmajam un otrajam solim, pavadÄ«tā laika dēļ. Un arÄ« Å”eit nevar veikt eksperimentu, jo eksperimentā mums nav tiesÄ«bu veikt pirmo soli, uzdevums tiek noteikts iepriekÅ”.

Neformālajās specifikācijās ir viegli nepamanÄ«t daudzas grÅ«tÄ«bas. Stingru funkciju specifikāciju rakstÄ«Å”anā nav nekā sarežģīta; es to neapspriedÄ«Å”u. Tā vietā mēs runāsim par stingru standarta uzvedÄ«bas specifikāciju rakstÄ«Å”anu. Pastāv teorēma, kas nosaka, ka jebkuru darbÄ«bu kopumu var aprakstÄ«t, izmantojot droŔības rekvizÄ«tu (droŔība) un izdzÄ«voÅ”anas Ä«paŔības (dzÄ«vÄ«gums). DroŔība nozÄ«mē, ka nekas slikts nenotiks, programma nesniegs nepareizu atbildi. IzdzÄ«voÅ”ana nozÄ«mē, ka agrāk vai vēlāk notiks kaut kas labs, t.i., programma agrāk vai vēlāk sniegs pareizo atbildi. Parasti svarÄ«gāks rādÄ«tājs ir droŔība, Å”eit visbiežāk rodas kļūdas. Tāpēc, lai ietaupÄ«tu laiku, es nerunāŔu par izdzÄ«voÅ”anu, lai gan tas, protams, arÄ« ir svarÄ«gs.

Mēs panākam droŔību, vispirms norādot iespējamo sākotnējo stāvokļu kopu. Un, otrkārt, attiecÄ«bas ar visiem iespējamiem nākamajiem stāvokļiem katram Å”tatam. UzvedÄ«simies kā zinātnieki un definēsim stāvokļus matemātiski. Sākotnējo stāvokļu kopu apraksta ar formulu, piemēram, EiklÄ«da algoritma gadÄ«jumā: (x = M) āˆ§ (y = N). Par noteiktām vērtÄ«bām M Šø N ir tikai viens sākuma stāvoklis. AttiecÄ«bas ar nākamo stāvokli apraksta ar formulu, kurā nākamā stāvokļa mainÄ«gie tiek ierakstÄ«ti ar pirmskaitli, bet paÅ”reizējā stāvokļa mainÄ«gie bez pirmskaitļa. EiklÄ«da algoritma gadÄ«jumā mēs nodarbosimies ar divu formulu disjunkciju, no kurām vienā x ir lielākā vērtÄ«ba, bet otrajā - y:

ProgrammÄ“Å”ana ir vairāk nekā kodÄ“Å”ana

Pirmajā gadÄ«jumā jaunā y vērtÄ«ba ir vienāda ar iepriekŔējo y vērtÄ«bu, un mēs iegÅ«stam jauno x vērtÄ«bu, atņemot mazāko mainÄ«go no lielākā. Otrajā gadÄ«jumā mēs rÄ«kojamies pretēji.

AtgriezÄ«simies pie EiklÄ«da algoritma. Pieņemsim vēlreiz, ka M = 12, N = 18. Tas definē vienu sākotnējo stāvokli, (x = 12) āˆ§ (y = 18). Pēc tam mēs pievienojam Ŕīs vērtÄ«bas iepriekÅ” minētajā formulā un iegÅ«stam:

ProgrammÄ“Å”ana ir vairāk nekā kodÄ“Å”ana

Å eit ir vienÄ«gais iespējamais risinājums: x' = 18 - 12 āˆ§ y' = 12, un mēs iegÅ«stam uzvedÄ«bu: [x = 12, y = 18]. Tādā paŔā veidā mēs varam aprakstÄ«t visus mÅ«su uzvedÄ«bas stāvokļus: [x = 12, y = 18] ā†’ [x = 12, y = 6] ā†’ [x = 6, y = 6].

Pēdējā stāvoklī [x = 6, y = 6] abas izteiksmes daļas būs nepatiesas, tāpēc tai nav nākamā stāvokļa. Tātad, mums ir pilnīga otrā posma specifikācija - kā mēs redzam, tā ir diezgan parasta matemātika, piemēram, inženieru un zinātnieku, un nav dīvaina, piemēram, datorzinātnēs.

Šīs divas formulas var apvienot vienā temporālās loģikas formulā. Tas ir eleganti un viegli izskaidrojams, bet tagad tam nav laika. Laicīgā loģika mums var būt nepiecieŔama tikai dzīvīguma īpaŔībai, droŔībai tā nav vajadzīga. Man nepatīk temporālā loģika kā tāda, tā nav gluži parasta matemātika, bet dzīvīguma gadījumā tas ir nepiecieŔams ļaunums.

EiklÄ«da algoritmā katrai vērtÄ«bai x Šø y ir unikālas vērtÄ«bas x' Šø y', kas padara saistÄ«bu ar nākamo stāvokli patiesu. Citiem vārdiem sakot, EiklÄ«da algoritms ir deterministisks. Lai modelētu nedeterministisku algoritmu, paÅ”reizējam stāvoklim ir jābÅ«t vairākiem iespējamiem nākotnes stāvokļiem, un katrai neapstrādātā mainÄ«gā vērtÄ«bai ir jābÅ«t vairākām primārā mainÄ«gā vērtÄ«bām, lai attiecÄ«bas ar nākamo stāvokli bÅ«tu patiesas. Tas nav grÅ«ti izdarāms, bet es tagad nesniegÅ”u piemērus.

Lai izveidotu darba rīku, nepiecieŔama formālā matemātika. Kā specifikāciju padarīt formālu? Lai to izdarītu, mums būs nepiecieŔama formāla valoda, piem. TLA+. Eiklīda algoritma specifikācija Ŕajā valodā izskatīsies Ŕādi:

ProgrammÄ“Å”ana ir vairāk nekā kodÄ“Å”ana

VienādÄ«bas zÄ«mes simbols ar trÄ«sstÅ«ri nozÄ«mē, ka vērtÄ«ba pa kreisi no zÄ«mes tiek noteikta kā vienāda ar vērtÄ«bu pa labi no zÄ«mes. BÅ«tÄ«bā specifikācija ir definÄ«cija, mÅ«su gadÄ«jumā divas definÄ«cijas. TLA+ specifikācijai ir jāpievieno deklarācijas un zināma sintakse, kā parādÄ«ts augstāk esoÅ”ajā slaidā. ASCII formātā tas izskatÄ«tos Ŕādi:

ProgrammÄ“Å”ana ir vairāk nekā kodÄ“Å”ana

Kā redzat, nekas sarežģīts. TLA+ specifikāciju var pārbaudÄ«t, t.i., mazā modelÄ« ir iespējams apiet visas iespējamās darbÄ«bas. MÅ«su gadÄ«jumā Å”is modelis bÅ«s noteiktas vērtÄ«bas M Šø N. Å Ä« ir ļoti efektÄ«va un vienkārÅ”a verifikācijas metode, kas ir pilnÄ«bā automātiska. Turklāt ir iespējams uzrakstÄ«t formālus patiesÄ«bas pierādÄ«jumus un pārbaudÄ«t tos mehāniski, taču tas aizņem daudz laika, tāpēc gandrÄ«z neviens to nedara.

TLA+ galvenais trÅ«kums ir tas, ka tā ir matemātika, un programmētāji un datorzinātnieki baidās no matemātikas. No pirmā acu uzmetiena tas izklausās kā joks, bet diemžēl es to saku ļoti nopietni. Mans kolēģis tikko stāstÄ«ja, kā viņŔ mēģināja izskaidrot TLA+ vairākiem izstrādātājiem. TiklÄ«dz formulas parādÄ«jās ekrānā, viņu acis uzreiz kļuva stiklveida. Tātad, ja TLA+ ir biedējoÅ”s, varat to izmantot PlusCal, ir sava veida rotaļlietu programmÄ“Å”anas valoda. Izteiksme programmā PlusCal var bÅ«t jebkura TLA+ izteiksme, tas ir, bÅ«tÄ«bā jebkura matemātiska izteiksme. Turklāt PlusCal ir sintakse nedeterministiskiem algoritmiem. Tā kā PlusCal var rakstÄ«t jebkuru TLA+ izteiksmi, tā ir ievērojami izteiksmÄ«gāka nekā jebkura reāla programmÄ“Å”anas valoda. Pēc tam PlusCal ir apkopots viegli lasāmā TLA+ specifikācijā. Tas, protams, nenozÄ«mē, ka sarežģītā PlusCal specifikācija TLA+ pārtaps par vienkārÅ”u ā€“ tikai tāpēc, ka atbilstÄ«ba starp tām ir acÄ«mredzama, nekāda papildu sarežģītÄ«ba neparādÄ«sies. Visbeidzot, Å”o specifikāciju var pārbaudÄ«t, izmantojot TLA+ rÄ«kus. Kopumā PlusCal var palÄ«dzēt pārvarēt matemātikas fobiju; to ir viegli saprast pat programmētājiem un datorzinātniekiem. Es kādu laiku (apmēram 10 gadus) publicēju tajā algoritmus.

VarbÅ«t kāds iebildÄ«s, ka TLA+ un PlusCal ir matemātika un matemātika darbojas tikai ar izdomātiem piemēriem. Praksē jums ir nepiecieÅ”ama Ä«sta valoda ar veidiem, procedÅ«rām, objektiem utt. Tas ir nepareizi. LÅ«k, ko raksta Kriss Ņūkombs, kurÅ” strādāja Amazon: ā€œMēs esam izmantojuÅ”i TLA+ desmit lielos projektos, un katrā gadÄ«jumā tā izmantoÅ”ana bÅ«tiski ietekmēja attÄ«stÄ«bu, jo mēs varējām noÄ·ert bÄ«stamas kļūdas, pirms tās nonāca ražoÅ”anā, un tāpēc, ka tas sniedza mums ieskatu un pārliecÄ«bu, kas bija nepiecieÅ”ama, lai kļūtu agresÄ«vs. veiktspējas optimizācija, neietekmējot programmas patiesumu". Bieži var dzirdēt, ka, izmantojot formālas metodes, mēs iegÅ«stam neefektÄ«vu kodu ā€“ praksē viss ir tieÅ”i otrādi. Turklāt pastāv uzskats, ka vadÄ«tājus nevar pārliecināt par formālu metožu nepiecieÅ”amÄ«bu, pat ja programmētāji ir pārliecināti par to lietderÄ«bu. Un Ņūkombs raksta: ā€œVadÄ«tāji tagad visos iespējamos veidos cenÅ”as rakstÄ«t specifikācijas TLA+ un Ä«paÅ”i atvēl tam laiku.ā€. Tātad, kad vadÄ«tāji redz, ka TLA+ darbojas, viņi to pieņem. Kriss Ņūkombs to rakstÄ«ja apmēram pirms seÅ”iem mēneÅ”iem (2014. gada oktobrÄ«), bet tagad, cik man zināms, TLA+ tiek izmantots 14 projektos, nevis 10. Vēl viens piemērs attiecas uz XBox 360 dizainu. Pie Čārlza Tekera ieradās praktikants un uzrakstÄ«ja specifikāciju atmiņas sistēmai. Pateicoties Å”ai specifikācijai, tika atrasta kļūda, kas citādi netiktu atklāta un izraisÄ«tu katra XBox 360 avāriju pēc četru stundu lietoÅ”anas. IBM inženieri apstiprināja, ka viņu testi nebÅ«tu atklājuÅ”i Å”o kļūdu.

Vairāk par TLA+ var lasÄ«t internetā, bet tagad parunāsim par neformālajām specifikācijām. Mums reti ir jāraksta programmas, kas aprēķina vismazāko dalÄ«tāju un tamlÄ«dzÄ«gi. Daudz biežāk mēs rakstām tādas programmas kā diezgan printera rÄ«ks, ko rakstÄ«ju TLA+. Pēc vienkārŔākās apstrādes TLA+ kods izskatÄ«tos Ŕādi:

ProgrammÄ“Å”ana ir vairāk nekā kodÄ“Å”ana

Taču iepriekÅ” minētajā piemērā lietotājs, visticamāk, vēlējās, lai savienojums un vienādÄ«bas zÄ«mes tiktu lÄ«dzināti. Tātad pareizais formatējums izskatÄ«tos vairāk Ŕādi:

ProgrammÄ“Å”ana ir vairāk nekā kodÄ“Å”ana

Apsveriet citu piemēru:

ProgrammÄ“Å”ana ir vairāk nekā kodÄ“Å”ana

Å eit, gluži pretēji, vienādÄ«bas zÄ«mju sakārtoÅ”ana, saskaitÄ«Å”ana un reizināŔana avotā bija nejauÅ”a, tāpēc pietiek ar vienkārŔāko apstrādi. Kopumā pareizam formatējumam nav precÄ«zas matemātiskas definÄ«cijas, jo ā€œpareiziā€ Å”ajā gadÄ«jumā nozÄ«mē ā€œko vēlas lietotājsā€, un to nevar noteikt matemātiski.

Å Ä·iet, ja mums nav patiesÄ«bas definÄ«cijas, tad specifikācija ir bezjēdzÄ«ga. Bet tā nav taisnÄ«ba. Tas, ka mēs nezinām, kas programmai ir jādara, nenozÄ«mē, ka mums nav jādomā par to, kā tai bÅ«tu jādarbojas ā€” gluži pretēji, mums tai ir jāvelta vēl vairāk pūļu. ÄŖpaÅ”i svarÄ«ga Å”eit ir specifikācija. Nav iespējams noteikt optimālo programmu strukturētai drukāŔanai, taču tas nenozÄ«mē, ka mums tas vispār nebÅ«tu jāuzņemas, un koda rakstÄ«Å”ana kā apziņas plÅ«sma tā nav. Es beidzot uzrakstÄ«ju seÅ”u noteikumu specifikāciju ar definÄ«cijām komentāru veidā Java failā. Å eit ir piemērs vienam no noteikumiem: a left-comment token is LeftComment aligned with its covering token. Å is noteikums ir uzrakstÄ«ts, teiksim, matemātiskā angļu valodā: LeftComment aligned, left-comment Šø covering token ā€” termini ar definÄ«cijām. MatemātiÄ·i apraksta matemātiku Ŕādi: viņi raksta terminu definÄ«cijas un, pamatojoties uz tiem, veido noteikumus. Å Ä«s specifikācijas priekÅ”rocÄ«ba ir tāda, ka seÅ”us noteikumus ir daudz vieglāk saprast un atkļūdot nekā 850 koda rindiņas. Man jāsaka, ka Å”o noteikumu rakstÄ«Å”ana nebija vienkārÅ”a, to atkļūdoÅ”ana prasÄ«ja diezgan daudz laika. Es uzrakstÄ«ju kodu tieÅ”i Å”im nolÅ«kam, kas man norādÄ«ja, kurÅ” noteikums tika izmantots. Tā kā es pārbaudÄ«ju Å”os seÅ”us noteikumus ar dažiem piemēriem, man nebija jāatkļūdo 850 koda rindiņas, un kļūdas bija diezgan viegli atrast. Java tam ir lieliski rÄ«ki. Ja es bÅ«tu tikko uzrakstÄ«jis kodu, tas bÅ«tu prasÄ«jis daudz ilgāku laiku un formatējums bÅ«tu sliktāks.

Kāpēc nevarēja izmantot formālu specifikāciju? No vienas puses, pareiza izpilde Å”eit nav pārāk svarÄ«ga. Strukturēta izdruka noteikti dažiem neapmierinās, tāpēc man nebija jāpanāk, lai tā darbotos pareizi visās neparastajās situācijās. Vēl svarÄ«gāk ir tas, ka man nebija atbilstoÅ”u instrumentu. TLA+ modeļu pārbaudÄ«tājs Å”eit ir bezjēdzÄ«gs, tāpēc man bÅ«tu jāraksta piemēri ar roku.

Dotajai specifikācijai ir iezÄ«mes, kas ir kopÄ«gas visām specifikācijām. Tas ir augstāks lÄ«menis nekā kods. To var ieviest jebkurā valodā. Nav rÄ«ku vai metožu tā rakstÄ«Å”anai. Neviens programmÄ“Å”anas kurss nepalÄ«dzēs uzrakstÄ«t Å”o specifikāciju. Un nav rÄ«ku, kas varētu padarÄ«t Å”o specifikāciju nevajadzÄ«gu, ja vien jÅ«s, protams, nerakstāt valodu, kas ir Ä«paÅ”i paredzēta strukturētu izdruku programmu rakstÄ«Å”anai TLA+. Visbeidzot, Å”ajā specifikācijā nekas nav teikts par to, kā tieÅ”i mēs rakstÄ«sim kodu, tajā ir tikai norādÄ«ts, ko kods dara. Mēs rakstām specifikāciju, lai palÄ«dzētu mums pārdomāt problēmu, pirms sākam domāt par kodu.

Bet Ŕai specifikācijai ir arī pazīmes, kas to atŔķir no citām specifikācijām. 95% citu specifikāciju ir daudz īsākas un vienkārŔākas:

ProgrammÄ“Å”ana ir vairāk nekā kodÄ“Å”ana

Turklāt Ŕī specifikācija ir noteikumu kopums. Tas parasti liecina par sliktu specifikāciju. Izprast noteikumu kopuma sekas ir diezgan grÅ«ti, tāpēc man bija jāpavada daudz laika, lai tos atkļūdotu. Tomēr Å”ajā gadÄ«jumā es nevarēju atrast labāku veidu.

Ir vērts pateikt dažus vārdus par programmām, kas darbojas nepārtraukti. Parasti tās darbojas paralēli, piemēram, operētājsistēmas vai sadalÄ«tas sistēmas. Ä»oti maz cilvēku var tos saprast savā prātā vai uz papÄ«ra, un es neesmu viens no tiem, lai gan kādreiz es to varēju. Tāpēc mums ir nepiecieÅ”ami rÄ«ki, kas pārbaudÄ«s mÅ«su darbu - piemēram, TLA+ vai PlusCal.

Kāpēc man bija jāraksta specifikācija, ja es jau zināju, kas kodam jādara? PatiesÄ«bā es tikai domāju, ka es to zinu. Turklāt, ja ir ieviesta specifikācija, ārējam vairs nav jāiedziļinās kodā, lai saprastu, ko tieÅ”i tas dara. Man ir noteikums: vispārējiem noteikumiem nevajadzētu bÅ«t. Protams, Å”im noteikumam ir izņēmums, tas ir vienÄ«gais vispārÄ«gais noteikums, ko es ievēroju: koda darbÄ«bas specifikācijai ir jāpasaka cilvēkiem viss, kas viņiem jāzina, lietojot Å”o kodu.

Kas tad Ä«sti programmētājiem jāzina par domāŔanu? Sākumā tas pats, kas visiem: ja tu neraksti, tad tev tikai Ŕķiet, ka tu domā. Turklāt jums ir jādomā pirms kodÄ“Å”anas, kas nozÄ«mē, ka pirms kodÄ“Å”anas jums ir jāraksta. Specifikācijas ir tas, ko mēs rakstām pirms kodÄ“Å”anas. Specifikācija ir nepiecieÅ”ama jebkuram kodam, ko var izmantot vai mainÄ«t ikviens. Un Å”is ā€œkādsā€ var izrādÄ«ties koda autors mēnesi pēc tā uzrakstÄ«Å”anas. Specifikācija ir nepiecieÅ”ama lielām programmām un sistēmām, klasēm, metodēm un dažreiz pat vienas metodes sarežģītām sadaļām. Kas tieÅ”i bÅ«tu jāraksta par kodu? Jums jāapraksta, ko tas dara, tas ir, kaut kas var bÅ«t noderÄ«gs ikvienam, kas izmanto Å”o kodu. Dažreiz var bÅ«t nepiecieÅ”ams arÄ« norādÄ«t, kā tieÅ”i kods sasniedz savu mērÄ·i. Ja mēs Å”o metodi izgājām algoritmu kursā, tad to saucam par algoritmu. Ja tas ir kaut kas specializētāks un jauns, tad mēs to saucam par augsta lÄ«meņa dizainu. Å eit nav formālas atŔķirÄ«bas: abi ir abstrakti programmas modeļi.

Kā tieÅ”i jums vajadzētu rakstÄ«t koda specifikāciju? Galvenais: tam jābÅ«t vienu lÄ«meni augstākam par paÅ”u kodu. Tam jāapraksta stāvokļi un uzvedÄ«ba. Tam jābÅ«t tik stingrai, cik to prasa uzdevums. Ja rakstāt specifikāciju, kā Ä«stenot uzdevumu, tad to var rakstÄ«t pseidokodā vai izmantojot PlusCal. Jums jāiemācās rakstÄ«t specifikācijas, izmantojot formālas specifikācijas. Tas iegÅ«s nepiecieÅ”amās prasmes, kas palÄ«dzēs arÄ« neformālajās. Kā iemācÄ«ties rakstÄ«t oficiālas specifikācijas? Kad iemācÄ«jāmies programmēt, rakstÄ«jām programmas un pēc tam tās atkļūdojām. Tas pats Å”eit: jums ir jāuzraksta specifikācija, jāpārbauda tā ar modeļa pārbaudÄ«tāju un jāizlabo kļūdas. TLA+ var nebÅ«t labākā valoda formālai specifikācijai, un cita valoda, iespējams, bÅ«tu labāk piemērota jÅ«su Ä«paÅ”ajām vajadzÄ«bām. Lieliskā TLA+ lieta ir tā, ka tā lieliski māca matemātisko domāŔanu.

Kā saistÄ«t specifikāciju un kodu? Izmantojot komentārus, kas saista matemātiskos jēdzienus un to realizāciju. Ja strādājat ar grafikiem, tad programmas lÄ«menÄ« jums bÅ«s mezglu masÄ«vi un saiÅ”u masÄ«vi. Tātad jums ir jāuzraksta, kā tieÅ”i grafu realizē Ŕīs programmÄ“Å”anas struktÅ«ras.

JāatzÄ«mē, ka nekas no iepriekÅ” minētā neattiecas uz paÅ”u koda rakstÄ«Å”anas procesu. Rakstot kodu, tas ir, veicot treÅ”o darbÄ«bu, jums ir arÄ« jādomā un jāpārdomā programma. Ja apakÅ”uzdevums izrādās sarežģīts vai nav acÄ«mredzams, jums ir jāraksta tā specifikācija. Bet es Å”eit nerunāju par paÅ”u kodu. JÅ«s varat izmantot jebkuru programmÄ“Å”anas valodu, jebkuru metodiku, tas nav par tiem. Turklāt nekas no iepriekÅ”minētā neatbrÄ«vo no nepiecieÅ”amÄ«bas pārbaudÄ«t un atkļūdot kodu. Pat ja abstraktais modelis ir uzrakstÄ«ts pareizi, tā ievieÅ”anā var bÅ«t kļūdas.

Specifikāciju rakstÄ«Å”ana ir papildu solis kodÄ“Å”anas procesā. Pateicoties tam, daudzas kļūdas var pieÄ·ert ar mazāku piepÅ«li - mēs to zinām no Amazon programmētāju pieredzes. Ar specifikācijām programmu kvalitāte kļūst augstāka. Kāpēc tad mēs tik bieži iztiekam bez tiem? Jo rakstÄ«t ir grÅ«ti. Bet rakstÄ«t ir grÅ«ti, jo tam ir jādomā, un arÄ« domāt ir grÅ«ti. Vienmēr ir vieglāk izlikties, ka domājat. Å eit var vilkt analoÄ£iju ar skrieÅ”anu ā€“ jo mazāk skrien, jo lēnāk skrien. Jums ir jātrenē savi muskuļi un jāvingrinās rakstÄ«t. Tas prasa praksi.

Specifikācija var bÅ«t nepareiza. Iespējams, kaut kur esat pieļāvis kļūdu, prasÄ«bas ir mainÄ«juŔās, vai arÄ« ir jāveic uzlabojumi. JebkurÅ” kods, ko kāds izmanto, ir jāmaina, tāpēc agri vai vēlu specifikācija vairs nesakritÄ«s ar programmu. Ideālā gadÄ«jumā Å”ajā gadÄ«jumā jums ir jāraksta jauna specifikācija un pilnÄ«bā jāpārraksta kods. Mēs ļoti labi zinām, ka neviens to nedara. Praksē mēs labojam kodu un, iespējams, atjauninām specifikāciju. Ja agrāk vai vēlāk tas noteikti notiks, tad kāpēc vispār rakstÄ«t specifikācijas? Pirmkārt, personai, kas rediģēs jÅ«su kodu, katrs papildu vārds specifikācijā bÅ«s zelta vērts, un Ŕī persona, iespējams, esat jÅ«s. Es bieži spārdos sevi par to, ka rediģējot kodu, neesmu pietiekami precÄ«zs. Un es rakstu vairāk specifikācijas nekā kodu. Tāpēc, rediģējot kodu, specifikācija vienmēr ir jāatjaunina. Otrkārt, ar katru labojumu kods kļūst sliktāks, to kļūst grÅ«tāk lasÄ«t un uzturēt. Tas ir entropijas pieaugums. Bet, ja nesākat ar specifikāciju, katra jÅ«su rakstÄ«tā rindiņa bÅ«s labojums, un kods bÅ«s apjomÄ«gs un grÅ«ti nolasāms no paÅ”a sākuma.

Kā teikts Eizenhauers, neviena kauja netika uzvarēta pēc plāna, un neviena kauja netika uzvarēta bez plāna. Un viņŔ kaut ko zināja par kaujām. Pastāv viedoklis, ka specifikāciju rakstÄ«Å”ana ir laika izŔķieÅ”ana. Dažreiz tā ir taisnÄ«ba, un uzdevums ir tik vienkārÅ”s, ka nav jēgas to pārdomāt. Bet jums vienmēr jāatceras, ka tad, kad jums tiek ieteikts nerakstÄ«t specifikācijas, tas nozÄ«mē, ka jums ir ieteicams nedomāt. Un jums par to vajadzētu padomāt katru reizi. Uzdevuma pārdomāŔana negarantē, ka nepieļausit kļūdas. Kā zināms, neviens nav izgudrojis burvju nÅ«jiņu, un programmÄ“Å”ana ir grÅ«ts uzdevums. Bet, ja jÅ«s nepārdomājat uzdevumu, jÅ«s noteikti pieļausit kļūdas.

Vairāk par TLA+ un PlusCal varat lasÄ«t speciālā mājaslapā, turp var doties no manas mājas lapas ŠæŠ¾ ссыŠ»ŠŗŠµ. Tas man ir viss, paldies par uzmanÄ«bu.

LÅ«dzu, atcerieties, ka Å”is ir tulkojums. Rakstot komentārus, atcerieties, ka autors tos nelasÄ«s. Ja ļoti vēlies patērzēt ar autoru, viņŔ bÅ«s Hydra 2019 konferencē, kas notiks 11. gada 12.-2019.jÅ«lijā Sanktpēterburgā. Biļetes var iegādāties oficiālajā tÄ«mekļa vietnē.

Avots: www.habr.com

Pievieno komentāru